tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: route_protosw.pr_input



> Date: Wed, 5 Sep 2018 08:21:12 +0200
> From: Maxime Villard <max%m00nbsd.net@localhost>
> 
> In net/rtsock.c, I don't understand where we use the 'pr_input' field of
> COMPATNAME(route_protosw)[]. To me it can't be used: .pr_input takes a
> variadic function, but if you grep through the tree, you can see that
> the variadic .pr_input functions we call always take three arguments, as
> opposed to raw_input() which takes five.
> 
> Therefore raw_input() is never called via .pr_input, and we can set the
> field to NULL. Then we can switch all the .pr_input functions to be static
> and not variadic.
> 
> This will clear a lot of confusion, and will allow us to find problems
> related to types -- like this one.

I have been sitting on a patch (joint effort by me and rtr@, mostly
rtr@, a couple years ago) to kill all the variadics in *_input and put
proto-specific types with no casts on them.  Haven't tried it in a
while but it worked at some point.  There was some objection on
tech-net at the time but I forget the details now.
From 7a95be340041328915c966bf2b5373af04e0d192 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
Date: Mon, 3 Sep 2018 15:21:27 +0000
Subject: [PATCH] WIP: domain-specific types for pr_input routines

---
 sys/kern/uipc_domain.c              |  31 +++++--
 sys/kern/uipc_mbuf.c                |   6 +-
 sys/kern/uipc_proto.c               |  10 +--
 sys/net/if.c                        |  10 ++-
 sys/net/link_proto.c                |   8 +-
 sys/net/rtsock.c                    |  37 ++++++--
 sys/netatalk/at.h                   |   2 +-
 sys/netatalk/at_proto.c             |   6 +-
 sys/netbt/bt_proto.c                |  12 +--
 sys/netcan/can_proto.c              |   8 +-
 sys/netinet/if_arp.c                |   7 +-
 sys/netinet/in_proto.c              | 164 ++++++++++++++++++++++++++----------
 sys/netinet/in_proto.h              |  10 ++-
 sys/netinet/ip_icmp.c               |   2 +-
 sys/netinet/ip_input.c              |  20 +++--
 sys/netinet/raw_ip.c                |   2 +-
 sys/netinet6/icmp6.c                |   2 +-
 sys/netinet6/in6_proto.c            | 160 +++++++++++++++++++++++++----------
 sys/netinet6/ip6_input.c            |  28 +++---
 sys/netinet6/ip6protosw.h           |  28 +-----
 sys/netipsec/ipsec_input.c          |  10 ++-
 sys/netipsec/keysock.c              |  10 +--
 sys/netmpls/mpls_proto.c            |  11 +--
 sys/rump/net/lib/libsockin/sockin.c |  16 ++--
 sys/sys/domain.h                    |   3 +-
 sys/sys/protosw.h                   |   2 -
 26 files changed, 396 insertions(+), 209 deletions(-)

diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c
index 7290ee55cfeb..9cd37f20ff99 100644
--- a/sys/kern/uipc_domain.c
+++ b/sys/kern/uipc_domain.c
@@ -139,6 +139,7 @@ void
 domain_attach(struct domain *dp)
 {
 	const struct protosw *pr;
+	size_t i;
 
 	STAILQ_INSERT_TAIL(&domains, dp, dom_link);
 	if (dp->dom_family < __arraycount(domain_array))
@@ -154,7 +155,8 @@ domain_attach(struct domain *dp)
 		MOWNER_ATTACH(&dp->dom_mowner);
 	}
 #endif
-	for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
+	for (i = 0; i < dp->dom_nprotosw; i++) {
+		pr = dp->dom_protosw[i];
 		if (pr->pr_init)
 			(*pr->pr_init)();
 	}
@@ -184,14 +186,17 @@ pffindtype(int family, int type)
 {
 	struct domain *dp;
 	const struct protosw *pr;
+	size_t i;
 
 	dp = pffinddomain(family);
 	if (dp == NULL)
 		return NULL;
 
-	for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
+	for (i = 0; i < dp->dom_nprotosw; i++) {
+		pr = dp->dom_protosw[i];
 		if (pr->pr_type && pr->pr_type == type)
 			return pr;
+	}
 
 	return NULL;
 }
@@ -202,6 +207,7 @@ pffindproto(int family, int protocol, int type)
 	struct domain *dp;
 	const struct protosw *pr;
 	const struct protosw *maybe = NULL;
+	size_t i;
 
 	if (family == 0)
 		return NULL;
@@ -210,7 +216,8 @@ pffindproto(int family, int protocol, int type)
 	if (dp == NULL)
 		return NULL;
 
-	for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
+	for (i = 0; i < dp->dom_nprotosw; i++) {
+		pr = dp->dom_protosw[i];
 		if ((pr->pr_protocol == protocol) && (pr->pr_type == type))
 			return pr;
 
@@ -690,9 +697,11 @@ pfctlinput(int cmd, const struct sockaddr *sa)
 {
 	struct domain *dp;
 	const struct protosw *pr;
+	size_t i;
 
 	DOMAIN_FOREACH(dp) {
-		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
+		for (i = 0; i < dp->dom_nprotosw; i++) {
+			pr = dp->dom_protosw[i];
 			if (pr->pr_ctlinput != NULL)
 				(*pr->pr_ctlinput)(cmd, sa, NULL);
 		}
@@ -704,6 +713,7 @@ pfctlinput2(int cmd, const struct sockaddr *sa, void *ctlparam)
 {
 	struct domain *dp;
 	const struct protosw *pr;
+	size_t i;
 
 	if (sa == NULL)
 		return;
@@ -717,7 +727,8 @@ pfctlinput2(int cmd, const struct sockaddr *sa, void *ctlparam)
 		if (dp->dom_family != sa->sa_family)
 			continue;
 
-		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
+		for (i = 0; i < dp->dom_nprotosw; i++) {
+			pr = dp->dom_protosw[i];
 			if (pr->pr_ctlinput != NULL)
 				(*pr->pr_ctlinput)(cmd, sa, ctlparam);
 		}
@@ -729,13 +740,16 @@ pfslowtimo(void *arg)
 {
 	struct domain *dp;
 	const struct protosw *pr;
+	size_t i;
 
 	pfslowtimo_now++;
 
 	DOMAIN_FOREACH(dp) {
-		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
+		for (i = 0; i < dp->dom_nprotosw; i++) {
+			pr = dp->dom_protosw[i];
 			if (pr->pr_slowtimo)
 				(*pr->pr_slowtimo)();
+		}
 	}
 	callout_schedule(&pfslowtimo_ch, hz / PR_SLOWHZ);
 }
@@ -745,13 +759,16 @@ pffasttimo(void *arg)
 {
 	struct domain *dp;
 	const struct protosw *pr;
+	size_t i;
 
 	pffasttimo_now++;
 
 	DOMAIN_FOREACH(dp) {
-		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
+		for (i = 0; i < dp->dom_nprotosw; i++) {
+			pr = dp->dom_protosw[i];
 			if (pr->pr_fasttimo)
 				(*pr->pr_fasttimo)();
+		}
 	}
 	callout_schedule(&pffasttimo_ch, hz / PR_FASTHZ);
 }
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index eecb313fed1f..c48096bc83c4 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -244,15 +244,17 @@ mb_drain(void *arg, int flags)
 	struct domain *dp;
 	const struct protosw *pr;
 	struct ifnet *ifp;
+	unsigned i;
 	int s;
 
 	KERNEL_LOCK(1, NULL);
 	s = splvm();
 	DOMAIN_FOREACH(dp) {
-		for (pr = dp->dom_protosw;
-		     pr < dp->dom_protoswNPROTOSW; pr++)
+		for (i = 0; i < dp->dom_nprotosw; i++) {
+			pr = dp->dom_protosw[i];
 			if (pr->pr_drain)
 				(*pr->pr_drain)();
+		}
 	}
 	/* XXX we cannot use psref in H/W interrupt */
 	if (!cpu_intr_p()) {
diff --git a/sys/kern/uipc_proto.c b/sys/kern/uipc_proto.c
index 52106c55db8b..4e2ceef7a562 100644
--- a/sys/kern/uipc_proto.c
+++ b/sys/kern/uipc_proto.c
@@ -51,22 +51,22 @@ __KERNEL_RCSID(0, "$NetBSD: uipc_proto.c,v 1.23 2014/05/18 14:46:15 rmind Exp $"
 
 DOMAIN_DEFINE(unixdomain);	/* forward define and add to link set */
 
-const struct protosw unixsw[] = {
-	{
+const struct protosw *unixsw[] = {
+	&(const struct protosw) {
 		.pr_type = SOCK_STREAM,
 		.pr_domain = &unixdomain,
 		.pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_RIGHTS|PR_LISTEN,
 		.pr_ctloutput = uipc_ctloutput,
 		.pr_usrreqs = &unp_usrreqs,
 	},
-	{
+	&(const struct protosw) {
 		.pr_type = SOCK_DGRAM,
 		.pr_domain = &unixdomain,
 		.pr_flags = PR_ATOMIC|PR_ADDR|PR_RIGHTS,
 		.pr_ctloutput = uipc_ctloutput,
 		.pr_usrreqs = &unp_usrreqs,
 	},
-	{
+	&(const struct protosw) {
 		.pr_type = SOCK_SEQPACKET,
 		.pr_domain = &unixdomain,
 		.pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_RIGHTS|PR_LISTEN|
@@ -83,5 +83,5 @@ struct domain unixdomain = {
 	.dom_externalize = unp_externalize,
 	.dom_dispose = unp_dispose,
 	.dom_protosw = unixsw,
-	.dom_protoswNPROTOSW = &unixsw[__arraycount(unixsw)],
+	.dom_nprotosw = __arraycount(unixsw),
 };
diff --git a/sys/net/if.c b/sys/net/if.c
index a584f6f17330..8e8aba87b8b9 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1304,7 +1304,8 @@ if_detach(struct ifnet *ifp)
 #endif
 	struct domain *dp;
 	const struct protosw *pr;
-	int s, i, family, purged;
+	size_t i;
+	int s, family, purged;
 	uint64_t xc;
 
 #ifdef IFAREF_DEBUG
@@ -1390,8 +1391,8 @@ again:
 		 * ifp->if_addrlist.
 		 */
 		purged = 0;
-		for (pr = dp->dom_protosw;
-		     pr < dp->dom_protoswNPROTOSW; pr++) {
+		for (i = 0; i < dp->dom_nprotosw; i++) {
+			pr = dp->dom_protosw[i];
 			so.so_proto = pr;
 			if (pr->pr_usrreqs) {
 				(void) (*pr->pr_usrreqs->pr_purgeif)(&so, ifp);
@@ -1447,7 +1448,8 @@ restart:
 		 * addresses.  (Protocols which might store ifnet
 		 * pointers are marked with PR_PURGEIF.)
 		 */
-		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
+		for (i = 0; i < dp->dom_nprotosw; i++) {
+			pr = dp->dom_protosw[i];
 			so.so_proto = pr;
 			if (pr->pr_usrreqs && pr->pr_flags & PR_PURGEIF)
 				(void)(*pr->pr_usrreqs->pr_purgeif)(&so, ifp);
diff --git a/sys/net/link_proto.c b/sys/net/link_proto.c
index 3fa520368634..93a6f19cd223 100644
--- a/sys/net/link_proto.c
+++ b/sys/net/link_proto.c
@@ -98,12 +98,12 @@ static const struct pr_usrreqs link_usrreqs = {
 	.pr_purgeif	= link_purgeif,
 };
 
-const struct protosw linksw[] = {
-	{	.pr_type = SOCK_DGRAM,
+const struct protosw *linksw[] = {
+	&(const struct protosw) {
+		.pr_type = SOCK_DGRAM,
 		.pr_domain = &linkdomain,
 		.pr_protocol = 0,	/* XXX */
 		.pr_flags = PR_ATOMIC|PR_ADDR|PR_PURGEIF,
-		.pr_input = NULL,
 		.pr_ctlinput = NULL,
 		.pr_ctloutput = NULL,
 		.pr_usrreqs = &link_usrreqs,
@@ -117,7 +117,7 @@ struct domain linkdomain = {
 	.dom_externalize = NULL,
 	.dom_dispose = NULL,
 	.dom_protosw = linksw,
-	.dom_protoswNPROTOSW = &linksw[__arraycount(linksw)],
+	.dom_nprotosw = __arraycount(linksw),
 	.dom_sockaddr_cmp = sockaddr_dl_cmp
 };
 
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index 497f01a570cf..2ca73b47761d 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -159,6 +159,16 @@ struct route_info COMPATNAME(route_info) = {
 	.ri_maxqlen = IFQ_MAXLEN,
 };
 
+struct routeprotosw {
+	struct protosw	routepr_protosw;
+#ifdef notyet
+	void		(*routepr_input)(struct mbuf *,
+			    struct sockaddr *, struct sockaddr *);
+#else
+	void		(*routepr_input)(struct mbuf *, ...);
+#endif
+};
+
 static void COMPATNAME(route_init)(void);
 static int COMPATNAME(route_output)(struct mbuf *, struct socket *);
 
@@ -174,7 +184,8 @@ static int sysctl_iflist(int, struct rt_walkarg *, int);
 static int sysctl_rtable(SYSCTLFN_PROTO);
 static void rt_adjustcount(int, int);
 
-static const struct protosw COMPATNAME(route_protosw)[];
+static const struct routeprotosw COMPATNAME(routesw)[];
+static const struct protosw *COMPATNAME(routeprotosw)[];
 
 struct routecb {
 	struct rawcb	rocb_rcb;
@@ -467,7 +478,7 @@ COMPATNAME(route_send)(struct socket *so, struct mbuf *m,
 	int s;
 
 	KASSERT(solocked(so));
-	KASSERT(so->so_proto == &COMPATNAME(route_protosw)[0]);
+	KASSERT(so->so_proto == &COMPATNAME(routesw)[0].routepr_protosw);
 
 	s = splsoftnet();
 	error = raw_send(so, m, nam, control, l, &COMPATNAME(route_output));
@@ -2009,8 +2020,14 @@ COMPATNAME(route_enqueue)(struct mbuf *m, int family)
 static void
 COMPATNAME(route_init)(void)
 {
+	size_t i;
 	struct route_info * const ri = &COMPATNAME(route_info);
 
+	for (i = 0; i < COMPATNAME(routedomain).dom_nprotosw; i++) {
+		COMPATNAME(routedomain).dom_protosw[i] =
+		    &COMPATNAME(routesw)[i].routepr_protosw;
+	}
+
 #ifndef COMPAT_RTSOCK
 	rt_init();
 #endif
@@ -2058,26 +2075,30 @@ static const struct pr_usrreqs route_usrreqs = {
 	.pr_purgeif	= COMPATNAME(route_purgeif_wrapper),
 };
 
-static const struct protosw COMPATNAME(route_protosw)[] = {
-	{
+static const struct routeprotosw COMPATNAME(routesw)[] = {
+{
+	.routepr_protosw = {
 		.pr_type = SOCK_RAW,
 		.pr_domain = &COMPATNAME(routedomain),
 		.pr_flags = PR_ATOMIC|PR_ADDR,
-		.pr_input = raw_input,
 		.pr_ctlinput = raw_ctlinput,
 		.pr_ctloutput = route_ctloutput,
 		.pr_usrreqs = &route_usrreqs,
 		.pr_init = rt_pr_init,
 	},
+	.routepr_input = raw_input,
+},
 };
 
+static const struct protosw
+    *COMPATNAME(routeprotosw)[__arraycount(COMPATNAME(routesw))];
+
 struct domain COMPATNAME(routedomain) = {
 	.dom_family = PF_XROUTE,
 	.dom_name = DOMAINNAME,
 	.dom_init = COMPATNAME(route_init),
-	.dom_protosw = COMPATNAME(route_protosw),
-	.dom_protoswNPROTOSW =
-	    &COMPATNAME(route_protosw)[__arraycount(COMPATNAME(route_protosw))],
+	.dom_protosw = COMPATNAME(routeprotosw),
+	.dom_nprotosw = __arraycount(COMPATNAME(routeprotosw)),
 };
 
 static void
diff --git a/sys/netatalk/at.h b/sys/netatalk/at.h
index e369937d4ab1..c1c74cbba71a 100644
--- a/sys/netatalk/at.h
+++ b/sys/netatalk/at.h
@@ -99,7 +99,7 @@ struct sockaddr_at {
 #include <sys/protosw.h>
 
 extern struct domain atalkdomain;
-extern const struct protosw atalksw[];
+extern const struct protosw *atalksw[];
 #endif
 
 #if defined(_KERNEL) || defined(_TEST)
diff --git a/sys/netatalk/at_proto.c b/sys/netatalk/at_proto.c
index af22417cdb5c..ad9adf1f5ba9 100644
--- a/sys/netatalk/at_proto.c
+++ b/sys/netatalk/at_proto.c
@@ -49,8 +49,8 @@ __KERNEL_RCSID(0, "$NetBSD: at_proto.c,v 1.22 2017/09/21 07:15:34 ozaki-r Exp $"
 
 DOMAIN_DEFINE(atalkdomain);	/* forward declare and add to link set */
 
-const struct protosw atalksw[] = {
-    {
+const struct protosw *atalksw[] = {
+    &(const struct protosw) {
 	.pr_type = SOCK_DGRAM,
 	.pr_domain = &atalkdomain,
 	.pr_protocol = ATPROTO_DDP,
@@ -67,7 +67,7 @@ struct domain atalkdomain = {
 	.dom_externalize = NULL,
 	.dom_dispose = NULL,
 	.dom_protosw = atalksw,
-	.dom_protoswNPROTOSW = &atalksw[__arraycount(atalksw)],
+	.dom_nprotosw = __arraycount(atalksw),
 	.dom_rtattach = rt_inithead,
 	.dom_rtoffset = 32,
 	.dom_maxrtkey = sizeof(struct sockaddr_at),
diff --git a/sys/netbt/bt_proto.c b/sys/netbt/bt_proto.c
index 15e2c99d7411..5f27d783170b 100644
--- a/sys/netbt/bt_proto.c
+++ b/sys/netbt/bt_proto.c
@@ -62,8 +62,8 @@ PR_WRAP_CTLOUTPUT(rfcomm_ctloutput)
 #define	l2cap_ctloutput		l2cap_ctloutput_wrapper
 #define	rfcomm_ctloutput	rfcomm_ctloutput_wrapper
 
-static const struct protosw btsw[] = {
-	{ /* raw HCI commands */
+static const struct protosw *btsw[] = {
+	&(const struct protosw) { /* raw HCI commands */
 		.pr_type = SOCK_RAW,
 		.pr_domain = &btdomain,
 		.pr_protocol = BTPROTO_HCI,
@@ -72,7 +72,7 @@ static const struct protosw btsw[] = {
 		.pr_ctloutput = hci_ctloutput,
 		.pr_usrreqs = &hci_usrreqs,
 	},
-	{ /* HCI SCO data (audio) */
+	&(const struct protosw) { /* HCI SCO data (audio) */
 		.pr_type = SOCK_SEQPACKET,
 		.pr_domain = &btdomain,
 		.pr_protocol = BTPROTO_SCO,
@@ -80,7 +80,7 @@ static const struct protosw btsw[] = {
 		.pr_ctloutput = sco_ctloutput,
 		.pr_usrreqs = &sco_usrreqs,
 	},
-	{ /* L2CAP Connection Oriented */
+	&(const struct protosw) { /* L2CAP Connection Oriented */
 		.pr_type = SOCK_SEQPACKET,
 		.pr_domain = &btdomain,
 		.pr_protocol = BTPROTO_L2CAP,
@@ -89,7 +89,7 @@ static const struct protosw btsw[] = {
 		.pr_usrreqs = &l2cap_usrreqs,
 		.pr_init = l2cap_init,
 	},
-	{ /* RFCOMM */
+	&(const struct protosw) { /* RFCOMM */
 		.pr_type = SOCK_STREAM,
 		.pr_domain = &btdomain,
 		.pr_protocol = BTPROTO_RFCOMM,
@@ -105,7 +105,7 @@ struct domain btdomain = {
 	.dom_name = "bluetooth",
 	.dom_init = bt_init,
 	.dom_protosw = btsw,
-	.dom_protoswNPROTOSW = &btsw[__arraycount(btsw)],
+	.dom_nprotosw = __arraycount(btsw),
 };
 
 kmutex_t *bt_lock;
diff --git a/sys/netcan/can_proto.c b/sys/netcan/can_proto.c
index 1d5c2cc53489..0437811deaa5 100644
--- a/sys/netcan/can_proto.c
+++ b/sys/netcan/can_proto.c
@@ -50,15 +50,15 @@ __KERNEL_RCSID(0, "$NetBSD: can_proto.c,v 1.2 2017/05/27 21:02:56 bouyer Exp $")
 
 DOMAIN_DEFINE(candomain);	/* forward declare and add to link set */
 
-const struct protosw cansw[] = {
-{
+const struct protosw *cansw[] = {
+    &(const struct protosw) {
 	.pr_type = SOCK_RAW,
 	.pr_domain = &candomain,
 	.pr_init = can_init,
 	.pr_flags = PR_ATOMIC|PR_ADDR,
 	.pr_usrreqs = &can_usrreqs,
 	.pr_ctloutput = &can_ctloutput,
-}
+    },
 };
 
 struct domain candomain = {
@@ -67,7 +67,7 @@ struct domain candomain = {
 	.dom_init = can_init,
 	.dom_externalize = NULL, .dom_dispose = NULL,
 	.dom_protosw = cansw,
-	.dom_protoswNPROTOSW = &cansw[__arraycount(cansw)],
+	.dom_nprotosw = __arraycount(cansw),
 	.dom_ifqueues = { &canintrq, NULL },
 	.dom_link = { NULL },
 	.dom_mowner = MOWNER_INIT("",""),
diff --git a/sys/netinet/if_arp.c b/sys/netinet/if_arp.c
index c6b71ce23a8e..3a75f0b511b9 100644
--- a/sys/netinet/if_arp.c
+++ b/sys/netinet/if_arp.c
@@ -255,13 +255,12 @@ arp_fasttimo(void)
 	}
 }
 
-static const struct protosw arpsw[] = {
-	{
+static const struct protosw *arpsw[] = {
+	&(const struct protosw) {
 		.pr_type = 0,
 		.pr_domain = &arpdomain,
 		.pr_protocol = 0,
 		.pr_flags = 0,
-		.pr_input = 0,
 		.pr_ctlinput = 0,
 		.pr_ctloutput = 0,
 		.pr_usrreqs = 0,
@@ -276,7 +275,7 @@ struct domain arpdomain = {
 	.dom_family = PF_ARP,
 	.dom_name = "arp",
 	.dom_protosw = arpsw,
-	.dom_protoswNPROTOSW = &arpsw[__arraycount(arpsw)],
+	.dom_nprotosw = __arraycount(arpsw),
 };
 
 static void sysctl_net_inet_arp_setup(struct sysctllog **);
diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c
index 4555ed40d434..db8b7510062c 100644
--- a/sys/netinet/in_proto.c
+++ b/sys/netinet/in_proto.c
@@ -263,213 +263,276 @@ PR_WRAP_CTLINPUT(esp4_ctlinput)
 
 #endif /* IPSEC */
 
-const struct protosw inetsw[] = {
-{	.pr_domain = &inetdomain,
+const struct ipprotosw inetsw[] = {
+{
+    .ippr_protosw = {
+	.pr_domain = &inetdomain,
 	.pr_init = ip_init,
 	.pr_fasttimo = ip_fasttimo,
 	.pr_slowtimo = ip_slowtimo,
 	.pr_drain = ip_drainstub,
+    },
 },
-{	.pr_type = SOCK_RAW,
+{
+    .ippr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inetdomain,
 	.pr_protocol = IPPROTO_ICMP,
 	.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
-	.pr_input = icmp_input,
 	.pr_ctlinput = rip_ctlinput,
 	.pr_ctloutput = rip_ctloutput,
 	.pr_usrreqs = &rip_usrreqs,
 	.pr_init = icmp_init,
+    },
+    .ippr_input = icmp_input,
 },
-{	.pr_type = SOCK_DGRAM,
+{
+    .ippr_protosw = {
+	.pr_type = SOCK_DGRAM,
 	.pr_domain = &inetdomain,
 	.pr_protocol = IPPROTO_UDP,
 	.pr_flags = PR_ATOMIC|PR_ADDR|PR_PURGEIF,
-	.pr_input = udp_input,
 	.pr_ctlinput = udp_ctlinput,
 	.pr_ctloutput = udp_ctloutput,
 	.pr_usrreqs = &udp_usrreqs,
 	.pr_init = udp_init,
+    },
+    .ippr_input = udp_input,
 },
-{	.pr_type = SOCK_STREAM,
+{
+    .ippr_protosw = {
+	.pr_type = SOCK_STREAM,
 	.pr_domain = &inetdomain,
 	.pr_protocol = IPPROTO_TCP,
 	.pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_LISTEN|PR_ABRTACPTDIS|PR_PURGEIF,
-	.pr_input = tcp_input,
 	.pr_ctlinput = tcp_ctlinput,
 	.pr_ctloutput = tcp_ctloutput,
 	.pr_usrreqs = &tcp_usrreqs,
 	.pr_init = tcp_init,
 	.pr_fasttimo = tcp_fasttimo,
 	.pr_drain = tcp_drainstub,
+    },
+    .ippr_input = tcp_input,
 },
 #ifdef DCCP
-{	.pr_type = SOCK_CONN_DGRAM,
+{
+    .ippr_protosw = {
+	.pr_type = SOCK_CONN_DGRAM,
 	.pr_domain = &inetdomain,
 	.pr_protocol = IPPROTO_DCCP,
 	.pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_ATOMIC|PR_LISTEN|PR_ABRTACPTDIS,
-	.pr_input = dccp_input,
 	.pr_ctlinput = dccp_ctlinput,
 	.pr_ctloutput = dccp_ctloutput,
 	.pr_usrreqs = &dccp_usrreqs,
 	.pr_init = dccp_init,
+    },
+    .ippr_input = dccp_input,
 },
 #endif
 #ifdef SCTP
-{	.pr_type = SOCK_DGRAM,
+{
+    .ippr_protosw = {
+	.pr_type = SOCK_DGRAM,
 	.pr_domain = &inetdomain,
 	.pr_protocol = IPPROTO_SCTP,
 	.pr_flags = PR_ADDR_OPT|PR_WANTRCVD,
-	.pr_input = sctp_input,
 	.pr_ctlinput = sctp_ctlinput,
 	.pr_ctloutput = sctp_ctloutput,
 	.pr_usrreqs = &sctp_usrreqs,
 	.pr_init = sctp_init,
 	.pr_drain = sctp_drain
+    },
+    .ippr_input = sctp_input,
 },
-{	.pr_type = SOCK_SEQPACKET,
+{
+    .ippr_protosw = {
+	.pr_type = SOCK_SEQPACKET,
 	.pr_domain = &inetdomain,
 	.pr_protocol = IPPROTO_SCTP,
 	.pr_flags = PR_ADDR_OPT|PR_WANTRCVD,
-	.pr_input = sctp_input,
 	.pr_ctlinput = sctp_ctlinput,
 	.pr_ctloutput = sctp_ctloutput,
 	.pr_usrreqs = &sctp_usrreqs,
 	.pr_drain = sctp_drain
+    },
+    .ippr_input = sctp_input,
 },
-{	.pr_type = SOCK_STREAM,
+{
+    .ippr_protosw = {
+	.pr_type = SOCK_STREAM,
 	.pr_domain = &inetdomain,
 	.pr_protocol = IPPROTO_SCTP,
 	.pr_flags = PR_CONNREQUIRED|PR_ADDR_OPT|PR_WANTRCVD|PR_LISTEN,
-	.pr_input = sctp_input,
 	.pr_ctlinput = sctp_ctlinput,
 	.pr_ctloutput = sctp_ctloutput,
 	.pr_usrreqs = &sctp_usrreqs,
 	.pr_drain = sctp_drain
+    },
+    .ippr_input = sctp_input,
 },
 #endif /* SCTP */
-{	.pr_type = SOCK_RAW,
+{
+    .ippr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inetdomain,
 	.pr_protocol = IPPROTO_RAW,
 	.pr_flags = PR_ATOMIC|PR_ADDR|PR_PURGEIF,
-	.pr_input = rip_input,
 	.pr_ctlinput = rip_ctlinput,
 	.pr_ctloutput = rip_ctloutput,
 	.pr_usrreqs = &rip_usrreqs,
+    },
+    .ippr_input = rip_input,
 },
 #ifdef GATEWAY
-{	.pr_domain = &inetdomain,
+{
+    .ippr_protosw = {
+	.pr_domain = &inetdomain,
 	.pr_protocol = IPPROTO_IP,
 	.pr_slowtimo = ipflow_slowtimo,
 	.pr_init = ipflow_poolinit,
+    },
 },
 #endif /* GATEWAY */
 #ifdef IPSEC
-{	.pr_type = SOCK_RAW,
+{
+    .ippr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inetdomain,
 	.pr_protocol = IPPROTO_AH,
 	.pr_flags = PR_ATOMIC|PR_ADDR,
-	.pr_input = ipsec4_common_input,
 	.pr_ctlinput = ah4_ctlinput,
+    },
+    .ippr_input = ipsec4_common_input,
 },
-{	.pr_type = SOCK_RAW,
+{
+    .ippr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inetdomain,
 	.pr_protocol = IPPROTO_ESP,
 	.pr_flags = PR_ATOMIC|PR_ADDR,
-	.pr_input = ipsec4_common_input,
 	.pr_ctlinput = esp4_ctlinput,
+    },
+    .ippr_input = ipsec4_common_input,
 },
-{	.pr_type = SOCK_RAW,
+{
+    .ippr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inetdomain,
 	.pr_protocol = IPPROTO_IPCOMP,
 	.pr_flags = PR_ATOMIC|PR_ADDR,
-	.pr_input = ipsec4_common_input,
+    },
+    .ippr_input = ipsec4_common_input,
 },
 #endif /* IPSEC */
-{	.pr_type = SOCK_RAW,
+{
+    .ippr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inetdomain,
 	.pr_protocol = IPPROTO_IPV4,
 	.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
-	.pr_input = encap4_input,
 	.pr_ctlinput = rip_ctlinput,
 	.pr_ctloutput = rip_ctloutput,
 	.pr_usrreqs = &rip_usrreqs,
 	.pr_init = encap_init,
+    },
+    .ippr_input = encap4_input,
 },
 #ifdef INET6
-{	.pr_type = SOCK_RAW,
+{
+    .ippr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inetdomain,
 	.pr_protocol = IPPROTO_IPV6,
 	.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
-	.pr_input = encap4_input,
 	.pr_ctlinput = rip_ctlinput,
 	.pr_ctloutput = rip_ctloutput,
 	.pr_usrreqs = &rip_usrreqs,
 	.pr_init = encap_init,
+    },
+    .ippr_input = encap4_input,
 },
 #endif /* INET6 */
 #if NCARP > 0
-{	.pr_type = SOCK_RAW,
+{
+    .ippr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inetdomain,
 	.pr_protocol = IPPROTO_CARP,
 	.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
-	.pr_input = carp_proto_input,
 	.pr_ctloutput = rip_ctloutput,
 	.pr_usrreqs = &rip_usrreqs,
 	.pr_init = carp_init,
+    },
+    .ippr_input = carp_proto_input,
 },
 #endif /* NCARP > 0 */
-{	.pr_type = SOCK_RAW,
+{
+    .ippr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inetdomain,
 	.pr_protocol = IPPROTO_L2TP,
 	.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
-	.pr_input = encap4_input,
 	.pr_ctlinput = rip_ctlinput,
 	.pr_ctloutput = rip_ctloutput,
 	.pr_usrreqs = &rip_usrreqs,	/*XXX*/
 	.pr_init = encap_init,
+    },
+    .ippr_input = encap4_input,
 },
 #if NPFSYNC > 0
-{	.pr_type = SOCK_RAW,
+{
+    .ippr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inetdomain,
 	.pr_protocol = IPPROTO_PFSYNC,
 	.pr_flags	 = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
-	.pr_input	 = pfsync_input,
 	.pr_ctloutput = rip_ctloutput,
 	.pr_usrreqs	 = &rip_usrreqs,
+    },
+    .ippr_input	 = pfsync_input,
 },
 #endif /* NPFSYNC > 0 */
-{	.pr_type = SOCK_RAW,
+{
+    .ippr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inetdomain,
 	.pr_protocol = IPPROTO_IGMP,
 	.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
-	.pr_input = igmp_input, 
 	.pr_ctloutput = rip_ctloutput,
 	.pr_ctlinput = rip_ctlinput,
 	.pr_usrreqs = &rip_usrreqs,
 	.pr_fasttimo = igmp_fasttimo,
 	.pr_slowtimo = igmp_slowtimo,
 	.pr_init = igmp_init,
+    },
+    .ippr_input = igmp_input,
 },
 #ifdef PIM
-{	.pr_type = SOCK_RAW,
+{
+    .ippr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inetdomain,
 	.pr_protocol = IPPROTO_PIM,
 	.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
-	.pr_input = pim_input, 
 	.pr_ctloutput = rip_ctloutput,
 	.pr_ctlinput = rip_ctlinput,
 	.pr_usrreqs = &rip_usrreqs,
+    },
+    .ippr_input = pim_input,
 },
 #endif /* PIM */
 /* raw wildcard */
-{	.pr_type = SOCK_RAW,
+{
+    .ippr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inetdomain,
 	.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
-	.pr_input = rip_input, 
 	.pr_ctloutput = rip_ctloutput,
 	.pr_ctlinput = rip_ctlinput,
 	.pr_usrreqs = &rip_usrreqs,
 	.pr_init = rip_init,
+    },
+    .ippr_input = rip_input,
 },
 };
 
@@ -480,11 +543,24 @@ const struct sockaddr_in in_any = {
 	, .sin_addr = {.s_addr = 0 /* INADDR_ANY */}
 };
 
+static const struct protosw *inetprotosw[__arraycount(inetsw)];
+
+static void
+in_dom_init(void)
+{
+	size_t i;
+
+	for (i = 0; i < inetdomain.dom_nprotosw; i++) {
+		inetdomain.dom_protosw[i] = &inetsw[i].ippr_protosw;
+	}
+}
+
 struct domain inetdomain = {
-	.dom_family = PF_INET, .dom_name = "internet", .dom_init = NULL,
+	.dom_family = PF_INET, .dom_name = "internet",
+	.dom_init = in_dom_init,
 	.dom_externalize = NULL, .dom_dispose = NULL,
-	.dom_protosw = inetsw,
-	.dom_protoswNPROTOSW = &inetsw[__arraycount(inetsw)],
+	.dom_protosw = inetprotosw,
+	.dom_nprotosw = __arraycount(inetprotosw),
 	.dom_rtattach = rt_inithead,
 	.dom_rtoffset = 32,
 	.dom_maxrtkey = sizeof(struct ip_pack4),
diff --git a/sys/netinet/in_proto.h b/sys/netinet/in_proto.h
index 747e30a6c249..c342aabc4364 100644
--- a/sys/netinet/in_proto.h
+++ b/sys/netinet/in_proto.h
@@ -34,6 +34,14 @@
 #ifndef _NETINET_IN_PROTO_H_
 #define _NETINET_IN_PROTO_H_
 
-extern const struct protosw inetsw[];
+struct ipprotosw {
+	struct protosw	ippr_protosw;
+#ifdef notyet
+	void		(*ippr_input)(struct mbuf *, int, int);
+#endif
+	void		(*ippr_input)(struct mbuf *, ...);
+};
+
+extern const struct ipprotosw inetsw[];
 
 #endif /* !_NETINET_IN_PROTO_H_ */
diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c
index c49cbe39ae6b..c376c8ad6f7d 100644
--- a/sys/netinet/ip_icmp.c
+++ b/sys/netinet/ip_icmp.c
@@ -534,7 +534,7 @@ _icmp_input(struct mbuf *m, int hlen, int proto)
 			goto badcode;
 
 		icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
-		ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput;
+		ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].ippr_protosw.pr_ctlinput;
 		if (ctlfunc)
 			(void) (*ctlfunc)(code, sintosa(&icmpsrc),
 			    &icp->icmp_ip);
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 51340b81816c..279bb4d24aeb 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -270,24 +270,29 @@ void
 ip_init(void)
 {
 	const struct protosw *pr;
+	const struct ipprotosw *ippr;
+	size_t i;
 
 	in_init();
 	sysctl_net_inet_ip_setup(NULL);
 
 	pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW);
 	KASSERT(pr != NULL);
+	ippr = const_container_of(pr, struct ipprotosw, ippr_protosw);
 
 	ip_pktq = pktq_create(IFQ_MAXLEN, ipintr, NULL);
 	KASSERT(ip_pktq != NULL);
 
-	for (u_int i = 0; i < IPPROTO_MAX; i++) {
-		ip_protox[i] = pr - inetsw;
+	for (i = 0; i < IPPROTO_MAX; i++) {
+		ip_protox[i] = ippr - inetsw;
 	}
-	for (pr = inetdomain.dom_protosw;
-	    pr < inetdomain.dom_protoswNPROTOSW; pr++)
+	for (i = 0; i < inetdomain.dom_nprotosw; i++) {
+		pr = inetdomain.dom_protosw[i];
+		ippr = const_container_of(pr, struct ipprotosw, ippr_protosw);
 		if (pr->pr_domain->dom_family == PF_INET &&
 		    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
-			ip_protox[pr->pr_protocol] = pr - inetsw;
+			ip_protox[pr->pr_protocol] = ippr - inetsw;
+	}
 
 	ip_reass_init();
 
@@ -777,7 +782,8 @@ ours:
 	 * code - like UDP/TCP/raw IP.
 	 */
 	if (ipsec_used &&
-	    (inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) != 0) {
+	    (inetsw[ip_protox[ip->ip_p]].ippr_protosw.pr_flags & PR_LASTHDR)
+		!= 0) {
 		if (ipsec_ip_input(m, false) != 0) {
 			goto out;
 		}
@@ -804,7 +810,7 @@ ours:
 
 	const int off = hlen, nh = ip->ip_p;
 
-	(*inetsw[ip_protox[nh]].pr_input)(m, off, nh);
+	(*inetsw[ip_protox[nh]].ippr_input)(m, off, nh);
 	return;
 
 out:
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index 212803a8d3dc..3d027d7fcd30 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -226,7 +226,7 @@ rip_input(struct mbuf *m, ...)
 #endif
 	if (last != NULL) {
 		rip_sbappendaddr(last, ip, sintosa(&ripsrc), hlen, m);
-	} else if (inetsw[ip_protox[ip->ip_p]].pr_input == rip_input) {
+	} else if (inetsw[ip_protox[ip->ip_p]].ippr_input == rip_input) {
 		uint64_t *ips;
 
 		icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL,
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
index bf98e5dc3e04..ae027555ec90 100644
--- a/sys/netinet6/icmp6.c
+++ b/sys/netinet6/icmp6.c
@@ -1078,7 +1078,7 @@ icmp6_notify_error(struct mbuf *m, int off, int icmp6len, int code)
 		}
 
 		ctlfunc = (void (*)(int, struct sockaddr *, void *))
-		    (inet6sw[ip6_protox[nxt]].pr_ctlinput);
+		    (inet6sw[ip6_protox[nxt]].ip6pr_protosw.pr_ctlinput);
 		if (ctlfunc) {
 			(void)(*ctlfunc)(code, sin6tosa(&icmp6dst), &ip6cp);
 		}
diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c
index 3c75b99d0be6..b6e1cc79c2b6 100644
--- a/sys/netinet6/in6_proto.c
+++ b/sys/netinet6/in6_proto.c
@@ -264,204 +264,270 @@ tcp6_init(void)
 }
 
 const struct ip6protosw inet6sw[] = {
-{	.pr_domain = &inet6domain,
+{
+    .ip6pr_protosw = {
+	.pr_domain = &inet6domain,
 	.pr_protocol = IPPROTO_IPV6,
 	.pr_init = ip6_init,
 	.pr_fasttimo = frag6_fasttimo,
 	.pr_slowtimo = frag6_slowtimo,
 	.pr_drain = frag6_drainstub,
+	},
 },
-{	.pr_type = SOCK_RAW,
+{
+    .ip6pr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inet6domain,
 	.pr_protocol = IPPROTO_ICMPV6,
 	.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
-	.pr_input = icmp6_input,
 	.pr_ctlinput = rip6_ctlinput,
 	.pr_ctloutput = icmp6_ctloutput,
 	.pr_usrreqs = &rip6_usrreqs,
 	.pr_init = icmp6_init,
+    },
+    .ip6pr_input = icmp6_input,
 },
-{	.pr_type = SOCK_DGRAM,
+{
+    .ip6pr_protosw = {
+	.pr_type = SOCK_DGRAM,
 	.pr_domain = &inet6domain,
 	.pr_protocol = IPPROTO_UDP,
 	.pr_flags = PR_ATOMIC|PR_ADDR|PR_PURGEIF,
-	.pr_input = udp6_input,
 	.pr_ctlinput = udp6_ctlinput,
 	.pr_ctloutput = udp6_ctloutput,
 	.pr_usrreqs = &udp6_usrreqs,
 	.pr_init = udp6_init,
+    },
+    .ip6pr_input = udp6_input,
 },
-{	.pr_type = SOCK_STREAM,
+{
+    .ip6pr_protosw = {
+	.pr_type = SOCK_STREAM,
 	.pr_domain = &inet6domain,
 	.pr_protocol = IPPROTO_TCP,
 	.pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_LISTEN|PR_ABRTACPTDIS|PR_PURGEIF,
-	.pr_input = tcp6_input,
 	.pr_ctlinput = tcp6_ctlinput,
 	.pr_ctloutput = tcp_ctloutput,
 	.pr_usrreqs = &tcp_usrreqs,
 	.pr_init = tcp6_init,
 	.pr_fasttimo = tcp_fasttimo,
 	.pr_drain = tcp_drainstub,
+    },
+    .ip6pr_input = tcp6_input,
 },
 #ifdef DCCP
-{	.pr_type = SOCK_CONN_DGRAM,
+{
+    .ip6pr_protosw = {
+	.pr_type = SOCK_CONN_DGRAM,
 	.pr_domain = &inet6domain,
 	.pr_protocol = IPPROTO_DCCP,
 	.pr_flags = PR_CONNREQUIRED|PR_ATOMIC|PR_LISTEN,
-	.pr_input = dccp6_input,
 	.pr_ctlinput = dccp6_ctlinput,
 	.pr_ctloutput = dccp_ctloutput,
 	.pr_usrreqs = &dccp6_usrreqs,
 #ifndef INET
 	.pr_init = dccp_init,
 #endif
+    },
+    .ip6pr_input = dccp6_input,
 },
 #endif /* DCCP */
 #ifdef SCTP
-{	.pr_type = SOCK_DGRAM,
+{
+    .ip6pr_protosw = {
+	.pr_type = SOCK_DGRAM,
 	.pr_domain = &inet6domain,
 	.pr_protocol = IPPROTO_SCTP,
 	.pr_flags = PR_ADDR_OPT|PR_WANTRCVD,
-	.pr_input = sctp6_input,
 	.pr_ctlinput = sctp6_ctlinput,
 	.pr_ctloutput = sctp_ctloutput,
 	.pr_usrreqs = &sctp6_usrreqs,
 	.pr_drain = sctp_drain,
+    },
+    .ip6pr_input = sctp6_input,
 },
-{	.pr_type = SOCK_SEQPACKET,
+{
+    .ip6pr_protosw = {
+	.pr_type = SOCK_SEQPACKET,
 	.pr_domain = &inet6domain,
 	.pr_protocol = IPPROTO_SCTP,
 	.pr_flags = PR_ADDR_OPT|PR_WANTRCVD,
-	.pr_input = sctp6_input,
 	.pr_ctlinput = sctp6_ctlinput,
 	.pr_ctloutput = sctp_ctloutput,
 	.pr_drain = sctp_drain,
+    },
+    .ip6pr_input = sctp6_input,
 },
-{	.pr_type = SOCK_STREAM,
+{
+    .ip6pr_protosw = {
+	.pr_type = SOCK_STREAM,
 	.pr_domain = &inet6domain,
 	.pr_protocol = IPPROTO_SCTP,
 	.pr_flags = PR_CONNREQUIRED|PR_ADDR_OPT|PR_WANTRCVD|PR_LISTEN,
-	.pr_input = sctp6_input,
 	.pr_ctlinput = sctp6_ctlinput,
 	.pr_ctloutput = sctp_ctloutput,
 	.pr_drain = sctp_drain,
+    },
+    .ip6pr_input = sctp6_input,
 },
 #endif /* SCTP */
-{	.pr_type = SOCK_RAW,
+{
+    .ip6pr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inet6domain,
 	.pr_protocol = IPPROTO_RAW,
 	.pr_flags = PR_ATOMIC|PR_ADDR|PR_PURGEIF,
-	.pr_input = rip6_input,
 	.pr_ctlinput = rip6_ctlinput,
 	.pr_ctloutput = rip6_ctloutput,
 	.pr_usrreqs = &rip6_usrreqs,
+    },
+    .ip6pr_input = rip6_input,
 },
 #ifdef GATEWAY
-{	.pr_domain = &inet6domain,
+{
+    .ip6pr_protosw = {
+	.pr_domain = &inet6domain,
 	.pr_protocol = IPPROTO_IPV6,
 	.pr_slowtimo = ip6flow_slowtimo,
 	.pr_init = ip6flow_poolinit,
+    }
 },
 #endif /* GATEWAY */
-{	.pr_type = SOCK_RAW,
+{
+    .ip6pr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inet6domain,
 	.pr_protocol = IPPROTO_DSTOPTS,
 	.pr_flags = PR_ATOMIC|PR_ADDR,
-	.pr_input = dest6_input,
+    },
+    .ip6pr_input = dest6_input,
 },
-{	.pr_type = SOCK_RAW,
+{
+    .ip6pr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inet6domain,
 	.pr_protocol = IPPROTO_ROUTING,
 	.pr_flags = PR_ATOMIC|PR_ADDR,
-	.pr_input = route6_input,
+    },
+    .ip6pr_input = route6_input,
 },
-{	.pr_type = SOCK_RAW,
+{
+    .ip6pr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inet6domain,
 	.pr_protocol = IPPROTO_FRAGMENT,
 	.pr_flags = PR_ATOMIC|PR_ADDR,
-	.pr_input = frag6_input,
+    },
+    .ip6pr_input = frag6_input,
 },
 #ifdef IPSEC
-{	.pr_type = SOCK_RAW,
+{
+    .ip6pr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inet6domain,
 	.pr_protocol = IPPROTO_AH,
 	.pr_flags = PR_ATOMIC|PR_ADDR,
-	.pr_input = ipsec6_common_input,
 	.pr_ctlinput = ah6_ctlinput,
+    },
+    .ip6pr_input = ipsec6_common_input,
 },
-{	.pr_type = SOCK_RAW,
+{
+    .ip6pr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inet6domain,
 	.pr_protocol = IPPROTO_ESP,
 	.pr_flags = PR_ATOMIC|PR_ADDR,
-	.pr_input = ipsec6_common_input,
 	.pr_ctlinput = esp6_ctlinput,
+    },
+    .ip6pr_input = ipsec6_common_input,
 },
-{	.pr_type = SOCK_RAW,
+{
+    .ip6pr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inet6domain,
 	.pr_protocol = IPPROTO_IPCOMP,
 	.pr_flags = PR_ATOMIC|PR_ADDR,
-	.pr_input = ipsec6_common_input,
+    },
+    .ip6pr_input = ipsec6_common_input,
 },
 #endif /* IPSEC */
 #ifdef INET
-{	.pr_type = SOCK_RAW,
+{
+    .ip6pr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inet6domain,
 	.pr_protocol = IPPROTO_IPV4,
 	.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
-	.pr_input = encap6_input,
 	.pr_ctlinput = encap6_ctlinput,
 	.pr_ctloutput = rip6_ctloutput,
 	.pr_usrreqs = &rip6_usrreqs,
 	.pr_init = encap_init,
+    },
+    .ip6pr_input = encap6_input,
 },
 #endif
-{	.pr_type = SOCK_RAW,
+{
+    .ip6pr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inet6domain,
 	.pr_protocol = IPPROTO_IPV6,
 	.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
-	.pr_input = encap6_input,
 	.pr_ctlinput = encap6_ctlinput,
 	.pr_ctloutput = rip6_ctloutput,
 	.pr_usrreqs = &rip6_usrreqs,
 	.pr_init = encap_init,
+    },
+    .ip6pr_input = encap6_input,
 },
 #if NCARP > 0
-{	.pr_type = SOCK_RAW,
+{
+    .ip6pr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inet6domain,
 	.pr_protocol = IPPROTO_CARP,
 	.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
-	.pr_input = carp6_proto_input,
 	.pr_ctloutput = rip6_ctloutput,
 	.pr_usrreqs = &rip6_usrreqs,
+    },
+    .ip6pr_input = carp6_proto_input,
 },
 #endif /* NCARP */
-{	.pr_type = SOCK_RAW,
+{
+    .ip6pr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inet6domain,
 	.pr_protocol = IPPROTO_L2TP,
 	.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
-	.pr_input = encap6_input,
 	.pr_ctlinput = rip6_ctlinput,
 	.pr_ctloutput = rip6_ctloutput,
 	.pr_usrreqs = &rip6_usrreqs,
 	.pr_init = encap_init,
+    },
+    .ip6pr_input = encap6_input,
 },
-{	.pr_type = SOCK_RAW,
+{
+    .ip6pr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inet6domain,
 	.pr_protocol = IPPROTO_PIM,
 	.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
-	.pr_input = pim6_input,
 	.pr_ctloutput = rip6_ctloutput,
 	.pr_usrreqs = &rip6_usrreqs,
 	.pr_init = pim6_init,
+    },
+    .ip6pr_input = pim6_input,
 },
 /* raw wildcard */
-{	.pr_type = SOCK_RAW,
+{
+    .ip6pr_protosw = {
+	.pr_type = SOCK_RAW,
 	.pr_domain = &inet6domain,
 	.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
-	.pr_input = rip6_input,
 	.pr_ctloutput = rip6_ctloutput,
 	.pr_usrreqs = &rip6_usrreqs,
 	.pr_init = rip6_init,
+    },
+    .ip6pr_input = rip6_input,
 },
 };
 
@@ -474,19 +540,25 @@ static const struct sockaddr_in6 in6_any = {
 	, .sin6_scope_id = 0
 };
 
+static const struct protosw *inet6protosw[__arraycount(inet6sw)];
+
 bool in6_present = false;
 static void
 in6_dom_init(void)
 {
+	size_t i;
 
 	in6_present = true;
+
+	for (i = 0; i < inet6domain.dom_nprotosw; i++)
+		inet6domain.dom_protosw[i] = &inet6sw[i].ip6pr_protosw;
 }
 
 struct domain inet6domain = {
 	.dom_family = AF_INET6, .dom_name = "internet6",
 	.dom_init = in6_dom_init, .dom_externalize = NULL, .dom_dispose = NULL,
-	.dom_protosw = (const struct protosw *)inet6sw,
-	.dom_protoswNPROTOSW = (const struct protosw *)&inet6sw[sizeof(inet6sw)/sizeof(inet6sw[0])],
+	.dom_protosw = inet6protosw,
+	.dom_nprotosw = __arraycount(inet6protosw),
 	.dom_rtattach = rt_inithead,
 	.dom_rtoffset = offsetof(struct sockaddr_in6, sin6_addr) << 3,
 	.dom_maxrtkey = sizeof(struct ip_pack6),
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index b32fd6f53647..dd0d9660fcef 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -159,22 +159,28 @@ static void sysctl_net_inet6_ip6_setup(struct sysctllog **);
 void
 ip6_init(void)
 {
-	const struct ip6protosw *pr;
-	int i;
+	const struct protosw *pr;
+	const struct ip6protosw *ip6pr;
+	size_t i;
 
 	in6_init();
 
 	sysctl_net_inet6_ip6_setup(NULL);
-	pr = (const struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
-	if (pr == 0)
-		panic("ip6_init");
+
+	pr = pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
+	KASSERT(pr != NULL);
+	ip6pr = const_container_of(pr, struct ip6protosw, ip6pr_protosw);
+
 	for (i = 0; i < IPPROTO_MAX; i++)
-		ip6_protox[i] = pr - inet6sw;
-	for (pr = (const struct ip6protosw *)inet6domain.dom_protosw;
-	    pr < (const struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++)
+		ip6_protox[i] = ip6pr - inet6sw;
+	for (i = 0; i < inet6domain.dom_nprotosw; i++) {
+		pr = inet6domain.dom_protosw[i];
+		ip6pr = const_container_of(pr,
+		    struct ip6protosw, ip6pr_protosw);
 		if (pr->pr_domain->dom_family == PF_INET6 &&
 		    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
-			ip6_protox[pr->pr_protocol] = pr - inet6sw;
+			ip6_protox[pr->pr_protocol] = ip6pr - inet6sw;
+	}
 
 	ip6_pktq = pktq_create(IFQ_MAXLEN, ip6intr, NULL);
 	KASSERT(ip6_pktq != NULL);
@@ -739,7 +745,7 @@ hbhcheck:
 			 * header. Note that we do not visit this with
 			 * protocols with pcb layer code - like udp/tcp/raw ip.
 			 */
-			if ((inet6sw[ip_protox[nxt]].pr_flags
+			if ((inet6sw[ip_protox[nxt]].ip6pr_protosw.pr_flags
 			    & PR_LASTHDR) != 0) {
 				int error;
 
@@ -750,7 +756,7 @@ hbhcheck:
 		}
 #endif
 
-		nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
+		nxt = (*inet6sw[ip6_protox[nxt]].ip6pr_input)(&m, &off, nxt);
 	}
 	return;
 
diff --git a/sys/netinet6/ip6protosw.h b/sys/netinet6/ip6protosw.h
index 7d8c97ecfaa6..7babcf0e0f7e 100644
--- a/sys/netinet6/ip6protosw.h
+++ b/sys/netinet6/ip6protosw.h
@@ -112,32 +112,8 @@ struct ip6ctlparam {
 };
 
 struct ip6protosw {
-	int 	pr_type;		/* socket type used for */
-	struct	domain *pr_domain;	/* domain protocol a member of */
-	short	pr_protocol;		/* protocol number */
-	short	pr_flags;		/* see below */
-
-/* protocol-protocol hooks */
-	int	(*pr_input)		/* input to protocol (from below) */
-			(struct mbuf **, int *, int);
-	void	*(*pr_ctlinput)		/* control input (from below) */
-			(int, const struct sockaddr *, void *);
-	int	(*pr_ctloutput)		/* control output (from above) */
-			(int, struct socket *, struct sockopt *);
-
-/* user-protocol hook */
-	const struct pr_usrreqs *pr_usrreqs;
-
-/* utility hooks */
-	void	(*pr_init)		/* initialization hook */
-			(void);
-
-	void	(*pr_fasttimo)		/* fast timeout (200ms) */
-			(void);
-	void	(*pr_slowtimo)		/* slow timeout (500ms) */
-			(void);
-	void	(*pr_drain)		/* flush any excess space possible */
-			(void);
+	struct protosw	ip6pr_protosw;
+	int		(*ip6pr_input)(struct mbuf **, int *, int);
 };
 
 #ifdef _KERNEL
diff --git a/sys/netipsec/ipsec_input.c b/sys/netipsec/ipsec_input.c
index a366d8f3999e..5aec634fd048 100644
--- a/sys/netipsec/ipsec_input.c
+++ b/sys/netipsec/ipsec_input.c
@@ -377,12 +377,13 @@ cantpull:
 
 	key_sa_recordxfer(sav, m);
 
-	if ((inetsw[ip_protox[prot]].pr_flags & PR_LASTHDR) != 0 &&
+	if ((inetsw[ip_protox[prot]].ippr_protosw.pr_flags &
+		PR_LASTHDR) != 0 &&
 	    ipsec_in_reject(m, NULL)) {
 		error = EINVAL;
 		goto bad;
 	}
-	(*inetsw[ip_protox[prot]].pr_input)(m, skip, prot);
+	(*inetsw[ip_protox[prot]].ippr_input)(m, skip, prot);
 	return 0;
 
 bad:
@@ -524,12 +525,13 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
 		 * Note that we do not visit this with protocols with pcb layer
 		 * code - like udp/tcp/raw ip.
 		 */
-		if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 &&
+		if ((inet6sw[ip6_protox[nxt]].ip6pr_protosw.pr_flags &
+			PR_LASTHDR) != 0 &&
 		    ipsec_in_reject(m, NULL)) {
 			error = EINVAL;
 			goto bad;
 		}
-		nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &skip, nxt);
+		nxt = (*inet6sw[ip6_protox[nxt]].ip6pr_input)(&m, &skip, nxt);
 	}
 	return 0;
 
diff --git a/sys/netipsec/keysock.c b/sys/netipsec/keysock.c
index e670981ad630..92e2d4e0b308 100644
--- a/sys/netipsec/keysock.c
+++ b/sys/netipsec/keysock.c
@@ -77,7 +77,7 @@ static struct sockaddr key_src = {
     .sa_family = PF_KEY,
 };
 
-static const struct protosw keysw[];
+static const struct protosw *keysw[];
 
 static int key_sendup0(struct rawcb *, struct mbuf *, int, int);
 
@@ -676,7 +676,7 @@ key_send(struct socket *so, struct mbuf *m, struct sockaddr *nam,
 	int s;
 
 	KASSERT(solocked(so));
-	KASSERT(so->so_proto == &keysw[0]);
+	KASSERT(so->so_proto == keysw[0]);
 
 	s = splsoftnet();
 	error = raw_send(so, m, nam, control, l, &key_output);
@@ -754,8 +754,8 @@ static const struct pr_usrreqs key_usrreqs = {
 	.pr_purgeif	= key_purgeif,
 };
 
-static const struct protosw keysw[] = {
-    {
+static const struct protosw *keysw[] = {
+    &(const struct protosw) {
 	.pr_type = SOCK_RAW,
 	.pr_domain = &keydomain,
 	.pr_protocol = PF_KEY_V2,
@@ -771,5 +771,5 @@ struct domain keydomain = {
     .dom_name = "key",
     .dom_init = key_init,
     .dom_protosw = keysw,
-    .dom_protoswNPROTOSW = &keysw[__arraycount(keysw)],
+    .dom_nprotosw = __arraycount(keysw),
 };
diff --git a/sys/netmpls/mpls_proto.c b/sys/netmpls/mpls_proto.c
index 02a92b7ca6ee..bf52da63a70b 100644
--- a/sys/netmpls/mpls_proto.c
+++ b/sys/netmpls/mpls_proto.c
@@ -355,17 +355,18 @@ static const struct pr_usrreqs mpls_usrreqs = {
 	.pr_purgeif	= mpls_purgeif,
 };
 
-const struct protosw mplssw[] = {
-	{	.pr_domain = &mplsdomain,
+const struct protosw *mplssw[] = {
+	&(const struct protosw) {
+		.pr_domain = &mplsdomain,
 		.pr_init = mpls_init,
 	},
-	{
+	&(const struct protosw) {
 		.pr_type = SOCK_DGRAM,
 		.pr_domain = &mplsdomain,
 		.pr_flags = PR_ATOMIC | PR_ADDR,
 		.pr_usrreqs = &mpls_usrreqs,
 	},
-	{
+	&(const struct protosw) {
 		.pr_type = SOCK_RAW,
 		.pr_domain = &mplsdomain,
 		.pr_flags = PR_ATOMIC | PR_ADDR,
@@ -380,7 +381,7 @@ struct domain mplsdomain = {
 	.dom_externalize = NULL,
 	.dom_dispose = NULL, 
 	.dom_protosw = mplssw,
-	.dom_protoswNPROTOSW = &mplssw[__arraycount(mplssw)],
+	.dom_nprotosw = __arraycount(mplssw),
 	.dom_rtattach = rt_inithead,
 	.dom_rtoffset = offsetof(struct sockaddr_mpls, smpls_addr) << 3,
 	.dom_maxrtkey = sizeof(union mpls_shim),
diff --git a/sys/rump/net/lib/libsockin/sockin.c b/sys/rump/net/lib/libsockin/sockin.c
index e10cfe1e057b..6dad3b280098 100644
--- a/sys/rump/net/lib/libsockin/sockin.c
+++ b/sys/rump/net/lib/libsockin/sockin.c
@@ -111,8 +111,8 @@ static const struct pr_usrreqs sockin_usrreqs = {
 	.pr_purgeif = sockin_purgeif,
 };
 
-const struct protosw sockinsw[] = {
-{
+const struct protosw *sockinsw[] = {
+&(const struct protosw) {
 	.pr_type = SOCK_DGRAM,
 	.pr_domain = &sockindomain,
 	.pr_protocol = IPPROTO_UDP,
@@ -120,7 +120,7 @@ const struct protosw sockinsw[] = {
 	.pr_usrreqs = &sockin_usrreqs,
 	.pr_ctloutput = sockin_ctloutput,
 },
-{
+&(const struct protosw) {
 	.pr_type = SOCK_STREAM,
 	.pr_domain = &sockindomain,
 	.pr_protocol = IPPROTO_TCP,
@@ -128,8 +128,8 @@ const struct protosw sockinsw[] = {
 	.pr_usrreqs = &sockin_usrreqs,
 	.pr_ctloutput = sockin_ctloutput,
 }};
-const struct protosw sockin6sw[] = {
-{
+const struct protosw *sockin6sw[] = {
+&(const struct protosw) {
 	.pr_type = SOCK_DGRAM,
 	.pr_domain = &sockin6domain,
 	.pr_protocol = IPPROTO_UDP,
@@ -137,7 +137,7 @@ const struct protosw sockin6sw[] = {
 	.pr_usrreqs = &sockin_usrreqs,
 	.pr_ctloutput = sockin_ctloutput,
 },
-{
+&(const struct protosw) {
 	.pr_type = SOCK_STREAM,
 	.pr_domain = &sockin6domain,
 	.pr_protocol = IPPROTO_TCP,
@@ -153,7 +153,7 @@ struct domain sockindomain = {
 	.dom_externalize = NULL,
 	.dom_dispose = NULL,
 	.dom_protosw = sockinsw,
-	.dom_protoswNPROTOSW = &sockinsw[__arraycount(sockinsw)],
+	.dom_nprotosw = __arraycount(sockinsw),
 	.dom_rtattach = rt_inithead,
 	.dom_rtoffset = 32,
 	.dom_maxrtkey = sizeof(struct sockaddr_in),
@@ -171,7 +171,7 @@ struct domain sockin6domain = {
 	.dom_externalize = NULL,
 	.dom_dispose = NULL,
 	.dom_protosw = sockin6sw,
-	.dom_protoswNPROTOSW = &sockin6sw[__arraycount(sockin6sw)],
+	.dom_nprotosw = __arraycount(sockin6sw),
 	.dom_rtattach = rt_inithead,
 	.dom_rtoffset = 32,
 	.dom_maxrtkey = sizeof(struct sockaddr_in6),
diff --git a/sys/sys/domain.h b/sys/sys/domain.h
index d01b51cc91fa..67e82ecf1b35 100644
--- a/sys/sys/domain.h
+++ b/sys/sys/domain.h
@@ -61,7 +61,8 @@ struct	domain {
 			(struct mbuf *, struct lwp *, int);
 	void	(*dom_dispose)		/* dispose of internalized rights */
 			(struct mbuf *);
-	const struct protosw *dom_protosw, *dom_protoswNPROTOSW;
+	const struct protosw **dom_protosw;
+	size_t	dom_nprotosw;
 	int	(*dom_rtattach)		/* initialize routing table */
 			(rtbl_t **, int);
 	int	dom_rtoffset;		/* an arg to rtattach, in bits */
diff --git a/sys/sys/protosw.h b/sys/sys/protosw.h
index 791d71e11af1..64e8cd8a4639 100644
--- a/sys/sys/protosw.h
+++ b/sys/sys/protosw.h
@@ -75,8 +75,6 @@ struct protosw {
 	short	pr_flags;		/* see below */
 
 /* protocol-protocol hooks */
-	void	(*pr_input)		/* input to protocol (from below) */
-			(struct mbuf *, ...);
 	void	*(*pr_ctlinput)		/* control input (from below) */
 			(int, const struct sockaddr *, void *);
 	int	(*pr_ctloutput)		/* control output (from above) */
-- 
2.11.0



Home | Main Index | Thread Index | Old Index