Module Name:    src
Committed By:   tls
Date:           Sun Aug 10 06:56:30 UTC 2014

Modified Files:
        src/sys/netinet6 [tls-earlyentropy]: icmp6.c in6.c in6.h in6_gif.c
            in6_ifattach.c in6_pcb.c in6_pcb.h in6_proto.c in6_src.c in6_var.h
            ip6_flow.c ip6_forward.c ip6_input.c ip6_mroute.c ip6_output.c
            ip6_var.h ip6protosw.h mld6.c nd6.c nd6.h nd6_nbr.c nd6_rtr.c
            raw_ip6.c scope6.c udp6_usrreq.c udp6_var.h

Log Message:
Rebase.


To generate a diff of this commit:
cvs rdiff -u -r1.165 -r1.165.2.1 src/sys/netinet6/icmp6.c
cvs rdiff -u -r1.169 -r1.169.2.1 src/sys/netinet6/in6.c
cvs rdiff -u -r1.75 -r1.75.2.1 src/sys/netinet6/in6.h
cvs rdiff -u -r1.59 -r1.59.10.1 src/sys/netinet6/in6_gif.c
cvs rdiff -u -r1.89 -r1.89.2.1 src/sys/netinet6/in6_ifattach.c
cvs rdiff -u -r1.124 -r1.124.2.1 src/sys/netinet6/in6_pcb.c
cvs rdiff -u -r1.37 -r1.37.12.1 src/sys/netinet6/in6_pcb.h
cvs rdiff -u -r1.100 -r1.100.2.1 src/sys/netinet6/in6_proto.c
cvs rdiff -u -r1.53 -r1.53.12.1 src/sys/netinet6/in6_src.c
cvs rdiff -u -r1.68 -r1.68.2.1 src/sys/netinet6/in6_var.h
cvs rdiff -u -r1.22 -r1.22.2.1 src/sys/netinet6/ip6_flow.c
cvs rdiff -u -r1.72 -r1.72.4.1 src/sys/netinet6/ip6_forward.c
cvs rdiff -u -r1.145 -r1.145.2.1 src/sys/netinet6/ip6_input.c
cvs rdiff -u -r1.106 -r1.106.2.1 src/sys/netinet6/ip6_mroute.c
cvs rdiff -u -r1.155 -r1.155.2.1 src/sys/netinet6/ip6_output.c
cvs rdiff -u -r1.59 -r1.59.12.1 src/sys/netinet6/ip6_var.h
cvs rdiff -u -r1.21 -r1.21.54.1 src/sys/netinet6/ip6protosw.h
cvs rdiff -u -r1.55 -r1.55.22.1 src/sys/netinet6/mld6.c
cvs rdiff -u -r1.148 -r1.148.2.1 src/sys/netinet6/nd6.c
cvs rdiff -u -r1.58 -r1.58.6.1 src/sys/netinet6/nd6.h
cvs rdiff -u -r1.99 -r1.99.2.1 src/sys/netinet6/nd6_nbr.c
cvs rdiff -u -r1.90 -r1.90.2.1 src/sys/netinet6/nd6_rtr.c
cvs rdiff -u -r1.113 -r1.113.2.1 src/sys/netinet6/raw_ip6.c
cvs rdiff -u -r1.8 -r1.8.36.1 src/sys/netinet6/scope6.c
cvs rdiff -u -r1.93 -r1.93.2.1 src/sys/netinet6/udp6_usrreq.c
cvs rdiff -u -r1.25 -r1.25.12.1 src/sys/netinet6/udp6_var.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/netinet6/icmp6.c
diff -u src/sys/netinet6/icmp6.c:1.165 src/sys/netinet6/icmp6.c:1.165.2.1
--- src/sys/netinet6/icmp6.c:1.165	Tue Feb 25 18:30:12 2014
+++ src/sys/netinet6/icmp6.c	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: icmp6.c,v 1.165 2014/02/25 18:30:12 pooka Exp $	*/
+/*	$NetBSD: icmp6.c,v 1.165.2.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $	*/
 
 /*
@@ -62,14 +62,14 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.165 2014/02/25 18:30:12 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.165.2.1 2014/08/10 06:56:30 tls Exp $");
 
 #include "opt_inet.h"
 #include "opt_ipsec.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
-#include <sys/malloc.h>
+#include <sys/kmem.h>
 #include <sys/mbuf.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
@@ -253,10 +253,7 @@ icmp6_mtudisc_callback_register(void (*f
 			return;
 	}
 
-	mc = malloc(sizeof(*mc), M_PCB, M_NOWAIT);
-	if (mc == NULL)
-		panic("icmp6_mtudisc_callback_register");
-
+	mc = kmem_alloc(sizeof(*mc), KM_SLEEP);
 	mc->mc_func = func;
 	LIST_INSERT_HEAD(&icmp6_mtudisc_callbacks, mc, mc_list);
 }
@@ -1135,8 +1132,8 @@ icmp6_mtudisc_update(struct ip6ctlparam 
 			rt->rt_rmx.rmx_mtu = mtu;
 		}
 	}
-	if (rt) { /* XXX: need braces to avoid conflict with else in RTFREE. */
-		RTFREE(rt);
+	if (rt) {
+		rtfree(rt);
 	}
 
 	/*
@@ -1717,7 +1714,7 @@ ni6_store_addrs(struct icmp6_nodeinfo *n
 	struct icmp6_nodeinfo *nni6, struct ifnet *ifp0,
 	int resid)
 {
-	struct ifnet *ifp = ifp0 ? ifp0 : TAILQ_FIRST(&ifnet);
+	struct ifnet *ifp = ifp0 ? ifp0 : IFNET_FIRST();
 	struct in6_ifaddr *ifa6;
 	struct ifaddr *ifa;
 	struct ifnet *ifp_dep = NULL;
@@ -2191,7 +2188,7 @@ icmp6_redirect_input(struct mbuf *m, int
 			    "ICMP6 redirect rejected; no route "
 			    "with inet6 gateway found for redirect dst: %s\n",
 			    icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
-			RTFREE(rt);
+			rtfree(rt);
 			goto bad;
 		}
 
@@ -2203,7 +2200,7 @@ icmp6_redirect_input(struct mbuf *m, int
 				"%s\n",
 				ip6_sprintf(gw6),
 				icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
-			RTFREE(rt);
+			rtfree(rt);
 			goto bad;
 		}
 	} else {
@@ -2213,7 +2210,7 @@ icmp6_redirect_input(struct mbuf *m, int
 			icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
 		goto bad;
 	}
-	RTFREE(rt);
+	rtfree(rt);
 	rt = NULL;
     }
 	if (IN6_IS_ADDR_MULTICAST(&reddst6)) {
@@ -2319,7 +2316,8 @@ icmp6_redirect_input(struct mbuf *m, int
 		sockaddr_in6_init(&sdst, &reddst6, 0, 0, 0);
 		pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&sdst);
 #if defined(IPSEC)
-		key_sa_routechange((struct sockaddr *)&sdst);
+		if (ipsec_used)
+			key_sa_routechange((struct sockaddr *)&sdst);
 #endif
 	}
 

Index: src/sys/netinet6/in6.c
diff -u src/sys/netinet6/in6.c:1.169 src/sys/netinet6/in6.c:1.169.2.1
--- src/sys/netinet6/in6.c:1.169	Wed Jan 15 10:52:11 2014
+++ src/sys/netinet6/in6.c	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6.c,v 1.169 2014/01/15 10:52:11 roy Exp $	*/
+/*	$NetBSD: in6.c,v 1.169.2.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $	*/
 
 /*
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.169 2014/01/15 10:52:11 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.169.2.1 2014/08/10 06:56:30 tls Exp $");
 
 #include "opt_inet.h"
 #include "opt_compat_netbsd.h"
@@ -139,7 +139,7 @@ const struct sockaddr_in6 sa6_any = {siz
 				     0, 0, IN6ADDR_ANY_INIT, 0};
 
 static int in6_lifaddr_ioctl(struct socket *, u_long, void *,
-	struct ifnet *, struct lwp *);
+	struct ifnet *);
 static int in6_ifinit(struct ifnet *, struct in6_ifaddr *,
 	const struct sockaddr_in6 *, int);
 static void in6_unlink_ifa(struct in6_ifaddr *, struct ifnet *);
@@ -360,8 +360,7 @@ in6_mask2len(struct in6_addr *mask, u_ch
 #define ia62ifa(ia6)	(&((ia6)->ia_ifa))
 
 static int
-in6_control1(struct socket *so, u_long cmd, void *data, struct ifnet *ifp,
-    lwp_t *l)
+in6_control1(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
 {
 	struct	in6_ifreq *ifr = (struct in6_ifreq *)data;
 	struct	in6_ifaddr *ia = NULL;
@@ -385,7 +384,7 @@ in6_control1(struct socket *so, u_long c
 	case SIOCSIFADDRPREF:
 		if (ifp == NULL)
 			return EINVAL;
-		return ifaddrpref_ioctl(so, cmd, data, ifp, l);
+		return ifaddrpref_ioctl(so, cmd, data, ifp);
 	}
 
 	if (ifp == NULL)
@@ -428,7 +427,7 @@ in6_control1(struct socket *so, u_long c
 		/* Privileged. */
 		/* FALLTHROUGH */
 	case SIOCGLIFADDR:
-		return in6_lifaddr_ioctl(so, cmd, data, ifp, l);
+		return in6_lifaddr_ioctl(so, cmd, data, ifp);
 	}
 
 	/*
@@ -784,8 +783,7 @@ in6_control1(struct socket *so, u_long c
 }
 
 int
-in6_control(struct socket *so, u_long cmd, void *data, struct ifnet *ifp,
-    struct lwp *l)
+in6_control(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
 {
 	int error, s;
 
@@ -805,7 +803,7 @@ in6_control(struct socket *so, u_long cm
 	case OSIOCAIFADDR_IN6:
 #endif
 	case SIOCAIFADDR_IN6:
-		if (kauth_authorize_network(l->l_cred,
+		if (kauth_authorize_network(curlwp->l_cred,
 		    KAUTH_NETWORK_SOCKET,
 		    KAUTH_REQ_NETWORK_SOCKET_SETPRIV,
 		    so, NULL, NULL))
@@ -814,7 +812,7 @@ in6_control(struct socket *so, u_long cm
 	}
 
 	s = splnet();
-	error = in6_control1(so , cmd, data, ifp, l);
+	error = in6_control1(so , cmd, data, ifp);
 	splx(s);
 	return error;
 }
@@ -1168,7 +1166,7 @@ in6_update_ifa1(struct ifnet *ifp, struc
 			if (memcmp(&mltaddr.sin6_addr,
 			    &satocsin6(rt_getkey(rt))->sin6_addr,
 			    MLTMASK_LEN)) {
-				RTFREE(rt);
+				rtfree(rt);
 				rt = NULL;
 			} else if (rt->rt_ifp != ifp) {
 				IN6_DPRINTF("%s: rt_ifp %p -> %p (%s) "
@@ -1199,7 +1197,7 @@ in6_update_ifa1(struct ifnet *ifp, struc
 			if (error)
 				goto cleanup;
 		} else {
-			RTFREE(rt);
+			rtfree(rt);
 		}
 		imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
 		if (!imm) {
@@ -1253,7 +1251,7 @@ in6_update_ifa1(struct ifnet *ifp, struc
 			if (memcmp(&mltaddr.sin6_addr,
 			    &satocsin6(rt_getkey(rt))->sin6_addr,
 			    32 / NBBY)) {
-				RTFREE(rt);
+				rtfree(rt);
 				rt = NULL;
 			} else if (rt->rt_ifp != ifp) {
 				IN6_DPRINTF("%s: rt_ifp %p -> %p (%s) "
@@ -1284,7 +1282,7 @@ in6_update_ifa1(struct ifnet *ifp, struc
 				goto cleanup;
 #undef	MLTMASK_LEN
 		} else {
-			RTFREE(rt);
+			rtfree(rt);
 		}
 		imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
 		if (!imm) {
@@ -1333,7 +1331,8 @@ in6_update_ifa1(struct ifnet *ifp, struc
 				    mindelay;
 			}
 		}
-		nd6_dad_start(&ia->ia_ifa, dad_delay);
+		/* +1 ensures callout is always used */
+		nd6_dad_start(&ia->ia_ifa, dad_delay + 1);
 	}
 
 	return error;
@@ -1508,7 +1507,7 @@ in6_purgeif(struct ifnet *ifp)
  */
 static int
 in6_lifaddr_ioctl(struct socket *so, u_long cmd, void *data, 
-	struct ifnet *ifp, struct lwp *l)
+	struct ifnet *ifp)
 {
 	struct in6_ifaddr *ia;
 	struct if_laddrreq *iflr = (struct if_laddrreq *)data;
@@ -1618,7 +1617,7 @@ in6_lifaddr_ioctl(struct socket *so, u_l
 		ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
 		ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
 		ifra.ifra_flags = iflr->flags & ~IFLR_PREFIX;
-		return in6_control(so, SIOCAIFADDR_IN6, &ifra, ifp, l);
+		return in6_control(so, SIOCAIFADDR_IN6, &ifra, ifp);
 	    }
 	case SIOCGLIFADDR:
 	case SIOCDLIFADDR:
@@ -1729,7 +1728,7 @@ in6_lifaddr_ioctl(struct socket *so, u_l
 			    ia->ia_prefixmask.sin6_len);
 
 			ifra.ifra_flags = ia->ia6_flags;
-			return in6_control(so, SIOCDIFADDR_IN6, &ifra, ifp, l);
+			return in6_control(so, SIOCDIFADDR_IN6, &ifra, ifp);
 		}
 	    }
 	}
@@ -2157,15 +2156,17 @@ in6_if_link_up(struct ifnet *ifp)
 		}
 
 		if (ia->ia6_flags & IN6_IFF_TENTATIVE) {
+			int rand_delay;
 			/*
 			 * The TENTATIVE flag was likely set by hand
 			 * beforehand, implicitly indicating the need for DAD.
 			 * We may be able to skip the random delay in this
 			 * case, but we impose delays just in case.
 			 */
-			nd6_dad_start(ifa,
-			    cprng_fast32() %
-				(MAX_RTR_SOLICITATION_DELAY * hz));
+			rand_delay = cprng_fast32() %
+			    (MAX_RTR_SOLICITATION_DELAY * hz);
+			/* +1 ensures callout is always used */
+			nd6_dad_start(ifa, rand_delay + 1);
 		}
 	}
 
@@ -2274,7 +2275,7 @@ in6_setmaxmtu(void)
 	unsigned long maxmtu = 0;
 	struct ifnet *ifp;
 
-	TAILQ_FOREACH(ifp, &ifnet, if_list) {
+	IFNET_FOREACH(ifp) {
 		/* this function can be called during ifnet initialization */
 		if (!ifp->if_afdata[AF_INET6])
 			continue;

Index: src/sys/netinet6/in6.h
diff -u src/sys/netinet6/in6.h:1.75 src/sys/netinet6/in6.h:1.75.2.1
--- src/sys/netinet6/in6.h:1.75	Sat Oct 19 15:44:29 2013
+++ src/sys/netinet6/in6.h	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6.h,v 1.75 2013/10/19 15:44:29 christos Exp $	*/
+/*	$NetBSD: in6.h,v 1.75.2.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: in6.h,v 1.83 2001/03/29 02:55:07 jinmei Exp $	*/
 
 /*
@@ -403,9 +403,7 @@ extern const struct in6_addr in6addr_lin
 #define IPV6_CHECKSUM		26 /* int; checksum offset for raw socket */
 #define IPV6_V6ONLY		27 /* bool; make AF_INET6 sockets v6 only */
 
-#if 1 /* IPSEC */
 #define IPV6_IPSEC_POLICY	28 /* struct; get/set security policy */
-#endif
 #define IPV6_FAITH		29 /* bool; accept FAITH'ed connections */
 
 /* new socket options introduced in RFC3542 */
@@ -573,11 +571,13 @@ struct ip6_mtuinfo {
 #define IPV6CTL_ANONPORTMAX	29	/* maximum ephemeral port */
 #define IPV6CTL_LOWPORTMIN	30	/* minimum reserved port */
 #define IPV6CTL_LOWPORTMAX	31	/* maximum reserved port */
-/* 32 to 38: reserved */
+/* 32 to 34: reserved */
+#define IPV6CTL_AUTO_LINKLOCAL	35	/* automatic link-local addr assign */
+/* 36 to 38: reserved */
 #define IPV6CTL_USE_DEFAULTZONE	39	/* use default scope zone */
 /* 40: reserved */
 #define IPV6CTL_MAXFRAGS	41	/* max fragments */
-#define IPV6CTL_IFQ		42	/* ip6intrq node */
+#define IPV6CTL_IFQ		42	/* IPv6 packet input queue */
 #define IPV6CTL_RTADV_MAXROUTES 43	/* maximum number of routes */
 					/* via router advertisement */
 #define IPV6CTL_RTADV_NUMROUTES 44	/* current number of routes */

Index: src/sys/netinet6/in6_gif.c
diff -u src/sys/netinet6/in6_gif.c:1.59 src/sys/netinet6/in6_gif.c:1.59.10.1
--- src/sys/netinet6/in6_gif.c:1.59	Fri Mar  1 18:25:58 2013
+++ src/sys/netinet6/in6_gif.c	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6_gif.c,v 1.59 2013/03/01 18:25:58 joerg Exp $	*/
+/*	$NetBSD: in6_gif.c,v 1.59.10.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: in6_gif.c,v 1.62 2001/07/29 04:27:25 itojun Exp $	*/
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6_gif.c,v 1.59 2013/03/01 18:25:58 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_gif.c,v 1.59.10.1 2014/08/10 06:56:30 tls Exp $");
 
 #include "opt_inet.h"
 
@@ -441,16 +441,20 @@ in6_gif_ctlinput(int cmd, const struct s
 
 PR_WRAP_CTLINPUT(in6_gif_ctlinput)
 PR_WRAP_CTLOUTPUT(rip6_ctloutput)
-PR_WRAP_USRREQ(rip6_usrreq)
 
 #define	in6_gif_ctlinput	in6_gif_ctlinput_wrapper
 #define	rip6_ctloutput		rip6_ctloutput_wrapper
-#define	rip6_usrreq		rip6_usrreq_wrapper
 
 extern struct domain inet6domain;
-const struct ip6protosw in6_gif_protosw =
-{ SOCK_RAW,	&inet6domain,	0/* IPPROTO_IPV[46] */,	PR_ATOMIC|PR_ADDR,
-  in6_gif_input, rip6_output,	in6_gif_ctlinput, rip6_ctloutput,
-  rip6_usrreq,
-  0,            0,              0,              0,
+
+const struct ip6protosw in6_gif_protosw = {
+	.pr_type	= SOCK_RAW,
+	.pr_domain	= &inet6domain,
+	.pr_protocol	= 0 /* IPPROTO_IPV[46] */,
+	.pr_flags	= PR_ATOMIC | PR_ADDR,
+	.pr_input	= in6_gif_input,
+	.pr_output	= rip6_output,
+	.pr_ctlinput	= in6_gif_ctlinput,
+	.pr_ctloutput	= rip6_ctloutput,
+	.pr_usrreqs	= &rip6_usrreqs,
 };

Index: src/sys/netinet6/in6_ifattach.c
diff -u src/sys/netinet6/in6_ifattach.c:1.89 src/sys/netinet6/in6_ifattach.c:1.89.2.1
--- src/sys/netinet6/in6_ifattach.c:1.89	Fri Oct 25 15:44:39 2013
+++ src/sys/netinet6/in6_ifattach.c	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6_ifattach.c,v 1.89 2013/10/25 15:44:39 martin Exp $	*/
+/*	$NetBSD: in6_ifattach.c,v 1.89.2.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: in6_ifattach.c,v 1.124 2001/07/18 08:32:51 jinmei Exp $	*/
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6_ifattach.c,v 1.89 2013/10/25 15:44:39 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_ifattach.c,v 1.89.2.1 2014/08/10 06:56:30 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -473,7 +473,7 @@ get_ifid(struct ifnet *ifp0, struct ifne
 	}
 
 	/* next, try to get it from some other hardware interface */
-	TAILQ_FOREACH(ifp, &ifnet, if_list) {
+	IFNET_FOREACH(ifp) {
 		if (ifp == ifp0)
 			continue;
 		if (in6_get_hw_ifid(ifp, in6) != 0)
@@ -754,6 +754,8 @@ in6_ifattach(struct ifnet *ifp, struct i
 #ifdef IFT_PFSYNC
 	case IFT_PFSYNC:
 #endif
+		ND_IFINFO(ifp)->flags &= ~ND6_IFF_AUTO_LINKLOCAL;
+		ND_IFINFO(ifp)->flags |= ND6_IFF_IFDISABLED;
 		return;
 	}
 
@@ -784,6 +786,7 @@ in6_ifattach(struct ifnet *ifp, struct i
 		 * linklocals for 6to4 interface, but there's no use and
 		 * it is rather harmful to have one.
 		 */
+		ND_IFINFO(ifp)->flags &= ~ND6_IFF_AUTO_LINKLOCAL;
 		return;
 #endif
 	case IFT_CARP:
@@ -817,7 +820,9 @@ in6_ifattach(struct ifnet *ifp, struct i
 	/*
 	 * assign a link-local address, if there's none.
 	 */
-	if (ip6_auto_linklocal) {
+	if (!(ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) &&
+	    ND_IFINFO(ifp)->flags & ND6_IFF_AUTO_LINKLOCAL)
+	{
 		ia = in6ifa_ifpforlinklocal(ifp, 0);
 		if (ia == NULL && in6_ifattach_linklocal(ifp, altifp) != 0) {
 			printf("%s: cannot assign link-local address\n",
@@ -962,7 +967,7 @@ in6_tmpaddrtimer(void *ignored_arg)
 	    ip6_temp_regen_advance) * hz, in6_tmpaddrtimer, NULL);
 
 	memset(nullbuf, 0, sizeof(nullbuf));
-	TAILQ_FOREACH(ifp, &ifnet, if_list) {
+	IFNET_FOREACH(ifp) {
 		ndi = ND_IFINFO(ifp);
 		if (memcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) {
 			/*

Index: src/sys/netinet6/in6_pcb.c
diff -u src/sys/netinet6/in6_pcb.c:1.124 src/sys/netinet6/in6_pcb.c:1.124.2.1
--- src/sys/netinet6/in6_pcb.c:1.124	Sat Nov 23 14:20:22 2013
+++ src/sys/netinet6/in6_pcb.c	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6_pcb.c,v 1.124 2013/11/23 14:20:22 christos Exp $	*/
+/*	$NetBSD: in6_pcb.c,v 1.124.2.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: in6_pcb.c,v 1.84 2001/02/08 18:02:08 itojun Exp $	*/
 
 /*
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6_pcb.c,v 1.124 2013/11/23 14:20:22 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_pcb.c,v 1.124.2.1 2014/08/10 06:56:30 tls Exp $");
 
 #include "opt_inet.h"
 #include "opt_ipsec.h"
@@ -157,9 +157,6 @@ in6_pcballoc(struct socket *so, void *v)
 	struct inpcbtable *table = v;
 	struct in6pcb *in6p;
 	int s;
-#if defined(IPSEC)
-	int error;
-#endif
 
 	s = splnet();
 	in6p = pool_get(&in6pcb_pool, PR_NOWAIT);
@@ -175,12 +172,14 @@ in6_pcballoc(struct socket *so, void *v)
 	in6p->in6p_portalgo = PORTALGO_DEFAULT;
 	in6p->in6p_bindportonsend = false;
 #if defined(IPSEC)
-	error = ipsec_init_pcbpolicy(so, &in6p->in6p_sp);
-	if (error != 0) {
-		s = splnet();
-		pool_put(&in6pcb_pool, in6p);
-		splx(s);
-		return error;
+	if (ipsec_enabled) {
+		int error = ipsec_init_pcbpolicy(so, &in6p->in6p_sp);
+		if (error != 0) {
+			s = splnet();
+			pool_put(&in6pcb_pool, in6p);
+			splx(s);
+			return error;
+		}
 	}
 #endif /* IPSEC */
 	s = splnet();
@@ -567,7 +566,7 @@ in6_pcbconnect(void *v, struct mbuf *nam
 		in6p->in6p_flowinfo |=
 		    (htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK);
 #if defined(IPSEC)
-	if (in6p->in6p_socket->so_type == SOCK_STREAM)
+	if (ipsec_enabled && in6p->in6p_socket->so_type == SOCK_STREAM)
 		ipsec_pcbconn(in6p->in6p_sp);
 #endif
 	return (0);
@@ -581,7 +580,8 @@ in6_pcbdisconnect(struct in6pcb *in6p)
 	in6_pcbstate(in6p, IN6P_BOUND);
 	in6p->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
 #if defined(IPSEC)
-	ipsec_pcbdisconn(in6p->in6p_sp);
+	if (ipsec_enabled)
+		ipsec_pcbdisconn(in6p->in6p_sp);
 #endif
 	if (in6p->in6p_socket->so_state & SS_NOFDREF)
 		in6_pcbdetach(in6p);
@@ -597,25 +597,30 @@ in6_pcbdetach(struct in6pcb *in6p)
 		return;
 
 #if defined(IPSEC)
-	ipsec6_delete_pcbpolicy(in6p);
-#endif /* IPSEC */
-	so->so_pcb = 0;
-	if (in6p->in6p_options)
+	if (ipsec_enabled)
+		ipsec6_delete_pcbpolicy(in6p);
+#endif
+	so->so_pcb = NULL;
+
+	s = splnet();
+	in6_pcbstate(in6p, IN6P_ATTACHED);
+	LIST_REMOVE(&in6p->in6p_head, inph_lhash);
+	TAILQ_REMOVE(&in6p->in6p_table->inpt_queue, &in6p->in6p_head,
+	    inph_queue);
+	splx(s);
+
+	if (in6p->in6p_options) {
 		m_freem(in6p->in6p_options);
+	}
 	if (in6p->in6p_outputopts != NULL) {
 		ip6_clearpktopts(in6p->in6p_outputopts, -1);
 		free(in6p->in6p_outputopts, M_IP6OPT);
 	}
 	rtcache_free(&in6p->in6p_route);
+	sofree(so);				/* drops the socket's lock */
+
 	ip6_freemoptions(in6p->in6p_moptions);
-	s = splnet();
-	in6_pcbstate(in6p, IN6P_ATTACHED);
-	LIST_REMOVE(&in6p->in6p_head, inph_lhash);
-	TAILQ_REMOVE(&in6p->in6p_table->inpt_queue, &in6p->in6p_head,
-	    inph_queue);
 	pool_put(&in6pcb_pool, in6p);
-	splx(s);
-	sofree(so);				/* drops the socket's lock */
 	mutex_enter(softnet_lock);		/* reacquire it */
 }
 

Index: src/sys/netinet6/in6_pcb.h
diff -u src/sys/netinet6/in6_pcb.h:1.37 src/sys/netinet6/in6_pcb.h:1.37.12.1
--- src/sys/netinet6/in6_pcb.h:1.37	Mon Jun 25 15:28:39 2012
+++ src/sys/netinet6/in6_pcb.h	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6_pcb.h,v 1.37 2012/06/25 15:28:39 christos Exp $	*/
+/*	$NetBSD: in6_pcb.h,v 1.37.12.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: in6_pcb.h,v 1.45 2001/02/09 05:59:46 itojun Exp $	*/
 
 /*

Index: src/sys/netinet6/in6_proto.c
diff -u src/sys/netinet6/in6_proto.c:1.100 src/sys/netinet6/in6_proto.c:1.100.2.1
--- src/sys/netinet6/in6_proto.c:1.100	Thu Jan  2 18:29:01 2014
+++ src/sys/netinet6/in6_proto.c	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6_proto.c,v 1.100 2014/01/02 18:29:01 pooka Exp $	*/
+/*	$NetBSD: in6_proto.c,v 1.100.2.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: in6_proto.c,v 1.66 2000/10/10 15:35:47 itojun Exp $	*/
 
 /*
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6_proto.c,v 1.100 2014/01/02 18:29:01 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_proto.c,v 1.100.2.1 2014/08/10 06:56:30 tls Exp $");
 
 #include "opt_gateway.h"
 #include "opt_inet.h"
@@ -135,14 +135,6 @@ DOMAIN_DEFINE(inet6domain);	/* forward d
 
 /* Wrappers to acquire kernel_lock. */
 
-PR_WRAP_USRREQ(rip6_usrreq)
-PR_WRAP_USRREQ(udp6_usrreq)
-PR_WRAP_USRREQ(tcp_usrreq)
-
-#define	rip6_usrreq 	rip6_usrreq_wrapper
-#define	udp6_usrreq 	udp6_usrreq_wrapper
-#define	tcp_usrreq 	tcp_usrreq_wrapper
-
 PR_WRAP_CTLINPUT(rip6_ctlinput)
 PR_WRAP_CTLINPUT(encap6_ctlinput)
 PR_WRAP_CTLINPUT(udp6_ctlinput)
@@ -199,7 +191,7 @@ const struct ip6protosw inet6sw[] = {
 	.pr_input = udp6_input,
 	.pr_ctlinput = udp6_ctlinput,
 	.pr_ctloutput = udp6_ctloutput,
-	.pr_usrreq = udp6_usrreq,
+	.pr_usrreqs = &udp6_usrreqs,
 	.pr_init = udp6_init,
 },
 {	.pr_type = SOCK_STREAM,
@@ -209,7 +201,7 @@ const struct ip6protosw inet6sw[] = {
 	.pr_input = tcp6_input,
 	.pr_ctlinput = tcp6_ctlinput,
 	.pr_ctloutput = tcp_ctloutput,
-	.pr_usrreq = tcp_usrreq,
+	.pr_usrreqs = &tcp_usrreqs,
 	.pr_init = tcp6_init,
 	.pr_fasttimo = tcp_fasttimo,
 	.pr_drain = tcp_drainstub,
@@ -222,7 +214,7 @@ const struct ip6protosw inet6sw[] = {
 	.pr_output = rip6_output,
 	.pr_ctlinput = rip6_ctlinput,
 	.pr_ctloutput = rip6_ctloutput,
-	.pr_usrreq = rip6_usrreq,
+	.pr_usrreqs = &rip6_usrreqs,
 },
 #ifdef GATEWAY
 {	.pr_domain = &inet6domain,
@@ -239,7 +231,7 @@ const struct ip6protosw inet6sw[] = {
 	.pr_output = rip6_output,
 	.pr_ctlinput = rip6_ctlinput,
 	.pr_ctloutput = icmp6_ctloutput,
-	.pr_usrreq = rip6_usrreq,
+	.pr_usrreqs = &rip6_usrreqs,
 	.pr_init = icmp6_init,
 },
 {	.pr_type = SOCK_RAW,
@@ -291,7 +283,7 @@ const struct ip6protosw inet6sw[] = {
 	.pr_output = rip6_output,
 	.pr_ctlinput = encap6_ctlinput,
 	.pr_ctloutput = rip6_ctloutput,
-	.pr_usrreq = rip6_usrreq,
+	.pr_usrreqs = &rip6_usrreqs,
 	.pr_init = encap_init,
 },
 #endif
@@ -303,7 +295,7 @@ const struct ip6protosw inet6sw[] = {
 	.pr_output = rip6_output,
 	.pr_ctlinput = encap6_ctlinput,
 	.pr_ctloutput = rip6_ctloutput,
-	.pr_usrreq = rip6_usrreq,
+	.pr_usrreqs = &rip6_usrreqs,
 	.pr_init = encap_init,
 },
 #if NETHERIP > 0
@@ -315,7 +307,7 @@ const struct ip6protosw inet6sw[] = {
 	.pr_output = rip6_output,
 	.pr_ctlinput = rip6_ctlinput,
 	.pr_ctloutput = rip6_ctloutput,
-	.pr_usrreq = rip6_usrreq,
+	.pr_usrreqs = &rip6_usrreqs,
 },
 #endif
 #if NCARP > 0
@@ -326,7 +318,7 @@ const struct ip6protosw inet6sw[] = {
 	.pr_input = carp6_proto_input,
 	.pr_output = rip6_output,
 	.pr_ctloutput = rip6_ctloutput,
-	.pr_usrreq = rip6_usrreq,
+	.pr_usrreqs = &rip6_usrreqs,
 },
 #endif /* NCARP */
 {	.pr_type = SOCK_RAW,
@@ -336,7 +328,7 @@ const struct ip6protosw inet6sw[] = {
 	.pr_input = pim6_input,
 	.pr_output = rip6_output,
 	.pr_ctloutput = rip6_ctloutput,
-	.pr_usrreq = rip6_usrreq,
+	.pr_usrreqs = &rip6_usrreqs,
 	.pr_init = pim6_init,
 },
 /* raw wildcard */
@@ -346,7 +338,7 @@ const struct ip6protosw inet6sw[] = {
 	.pr_input = rip6_input,
 	.pr_output = rip6_output,
 	.pr_ctloutput = rip6_ctloutput,
-	.pr_usrreq = rip6_usrreq,
+	.pr_usrreqs = &rip6_usrreqs,
 	.pr_init = rip6_init,
 },
 };
@@ -377,7 +369,7 @@ struct domain inet6domain = {
 	.dom_rtoffset = offsetof(struct sockaddr_in6, sin6_addr) << 3,
 	.dom_maxrtkey = sizeof(struct ip_pack6),
 	.dom_ifattach = in6_domifattach, .dom_ifdetach = in6_domifdetach,
-	.dom_ifqueues = { &ip6intrq, NULL },
+	.dom_ifqueues = { NULL, NULL },
 	.dom_link = { NULL },
 	.dom_mowner = MOWNER_INIT("",""),
 	.dom_sa_cmpofs = offsetof(struct sockaddr_in6, sin6_addr),
@@ -476,8 +468,3 @@ int	icmp6_rediraccept = 1;		/* accept an
 int	icmp6_redirtimeout = 10 * 60;	/* 10 minutes */
 int	icmp6errppslim = 100;		/* 100pps */
 int	icmp6_nodeinfo = 1;		/* enable/disable NI response */
-
-/* UDP on IP6 parameters */
-int	udp6_sendspace = 9216;		/* really max datagram size */
-int	udp6_recvspace = 40 * (1024 + sizeof(struct sockaddr_in6));
-					/* 40 1K datagrams */

Index: src/sys/netinet6/in6_src.c
diff -u src/sys/netinet6/in6_src.c:1.53 src/sys/netinet6/in6_src.c:1.53.12.1
--- src/sys/netinet6/in6_src.c:1.53	Mon Jun 25 15:28:39 2012
+++ src/sys/netinet6/in6_src.c	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6_src.c,v 1.53 2012/06/25 15:28:39 christos Exp $	*/
+/*	$NetBSD: in6_src.c,v 1.53.12.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: in6_src.c,v 1.159 2005/10/19 01:40:32 t-momose Exp $	*/
 
 /*
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6_src.c,v 1.53 2012/06/25 15:28:39 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_src.c,v 1.53.12.1 2014/08/10 06:56:30 tls Exp $");
 
 #include "opt_inet.h"
 
@@ -591,7 +591,7 @@ selectroute(struct sockaddr_in6 *dstsock
 	/* If the caller specify the outgoing interface explicitly, use it. */
 	if (opts && (pi = opts->ip6po_pktinfo) != NULL && pi->ipi6_ifindex) {
 		/* XXX boundary check is assumed to be already done. */
-		ifp = ifindex2ifnet[pi->ipi6_ifindex];
+		ifp = if_byindex(pi->ipi6_ifindex);
 		if (ifp != NULL &&
 		    (norouteok || retrt == NULL ||
 		    IN6_IS_ADDR_MULTICAST(dst))) {

Index: src/sys/netinet6/in6_var.h
diff -u src/sys/netinet6/in6_var.h:1.68 src/sys/netinet6/in6_var.h:1.68.2.1
--- src/sys/netinet6/in6_var.h:1.68	Mon Jan 13 18:57:49 2014
+++ src/sys/netinet6/in6_var.h	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6_var.h,v 1.68 2014/01/13 18:57:49 roy Exp $	*/
+/*	$NetBSD: in6_var.h,v 1.68.2.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: in6_var.h,v 1.81 2002/06/08 11:16:51 itojun Exp $	*/
 
 /*
@@ -479,6 +479,11 @@ struct	in6_rrenumreq {
 #endif
 
 #ifdef _KERNEL
+
+#include <net/pktqueue.h>
+
+extern pktqueue_t *ip6_pktq;
+
 MALLOC_DECLARE(M_IP6OPT);
 
 extern struct in6_ifaddr *in6_ifaddr;
@@ -489,7 +494,6 @@ do {								\
 		((struct in6_ifextra *)((ifp)->if_afdata[AF_INET6]))->in6_ifstat->tag++; \
 } while (/*CONSTCOND*/ 0)
 
-extern struct ifqueue ip6intrq;		/* IP6 packet input queue */
 extern const struct in6_addr zeroin6_addr;
 extern const u_char inet6ctlerrmap[];
 extern unsigned long in6_maxmtu;
@@ -676,8 +680,7 @@ struct in6_multi_mship *in6_joingroup(st
 	int *, int);
 int	in6_leavegroup(struct in6_multi_mship *);
 int	in6_mask2len(struct in6_addr *, u_char *);
-int	in6_control(struct socket *, u_long, void *, struct ifnet *,
-	struct lwp *);
+int	in6_control(struct socket *, u_long, void *, struct ifnet *);
 int	in6_update_ifa(struct ifnet *, struct in6_aliasreq *,
 	struct in6_ifaddr *, int);
 void	in6_purgeaddr(struct ifaddr *);

Index: src/sys/netinet6/ip6_flow.c
diff -u src/sys/netinet6/ip6_flow.c:1.22 src/sys/netinet6/ip6_flow.c:1.22.2.1
--- src/sys/netinet6/ip6_flow.c:1.22	Tue Apr  1 13:11:44 2014
+++ src/sys/netinet6/ip6_flow.c	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip6_flow.c,v 1.22 2014/04/01 13:11:44 pooka Exp $	*/
+/*	$NetBSD: ip6_flow.c,v 1.22.2.1 2014/08/10 06:56:30 tls Exp $	*/
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip6_flow.c,v 1.22 2014/04/01 13:11:44 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip6_flow.c,v 1.22.2.1 2014/08/10 06:56:30 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -308,13 +308,14 @@ ip6flow_fastforward(struct mbuf **mp)
 
 	ip6f->ip6f_uses++;
 
+	KERNEL_LOCK(1, NULL);
 	/* Send on its way - straight to the interface output routine. */
 	if ((error = (*rt->rt_ifp->if_output)(rt->rt_ifp, m, dst, rt)) != 0) {
 		ip6f->ip6f_dropped++;
 	} else {
 		ip6f->ip6f_forwarded++;
 	}
-
+	KERNEL_UNLOCK_ONE(NULL);
 	return 1;
 }
 

Index: src/sys/netinet6/ip6_forward.c
diff -u src/sys/netinet6/ip6_forward.c:1.72 src/sys/netinet6/ip6_forward.c:1.72.4.1
--- src/sys/netinet6/ip6_forward.c:1.72	Sat Jun 29 21:06:58 2013
+++ src/sys/netinet6/ip6_forward.c	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip6_forward.c,v 1.72 2013/06/29 21:06:58 rmind Exp $	*/
+/*	$NetBSD: ip6_forward.c,v 1.72.4.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: ip6_forward.c,v 1.109 2002/09/11 08:10:17 sakane Exp $	*/
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip6_forward.c,v 1.72 2013/06/29 21:06:58 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip6_forward.c,v 1.72.4.1 2014/08/10 06:56:30 tls Exp $");
 
 #include "opt_gateway.h"
 #include "opt_ipsec.h"
@@ -100,9 +100,8 @@ ip6_forward(struct mbuf *m, int srcrt)
 	u_int32_t inzone, outzone;
 	struct in6_addr src_in6, dst_in6;
 #ifdef IPSEC
-	struct secpolicy *sp = NULL;
 	int needipsec = 0;
-	int s;
+	struct secpolicy *sp = NULL;
 #endif
 
 	/*
@@ -155,19 +154,21 @@ ip6_forward(struct mbuf *m, int srcrt)
 	mcopy = m_copy(m, 0, imin(m->m_pkthdr.len, ICMPV6_PLD_MAXLEN));
 
 #ifdef IPSEC
-	/* Check the security policy (SP) for the packet */
+	if (ipsec_used) {
+		/* Check the security policy (SP) for the packet */
 
-	sp = ipsec6_check_policy(m,NULL,0,&needipsec,&error);
-	if (error != 0) {
-		/*
-		 * Hack: -EINVAL is used to signal that a packet
-		 * should be silently discarded.  This is typically
-		 * because we asked key management for an SA and
-		 * it was delayed (e.g. kicked up to IKE).
-		 */
-	if (error == -EINVAL)
-		error = 0;
-	goto freecopy;
+		sp = ipsec6_check_policy(m, NULL, 0, &needipsec, &error);
+		if (error != 0) {
+			/*
+			 * Hack: -EINVAL is used to signal that a packet
+			 * should be silently discarded.  This is typically
+			 * because we asked key management for an SA and
+			 * it was delayed (e.g. kicked up to IKE).
+			 */
+			if (error == -EINVAL)
+				error = 0;
+			goto freecopy;
+		}
 	}
 #endif /* IPSEC */
 
@@ -261,8 +262,8 @@ ip6_forward(struct mbuf *m, int srcrt)
 	 * ipsec6_proces_packet will send the packet using ip6_output 
 	 */
 	if (needipsec) {
-		s = splsoftnet();
-		error = ipsec6_process_packet(m,sp->req);
+		int s = splsoftnet();
+		error = ipsec6_process_packet(m, sp->req);
 		splx(s);
 		if (mcopy)
 			goto freecopy;

Index: src/sys/netinet6/ip6_input.c
diff -u src/sys/netinet6/ip6_input.c:1.145 src/sys/netinet6/ip6_input.c:1.145.2.1
--- src/sys/netinet6/ip6_input.c:1.145	Tue Feb 25 18:30:12 2014
+++ src/sys/netinet6/ip6_input.c	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip6_input.c,v 1.145 2014/02/25 18:30:12 pooka Exp $	*/
+/*	$NetBSD: ip6_input.c,v 1.145.2.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $	*/
 
 /*
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.145 2014/02/25 18:30:12 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.145.2.1 2014/08/10 06:56:30 tls Exp $");
 
 #include "opt_gateway.h"
 #include "opt_inet.h"
@@ -90,13 +90,14 @@ __KERNEL_RCSID(0, "$NetBSD: ip6_input.c,
 #include <net/if_types.h>
 #include <net/if_dl.h>
 #include <net/route.h>
-#include <net/netisr.h>
+#include <net/pktqueue.h>
 #include <net/pfil.h>
 
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
 #ifdef INET
 #include <netinet/ip.h>
+#include <netinet/ip_var.h>
 #include <netinet/ip_icmp.h>
 #endif /* INET */
 #include <netinet/ip6.h>
@@ -135,9 +136,8 @@ __KERNEL_RCSID(0, "$NetBSD: ip6_input.c,
 extern struct domain inet6domain;
 
 u_char ip6_protox[IPPROTO_MAX];
-static int ip6qmaxlen = IFQ_MAXLEN;
 struct in6_ifaddr *in6_ifaddr;
-struct ifqueue ip6intrq;
+pktqueue_t *ip6_pktq __read_mostly;
 
 extern callout_t in6_tmpaddrtimer_ch;
 
@@ -150,6 +150,7 @@ pfil_head_t *inet6_pfil_hook;
 percpu_t *ip6stat_percpu;
 
 static void ip6_init2(void *);
+static void ip6intr(void *);
 static struct m_tag *ip6_setdstifaddr(struct mbuf *, const struct in6_ifaddr *);
 
 static int ip6_process_hopopts(struct mbuf *, u_int8_t *, int, u_int32_t *,
@@ -178,7 +179,10 @@ ip6_init(void)
 		if (pr->pr_domain->dom_family == PF_INET6 &&
 		    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
 			ip6_protox[pr->pr_protocol] = pr - inet6sw;
-	ip6intrq.ifq_maxlen = ip6qmaxlen;
+
+	ip6_pktq = pktq_create(IFQ_MAXLEN, ip6intr, NULL);
+	KASSERT(ip6_pktq != NULL);
+
 	scope6_init();
 	addrsel_policy_init();
 	nd6_init();
@@ -215,28 +219,24 @@ ip6_init2(void *dummy)
 /*
  * IP6 input interrupt handling. Just pass the packet to ip6_input.
  */
-void
-ip6intr(void)
+static void
+ip6intr(void *arg __unused)
 {
-	int s;
 	struct mbuf *m;
 
 	mutex_enter(softnet_lock);
-	KERNEL_LOCK(1, NULL);
-	for (;;) {
-		s = splnet();
-		IF_DEQUEUE(&ip6intrq, m);
-		splx(s);
-		if (m == 0)
-			break;
-		/* drop the packet if IPv6 operation is disabled on the IF */
-		if ((ND_IFINFO(m->m_pkthdr.rcvif)->flags & ND6_IFF_IFDISABLED)) {
+	while ((m = pktq_dequeue(ip6_pktq)) != NULL) {
+		const ifnet_t *ifp = m->m_pkthdr.rcvif;
+
+		/*
+		 * Drop the packet if IPv6 is disabled on the interface.
+		 */
+		if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)) {
 			m_freem(m);
-			break;
+			continue;
 		}
 		ip6_input(m);
 	}
-	KERNEL_UNLOCK_ONE(NULL);
 	mutex_exit(softnet_lock);
 }
 
@@ -257,12 +257,6 @@ ip6_input(struct mbuf *m)
 		struct sockaddr		dst;
 		struct sockaddr_in6	dst6;
 	} u;
-#ifdef IPSEC
-	struct m_tag *mtag;
-	struct tdb_ident *tdbi;
-	struct secpolicy *sp;
-	int s, error;
-#endif
 
 	/*
 	 * make sure we don't have onion peering information into m_tag.
@@ -345,7 +339,7 @@ ip6_input(struct mbuf *m)
 	 * not the decapsulated packet.
 	 */
 #if defined(IPSEC)
-	if (!ipsec_indone(m))
+	if (!ipsec_used || !ipsec_indone(m))
 #else
 	if (1)
 #endif
@@ -753,45 +747,58 @@ ip6_input(struct mbuf *m)
 		}
 
 #ifdef IPSEC
-	/*
-	 * enforce IPsec policy checking if we are seeing last 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 & PR_LASTHDR) != 0) {
-		/*
-		 * Check if the packet has already had IPsec processing
-		 * done.  If so, then just pass it along.  This tag gets
-		 * set during AH, ESP, etc. input handling, before the
-		 * packet is returned to the ip input queue for delivery.
-		 */
-		mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL);
-		s = splsoftnet();
-		if (mtag != NULL) {
-			tdbi = (struct tdb_ident *)(mtag + 1);
-			sp = ipsec_getpolicy(tdbi, IPSEC_DIR_INBOUND);
-		} else {
-			sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND,
-									IP_FORWARDING, &error);
-		}
-		if (sp != NULL) {
+		if (ipsec_used) {
+			struct m_tag *mtag;
+			struct tdb_ident *tdbi;
+			struct secpolicy *sp;
+			int s, error;
+
 			/*
-			 * Check security policy against packet attributes.
+			 * enforce IPsec policy checking if we are seeing last
+			 * header. note that we do not visit this with
+			 * protocols with pcb layer code - like udp/tcp/raw ip.
 			 */
-			error = ipsec_in_reject(sp, m);
-			KEY_FREESP(&sp);
-		} else {
-			/* XXX error stat??? */
-			error = EINVAL;
-			DPRINTF(("ip6_input: no SP, packet discarded\n"));/*XXX*/
+			if ((inet6sw[ip_protox[nxt]].pr_flags
+			    & PR_LASTHDR) != 0) {
+				/*
+				 * Check if the packet has already had IPsec
+				 * processing done. If so, then just pass it
+				 * along. This tag gets set during AH, ESP,
+				 * etc. input handling, before the packet is
+				 * returned to the ip input queue for delivery.
+				 */
+				mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE,
+				    NULL);
+				s = splsoftnet();
+				if (mtag != NULL) {
+					tdbi = (struct tdb_ident *)(mtag + 1);
+					sp = ipsec_getpolicy(tdbi,
+					    IPSEC_DIR_INBOUND);
+				} else {
+					sp = ipsec_getpolicybyaddr(m,
+					    IPSEC_DIR_INBOUND, IP_FORWARDING,
+					    &error);
+				}
+				if (sp != NULL) {
+					/*
+					 * Check security policy against packet
+					 * attributes.
+					 */
+					error = ipsec_in_reject(sp, m);
+					KEY_FREESP(&sp);
+				} else {
+					/* XXX error stat??? */
+					error = EINVAL;
+					DPRINTF(("ip6_input: no SP, packet"
+					    " discarded\n"));/*XXX*/
+				}
+				splx(s);
+				if (error)
+					goto bad;
+			}
 		}
-		splx(s);
-		if (error)
-			goto bad;
-	}
 #endif /* IPSEC */
 
-
 		nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
 	}
 	return;
@@ -1847,6 +1854,15 @@ sysctl_net_inet6_ip6_setup(struct sysctl
 		       IPV6CTL_V6ONLY, CTL_EOL);
 	sysctl_createv(clog, 0, NULL, NULL,
 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+		       CTLTYPE_INT, "auto_linklocal",
+		       SYSCTL_DESCR("Default value of per-interface flag for "
+		                    "adding an IPv6 link-local address to "
+				    "interfaces when attached"),
+		       NULL, 0, &ip6_auto_linklocal, 0,
+		       CTL_NET, PF_INET6, IPPROTO_IPV6,
+		       IPV6CTL_AUTO_LINKLOCAL, CTL_EOL);
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 		       CTLTYPE_INT, "anonportmin",
 		       SYSCTL_DESCR("Lowest ephemeral port number to assign"),
 		       sysctl_net_inet_ip_ports, 0, &ip6_anonportmin, 0,

Index: src/sys/netinet6/ip6_mroute.c
diff -u src/sys/netinet6/ip6_mroute.c:1.106 src/sys/netinet6/ip6_mroute.c:1.106.2.1
--- src/sys/netinet6/ip6_mroute.c:1.106	Tue Feb 25 18:30:12 2014
+++ src/sys/netinet6/ip6_mroute.c	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip6_mroute.c,v 1.106 2014/02/25 18:30:12 pooka Exp $	*/
+/*	$NetBSD: ip6_mroute.c,v 1.106.2.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: ip6_mroute.c,v 1.49 2001/07/25 09:21:18 jinmei Exp $	*/
 
 /*
@@ -117,7 +117,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip6_mroute.c,v 1.106 2014/02/25 18:30:12 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip6_mroute.c,v 1.106.2.1 2014/08/10 06:56:30 tls Exp $");
 
 #include "opt_inet.h"
 #include "opt_mrouting.h"
@@ -658,13 +658,7 @@ add_m6if(struct mif6ctl *mifcp)
 	mifp = mif6table + mifcp->mif6c_mifi;
 	if (mifp->m6_ifp)
 		return EADDRINUSE; /* XXX: is it appropriate? */
-	if (mifcp->mif6c_pifi == 0 || mifcp->mif6c_pifi >= if_indexlim)
-		return ENXIO;
-	/*
-	 * XXX: some OSes can remove ifp and clear ifindex2ifnet[id]
-	 * even for id between 0 and if_index.
-	 */
-	if ((ifp = ifindex2ifnet[mifcp->mif6c_pifi]) == NULL)
+	if (!mifcp->mif6c_pifi || (ifp = if_byindex(mifcp->mif6c_pifi)) == NULL)
 		return ENXIO;
 
 	if (mifcp->mif6c_flags & MIFF_REGISTER) {

Index: src/sys/netinet6/ip6_output.c
diff -u src/sys/netinet6/ip6_output.c:1.155 src/sys/netinet6/ip6_output.c:1.155.2.1
--- src/sys/netinet6/ip6_output.c:1.155	Thu Oct  3 20:27:55 2013
+++ src/sys/netinet6/ip6_output.c	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip6_output.c,v 1.155 2013/10/03 20:27:55 christos Exp $	*/
+/*	$NetBSD: ip6_output.c,v 1.155.2.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $	*/
 
 /*
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.155 2013/10/03 20:27:55 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.155.2.1 2014/08/10 06:56:30 tls Exp $");
 
 #include "opt_inet.h"
 #include "opt_inet6.h"
@@ -181,7 +181,6 @@ ip6_output(
 	int needipsec = 0;
 #ifdef IPSEC
 	struct secpolicy *sp = NULL;
-	int s;
 #endif
 
 	memset(&ip6route, 0, sizeof(ip6route));
@@ -241,20 +240,22 @@ ip6_output(
 	if (exthdrs.ip6e_dest2) optlen += exthdrs.ip6e_dest2->m_len;
 
 #ifdef IPSEC
-	/* Check the security policy (SP) for the packet */
-    
-	sp = ipsec6_check_policy(m,so,flags,&needipsec,&error);
-	if (error != 0) {
-		/*
-		 * Hack: -EINVAL is used to signal that a packet
-		 * should be silently discarded.  This is typically
-		 * because we asked key management for an SA and
-		 * it was delayed (e.g. kicked up to IKE).
-		 */
-	if (error == -EINVAL) 
-		error = 0;
-	goto freehdrs;
-    }
+	if (ipsec_used) {
+		/* Check the security policy (SP) for the packet */
+	    
+		sp = ipsec6_check_policy(m, so, flags, &needipsec, &error);
+		if (error != 0) {
+			/*
+			 * Hack: -EINVAL is used to signal that a packet
+			 * should be silently discarded.  This is typically
+			 * because we asked key management for an SA and
+			 * it was delayed (e.g. kicked up to IKE).
+			 */
+			if (error == -EINVAL) 
+				error = 0;
+			goto freehdrs;
+		}
+	}
 #endif /* IPSEC */
 
 
@@ -464,8 +465,8 @@ ip6_output(
 
 #ifdef IPSEC
 	if (needipsec) {
-		s = splsoftnet();
-		error = ipsec6_process_packet(m,sp->req);
+		int s = splsoftnet();
+		error = ipsec6_process_packet(m, sp->req);
 
 		/*
 		 * Preserve KAME behaviour: ENOENT can be returned
@@ -480,8 +481,6 @@ ip6_output(
 	}
 #endif /* IPSEC */    
 
-
-
 	/* adjust pointer */
 	ip6 = mtod(m, struct ip6_hdr *);
 
@@ -1652,9 +1651,13 @@ else 					\
 
 #if defined(IPSEC)
 		case IPV6_IPSEC_POLICY:
-			error = ipsec6_set_policy(in6p, optname,
-			    sopt->sopt_data, sopt->sopt_size, kauth_cred_get());
-			break;
+			if (ipsec_enabled) {
+				error = ipsec6_set_policy(in6p, optname,
+				    sopt->sopt_data, sopt->sopt_size,
+				    kauth_cred_get());
+				break;
+			}
+			/*FALLTHROUGH*/
 #endif /* IPSEC */
 
 		default:
@@ -1841,17 +1844,20 @@ else 					\
 
 #if defined(IPSEC)
 		case IPV6_IPSEC_POLICY:
-		    {
-			struct mbuf *m = NULL;
-
-			/* XXX this will return EINVAL as sopt is empty */
-			error = ipsec6_get_policy(in6p, sopt->sopt_data,
-			    sopt->sopt_size, &m);
-			if (!error)
-				error = sockopt_setmbuf(sopt, m);
+			if (ipsec_used) {
+				struct mbuf *m = NULL;
 
-			break;
-		    }
+				/*
+				 * XXX: this will return EINVAL as sopt is
+				 * empty
+				 */
+				error = ipsec6_get_policy(in6p, sopt->sopt_data,
+				    sopt->sopt_size, &m);
+				if (!error)
+					error = sockopt_setmbuf(sopt, m);
+				break;
+			}
+			/*FALLTHROUGH*/
 #endif /* IPSEC */
 
 		default:
@@ -2277,11 +2283,10 @@ ip6_setmoptions(const struct sockopt *so
 			break;
 
 		if (ifindex != 0) {
-			if (if_indexlim <= ifindex || !ifindex2ifnet[ifindex]) {
+			if ((ifp = if_byindex(ifindex)) == NULL) {
 				error = ENXIO;	/* XXX EINVAL? */
 				break;
 			}
-			ifp = ifindex2ifnet[ifindex];
 			if ((ifp->if_flags & IFF_MULTICAST) == 0) {
 				error = EADDRNOTAVAIL;
 				break;
@@ -2379,12 +2384,10 @@ ip6_setmoptions(const struct sockopt *so
 			/*
 			 * If the interface is specified, validate it.
 			 */
-			if (if_indexlim <= mreq.ipv6mr_interface ||
-			    !ifindex2ifnet[mreq.ipv6mr_interface]) {
+			if ((ifp = if_byindex(mreq.ipv6mr_interface)) == NULL) {
 				error = ENXIO;	/* XXX EINVAL? */
 				break;
 			}
-			ifp = ifindex2ifnet[mreq.ipv6mr_interface];
 		}
 
 		/*
@@ -2438,12 +2441,10 @@ ip6_setmoptions(const struct sockopt *so
 		 * to its ifnet structure.
 		 */
 		if (mreq.ipv6mr_interface != 0) {
-			if (if_indexlim <= mreq.ipv6mr_interface ||
-			    !ifindex2ifnet[mreq.ipv6mr_interface]) {
+			if ((ifp = if_byindex(mreq.ipv6mr_interface)) == NULL) {
 				error = ENXIO;	/* XXX EINVAL? */
 				break;
 			}
-			ifp = ifindex2ifnet[mreq.ipv6mr_interface];
 		} else
 			ifp = NULL;
 
@@ -2737,12 +2738,9 @@ ip6_setpktopt(int optname, u_char *buf, 
 			return (EINVAL);
 		}
 
-		/* validate the interface index if specified. */
-		if (pktinfo->ipi6_ifindex >= if_indexlim) {
-			 return (ENXIO);
-		}
+		/* Validate the interface index if specified. */
 		if (pktinfo->ipi6_ifindex) {
-			ifp = ifindex2ifnet[pktinfo->ipi6_ifindex];
+			ifp = if_byindex(pktinfo->ipi6_ifindex);
 			if (ifp == NULL)
 				return (ENXIO);
 		}

Index: src/sys/netinet6/ip6_var.h
diff -u src/sys/netinet6/ip6_var.h:1.59 src/sys/netinet6/ip6_var.h:1.59.12.1
--- src/sys/netinet6/ip6_var.h:1.59	Sat Jun 23 03:14:04 2012
+++ src/sys/netinet6/ip6_var.h	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip6_var.h,v 1.59 2012/06/23 03:14:04 christos Exp $	*/
+/*	$NetBSD: ip6_var.h,v 1.59.12.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $	*/
 
 /*
@@ -312,11 +312,11 @@ extern int	ip6_hashsize;		/* size of has
 #endif
 
 struct in6pcb;
+extern const struct pr_usrreqs rip6_usrreqs;
 
 int	icmp6_ctloutput(int, struct socket *, struct sockopt *);
 
 void	ip6_init(void);
-void	ip6intr(void);
 void	ip6_input(struct mbuf *);
 const struct ip6aux *ip6_getdstifaddr(struct mbuf *);
 void	ip6_freepcbopts(struct ip6_pktopts *);
@@ -380,6 +380,7 @@ void	*rip6_ctlinput(int, const struct so
 int	rip6_ctloutput(int, struct socket *, struct sockopt *);
 int	rip6_output(struct mbuf *, struct socket *, struct sockaddr_in6 *,
 			 struct mbuf *);
+int	rip6_attach(struct socket *, int);
 int	rip6_usrreq(struct socket *,
 	    int, struct mbuf *, struct mbuf *, struct mbuf *, struct lwp *);
 

Index: src/sys/netinet6/ip6protosw.h
diff -u src/sys/netinet6/ip6protosw.h:1.21 src/sys/netinet6/ip6protosw.h:1.21.54.1
--- src/sys/netinet6/ip6protosw.h:1.21	Wed Aug  6 15:01:23 2008
+++ src/sys/netinet6/ip6protosw.h	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip6protosw.h,v 1.21 2008/08/06 15:01:23 plunky Exp $	*/
+/*	$NetBSD: ip6protosw.h,v 1.21.54.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: ip6protosw.h,v 1.22 2001/02/08 18:02:08 itojun Exp $	*/
 
 /*
@@ -129,9 +129,7 @@ struct ip6protosw {
 			(int, struct socket *, struct sockopt *);
 
 /* user-protocol hook */
-	int	(*pr_usrreq)		/* user request: see list below */
-			(struct socket *, int, struct mbuf *,
-			     struct mbuf *, struct mbuf *, struct lwp *);
+	const struct pr_usrreqs *pr_usrreqs;
 
 /* utility hooks */
 	void	(*pr_init)		/* initialization hook */

Index: src/sys/netinet6/mld6.c
diff -u src/sys/netinet6/mld6.c:1.55 src/sys/netinet6/mld6.c:1.55.22.1
--- src/sys/netinet6/mld6.c:1.55	Sat Nov 19 22:51:29 2011
+++ src/sys/netinet6/mld6.c	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: mld6.c,v 1.55 2011/11/19 22:51:29 tls Exp $	*/
+/*	$NetBSD: mld6.c,v 1.55.22.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: mld6.c,v 1.25 2001/01/16 14:14:18 itojun Exp $	*/
 
 /*
@@ -102,7 +102,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.55 2011/11/19 22:51:29 tls Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.55.22.1 2014/08/10 06:56:30 tls Exp $");
 
 #include "opt_inet.h"
 
@@ -137,7 +137,7 @@ __KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.5
  * This structure is used to keep track of in6_multi chains which belong to
  * deleted interface addresses.
  */
-static LIST_HEAD(, multi6_kludge) in6_mk; /* XXX BSS initialization */
+static LIST_HEAD(, multi6_kludge) in6_mk = LIST_HEAD_INITIALIZER(in6_mk);
 
 struct multi6_kludge {
 	LIST_ENTRY(multi6_kludge) mk_entry;
@@ -897,3 +897,152 @@ in6_purgemkludge(struct ifnet *ifp)
 	LIST_REMOVE(mk, mk_entry);
 	free(mk, M_IPMADDR);
 }
+
+static int
+in6_mkludge_sysctl(SYSCTLFN_ARGS)
+{
+	struct multi6_kludge *mk;
+	struct in6_multi *in6m;
+	int error;
+	uint32_t tmp;
+	size_t written;
+
+	if (namelen != 1)
+		return EINVAL;
+
+	if (oldp == NULL) {
+		*oldlenp = 0;
+		LIST_FOREACH(mk, &in6_mk, mk_entry) {
+			if (mk->mk_ifp->if_index == name[0])
+				continue;
+			LIST_FOREACH(in6m, &mk->mk_head, in6m_entry) {
+				*oldlenp += sizeof(struct in6_addr) +
+				    sizeof(uint32_t);
+			}
+		}
+		return 0;
+	}
+
+	error = 0;
+	written = 0;
+	LIST_FOREACH(mk, &in6_mk, mk_entry) {
+		if (mk->mk_ifp->if_index == name[0])
+			continue;
+		LIST_FOREACH(in6m, &mk->mk_head, in6m_entry) {
+			if (written + sizeof(struct in6_addr) +
+			    sizeof(uint32_t) > *oldlenp)
+				goto done;
+			error = sysctl_copyout(l, &in6m->in6m_addr,
+			    oldp, sizeof(struct in6_addr));
+			if (error)
+				goto done;
+			oldp = (char *)oldp + sizeof(struct in6_addr);
+			written += sizeof(struct in6_addr);
+			tmp = in6m->in6m_refcount;
+			error = sysctl_copyout(l, &tmp, oldp, sizeof(tmp));
+			if (error)
+				goto done;
+			oldp = (char *)oldp + sizeof(tmp);
+			written += sizeof(tmp);
+		}
+	}
+
+done:
+	*oldlenp = written;
+	return error;
+}
+
+static int
+in6_multicast_sysctl(SYSCTLFN_ARGS)
+{
+	struct ifnet *ifp;
+	struct ifaddr *ifa;
+	struct in6_ifaddr *ifa6;
+	struct in6_multi *in6m;
+	uint32_t tmp;
+	int error;
+	size_t written;
+
+	if (namelen != 1)
+		return EINVAL;
+
+	ifp = if_byindex(name[0]);
+	if (ifp == NULL)
+		return ENODEV;
+
+	if (oldp == NULL) {
+		*oldlenp = 0;
+		IFADDR_FOREACH(ifa, ifp) {
+			if (ifa->ifa_addr == NULL)
+				continue;
+			if (ifa->ifa_addr->sa_family != AF_INET6)
+				continue;
+			ifa6 = (struct in6_ifaddr *)ifa;
+			LIST_FOREACH(in6m, &ifa6->ia6_multiaddrs, in6m_entry) {
+				*oldlenp += 2 * sizeof(struct in6_addr) +
+				    sizeof(uint32_t);
+			}
+		}
+		return 0;
+	}
+
+	error = 0;
+	written = 0;
+	IFADDR_FOREACH(ifa, ifp) {
+		if (ifa->ifa_addr == NULL)
+			continue;
+		if (ifa->ifa_addr->sa_family != AF_INET6)
+			continue;
+		ifa6 = (struct in6_ifaddr *)ifa;
+		LIST_FOREACH(in6m, &ifa6->ia6_multiaddrs, in6m_entry) {
+			if (written + 2 * sizeof(struct in6_addr) +
+			    sizeof(uint32_t) > *oldlenp)
+				goto done;
+			error = sysctl_copyout(l, &ifa6->ia_addr.sin6_addr,
+			    oldp, sizeof(struct in6_addr));
+			if (error)
+				goto done;
+			oldp = (char *)oldp + sizeof(struct in6_addr);
+			written += sizeof(struct in6_addr);
+			error = sysctl_copyout(l, &in6m->in6m_addr,
+			    oldp, sizeof(struct in6_addr));
+			if (error)
+				goto done;
+			oldp = (char *)oldp + sizeof(struct in6_addr);
+			written += sizeof(struct in6_addr);
+			tmp = in6m->in6m_refcount;
+			error = sysctl_copyout(l, &tmp, oldp, sizeof(tmp));
+			if (error)
+				goto done;
+			oldp = (char *)oldp + sizeof(tmp);
+			written += sizeof(tmp);
+		}
+	}
+done:
+	*oldlenp = written;
+	return error;
+}
+
+SYSCTL_SETUP(sysctl_in6_mklude_setup, "sysctl net.inet6.multicast_kludge subtree setup")
+{
+
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_NODE, "inet6", NULL,
+		       NULL, 0, NULL, 0,
+		       CTL_NET, PF_INET6, CTL_EOL);
+
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_NODE, "multicast",
+		       SYSCTL_DESCR("Multicast information"),
+		       in6_multicast_sysctl, 0, NULL, 0,
+		       CTL_NET, PF_INET6, CTL_CREATE, CTL_EOL);
+
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_NODE, "multicast_kludge",
+		       SYSCTL_DESCR("multicast kludge information"),
+		       in6_mkludge_sysctl, 0, NULL, 0,
+		       CTL_NET, PF_INET6, CTL_CREATE, CTL_EOL);
+}

Index: src/sys/netinet6/nd6.c
diff -u src/sys/netinet6/nd6.c:1.148 src/sys/netinet6/nd6.c:1.148.2.1
--- src/sys/netinet6/nd6.c:1.148	Thu Mar 20 13:34:35 2014
+++ src/sys/netinet6/nd6.c	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: nd6.c,v 1.148 2014/03/20 13:34:35 roy Exp $	*/
+/*	$NetBSD: nd6.c,v 1.148.2.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $	*/
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.148 2014/03/20 13:34:35 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.148.2.1 2014/08/10 06:56:30 tls Exp $");
 
 #include "opt_ipsec.h"
 
@@ -66,6 +66,7 @@ __KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.14
 #include <netinet6/ip6_var.h>
 #include <netinet6/scope6_var.h>
 #include <netinet6/nd6.h>
+#include <netinet6/in6_ifattach.h>
 #include <netinet/icmp6.h>
 #include <netinet6/icmp6_private.h>
 
@@ -177,13 +178,24 @@ nd6_ifattach(struct ifnet *ifp)
 	nd->basereachable = REACHABLE_TIME;
 	nd->reachable = ND_COMPUTE_RTIME(nd->basereachable);
 	nd->retrans = RETRANS_TIMER;
-	/*
-	 * Note that the default value of ip6_accept_rtadv is 0.
-	 * Because we do not set ND6_IFF_OVERRIDE_RTADV here, we won't
-	 * accept RAs by default.
-	 */
+
 	nd->flags = ND6_IFF_PERFORMNUD | ND6_IFF_ACCEPT_RTADV;
 
+	/* A loopback interface always has ND6_IFF_AUTO_LINKLOCAL.
+	 * A bridge interface should not have ND6_IFF_AUTO_LINKLOCAL
+	 * because one of it's members should. */
+	if ((ip6_auto_linklocal && ifp->if_type != IFT_BRIDGE) ||
+	    (ifp->if_flags & IFF_LOOPBACK))
+		nd->flags |= ND6_IFF_AUTO_LINKLOCAL;
+
+	/* A loopback interface does not need to accept RTADV.
+	 * A bridge interface should not accept RTADV
+	 * because one of it's members should. */
+	if (ip6_accept_rtadv &&
+	    !(ifp->if_flags & IFF_LOOPBACK) &&
+	    !(ifp->if_type != IFT_BRIDGE))
+		nd->flags |= ND6_IFF_ACCEPT_RTADV;
+
 	/* XXX: we cannot call nd6_setmtu since ifp is not fully initialized */
 	nd6_setmtu0(ifp, nd);
 
@@ -835,7 +847,7 @@ nd6_lookup1(const struct in6_addr *addr6
 		 * interface route.
 		 */
 		if (create) {
-			RTFREE(rt);
+			rtfree(rt);
 			rt = NULL;
 		}
 	}
@@ -1698,8 +1710,38 @@ nd6_ioctl(u_long cmd, void *data, struct
 				ia->ia6_flags |= IN6_IFF_TENTATIVE;
 			}
 		}
-	}
 
+		if (ND.flags & ND6_IFF_AUTO_LINKLOCAL) {
+			if (!(ND_IFINFO(ifp)->flags & ND6_IFF_AUTO_LINKLOCAL)) {
+				/* auto_linklocal 0->1 transition */
+
+				ND_IFINFO(ifp)->flags |= ND6_IFF_AUTO_LINKLOCAL;
+				in6_ifattach(ifp, NULL);
+			} else if (!(ND.flags & ND6_IFF_IFDISABLED) &&
+			    ifp->if_flags & IFF_UP)
+			{
+				/*
+				 * When the IF already has
+				 * ND6_IFF_AUTO_LINKLOCAL, no link-local
+				 * address is assigned, and IFF_UP, try to
+				 * assign one.
+				 */
+				 int haslinklocal = 0;
+
+				 IFADDR_FOREACH(ifa, ifp) {
+					if (ifa->ifa_addr->sa_family !=AF_INET6)
+						continue;
+					ia = (struct in6_ifaddr *)ifa;
+					if (IN6_IS_ADDR_LINKLOCAL(IA6_IN6(ia))){
+						haslinklocal = 1;
+						break;
+					}
+				 }
+				 if (!haslinklocal)
+					in6_ifattach(ifp, NULL);
+			}
+		}
+	}
 		ND_IFINFO(ifp)->flags = ND.flags;
 		break;
 #undef ND
@@ -2047,7 +2089,7 @@ nd6_slowtimo(void *ignored_arg)
 	KERNEL_LOCK(1, NULL);
       	callout_reset(&nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz,
 	    nd6_slowtimo, NULL);
-	TAILQ_FOREACH(ifp, &ifnet, if_list) {
+	IFNET_FOREACH(ifp) {
 		nd6if = ND_IFINFO(ifp);
 		if (nd6if->basereachable && /* already initialized */
 		    (nd6if->recalctm -= ND6_SLOWTIMER_INTERVAL) <= 0) {
@@ -2257,9 +2299,13 @@ nd6_output(struct ifnet *ifp, struct ifn
 		goto bad;
 	}
 
+	KERNEL_LOCK(1, NULL);
 	if ((ifp->if_flags & IFF_LOOPBACK) != 0)
-		return (*ifp->if_output)(origifp, m, sin6tocsa(dst), rt);
-	return (*ifp->if_output)(ifp, m, sin6tocsa(dst), rt);
+		error = (*ifp->if_output)(origifp, m, sin6tocsa(dst), rt);
+	else
+		error = (*ifp->if_output)(ifp, m, sin6tocsa(dst), rt);
+	KERNEL_UNLOCK_ONE(NULL);
+	return error;
 
   bad:
 	if (m != NULL)

Index: src/sys/netinet6/nd6.h
diff -u src/sys/netinet6/nd6.h:1.58 src/sys/netinet6/nd6.h:1.58.6.1
--- src/sys/netinet6/nd6.h:1.58	Tue May 21 08:37:27 2013
+++ src/sys/netinet6/nd6.h	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: nd6.h,v 1.58 2013/05/21 08:37:27 roy Exp $	*/
+/*	$NetBSD: nd6.h,v 1.58.6.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $	*/
 
 /*
@@ -93,6 +93,7 @@ struct nd_ifinfo {
 					 * DAD failure.  (XXX: not ND-specific)
 					 */
 #define	ND6_IFF_OVERRIDE_RTADV	0x10	/* See "RTADV Key", below. */
+#define	ND6_IFF_AUTO_LINKLOCAL	0x20
 
 /*
  * RTADV Key

Index: src/sys/netinet6/nd6_nbr.c
diff -u src/sys/netinet6/nd6_nbr.c:1.99 src/sys/netinet6/nd6_nbr.c:1.99.2.1
--- src/sys/netinet6/nd6_nbr.c:1.99	Mon Jan 13 18:23:36 2014
+++ src/sys/netinet6/nd6_nbr.c	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: nd6_nbr.c,v 1.99 2014/01/13 18:23:36 roy Exp $	*/
+/*	$NetBSD: nd6_nbr.c,v 1.99.2.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $	*/
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.99 2014/01/13 18:23:36 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.99.2.1 2014/08/10 06:56:30 tls Exp $");
 
 #include "opt_inet.h"
 #include "opt_ipsec.h"
@@ -1097,6 +1097,8 @@ nd6_newaddrmsg(struct ifaddr *ifa)
 /*
  * Start Duplicate Address Detection (DAD) for specified interface address.
  *
+ * Note that callout is used when xtick > 0 and not when xtick == 0.
+ *
  * xtick: minimum delay ticks for IFF_UP event
  */
 void

Index: src/sys/netinet6/nd6_rtr.c
diff -u src/sys/netinet6/nd6_rtr.c:1.90 src/sys/netinet6/nd6_rtr.c:1.90.2.1
--- src/sys/netinet6/nd6_rtr.c:1.90	Sat Sep 14 21:08:35 2013
+++ src/sys/netinet6/nd6_rtr.c	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: nd6_rtr.c,v 1.90 2013/09/14 21:08:35 martin Exp $	*/
+/*	$NetBSD: nd6_rtr.c,v 1.90.2.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: nd6_rtr.c,v 1.95 2001/02/07 08:09:47 itojun Exp $	*/
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.90 2013/09/14 21:08:35 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.90.2.1 2014/08/10 06:56:30 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -915,8 +915,7 @@ purge_detached(struct ifnet *ifp)
 		    !LIST_EMPTY(&pr->ndpr_advrtrs)))
 			continue;
 
-		for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa_next) {
-			ifa_next = ifa->ifa_list.tqe_next;
+		IFADDR_FOREACH_SAFE(ifa, ifp, ifa_next) {
 			if (ifa->ifa_addr->sa_family != AF_INET6)
 				continue;
 			ia = (struct in6_ifaddr *)ifa;
@@ -2162,19 +2161,15 @@ rt6_deleteroute(struct rtentry *rt, void
 int
 nd6_setdefaultiface(int ifindex)
 {
+	ifnet_t *ifp;
 	int error = 0;
 
-	if (ifindex < 0 || if_indexlim <= ifindex)
-		return (EINVAL);
-	if (ifindex != 0 && !ifindex2ifnet[ifindex])
-		return (EINVAL);
-
+	if ((ifp = if_byindex(ifindex)) == NULL) {
+		return EINVAL;
+	}
 	if (nd6_defifindex != ifindex) {
 		nd6_defifindex = ifindex;
-		if (nd6_defifindex > 0) {
-			nd6_defifp = ifindex2ifnet[nd6_defifindex];
-		} else
-			nd6_defifp = NULL;
+		nd6_defifp = nd6_defifindex > 0 ? ifp : NULL;
 
 		/*
 		 * Our current implementation assumes one-to-one maping between

Index: src/sys/netinet6/raw_ip6.c
diff -u src/sys/netinet6/raw_ip6.c:1.113 src/sys/netinet6/raw_ip6.c:1.113.2.1
--- src/sys/netinet6/raw_ip6.c:1.113	Tue Feb 25 18:30:12 2014
+++ src/sys/netinet6/raw_ip6.c	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: raw_ip6.c,v 1.113 2014/02/25 18:30:12 pooka Exp $	*/
+/*	$NetBSD: raw_ip6.c,v 1.113.2.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: raw_ip6.c,v 1.82 2001/07/23 18:57:56 jinmei Exp $	*/
 
 /*
@@ -62,21 +62,20 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: raw_ip6.c,v 1.113 2014/02/25 18:30:12 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: raw_ip6.c,v 1.113.2.1 2014/08/10 06:56:30 tls Exp $");
 
 #include "opt_ipsec.h"
 
 #include <sys/param.h>
 #include <sys/sysctl.h>
-#include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/socket.h>
 #include <sys/protosw.h>
 #include <sys/socketvar.h>
-#include <sys/errno.h>
 #include <sys/systm.h>
 #include <sys/proc.h>
 #include <sys/kauth.h>
+#include <sys/kmem.h>
 
 #include <net/if.h>
 #include <net/route.h>
@@ -205,7 +204,7 @@ rip6_input(struct mbuf **mp, int *offp, 
 			/*
 			 * Check AH/ESP integrity
 			 */
-			if (!ipsec6_in_reject(m,last)) 
+			if (ipsec_used && !ipsec6_in_reject(m, last)) 
 #endif /* IPSEC */
 			if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
 				if (last->in6p_flags & IN6P_CONTROLOPTS)
@@ -227,7 +226,7 @@ rip6_input(struct mbuf **mp, int *offp, 
 		last = in6p;
 	}
 #ifdef IPSEC
-	if (last && ipsec6_in_reject(m, last)) {
+	if (ipsec_used && last && ipsec6_in_reject(m, last)) {
 		m_freem(m);
 		/*
 		 * XXX ipsec6_in_reject update stat if there is an error
@@ -585,262 +584,380 @@ extern	u_long rip6_sendspace;
 extern	u_long rip6_recvspace;
 
 int
-rip6_usrreq(struct socket *so, int req, struct mbuf *m, 
-	struct mbuf *nam, struct mbuf *control, struct lwp *l)
+rip6_attach(struct socket *so, int proto)
 {
-	struct in6pcb *in6p = sotoin6pcb(so);
-	int s;
-	int error = 0;
+	struct in6pcb *in6p;
+	int s, error;
 
-	if (req == PRU_CONTROL)
-		return in6_control(so, (u_long)m, (void *)nam,
-		    (struct ifnet *)control, l);
-
-	if (req == PRU_PURGEIF) {
-		mutex_enter(softnet_lock);
-		in6_pcbpurgeif0(&raw6cbtable, (struct ifnet *)control);
-		in6_purgeif((struct ifnet *)control);
-		in6_pcbpurgeif(&raw6cbtable, (struct ifnet *)control);
-		mutex_exit(softnet_lock);
-		return 0;
-	}
-
-	switch (req) {
-	case PRU_ATTACH:
-		error = kauth_authorize_network(l->l_cred,
-		    KAUTH_NETWORK_SOCKET, KAUTH_REQ_NETWORK_SOCKET_RAWSOCK,
-		    KAUTH_ARG(AF_INET6),
-		    KAUTH_ARG(SOCK_RAW),
-		    KAUTH_ARG(so->so_proto->pr_protocol));
-		sosetlock(so);
-		if (in6p != NULL)
-			panic("rip6_attach");
-		if (error) {
-			break;
-		}
-		s = splsoftnet();
-		error = soreserve(so, rip6_sendspace, rip6_recvspace);
-		if (error != 0) {
-			splx(s);
-			break;
-		}
-		if ((error = in6_pcballoc(so, &raw6cbtable)) != 0) {
-			splx(s);
-			break;
-		}
-		splx(s);
-		in6p = sotoin6pcb(so);
-		in6p->in6p_ip6.ip6_nxt = (long)nam;
-		in6p->in6p_cksum = -1;
-
-		in6p->in6p_icmp6filt = malloc(sizeof(struct icmp6_filter),
-			M_PCB, M_NOWAIT);
-		if (in6p->in6p_icmp6filt == NULL) {
-			in6_pcbdetach(in6p);
-			error = ENOMEM;
-			break;
-		}
-		ICMP6_FILTER_SETPASSALL(in6p->in6p_icmp6filt);
-		break;
+	KASSERT(sotoin6pcb(so) == NULL);
+	sosetlock(so);
 
-	case PRU_DISCONNECT:
-		if ((so->so_state & SS_ISCONNECTED) == 0) {
-			error = ENOTCONN;
-			break;
-		}
-		in6p->in6p_faddr = in6addr_any;
-		so->so_state &= ~SS_ISCONNECTED;	/* XXX */
-		break;
+	error = kauth_authorize_network(curlwp->l_cred,
+	    KAUTH_NETWORK_SOCKET, KAUTH_REQ_NETWORK_SOCKET_RAWSOCK,
+	    KAUTH_ARG(AF_INET6),
+	    KAUTH_ARG(SOCK_RAW),
+	    KAUTH_ARG(so->so_proto->pr_protocol));
+	if (error) {
+		return error;
+	}
+	s = splsoftnet();
+	error = soreserve(so, rip6_sendspace, rip6_recvspace);
+	if (error) {
+		splx(s);
+		return error;
+	}
+	if ((error = in6_pcballoc(so, &raw6cbtable)) != 0) {
+		splx(s);
+		return error;
+	}
+	splx(s);
+	in6p = sotoin6pcb(so);
+	in6p->in6p_ip6.ip6_nxt = proto;
+	in6p->in6p_cksum = -1;
 
-	case PRU_ABORT:
-		soisdisconnected(so);
-		/* Fallthrough */
-	case PRU_DETACH:
-		if (in6p == NULL)
-			panic("rip6_detach");
-		if (so == ip6_mrouter)
-			ip6_mrouter_done();
-		/* xxx: RSVP */
-		if (in6p->in6p_icmp6filt != NULL) {
-			free(in6p->in6p_icmp6filt, M_PCB);
-			in6p->in6p_icmp6filt = NULL;
-		}
+	in6p->in6p_icmp6filt = kmem_alloc(sizeof(struct icmp6_filter), KM_SLEEP);
+	if (in6p->in6p_icmp6filt == NULL) {
 		in6_pcbdetach(in6p);
-		break;
+		return ENOMEM;
+	}
+	ICMP6_FILTER_SETPASSALL(in6p->in6p_icmp6filt);
+	KASSERT(solocked(so));
+	return error;
+}
 
-	case PRU_BIND:
-	    {
-		struct sockaddr_in6 *addr = mtod(nam, struct sockaddr_in6 *);
-		struct ifaddr *ia = NULL;
+static void
+rip6_detach(struct socket *so)
+{
+	struct in6pcb *in6p = sotoin6pcb(so);
 
-		if (nam->m_len != sizeof(*addr)) {
-			error = EINVAL;
-			break;
-		}
-		if (TAILQ_EMPTY(&ifnet) || addr->sin6_family != AF_INET6) {
-			error = EADDRNOTAVAIL;
-			break;
-		}
-		if ((error = sa6_embedscope(addr, ip6_use_defzone)) != 0)
-			break;
+	KASSERT(solocked(so));
+	KASSERT(in6p != NULL);
 
-		/*
-		 * we don't support mapped address here, it would confuse
-		 * users so reject it
-		 */
-		if (IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr)) {
-			error = EADDRNOTAVAIL;
-			break;
-		}
-		if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) &&
-		    (ia = ifa_ifwithaddr((struct sockaddr *)addr)) == 0) {
-			error = EADDRNOTAVAIL;
-			break;
-		}
-		if (ia && ((struct in6_ifaddr *)ia)->ia6_flags &
-		    (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|
-		     IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) {
-			error = EADDRNOTAVAIL;
-			break;
-		}
-		in6p->in6p_laddr = addr->sin6_addr;
-		break;
-	    }
+	if (so == ip6_mrouter) {
+		ip6_mrouter_done();
+	}
+	/* xxx: RSVP */
+	if (in6p->in6p_icmp6filt != NULL) {
+		kmem_free(in6p->in6p_icmp6filt, sizeof(struct icmp6_filter));
+		in6p->in6p_icmp6filt = NULL;
+	}
+	in6_pcbdetach(in6p);
+}
 
-	case PRU_CONNECT:
-	{
-		struct sockaddr_in6 *addr = mtod(nam, struct sockaddr_in6 *);
-		struct in6_addr *in6a = NULL;
-		struct ifnet *ifp = NULL;
-		int scope_ambiguous = 0;
+static int
+rip6_accept(struct socket *so, struct mbuf *nam)
+{
+	KASSERT(solocked(so));
 
-		if (nam->m_len != sizeof(*addr)) {
-			error = EINVAL;
-			break;
-		}
-		if (TAILQ_EMPTY(&ifnet)) {
-			error = EADDRNOTAVAIL;
-			break;
-		}
-		if (addr->sin6_family != AF_INET6) {
-			error = EAFNOSUPPORT;
-			break;
-		}
+	return EOPNOTSUPP;
+}
 
-		/*
-		 * Application should provide a proper zone ID or the use of
-		 * default zone IDs should be enabled.  Unfortunately, some
-		 * applications do not behave as it should, so we need a
-		 * workaround.  Even if an appropriate ID is not determined,
-		 * we'll see if we can determine the outgoing interface.  If we
-		 * can, determine the zone ID based on the interface below.
-		 */
-		if (addr->sin6_scope_id == 0 && !ip6_use_defzone)
-			scope_ambiguous = 1;
-		if ((error = sa6_embedscope(addr, ip6_use_defzone)) != 0)
-			return error;
+static int
+rip6_bind(struct socket *so, struct mbuf *nam, struct lwp *l)
+{
+	struct in6pcb *in6p = sotoin6pcb(so);
+	struct sockaddr_in6 *addr;
+	struct ifaddr *ia = NULL;
+	int error = 0;
 
-		/* Source address selection. XXX: need pcblookup? */
-		in6a = in6_selectsrc(addr, in6p->in6p_outputopts,
-		    in6p->in6p_moptions, &in6p->in6p_route,
-		    &in6p->in6p_laddr, &ifp, &error);
-		if (in6a == NULL) {
-			if (error == 0)
-				error = EADDRNOTAVAIL;
-			break;
-		}
-		/* XXX: see above */
-		if (ifp && scope_ambiguous &&
-		    (error = in6_setscope(&addr->sin6_addr, ifp, NULL)) != 0) {
-			break;
-		}
-		in6p->in6p_laddr = *in6a;
-		in6p->in6p_faddr = addr->sin6_addr;
-		soisconnected(so);
-		break;
+	KASSERT(solocked(so));
+	KASSERT(in6p != NULL);
+	KASSERT(nam != NULL);
+
+	addr = mtod(nam, struct sockaddr_in6 *);
+	if (nam->m_len != sizeof(*addr))
+		return EINVAL;
+	if (IFNET_EMPTY() || addr->sin6_family != AF_INET6)
+		return EADDRNOTAVAIL;
+
+	if ((error = sa6_embedscope(addr, ip6_use_defzone)) != 0)
+		return error;
+
+	/*
+	 * we don't support mapped address here, it would confuse
+	 * users so reject it
+	 */
+	if (IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr))
+		return EADDRNOTAVAIL;
+	if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) &&
+	    (ia = ifa_ifwithaddr((struct sockaddr *)addr)) == 0)
+		return EADDRNOTAVAIL;
+	if (ia && ((struct in6_ifaddr *)ia)->ia6_flags &
+	    (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|
+	     IN6_IFF_DETACHED|IN6_IFF_DEPRECATED))
+		return EADDRNOTAVAIL;
+	in6p->in6p_laddr = addr->sin6_addr;
+	return 0;
+}
+
+static int
+rip6_listen(struct socket *so, struct lwp *l)
+{
+	KASSERT(solocked(so));
+
+	return EOPNOTSUPP;
+}
+
+static int
+rip6_connect(struct socket *so, struct mbuf *nam, struct lwp *l)
+{
+	struct in6pcb *in6p = sotoin6pcb(so);
+	struct sockaddr_in6 *addr;
+	struct in6_addr *in6a = NULL;
+	struct ifnet *ifp = NULL;
+	int scope_ambiguous = 0;
+	int error = 0;
+
+	KASSERT(solocked(so));
+	KASSERT(in6p != NULL);
+	KASSERT(nam != NULL);
+
+	addr = mtod(nam, struct sockaddr_in6 *);
+
+	if (nam->m_len != sizeof(*addr))
+		return EINVAL;
+	if (IFNET_EMPTY())
+		return EADDRNOTAVAIL;
+	if (addr->sin6_family != AF_INET6)
+		return EAFNOSUPPORT;
+
+	/*
+	 * Application should provide a proper zone ID or the use of
+	 * default zone IDs should be enabled.  Unfortunately, some
+	 * applications do not behave as it should, so we need a
+	 * workaround.  Even if an appropriate ID is not determined,
+	 * we'll see if we can determine the outgoing interface.  If we
+	 * can, determine the zone ID based on the interface below.
+	 */
+	if (addr->sin6_scope_id == 0 && !ip6_use_defzone)
+		scope_ambiguous = 1;
+	if ((error = sa6_embedscope(addr, ip6_use_defzone)) != 0)
+		return error;
+
+	/* Source address selection. XXX: need pcblookup? */
+	in6a = in6_selectsrc(addr, in6p->in6p_outputopts,
+	    in6p->in6p_moptions, &in6p->in6p_route,
+	    &in6p->in6p_laddr, &ifp, &error);
+	if (in6a == NULL) {
+		if (error == 0)
+			return EADDRNOTAVAIL;
+		return error;
+	}
+	/* XXX: see above */
+	if (ifp && scope_ambiguous &&
+	    (error = in6_setscope(&addr->sin6_addr, ifp, NULL)) != 0) {
+		return error;
 	}
+	in6p->in6p_laddr = *in6a;
+	in6p->in6p_faddr = addr->sin6_addr;
+	soisconnected(so);
+	return error;
+}
 
-	case PRU_CONNECT2:
-		error = EOPNOTSUPP;
-		break;
+static int
+rip6_connect2(struct socket *so, struct socket *so2)
+{
+	KASSERT(solocked(so));
+
+	return EOPNOTSUPP;
+}
+
+static int
+rip6_disconnect(struct socket *so)
+{
+	struct in6pcb *in6p = sotoin6pcb(so);
+
+	KASSERT(solocked(so));
+	KASSERT(in6p != NULL);
+
+	if ((so->so_state & SS_ISCONNECTED) == 0)
+		return ENOTCONN;
+
+	in6p->in6p_faddr = in6addr_any;
+	so->so_state &= ~SS_ISCONNECTED;	/* XXX */
+	return 0;
+}
+
+static int
+rip6_shutdown(struct socket *so)
+{
+	KASSERT(solocked(so));
 
 	/*
 	 * Mark the connection as being incapable of futther input.
 	 */
-	case PRU_SHUTDOWN:
-		socantsendmore(so);
-		break;
+	socantsendmore(so);
+	return 0;
+}
+
+static int
+rip6_abort(struct socket *so)
+{
+	KASSERT(solocked(so));
+
+	soisdisconnected(so);
+	rip6_detach(so);
+	return 0;
+}
+
+static int
+rip6_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp)
+{
+	return in6_control(so, cmd, nam, ifp);
+}
+
+static int
+rip6_stat(struct socket *so, struct stat *ub)
+{
+	KASSERT(solocked(so));
+
+	/* stat: don't bother with a blocksize */
+	return 0;
+}
+
+static int
+rip6_peeraddr(struct socket *so, struct mbuf *nam)
+{
+	KASSERT(solocked(so));
+	KASSERT(sotoin6pcb(so) != NULL);
+	KASSERT(nam != NULL);
+
+	in6_setpeeraddr(sotoin6pcb(so), nam);
+	return 0;
+}
+
+static int
+rip6_sockaddr(struct socket *so, struct mbuf *nam)
+{
+	KASSERT(solocked(so));
+	KASSERT(sotoin6pcb(so) != NULL);
+	KASSERT(nam != NULL);
+
+	in6_setsockaddr(sotoin6pcb(so), nam);
+	return 0;
+}
+
+static int
+rip6_rcvd(struct socket *so, int flags, struct lwp *l)
+{
+	KASSERT(solocked(so));
+
+	return EOPNOTSUPP;
+}
+
+static int
+rip6_recvoob(struct socket *so, struct mbuf *m, int flags)
+{
+	KASSERT(solocked(so));
+
+	return EOPNOTSUPP;
+}
+
+static int
+rip6_send(struct socket *so, struct mbuf *m, struct mbuf *nam,
+    struct mbuf *control, struct lwp *l)
+{
+	struct in6pcb *in6p = sotoin6pcb(so);
+	struct sockaddr_in6 tmp;
+	struct sockaddr_in6 *dst;
+	int error = 0;
+
+	KASSERT(solocked(so));
+	KASSERT(in6p != NULL);
+	KASSERT(m != NULL);
+
 	/*
 	 * Ship a packet out. The appropriate raw output
 	 * routine handles any messaging necessary.
 	 */
-	case PRU_SEND:
-	{
-		struct sockaddr_in6 tmp;
-		struct sockaddr_in6 *dst;
-
-		/* always copy sockaddr to avoid overwrites */
-		if (so->so_state & SS_ISCONNECTED) {
-			if (nam) {
-				error = EISCONN;
-				break;
-			}
-			/* XXX */
-			sockaddr_in6_init(&tmp, &in6p->in6p_faddr, 0, 0, 0);
-			dst = &tmp;
-		} else {
-			if (nam == NULL) {
-				error = ENOTCONN;
-				break;
-			}
-			if (nam->m_len != sizeof(tmp)) {
-				error = EINVAL;
-				break;
-			}
 
-			tmp = *mtod(nam, struct sockaddr_in6 *);
-			dst = &tmp;
+	/* always copy sockaddr to avoid overwrites */
+	if (so->so_state & SS_ISCONNECTED) {
+		if (nam) {
+			error = EISCONN;
+			goto release;
+		}
+		/* XXX */
+		sockaddr_in6_init(&tmp, &in6p->in6p_faddr, 0, 0, 0);
+		dst = &tmp;
+	} else {
+		if (nam == NULL) {
+			error = ENOTCONN;
+			goto release;
+		}
+		if (nam->m_len != sizeof(tmp)) {
+			error = EINVAL;
+			goto release;
+		}
+
+		tmp = *mtod(nam, struct sockaddr_in6 *);
+		dst = &tmp;
 
-			if (dst->sin6_family != AF_INET6) {
-				error = EAFNOSUPPORT;
-				break;
-			}
+		if (dst->sin6_family != AF_INET6) {
+			error = EAFNOSUPPORT;
+			goto release;
 		}
-		error = rip6_output(m, so, dst, control);
-		m = NULL;
-		break;
 	}
+	error = rip6_output(m, so, dst, control);
+	m = NULL;
 
-	case PRU_SENSE:
-		/*
-		 * stat: don't bother with a blocksize
-		 */
-		return 0;
-	/*
-	 * Not supported.
-	 */
-	case PRU_RCVOOB:
-	case PRU_RCVD:
-	case PRU_LISTEN:
-	case PRU_ACCEPT:
-	case PRU_SENDOOB:
-		error = EOPNOTSUPP;
-		break;
+release:
+	if (m)
+		m_freem(m);
 
-	case PRU_SOCKADDR:
-		in6_setsockaddr(in6p, nam);
-		break;
+	return error;
+}
 
-	case PRU_PEERADDR:
-		in6_setpeeraddr(in6p, nam);
-		break;
+static int
+rip6_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control)
+{
+	KASSERT(solocked(so));
 
-	default:
-		panic("rip6_usrreq");
-	}
-	if (m != NULL)
-		m_freem(m);
-	return error;
+	if (m)
+	 	m_freem(m);
+
+	return EOPNOTSUPP;
+}
+
+static int
+rip6_purgeif(struct socket *so, struct ifnet *ifp)
+{
+
+	mutex_enter(softnet_lock);
+	in6_pcbpurgeif0(&raw6cbtable, ifp);
+	in6_purgeif(ifp);
+	in6_pcbpurgeif(&raw6cbtable, ifp);
+	mutex_exit(softnet_lock);
+
+	return 0;
+}
+
+int
+rip6_usrreq(struct socket *so, int req, struct mbuf *m, 
+	struct mbuf *nam, struct mbuf *control, struct lwp *l)
+{
+
+	KASSERT(req != PRU_ACCEPT);
+	KASSERT(req != PRU_BIND);
+	KASSERT(req != PRU_LISTEN);
+	KASSERT(req != PRU_CONNECT);
+	KASSERT(req != PRU_CONNECT2);
+	KASSERT(req != PRU_DISCONNECT);
+	KASSERT(req != PRU_SHUTDOWN);
+	KASSERT(req != PRU_ABORT);
+	KASSERT(req != PRU_CONTROL);
+	KASSERT(req != PRU_SENSE);
+	KASSERT(req != PRU_PEERADDR);
+	KASSERT(req != PRU_SOCKADDR);
+	KASSERT(req != PRU_RCVD);
+	KASSERT(req != PRU_RCVOOB);
+	KASSERT(req != PRU_SEND);
+	KASSERT(req != PRU_PURGEIF);
+	KASSERT(req != PRU_SENDOOB);
+
+	panic("rip6_usrreq");
+
+	return 0;
 }
 
 static int
@@ -881,3 +998,48 @@ sysctl_net_inet6_raw6_setup(struct sysct
 		       CTL_NET, PF_INET6, IPPROTO_RAW, RAW6CTL_STATS,
 		       CTL_EOL);
 }
+
+PR_WRAP_USRREQS(rip6)
+#define	rip6_attach		rip6_attach_wrapper
+#define	rip6_detach		rip6_detach_wrapper
+#define	rip6_accept		rip6_accept_wrapper
+#define	rip6_bind		rip6_bind_wrapper
+#define	rip6_listen		rip6_listen_wrapper
+#define	rip6_connect		rip6_connect_wrapper
+#define	rip6_connect2		rip6_connect2_wrapper
+#define	rip6_disconnect		rip6_disconnect_wrapper
+#define	rip6_shutdown		rip6_shutdown_wrapper
+#define	rip6_abort		rip6_abort_wrapper
+#define	rip6_ioctl		rip6_ioctl_wrapper
+#define	rip6_stat		rip6_stat_wrapper
+#define	rip6_peeraddr		rip6_peeraddr_wrapper
+#define	rip6_sockaddr		rip6_sockaddr_wrapper
+#define	rip6_rcvd		rip6_rcvd_wrapper
+#define	rip6_recvoob		rip6_recvoob_wrapper
+#define	rip6_send		rip6_send_wrapper
+#define	rip6_sendoob		rip6_sendoob_wrapper
+#define	rip6_purgeif		rip6_purgeif_wrapper
+#define	rip6_usrreq		rip6_usrreq_wrapper
+
+const struct pr_usrreqs rip6_usrreqs = {
+	.pr_attach	= rip6_attach,
+	.pr_detach	= rip6_detach,
+	.pr_accept	= rip6_accept,
+	.pr_bind	= rip6_bind,
+	.pr_listen	= rip6_listen,
+	.pr_connect	= rip6_connect,
+	.pr_connect2	= rip6_connect2,
+	.pr_disconnect	= rip6_disconnect,
+	.pr_shutdown	= rip6_shutdown,
+	.pr_abort	= rip6_abort,
+	.pr_ioctl	= rip6_ioctl,
+	.pr_stat	= rip6_stat,
+	.pr_peeraddr	= rip6_peeraddr,
+	.pr_sockaddr	= rip6_sockaddr,
+	.pr_rcvd	= rip6_rcvd,
+	.pr_recvoob	= rip6_recvoob,
+	.pr_send	= rip6_send,
+	.pr_sendoob	= rip6_sendoob,
+	.pr_purgeif	= rip6_purgeif,
+	.pr_generic	= rip6_usrreq,
+};

Index: src/sys/netinet6/scope6.c
diff -u src/sys/netinet6/scope6.c:1.8 src/sys/netinet6/scope6.c:1.8.36.1
--- src/sys/netinet6/scope6.c:1.8	Fri Sep 11 22:06:29 2009
+++ src/sys/netinet6/scope6.c	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: scope6.c,v 1.8 2009/09/11 22:06:29 dyoung Exp $	*/
+/*	$NetBSD: scope6.c,v 1.8.36.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME$	*/
 
 /*-
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: scope6.c,v 1.8 2009/09/11 22:06:29 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: scope6.c,v 1.8.36.1 2014/08/10 06:56:30 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/malloc.h>
@@ -130,7 +130,7 @@ scope6_set(struct ifnet *ifp, const stru
 				return (EINVAL);
 
 			if (i == IPV6_ADDR_SCOPE_LINKLOCAL &&
-			    idlist->s6id_list[i] >= if_indexlim) {
+			    !if_byindex(idlist->s6id_list[i])) {
 				/*
 				 * XXX: theoretically, there should be no
 				 * relationship between link IDs and interface
@@ -309,14 +309,8 @@ sa6_embedscope(struct sockaddr_in6 *sin6
 		 * zone IDs assuming a one-to-one mapping between interfaces
 		 * and links.
 		 */
-		if (if_indexlim <= zoneid)
-			return (ENXIO);
-#ifdef __FreeBSD__
-		ifp = ifnet_byindex(zoneid);
-#else
-		ifp = ifindex2ifnet[zoneid];
-#endif
-		if (ifp == NULL) /* XXX: this can happen for some OS */
+		ifp = if_byindex(zoneid);
+		if (ifp == NULL)
 			return (ENXIO);
 
 		/* XXX assignment to 16bit from 32bit variable */
@@ -363,14 +357,7 @@ sa6_recoverscope(struct sockaddr_in6 *si
 		 */
 		zoneid = ntohs(sin6->sin6_addr.s6_addr16[1]);
 		if (zoneid) {
-			/* sanity check */
-			if (/* zoneid < 0 || */ if_indexlim <= zoneid)
-				return (ENXIO);
-#ifdef __FreeBSD__
-			if (!ifnet_byindex(zoneid))
-#else
-			if (!ifindex2ifnet[zoneid])
-#endif
+			if (!if_byindex(zoneid))
 				return (ENXIO);
 			sin6->sin6_addr.s6_addr16[1] = 0;
 			sin6->sin6_scope_id = zoneid;

Index: src/sys/netinet6/udp6_usrreq.c
diff -u src/sys/netinet6/udp6_usrreq.c:1.93 src/sys/netinet6/udp6_usrreq.c:1.93.2.1
--- src/sys/netinet6/udp6_usrreq.c:1.93	Tue Feb 25 18:30:12 2014
+++ src/sys/netinet6/udp6_usrreq.c	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: udp6_usrreq.c,v 1.93 2014/02/25 18:30:12 pooka Exp $	*/
+/*	$NetBSD: udp6_usrreq.c,v 1.93.2.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: udp6_usrreq.c,v 1.86 2001/05/27 17:33:00 itojun Exp $	*/
 
 /*
@@ -62,18 +62,16 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: udp6_usrreq.c,v 1.93 2014/02/25 18:30:12 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udp6_usrreq.c,v 1.93.2.1 2014/08/10 06:56:30 tls Exp $");
 
 #include "opt_inet.h"
+#include "opt_inet_csum.h"
 
 #include <sys/param.h>
-#include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
-#include <sys/errno.h>
-#include <sys/stat.h>
 #include <sys/systm.h>
 #include <sys/proc.h>
 #include <sys/syslog.h>
@@ -87,19 +85,23 @@ __KERNEL_RCSID(0, "$NetBSD: udp6_usrreq.
 #include <netinet/in.h>
 #include <netinet/in_var.h>
 #include <netinet/in_systm.h>
+#include <netinet/in_offload.h>
 #include <netinet/ip.h>
 #include <netinet/ip_var.h>
 #include <netinet/in_pcb.h>
 #include <netinet/udp.h>
 #include <netinet/udp_var.h>
+#include <netinet/udp_private.h>
+
 #include <netinet/ip6.h>
+#include <netinet/icmp6.h>
 #include <netinet6/ip6_var.h>
+#include <netinet6/ip6_private.h>
 #include <netinet6/in6_pcb.h>
-#include <netinet/icmp6.h>
 #include <netinet6/udp6_var.h>
 #include <netinet6/udp6_private.h>
 #include <netinet6/ip6protosw.h>
-#include <netinet/in_offload.h>
+#include <netinet6/scope6_var.h>
 
 #include "faith.h"
 #if defined(NFAITH) && NFAITH > 0
@@ -115,13 +117,38 @@ extern struct inpcbtable udbtable;
 
 percpu_t *udp6stat_percpu;
 
+/* UDP on IP6 parameters */
+static int	udp6_sendspace = 9216;	/* really max datagram size */
+static int	udp6_recvspace = 40 * (1024 + sizeof(struct sockaddr_in6));
+					/* 40 1K datagrams */
+
 static	void udp6_notify(struct in6pcb *, int);
 static	void sysctl_net_inet6_udp6_setup(struct sysctllog **);
 
+#ifdef UDP_CSUM_COUNTERS
+#include <sys/device.h>
+struct evcnt udp6_hwcsum_bad = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
+    NULL, "udp6", "hwcsum bad");
+struct evcnt udp6_hwcsum_ok = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
+    NULL, "udp6", "hwcsum ok");
+struct evcnt udp6_hwcsum_data = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
+    NULL, "udp6", "hwcsum data");
+struct evcnt udp6_swcsum = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
+    NULL, "udp6", "swcsum");
+
+EVCNT_ATTACH_STATIC(udp6_hwcsum_bad);
+EVCNT_ATTACH_STATIC(udp6_hwcsum_ok);
+EVCNT_ATTACH_STATIC(udp6_hwcsum_data);
+EVCNT_ATTACH_STATIC(udp6_swcsum);
+
+#define	UDP_CSUM_COUNTER_INCR(ev)	(ev)->ev_count++
+#else
+#define	UDP_CSUM_COUNTER_INCR(ev)	/* nothing */
+#endif
+
 void
 udp6_init(void)
 {
-
 	sysctl_net_inet6_udp6_setup(NULL);
 	udp6stat_percpu = percpu_alloc(sizeof(uint64_t) * UDP6_NSTATS);
 
@@ -298,18 +325,472 @@ end:
 	return error;
 }
 
+static void
+udp6_sendup(struct mbuf *m, int off /* offset of data portion */,
+	struct sockaddr *src, struct socket *so)
+{
+	struct mbuf *opts = NULL;
+	struct mbuf *n;
+	struct in6pcb *in6p = NULL;
+
+	if (!so)
+		return;
+	if (so->so_proto->pr_domain->dom_family != AF_INET6)
+		return;
+	in6p = sotoin6pcb(so);
+
+#if defined(IPSEC)
+	/* check AH/ESP integrity. */
+	if (ipsec_used && so != NULL && ipsec6_in_reject_so(m, so)) {
+		IPSEC6_STATINC(IPSEC_STAT_IN_POLVIO);
+		if ((n = m_copypacket(m, M_DONTWAIT)) != NULL)
+			icmp6_error(n, ICMP6_DST_UNREACH,
+			    ICMP6_DST_UNREACH_ADMIN, 0);
+		return;
+	}
+#endif /*IPSEC*/
+
+	if ((n = m_copypacket(m, M_DONTWAIT)) != NULL) {
+		if (in6p && (in6p->in6p_flags & IN6P_CONTROLOPTS
+#ifdef SO_OTIMESTAMP
+		    || in6p->in6p_socket->so_options & SO_OTIMESTAMP
+#endif
+		    || in6p->in6p_socket->so_options & SO_TIMESTAMP)) {
+			struct ip6_hdr *ip6 = mtod(n, struct ip6_hdr *);
+			ip6_savecontrol(in6p, &opts, ip6, n);
+		}
 
-extern	int udp6_sendspace;
-extern	int udp6_recvspace;
+		m_adj(n, off);
+		if (sbappendaddr(&so->so_rcv, src, n, opts) == 0) {
+			m_freem(n);
+			if (opts)
+				m_freem(opts);
+			so->so_rcv.sb_overflowed++;
+			UDP6_STATINC(UDP6_STAT_FULLSOCK);
+		} else
+			sorwakeup(so);
+	}
+}
 
 int
-udp6_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *addr6,
-    struct mbuf *control, struct lwp *l)
+udp6_realinput(int af, struct sockaddr_in6 *src, struct sockaddr_in6 *dst,
+	struct mbuf *m, int off)
+{
+	u_int16_t sport, dport;
+	int rcvcnt;
+	struct in6_addr src6, *dst6;
+	const struct in_addr *dst4;
+	struct inpcb_hdr *inph;
+	struct in6pcb *in6p;
+
+	rcvcnt = 0;
+	off += sizeof(struct udphdr);	/* now, offset of payload */
+
+	if (af != AF_INET && af != AF_INET6)
+		goto bad;
+	if (src->sin6_family != AF_INET6 || dst->sin6_family != AF_INET6)
+		goto bad;
+
+	src6 = src->sin6_addr;
+	if (sa6_recoverscope(src) != 0) {
+		/* XXX: should be impossible. */
+		goto bad;
+	}
+	sport = src->sin6_port;
+
+	dport = dst->sin6_port;
+	dst4 = (struct in_addr *)&dst->sin6_addr.s6_addr[12];
+	dst6 = &dst->sin6_addr;
+
+	if (IN6_IS_ADDR_MULTICAST(dst6) ||
+	    (af == AF_INET && IN_MULTICAST(dst4->s_addr))) {
+		/*
+		 * Deliver a multicast or broadcast datagram to *all* sockets
+		 * for which the local and remote addresses and ports match
+		 * those of the incoming datagram.  This allows more than
+		 * one process to receive multi/broadcasts on the same port.
+		 * (This really ought to be done for unicast datagrams as
+		 * well, but that would cause problems with existing
+		 * applications that open both address-specific sockets and
+		 * a wildcard socket listening to the same port -- they would
+		 * end up receiving duplicates of every unicast datagram.
+		 * Those applications open the multiple sockets to overcome an
+		 * inadequacy of the UDP socket interface, but for backwards
+		 * compatibility we avoid the problem here rather than
+		 * fixing the interface.  Maybe 4.5BSD will remedy this?)
+		 */
+
+		/*
+		 * KAME note: traditionally we dropped udpiphdr from mbuf here.
+		 * we need udpiphdr for IPsec processing so we do that later.
+		 */
+		/*
+		 * Locate pcb(s) for datagram.
+		 */
+		TAILQ_FOREACH(inph, &udbtable.inpt_queue, inph_queue) {
+			in6p = (struct in6pcb *)inph;
+			if (in6p->in6p_af != AF_INET6)
+				continue;
+
+			if (in6p->in6p_lport != dport)
+				continue;
+			if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) {
+				if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr,
+				    dst6))
+					continue;
+			} else {
+				if (IN6_IS_ADDR_V4MAPPED(dst6) &&
+				    (in6p->in6p_flags & IN6P_IPV6_V6ONLY))
+					continue;
+			}
+			if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
+				if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr,
+				    &src6) || in6p->in6p_fport != sport)
+					continue;
+			} else {
+				if (IN6_IS_ADDR_V4MAPPED(&src6) &&
+				    (in6p->in6p_flags & IN6P_IPV6_V6ONLY))
+					continue;
+			}
+
+			udp6_sendup(m, off, (struct sockaddr *)src,
+				in6p->in6p_socket);
+			rcvcnt++;
+
+			/*
+			 * Don't look for additional matches if this one does
+			 * not have either the SO_REUSEPORT or SO_REUSEADDR
+			 * socket options set.  This heuristic avoids searching
+			 * through all pcbs in the common case of a non-shared
+			 * port.  It assumes that an application will never
+			 * clear these options after setting them.
+			 */
+			if ((in6p->in6p_socket->so_options &
+			    (SO_REUSEPORT|SO_REUSEADDR)) == 0)
+				break;
+		}
+	} else {
+		/*
+		 * Locate pcb for datagram.
+		 */
+		in6p = in6_pcblookup_connect(&udbtable, &src6, sport, dst6,
+					     dport, 0, 0);
+		if (in6p == 0) {
+			UDP_STATINC(UDP_STAT_PCBHASHMISS);
+			in6p = in6_pcblookup_bind(&udbtable, dst6, dport, 0);
+			if (in6p == 0)
+				return rcvcnt;
+		}
+
+		udp6_sendup(m, off, (struct sockaddr *)src, in6p->in6p_socket);
+		rcvcnt++;
+	}
+
+bad:
+	return rcvcnt;
+}
+
+int
+udp6_input_checksum(struct mbuf *m, const struct udphdr *uh, int off, int len)
+{
+
+	/*
+	 * XXX it's better to record and check if this mbuf is
+	 * already checked.
+	 */
+
+	if (__predict_false((m->m_flags & M_LOOP) && !udp_do_loopback_cksum)) {
+		goto good;
+	}
+	if (uh->uh_sum == 0) {
+		UDP6_STATINC(UDP6_STAT_NOSUM);
+		goto bad;
+	}
+
+	switch (m->m_pkthdr.csum_flags &
+	    ((m->m_pkthdr.rcvif->if_csum_flags_rx & M_CSUM_UDPv6) |
+	    M_CSUM_TCP_UDP_BAD | M_CSUM_DATA)) {
+	case M_CSUM_UDPv6|M_CSUM_TCP_UDP_BAD:
+		UDP_CSUM_COUNTER_INCR(&udp6_hwcsum_bad);
+		UDP6_STATINC(UDP6_STAT_BADSUM);
+		goto bad;
+
+#if 0 /* notyet */
+	case M_CSUM_UDPv6|M_CSUM_DATA:
+#endif
+
+	case M_CSUM_UDPv6:
+		/* Checksum was okay. */
+		UDP_CSUM_COUNTER_INCR(&udp6_hwcsum_ok);
+		break;
+
+	default:
+		/*
+		 * Need to compute it ourselves.  Maybe skip checksum
+		 * on loopback interfaces.
+		 */
+		UDP_CSUM_COUNTER_INCR(&udp6_swcsum);
+		if (in6_cksum(m, IPPROTO_UDP, off, len) != 0) {
+			UDP6_STATINC(UDP6_STAT_BADSUM);
+			goto bad;
+		}
+	}
+
+good:
+	return 0;
+bad:
+	return -1;
+}
+
+int
+udp6_input(struct mbuf **mp, int *offp, int proto)
+{
+	struct mbuf *m = *mp;
+	int off = *offp;
+	struct sockaddr_in6 src, dst;
+	struct ip6_hdr *ip6;
+	struct udphdr *uh;
+	u_int32_t plen, ulen;
+
+	ip6 = mtod(m, struct ip6_hdr *);
+
+#if defined(NFAITH) && 0 < NFAITH
+	if (faithprefix(&ip6->ip6_dst)) {
+		/* send icmp6 host unreach? */
+		m_freem(m);
+		return IPPROTO_DONE;
+	}
+#endif
+
+	UDP6_STATINC(UDP6_STAT_IPACKETS);
+
+	/* check for jumbogram is done in ip6_input.  we can trust pkthdr.len */
+	plen = m->m_pkthdr.len - off;
+	IP6_EXTHDR_GET(uh, struct udphdr *, m, off, sizeof(struct udphdr));
+	if (uh == NULL) {
+		IP6_STATINC(IP6_STAT_TOOSHORT);
+		return IPPROTO_DONE;
+	}
+	KASSERT(UDP_HDR_ALIGNED_P(uh));
+	ulen = ntohs((u_short)uh->uh_ulen);
+	/*
+	 * RFC2675 section 4: jumbograms will have 0 in the UDP header field,
+	 * iff payload length > 0xffff.
+	 */
+	if (ulen == 0 && plen > 0xffff)
+		ulen = plen;
+
+	if (plen != ulen) {
+		UDP6_STATINC(UDP6_STAT_BADLEN);
+		goto bad;
+	}
+
+	/* destination port of 0 is illegal, based on RFC768. */
+	if (uh->uh_dport == 0)
+		goto bad;
+
+	/* Be proactive about malicious use of IPv4 mapped address */
+	if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
+	    IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
+		/* XXX stat */
+		goto bad;
+	}
+
+	/*
+	 * Checksum extended UDP header and data.  Maybe skip checksum
+	 * on loopback interfaces.
+	 */
+	if (udp6_input_checksum(m, uh, off, ulen))
+		goto bad;
+
+	/*
+	 * Construct source and dst sockaddrs.
+	 */
+	memset(&src, 0, sizeof(src));
+	src.sin6_family = AF_INET6;
+	src.sin6_len = sizeof(struct sockaddr_in6);
+	src.sin6_addr = ip6->ip6_src;
+	src.sin6_port = uh->uh_sport;
+	memset(&dst, 0, sizeof(dst));
+	dst.sin6_family = AF_INET6;
+	dst.sin6_len = sizeof(struct sockaddr_in6);
+	dst.sin6_addr = ip6->ip6_dst;
+	dst.sin6_port = uh->uh_dport;
+
+	if (udp6_realinput(AF_INET6, &src, &dst, m, off) == 0) {
+		if (m->m_flags & M_MCAST) {
+			UDP6_STATINC(UDP6_STAT_NOPORTMCAST);
+			goto bad;
+		}
+		UDP6_STATINC(UDP6_STAT_NOPORT);
+		icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0);
+		m = NULL;
+	}
+
+bad:
+	if (m)
+		m_freem(m);
+	return IPPROTO_DONE;
+}
+
+static int
+udp6_attach(struct socket *so, int proto)
+{
+	struct in6pcb *in6p;
+	int s, error;
+
+	KASSERT(sotoin6pcb(so) == NULL);
+	sosetlock(so);
+
+	/*
+	 * MAPPED_ADDR implementation spec:
+	 *  Always attach for IPv6, and only when necessary for IPv4.
+	 */
+	s = splsoftnet();
+	error = in6_pcballoc(so, &udbtable);
+	splx(s);
+	if (error) {
+		return error;
+	}
+	error = soreserve(so, udp6_sendspace, udp6_recvspace);
+	if (error) {
+		return error;
+	}
+	in6p = sotoin6pcb(so);
+	in6p->in6p_cksum = -1;	/* just to be sure */
+
+	KASSERT(solocked(so));
+	return 0;
+}
+
+static void
+udp6_detach(struct socket *so)
+{
+	struct in6pcb *in6p = sotoin6pcb(so);
+	int s;
+
+	KASSERT(solocked(so));
+	KASSERT(in6p != NULL);
+
+	s = splsoftnet();
+	in6_pcbdetach(in6p);
+	splx(s);
+}
+
+static int
+udp6_accept(struct socket *so, struct mbuf *nam)
+{
+	KASSERT(solocked(so));
+
+	return EOPNOTSUPP;
+}
+
+static int
+udp6_bind(struct socket *so, struct mbuf *nam, struct lwp *l)
+{
+	struct in6pcb *in6p = sotoin6pcb(so);
+	int error = 0;
+	int s;
+
+	KASSERT(solocked(so));
+	KASSERT(in6p != NULL);
+
+	s = splsoftnet();
+	error = in6_pcbbind(in6p, nam, l);
+	splx(s);
+	return error;
+}
+
+static int
+udp6_listen(struct socket *so, struct lwp *l)
+{
+	KASSERT(solocked(so));
+
+	return EOPNOTSUPP;
+}
+
+static int
+udp6_connect(struct socket *so, struct mbuf *nam, struct lwp *l)
+{
+	struct in6pcb *in6p = sotoin6pcb(so);
+	int error = 0;
+	int s;
+
+	KASSERT(solocked(so));
+	KASSERT(in6p != NULL);
+
+	if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr))
+		return EISCONN;
+	s = splsoftnet();
+	error = in6_pcbconnect(in6p, nam, l);
+	splx(s);
+	if (error == 0)
+		soisconnected(so);
+
+	return error;
+}
+
+static int
+udp6_connect2(struct socket *so, struct socket *so2)
+{
+	KASSERT(solocked(so));
+
+	return EOPNOTSUPP;
+}
+
+static int
+udp6_disconnect(struct socket *so)
+{
+	struct in6pcb *in6p = sotoin6pcb(so);
+	int s;
+
+	KASSERT(solocked(so));
+	KASSERT(in6p != NULL);
+
+	if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr))
+		return ENOTCONN;
+
+	s = splsoftnet();
+	in6_pcbdisconnect(in6p);
+	memset((void *)&in6p->in6p_laddr, 0, sizeof(in6p->in6p_laddr));
+	splx(s);
+
+	so->so_state &= ~SS_ISCONNECTED;	/* XXX */
+	in6_pcbstate(in6p, IN6P_BOUND);		/* XXX */
+	return 0;
+}
+
+static int
+udp6_shutdown(struct socket *so)
 {
-	struct	in6pcb *in6p = sotoin6pcb(so);
-	int	error = 0;
-	int	s;
+	int s;
 
+	s = splsoftnet();
+	socantsendmore(so);
+	splx(s);
+
+	return 0;
+}
+
+static int
+udp6_abort(struct socket *so)
+{
+	int s;
+
+	KASSERT(solocked(so));
+	KASSERT(sotoin6pcb(so) != NULL);
+
+	s = splsoftnet();
+	soisdisconnected(so);
+	in6_pcbdetach(sotoin6pcb(so));
+	splx(s);
+
+	return 0;
+}
+
+static int
+udp6_ioctl(struct socket *so, u_long cmd, void *addr6, struct ifnet *ifp)
+{
 	/*
 	 * MAPPED_ADDR implementation info:
 	 *  Mapped addr support for PRU_CONTROL is not necessary.
@@ -320,117 +801,133 @@ udp6_usrreq(struct socket *so, int req, 
 	 *  So AF_INET socket need to be used to control AF_INET addrs,
 	 *  and AF_INET6 socket for AF_INET6 addrs.
 	 */
-	if (req == PRU_CONTROL)
-		return in6_control(so, (u_long)m, (void *)addr6,
-				   (struct ifnet *)control, l);
-
-	if (req == PRU_PURGEIF) {
-		mutex_enter(softnet_lock);
-		in6_pcbpurgeif0(&udbtable, (struct ifnet *)control);
-		in6_purgeif((struct ifnet *)control);
-		in6_pcbpurgeif(&udbtable, (struct ifnet *)control);
-		mutex_exit(softnet_lock);
-		return 0;
-	}
-
-	if (req == PRU_ATTACH)
-		sosetlock(so);
-	else if (in6p == NULL) {
-		error = EINVAL;
-		goto release;
-	}
+	return in6_control(so, cmd, addr6, ifp);
+}
 
-	switch (req) {
-	case PRU_ATTACH:
-		/*
-		 * MAPPED_ADDR implementation spec:
-		 *  Always attach for IPv6,
-		 *  and only when necessary for IPv4.
-		 */
-		if (in6p != NULL) {
-			error = EINVAL;
-			break;
-		}
-		s = splsoftnet();
-		error = in6_pcballoc(so, &udbtable);
-		splx(s);
-		if (error)
-			break;
-		error = soreserve(so, udp6_sendspace, udp6_recvspace);
-		if (error)
-			break;
-		in6p = sotoin6pcb(so);
-		in6p->in6p_cksum = -1;	/* just to be sure */
-		break;
+static int
+udp6_stat(struct socket *so, struct stat *ub)
+{
+	KASSERT(solocked(so));
 
-	case PRU_DETACH:
-		in6_pcbdetach(in6p);
-		break;
+	/* stat: don't bother with a blocksize */
+	return 0;
+}
 
-	case PRU_BIND:
-		s = splsoftnet();
-		error = in6_pcbbind(in6p, addr6, l);
-		splx(s);
-		break;
+static int
+udp6_peeraddr(struct socket *so, struct mbuf *nam)
+{
+	KASSERT(solocked(so));
+	KASSERT(sotoin6pcb(so) != NULL);
+	KASSERT(nam != NULL);
 
-	case PRU_CONNECT:
-		if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
-			error = EISCONN;
-			break;
-		}
-		s = splsoftnet();
-		error = in6_pcbconnect(in6p, addr6, l);
-		splx(s);
-		if (error == 0)
-			soisconnected(so);
-		break;
+	in6_setpeeraddr(sotoin6pcb(so), nam);
+	return 0;
+}
 
-	case PRU_DISCONNECT:
-		if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
-			error = ENOTCONN;
-			break;
-		}
-		s = splsoftnet();
-		in6_pcbdisconnect(in6p);
-		memset((void *)&in6p->in6p_laddr, 0, sizeof(in6p->in6p_laddr));
-		splx(s);
-		so->so_state &= ~SS_ISCONNECTED;		/* XXX */
-		in6_pcbstate(in6p, IN6P_BOUND);		/* XXX */
-		break;
+static int
+udp6_sockaddr(struct socket *so, struct mbuf *nam)
+{
+	KASSERT(solocked(so));
+	KASSERT(sotoin6pcb(so) != NULL);
+	KASSERT(nam != NULL);
 
-	case PRU_SHUTDOWN:
-		socantsendmore(so);
-		break;
+	in6_setsockaddr(sotoin6pcb(so), nam);
+	return 0;
+}
 
-	case PRU_SEND:
-		s = splsoftnet();
-		error = udp6_output(in6p, m, addr6, control, l);
-		splx(s);
-		return error;
+static int
+udp6_rcvd(struct socket *so, int flags, struct lwp *l)
+{
+	KASSERT(solocked(so));
 
-	case PRU_ABORT:
-		soisdisconnected(so);
-		in6_pcbdetach(in6p);
-		break;
+	return EOPNOTSUPP;
+}
 
-	case PRU_SOCKADDR:
-		in6_setsockaddr(in6p, addr6);
-		break;
+static int
+udp6_recvoob(struct socket *so, struct mbuf *m, int flags)
+{
+	KASSERT(solocked(so));
 
-	case PRU_PEERADDR:
-		in6_setpeeraddr(in6p, addr6);
-		break;
+	return EOPNOTSUPP;
+}
 
-	case PRU_SENSE:
-		/*
-		 * stat: don't bother with a blocksize
-		 */
-		return 0;
+static int
+udp6_send(struct socket *so, struct mbuf *m, struct mbuf *nam,
+    struct mbuf *control, struct lwp *l)
+{
+	struct in6pcb *in6p = sotoin6pcb(so);
+	int error = 0;
+	int s;
+
+	KASSERT(solocked(so));
+	KASSERT(in6p != NULL);
+	KASSERT(m != NULL);
+
+	s = splsoftnet();
+	error = udp6_output(in6p, m, nam, control, l);
+	splx(s);
+
+	return error;
+}
+
+static int
+udp6_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control)
+{
+	KASSERT(solocked(so));
+
+	if (m)
+		m_freem(m);
+	if (control)
+		m_freem(control);
+
+	return EOPNOTSUPP;
+}
+
+static int
+udp6_purgeif(struct socket *so, struct ifnet *ifp)
+{
+
+	mutex_enter(softnet_lock);
+	in6_pcbpurgeif0(&udbtable, ifp);
+	in6_purgeif(ifp);
+	in6_pcbpurgeif(&udbtable, ifp);
+	mutex_exit(softnet_lock);
 
-	case PRU_LISTEN:
-	case PRU_CONNECT2:
-	case PRU_ACCEPT:
-	case PRU_SENDOOB:
+	return 0;
+}
+
+int
+udp6_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *addr6,
+    struct mbuf *control, struct lwp *l)
+{
+	int error = 0;
+
+	KASSERT(req != PRU_ATTACH);
+	KASSERT(req != PRU_DETACH);
+	KASSERT(req != PRU_ACCEPT);
+	KASSERT(req != PRU_BIND);
+	KASSERT(req != PRU_LISTEN);
+	KASSERT(req != PRU_CONNECT);
+	KASSERT(req != PRU_CONNECT2);
+	KASSERT(req != PRU_DISCONNECT);
+	KASSERT(req != PRU_SHUTDOWN);
+	KASSERT(req != PRU_ABORT);
+	KASSERT(req != PRU_CONTROL);
+	KASSERT(req != PRU_SENSE);
+	KASSERT(req != PRU_PEERADDR);
+	KASSERT(req != PRU_SOCKADDR);
+	KASSERT(req != PRU_RCVD);
+	KASSERT(req != PRU_RCVOOB);
+	KASSERT(req != PRU_SEND);
+	KASSERT(req != PRU_SENDOOB);
+	KASSERT(req != PRU_PURGEIF);
+
+	if (sotoin6pcb(so) == NULL) {
+		error = EINVAL;
+		goto release;
+	}
+
+	switch (req) {
 	case PRU_FASTTIMO:
 	case PRU_SLOWTIMO:
 	case PRU_PROTORCV:
@@ -438,10 +935,6 @@ udp6_usrreq(struct socket *so, int req, 
 		error = EOPNOTSUPP;
 		break;
 
-	case PRU_RCVD:
-	case PRU_RCVOOB:
-		return EOPNOTSUPP;	/* do not free mbuf's */
-
 	default:
 		panic("udp6_usrreq");
 	}
@@ -521,3 +1014,48 @@ udp6_statinc(u_int stat)
 	KASSERT(stat < UDP6_NSTATS);
 	UDP6_STATINC(stat);
 }
+
+PR_WRAP_USRREQS(udp6)
+#define	udp6_attach	udp6_attach_wrapper
+#define	udp6_detach	udp6_detach_wrapper
+#define	udp6_accept	udp6_accept_wrapper
+#define	udp6_bind	udp6_bind_wrapper
+#define	udp6_listen	udp6_listen_wrapper
+#define	udp6_connect	udp6_connect_wrapper
+#define	udp6_connect2	udp6_connect2_wrapper
+#define	udp6_disconnect	udp6_disconnect_wrapper
+#define	udp6_shutdown	udp6_shutdown_wrapper
+#define	udp6_abort	udp6_abort_wrapper
+#define	udp6_ioctl	udp6_ioctl_wrapper
+#define	udp6_stat	udp6_stat_wrapper
+#define	udp6_peeraddr	udp6_peeraddr_wrapper
+#define	udp6_sockaddr	udp6_sockaddr_wrapper
+#define	udp6_rcvd	udp6_rcvd_wrapper
+#define	udp6_recvoob	udp6_recvoob_wrapper
+#define	udp6_send	udp6_send_wrapper
+#define	udp6_sendoob	udp6_sendoob_wrapper
+#define	udp6_purgeif	udp6_purgeif_wrapper
+#define	udp6_usrreq	udp6_usrreq_wrapper
+
+const struct pr_usrreqs udp6_usrreqs = {
+	.pr_attach	= udp6_attach,
+	.pr_detach	= udp6_detach,
+	.pr_accept	= udp6_accept,
+	.pr_bind	= udp6_bind,
+	.pr_listen	= udp6_listen,
+	.pr_connect	= udp6_connect,
+	.pr_connect2	= udp6_connect2,
+	.pr_disconnect	= udp6_disconnect,
+	.pr_shutdown	= udp6_shutdown,
+	.pr_abort	= udp6_abort,
+	.pr_ioctl	= udp6_ioctl,
+	.pr_stat	= udp6_stat,
+	.pr_peeraddr	= udp6_peeraddr,
+	.pr_sockaddr	= udp6_sockaddr,
+	.pr_rcvd	= udp6_rcvd,
+	.pr_recvoob	= udp6_recvoob,
+	.pr_send	= udp6_send,
+	.pr_sendoob	= udp6_sendoob,
+	.pr_purgeif	= udp6_purgeif,
+	.pr_generic	= udp6_usrreq,
+};

Index: src/sys/netinet6/udp6_var.h
diff -u src/sys/netinet6/udp6_var.h:1.25 src/sys/netinet6/udp6_var.h:1.25.12.1
--- src/sys/netinet6/udp6_var.h:1.25	Fri Jun 22 14:54:35 2012
+++ src/sys/netinet6/udp6_var.h	Sun Aug 10 06:56:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: udp6_var.h,v 1.25 2012/06/22 14:54:35 christos Exp $	*/
+/*	$NetBSD: udp6_var.h,v 1.25.12.1 2014/08/10 06:56:30 tls Exp $	*/
 /*	$KAME: udp6_var.h,v 1.11 2000/06/05 00:14:31 itojun Exp $	*/
 
 /*
@@ -99,6 +99,9 @@
 }
 
 #ifdef _KERNEL
+
+extern const struct pr_usrreqs udp6_usrreqs;
+
 void	*udp6_ctlinput(int, const struct sockaddr *, void *);
 int	udp6_ctloutput(int, struct socket *, struct sockopt *);
 void	udp6_init(void);
@@ -108,6 +111,9 @@ int	udp6_output(struct in6pcb *, struct 
 int	udp6_sysctl(int *, u_int, void *, size_t *, void *, size_t);
 int	udp6_usrreq(struct socket *, int, struct mbuf *, struct mbuf *,
     struct mbuf *, struct lwp *);
+int	udp6_realinput(int, struct sockaddr_in6 *, struct sockaddr_in6 *,
+    struct mbuf *, int);
+int	udp6_input_checksum(struct mbuf *, const struct udphdr *, int, int);
 
 void	udp6_statinc(u_int);
 #endif /* _KERNEL */

Reply via email to