diff options
Diffstat (limited to 'sys/netinet6')
-rw-r--r-- | sys/netinet6/icmp6.c | 24 | ||||
-rw-r--r-- | sys/netinet6/in6.c | 2 | ||||
-rw-r--r-- | sys/netinet6/in6_mcast.c | 7 | ||||
-rw-r--r-- | sys/netinet6/in6_pcb.c | 40 | ||||
-rw-r--r-- | sys/netinet6/in6_src.c | 2 | ||||
-rw-r--r-- | sys/netinet6/ip6_mroute.c | 2 | ||||
-rw-r--r-- | sys/netinet6/ip6_output.c | 35 | ||||
-rw-r--r-- | sys/netinet6/mld6.c | 7 | ||||
-rw-r--r-- | sys/netinet6/nd6.c | 40 | ||||
-rw-r--r-- | sys/netinet6/nd6.h | 1 | ||||
-rw-r--r-- | sys/netinet6/nd6_rtr.c | 5 | ||||
-rw-r--r-- | sys/netinet6/send.c | 2 |
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. |