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 */