summaryrefslogtreecommitdiffstats
path: root/sys/netinet6
diff options
context:
space:
mode:
authorbz <bz@FreeBSD.org>2010-09-02 17:43:44 +0000
committerbz <bz@FreeBSD.org>2010-09-02 17:43:44 +0000
commit18b40a43ee40b60f16950803b49724d0ef523293 (patch)
tree230de1f4337a85ebf5c0a3f05c9883bdd78fba3d /sys/netinet6
parentafcc72e27209509f7b650cea4f8607fb316ea2de (diff)
downloadFreeBSD-src-18b40a43ee40b60f16950803b49724d0ef523293.zip
FreeBSD-src-18b40a43ee40b60f16950803b49724d0ef523293.tar.gz
MFp4 CH=183052 183053 183258:
In protosw we define pr_protocol as short, while on the wire it is an uint8_t. That way we can have "internal" protocols like DIVERT, SEND or gaps for modules (PROTO_SPACER). Switch ipproto_{un,}register to accept a short protocol number(*) and do an upfront check for valid boundries. With this we also consistently report EPROTONOSUPPORT for out of bounds protocols, as we did for proto == 0. This allows a caller to not error for this case, which is especially important if we want to automatically call these from domain handling. (*) the functions have been without any in-tree consumer since the initial introducation, so this is considered save. Implement ip6proto_{un,}register() similarly to their legacy IP counter parts to allow modules to hook up dynamically. Reviewed by: philip, will MFC after: 1 week
Diffstat (limited to 'sys/netinet6')
-rw-r--r--sys/netinet6/ip6_input.c58
-rw-r--r--sys/netinet6/ip6_var.h3
2 files changed, 61 insertions, 0 deletions
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index ec82250..7e650a2 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -227,6 +227,64 @@ ip6_init(void)
netisr_register(&ip6_nh);
}
+/*
+ * The protocol to be inserted into ip6_protox[] must be already registered
+ * in inet6sw[], either statically or through pf_proto_register().
+ */
+int
+ip6proto_register(short ip6proto)
+{
+ struct ip6protosw *pr;
+
+ /* Sanity checks. */
+ if (ip6proto <= 0 || ip6proto >= IPPROTO_MAX)
+ return (EPROTONOSUPPORT);
+
+ /*
+ * The protocol slot must not be occupied by another protocol
+ * already. An index pointing to IPPROTO_RAW is unused.
+ */
+ pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
+ if (pr == NULL)
+ return (EPFNOSUPPORT);
+ if (ip6_protox[ip6proto] != pr - inet6sw) /* IPPROTO_RAW */
+ return (EEXIST);
+
+ /*
+ * Find the protocol position in inet6sw[] and set the index.
+ */
+ for (pr = (struct ip6protosw *)inet6domain.dom_protosw;
+ pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++) {
+ if (pr->pr_domain->dom_family == PF_INET6 &&
+ pr->pr_protocol && pr->pr_protocol == ip6proto) {
+ ip6_protox[pr->pr_protocol] = pr - inet6sw;
+ return (0);
+ }
+ }
+ return (EPROTONOSUPPORT);
+}
+
+int
+ip6proto_unregister(short ip6proto)
+{
+ struct ip6protosw *pr;
+
+ /* Sanity checks. */
+ if (ip6proto <= 0 || ip6proto >= IPPROTO_MAX)
+ return (EPROTONOSUPPORT);
+
+ /* Check if the protocol was indeed registered. */
+ pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
+ if (pr == NULL)
+ return (EPFNOSUPPORT);
+ if (ip6_protox[ip6proto] == pr - inet6sw) /* IPPROTO_RAW */
+ return (ENOENT);
+
+ /* Reset the protocol slot to IPPROTO_RAW. */
+ ip6_protox[ip6proto] = pr - inet6sw;
+ return (0);
+}
+
#ifdef VIMAGE
void
ip6_destroy()
diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h
index 3e91a79..51ae1f7 100644
--- a/sys/netinet6/ip6_var.h
+++ b/sys/netinet6/ip6_var.h
@@ -368,6 +368,9 @@ void ip6_init __P((void));
#ifdef VIMAGE
void ip6_destroy __P((void));
#endif
+int ip6proto_register(short);
+int ip6proto_unregister(short);
+
void ip6_input __P((struct mbuf *));
struct in6_ifaddr *ip6_getdstifaddr __P((struct mbuf *));
void ip6_freepcbopts __P((struct ip6_pktopts *));
OpenPOWER on IntegriCloud