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.
This commit is contained in:
parent
33bab57d1e
commit
de38924dc0
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=136694
@ -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;
|
||||
}
|
||||
|
||||
@ -1144,6 +1144,67 @@ ip_drain()
|
||||
in_rtqdrain();
|
||||
}
|
||||
|
||||
/*
|
||||
* 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,
|
||||
|
@ -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 *
|
||||
|
Loading…
Reference in New Issue
Block a user