summaryrefslogtreecommitdiffstats
path: root/sys/netinet6
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet6')
-rw-r--r--sys/netinet6/icmp6.c24
-rw-r--r--sys/netinet6/in6.c2
-rw-r--r--sys/netinet6/in6_mcast.c7
-rw-r--r--sys/netinet6/in6_pcb.c40
-rw-r--r--sys/netinet6/in6_src.c2
-rw-r--r--sys/netinet6/ip6_mroute.c2
-rw-r--r--sys/netinet6/ip6_output.c35
-rw-r--r--sys/netinet6/mld6.c7
-rw-r--r--sys/netinet6/nd6.c40
-rw-r--r--sys/netinet6/nd6.h1
-rw-r--r--sys/netinet6/nd6_rtr.c5
-rw-r--r--sys/netinet6/send.c2
12 files changed, 120 insertions, 47 deletions
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
index d22bc43..2114a0a 100644
--- a/sys/netinet6/icmp6.c
+++ b/sys/netinet6/icmp6.c
@@ -2351,8 +2351,6 @@ icmp6_redirect_input(struct mbuf *m, int off)
int icmp6len = ntohs(ip6->ip6_plen);
char *lladdr = NULL;
int lladdrlen = 0;
- u_char *redirhdr = NULL;
- int redirhdrlen = 0;
struct rtentry *rt = NULL;
int is_router;
int is_onlink;
@@ -2362,14 +2360,11 @@ icmp6_redirect_input(struct mbuf *m, int off)
union nd_opts ndopts;
char ip6buf[INET6_ADDRSTRLEN];
- if (!m)
- return;
+ M_ASSERTPKTHDR(m);
+ KASSERT(m->m_pkthdr.rcvif != NULL, ("%s: no rcvif", __func__));
ifp = m->m_pkthdr.rcvif;
- if (!ifp)
- return;
-
/* XXX if we are router, we don't update route by icmp6 redirect */
if (V_ip6_forwarding)
goto freeit;
@@ -2476,9 +2471,8 @@ icmp6_redirect_input(struct mbuf *m, int off)
icmp6len -= sizeof(*nd_rd);
nd6_option_init(nd_rd + 1, icmp6len, &ndopts);
if (nd6_options(&ndopts) < 0) {
- nd6log((LOG_INFO, "icmp6_redirect_input: "
- "invalid ND option, rejected: %s\n",
- icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
+ nd6log((LOG_INFO, "%s: invalid ND option, rejected: %s\n",
+ __func__, icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
/* nd6_options have incremented stats */
goto freeit;
}
@@ -2488,16 +2482,10 @@ icmp6_redirect_input(struct mbuf *m, int off)
lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
}
- if (ndopts.nd_opts_rh) {
- redirhdrlen = ndopts.nd_opts_rh->nd_opt_rh_len;
- redirhdr = (u_char *)(ndopts.nd_opts_rh + 1); /* xxx */
- }
-
if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
- nd6log((LOG_INFO,
- "icmp6_redirect_input: lladdrlen mismatch for %s "
+ nd6log((LOG_INFO, "%s: lladdrlen mismatch for %s "
"(if %d, icmp6 packet %d): %s\n",
- ip6_sprintf(ip6buf, &redtgt6),
+ __func__, ip6_sprintf(ip6buf, &redtgt6),
ifp->if_addrlen, lladdrlen - 2,
icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
goto bad;
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 1e6cb94..8514f73 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -152,7 +152,7 @@ in6_ifaddloop(struct ifaddr *ifa)
ia = ifa2ia6(ifa);
ifp = ifa->ifa_ifp;
IF_AFDATA_LOCK(ifp);
- ifa->ifa_rtrequest = NULL;
+ ifa->ifa_rtrequest = nd6_rtrequest;
/* XXX QL
* we need to report rt_newaddrmsg
diff --git a/sys/netinet6/in6_mcast.c b/sys/netinet6/in6_mcast.c
index 1438c32..a1f233a 100644
--- a/sys/netinet6/in6_mcast.c
+++ b/sys/netinet6/in6_mcast.c
@@ -150,7 +150,8 @@ static int sysctl_ip6_mcast_filters(SYSCTL_HANDLER_ARGS);
SYSCTL_DECL(_net_inet6_ip6); /* XXX Not in any common header. */
-SYSCTL_NODE(_net_inet6_ip6, OID_AUTO, mcast, CTLFLAG_RW, 0, "IPv6 multicast");
+static SYSCTL_NODE(_net_inet6_ip6, OID_AUTO, mcast, CTLFLAG_RW, 0,
+ "IPv6 multicast");
static u_long in6_mcast_maxgrpsrc = IPV6_MAX_GROUP_SRC_FILTER;
SYSCTL_ULONG(_net_inet6_ip6_mcast, OID_AUTO, maxgrpsrc,
@@ -170,7 +171,7 @@ SYSCTL_INT(_net_inet6_ip6_mcast, OID_AUTO, loop, CTLFLAG_RW | CTLFLAG_TUN,
&in6_mcast_loop, 0, "Loopback multicast datagrams by default");
TUNABLE_INT("net.inet6.ip6.mcast.loop", &in6_mcast_loop);
-SYSCTL_NODE(_net_inet6_ip6_mcast, OID_AUTO, filters,
+static SYSCTL_NODE(_net_inet6_ip6_mcast, OID_AUTO, filters,
CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_ip6_mcast_filters,
"Per-interface stack-wide source filters");
@@ -1713,7 +1714,7 @@ ip6_getmoptions(struct inpcb *inp, struct sockopt *sopt)
if (im6o == NULL)
optval = V_ip6_defmcasthlim;
else
- optval = im6o->im6o_multicast_loop;
+ optval = im6o->im6o_multicast_hlim;
INP_WUNLOCK(inp);
error = sooptcopyout(sopt, &optval, sizeof(u_int));
break;
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index d15c605..8f82963 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -187,6 +187,7 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam,
}
if (lport) {
struct inpcb *t;
+ struct tcptw *tw;
/* GROSS */
if (ntohs(lport) <= V_ipport_reservedhigh &&
@@ -206,8 +207,8 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam,
IN6_IS_ADDR_UNSPECIFIED(&t->in6p_faddr)) &&
(!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
!IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
- (t->inp_socket->so_options & SO_REUSEPORT)
- == 0) && (inp->inp_cred->cr_uid !=
+ (t->inp_flags2 & INP_REUSEPORT) == 0) &&
+ (inp->inp_cred->cr_uid !=
t->inp_cred->cr_uid))
return (EADDRINUSE);
#ifdef INET
@@ -233,10 +234,21 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam,
}
t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr,
lport, lookupflags, cred);
- if (t && (reuseport & ((t->inp_flags & INP_TIMEWAIT) ?
- intotw(t)->tw_so_options :
- t->inp_socket->so_options)) == 0)
+ if (t && (t->inp_flags & INP_TIMEWAIT)) {
+ /*
+ * XXXRW: If an incpb has had its timewait
+ * state recycled, we treat the address as
+ * being in use (for now). This is better
+ * than a panic, but not desirable.
+ */
+ tw = intotw(t);
+ if (tw == NULL ||
+ (reuseport & tw->tw_so_options) == 0)
+ return (EADDRINUSE);
+ } else if (t && (reuseport & t->inp_socket->so_options)
+ == 0) {
return (EADDRINUSE);
+ }
#ifdef INET
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
@@ -246,19 +258,19 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam,
t = in_pcblookup_local(pcbinfo, sin.sin_addr,
lport, lookupflags, cred);
if (t && t->inp_flags & INP_TIMEWAIT) {
- if ((reuseport &
- intotw(t)->tw_so_options) == 0 &&
- (ntohl(t->inp_laddr.s_addr) !=
+ tw = intotw(t);
+ if (tw == NULL)
+ return (EADDRINUSE);
+ if ((reuseport & tw->tw_so_options) == 0
+ && (ntohl(t->inp_laddr.s_addr) !=
INADDR_ANY || ((inp->inp_vflag &
INP_IPV6PROTO) ==
(t->inp_vflag & INP_IPV6PROTO))))
return (EADDRINUSE);
- }
- else if (t &&
- (reuseport & t->inp_socket->so_options)
- == 0 && (ntohl(t->inp_laddr.s_addr) !=
- INADDR_ANY || INP_SOCKAF(so) ==
- INP_SOCKAF(t->inp_socket)))
+ } else if (t && (reuseport == 0 ||
+ (t->inp_flags2 & INP_REUSEPORT) == 0) &&
+ (ntohl(t->inp_laddr.s_addr) != INADDR_ANY ||
+ (t->inp_vflag & INP_IPV6PROTO) != 0))
return (EADDRINUSE);
}
#endif
diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c
index c802bfc..2b3493e 100644
--- a/sys/netinet6/in6_src.c
+++ b/sys/netinet6/in6_src.c
@@ -927,7 +927,7 @@ struct walkarg {
static int in6_src_sysctl(SYSCTL_HANDLER_ARGS);
SYSCTL_DECL(_net_inet6_ip6);
-SYSCTL_NODE(_net_inet6_ip6, IPV6CTL_ADDRCTLPOLICY, addrctlpolicy,
+static SYSCTL_NODE(_net_inet6_ip6, IPV6CTL_ADDRCTLPOLICY, addrctlpolicy,
CTLFLAG_RD, in6_src_sysctl, "");
static int
diff --git a/sys/netinet6/ip6_mroute.c b/sys/netinet6/ip6_mroute.c
index 0c1ff78..a4f5044 100644
--- a/sys/netinet6/ip6_mroute.c
+++ b/sys/netinet6/ip6_mroute.c
@@ -156,7 +156,7 @@ static VNET_DEFINE(int, ip6_mrouter_ver) = 0;
SYSCTL_DECL(_net_inet6);
SYSCTL_DECL(_net_inet6_ip6);
-SYSCTL_NODE(_net_inet6, IPPROTO_PIM, pim, CTLFLAG_RW, 0, "PIM");
+static SYSCTL_NODE(_net_inet6, IPPROTO_PIM, pim, CTLFLAG_RW, 0, "PIM");
static struct mrt6stat mrt6stat;
SYSCTL_STRUCT(_net_inet6_ip6, OID_AUTO, mrt6stat, CTLFLAG_RW,
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index e4d5172..5372438 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -1421,7 +1421,38 @@ ip6_ctloutput(struct socket *so, struct sockopt *sopt)
optval = 0;
uproto = (int)so->so_proto->pr_protocol;
- if (level == IPPROTO_IPV6) {
+ if (level != IPPROTO_IPV6) {
+ error = EINVAL;
+
+ if (sopt->sopt_level == SOL_SOCKET &&
+ sopt->sopt_dir == SOPT_SET) {
+ switch (sopt->sopt_name) {
+ case SO_REUSEADDR:
+ INP_WLOCK(in6p);
+ if (IN_MULTICAST(ntohl(in6p->inp_laddr.s_addr))) {
+ if ((so->so_options &
+ (SO_REUSEADDR | SO_REUSEPORT)) != 0)
+ in6p->inp_flags2 |= INP_REUSEPORT;
+ else
+ in6p->inp_flags2 &= ~INP_REUSEPORT;
+ }
+ INP_WUNLOCK(in6p);
+ error = 0;
+ break;
+ case SO_REUSEPORT:
+ INP_WLOCK(in6p);
+ if ((so->so_options & SO_REUSEPORT) != 0)
+ in6p->inp_flags2 |= INP_REUSEPORT;
+ else
+ in6p->inp_flags2 &= ~INP_REUSEPORT;
+ INP_WUNLOCK(in6p);
+ error = 0;
+ break;
+ default:
+ break;
+ }
+ }
+ } else { /* level == IPPROTO_IPV6 */
switch (op) {
case SOPT_SET:
@@ -2044,8 +2075,6 @@ do { \
}
break;
}
- } else { /* level != IPPROTO_IPV6 */
- error = EINVAL;
}
return (error);
}
diff --git a/sys/netinet6/mld6.c b/sys/netinet6/mld6.c
index a56f83d..8f8e326 100644
--- a/sys/netinet6/mld6.c
+++ b/sys/netinet6/mld6.c
@@ -193,7 +193,7 @@ static int sysctl_mld_ifinfo(SYSCTL_HANDLER_ARGS);
* to a vnet in ifp->if_vnet.
*/
static struct mtx mld_mtx;
-MALLOC_DEFINE(M_MLD, "mld", "mld state");
+static MALLOC_DEFINE(M_MLD, "mld", "mld state");
#define MLD_EMBEDSCOPE(pin6, zoneid) \
if (IN6_IS_SCOPE_LINKLOCAL(pin6) || \
@@ -231,8 +231,9 @@ SYSCTL_VNET_PROC(_net_inet6_mld, OID_AUTO, gsrdelay,
/*
* Non-virtualized sysctls.
*/
-SYSCTL_NODE(_net_inet6_mld, OID_AUTO, ifinfo, CTLFLAG_RD | CTLFLAG_MPSAFE,
- sysctl_mld_ifinfo, "Per-interface MLDv2 state");
+static SYSCTL_NODE(_net_inet6_mld, OID_AUTO, ifinfo,
+ CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_mld_ifinfo,
+ "Per-interface MLDv2 state");
static int mld_v1enable = 1;
SYSCTL_INT(_net_inet6_mld, OID_AUTO, v1enable, CTLFLAG_RW,
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index ae7cc4a..875daa0 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -1174,6 +1174,46 @@ done:
}
+/*
+ * Rejuvenate this function for routing operations related
+ * processing.
+ */
+void
+nd6_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
+{
+ struct sockaddr_in6 *gateway = (struct sockaddr_in6 *)rt->rt_gateway;
+ struct nd_defrouter *dr;
+ struct ifnet *ifp = rt->rt_ifp;
+
+ RT_LOCK_ASSERT(rt);
+
+ switch (req) {
+ case RTM_ADD:
+ break;
+
+ case RTM_DELETE:
+ if (!ifp)
+ return;
+ /*
+ * Only indirect routes are interesting.
+ */
+ if ((rt->rt_flags & RTF_GATEWAY) == 0)
+ return;
+ /*
+ * check for default route
+ */
+ if (IN6_ARE_ADDR_EQUAL(&in6addr_any,
+ &SIN6(rt_key(rt))->sin6_addr)) {
+
+ dr = defrouter_lookup(&gateway->sin6_addr, ifp);
+ if (dr != NULL)
+ dr->installed = 0;
+ }
+ break;
+ }
+}
+
+
int
nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
{
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
index 6f63192..ca981d0 100644
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -406,6 +406,7 @@ void nd6_purge __P((struct ifnet *));
void nd6_nud_hint __P((struct rtentry *, struct in6_addr *, int));
int nd6_resolve __P((struct ifnet *, struct rtentry *, struct mbuf *,
struct sockaddr *, u_char *));
+void nd6_rtrequest __P((int, struct rtentry *, struct rt_addrinfo *));
int nd6_ioctl __P((u_long, caddr_t, struct ifnet *));
struct llentry *nd6_cache_lladdr __P((struct ifnet *, struct in6_addr *,
char *, int, int, int));
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
index 5352dd5..237f14c 100644
--- a/sys/netinet6/nd6_rtr.c
+++ b/sys/netinet6/nd6_rtr.c
@@ -751,9 +751,10 @@ defrtrlist_update(struct nd_defrouter *new)
/*
* If the preference does not change, there's no need
- * to sort the entries.
+ * to sort the entries. Also make sure the selected
+ * router is still installed in the kernel.
*/
- if (rtpref(new) == oldpref) {
+ if (dr->installed && rtpref(new) == oldpref) {
splx(s);
return (dr);
}
diff --git a/sys/netinet6/send.c b/sys/netinet6/send.c
index 71d88d0..5624366 100644
--- a/sys/netinet6/send.c
+++ b/sys/netinet6/send.c
@@ -55,7 +55,7 @@ __FBSDID("$FreeBSD$");
#include <netinet6/scope6_var.h>
#include <netinet6/send.h>
-MALLOC_DEFINE(M_SEND, "send", "Secure Neighbour Discovery");
+static MALLOC_DEFINE(M_SEND, "send", "Secure Neighbour Discovery");
/*
* The socket used to communicate with the SeND daemon.
OpenPOWER on IntegriCloud