diff options
author | andre <andre@FreeBSD.org> | 2004-10-19 15:45:57 +0000 |
---|---|---|
committer | andre <andre@FreeBSD.org> | 2004-10-19 15:45:57 +0000 |
commit | 00d43f4bd8218e12e456cef93e786e0a910ba560 (patch) | |
tree | 5e1381e3fd7b17aca48188a8e5c4717260ca205f /sys/netinet | |
parent | 8112f95a8c58a972c772b025bf4229fb1623a162 (diff) | |
download | FreeBSD-src-00d43f4bd8218e12e456cef93e786e0a910ba560.zip FreeBSD-src-00d43f4bd8218e12e456cef93e786e0a910ba560.tar.gz |
Support for dynamically loadable and unloadable IP protocols in the ipmux.
With pr_proto_register() it has become possible to dynamically load protocols
within the PF_INET domain. However the PF_INET domain has a second important
structure called ip_protox[] that is derived from the 'struct protosw inetsw[]'
and takes care of the de-multiplexing of the various protocols that ride on
top of IP packets.
The functions ipproto_[un]register() allow to dynamically adjust the ip_protox[]
array mux in a consistent and easy way. To register a protocol within
ip_protox[] the existence of a corresponding and matching protocol definition
in inetsw[] is required. The function does not allow to overwrite an already
registered protocol. The unregister function simply replaces the mux slot with
the default index pointer to IPPROTO_RAW as it was previously.
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/ip_input.c | 63 | ||||
-rw-r--r-- | sys/netinet/ip_var.h | 2 |
2 files changed, 64 insertions, 1 deletions
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 37fbfd6..b950504 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -261,7 +261,7 @@ ip_init() if (pr->pr_domain->dom_family == PF_INET && pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) { /* Be careful to only index valid IP protocols. */ - if (pr->pr_protocol && pr->pr_protocol < IPPROTO_MAX) + if (pr->pr_protocol <= IPPROTO_MAX) ip_protox[pr->pr_protocol] = pr - inetsw; } @@ -1145,6 +1145,67 @@ ip_drain() } /* + * The protocol to be inserted into ip_protox[] must be already registered + * in inetsw[], either statically or through pf_proto_register(). + */ +int +ipproto_register(u_char ipproto) +{ + struct protosw *pr; + + /* Sanity checks. */ + if (ipproto == 0) + return (EPROTONOSUPPORT); + + /* + * The protocol slot must not be occupied by another protocol + * already. An index pointing to IPPROTO_RAW is unused. + */ + pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW); + if (pr == NULL) + return (EPFNOSUPPORT); + if (ip_protox[ipproto] != pr - inetsw) /* IPPROTO_RAW */ + return (EEXIST); + + /* Find the protocol position in inetsw[] and set the index. */ + for (pr = inetdomain.dom_protosw; + pr < inetdomain.dom_protoswNPROTOSW; pr++) { + if (pr->pr_domain->dom_family == PF_INET && + pr->pr_protocol && pr->pr_protocol == ipproto) { + /* Be careful to only index valid IP protocols. */ + if (pr->pr_protocol <= IPPROTO_MAX) { + ip_protox[pr->pr_protocol] = pr - inetsw; + return (0); + } else + return (EINVAL); + } + } + return (EPROTONOSUPPORT); +} + +int +ipproto_unregister(u_char ipproto) +{ + struct protosw *pr; + + /* Sanity checks. */ + if (ipproto == 0) + return (EPROTONOSUPPORT); + + /* Check if the protocol was indeed registered. */ + pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW); + if (pr == NULL) + return (EPFNOSUPPORT); + if (ip_protox[ipproto] == pr - inetsw) /* IPPROTO_RAW */ + return (ENOENT); + + /* Reset the protocol slot to IPPROTO_RAW. */ + ip_protox[ipproto] = pr - inetsw; + return (0); +} + + +/* * Do option processing on a datagram, * possibly discarding it if bad options are encountered, * or forwarding it if source-routed. diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index 2fa80d3..b4c99d2 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -168,6 +168,8 @@ extern int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *, int ip_output(struct mbuf *, struct mbuf *, struct route *, int, struct ip_moptions *, struct inpcb *); +int ipproto_register(u_char); +int ipproto_unregister(u_char); struct mbuf * ip_reass(struct mbuf *); struct in_ifaddr * |