summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netinet6
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-11-06 15:42:44 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-11-15 10:56:14 +0100
commite0b4edbdcc3558d3f38af8398f995c2e9f019f07 (patch)
treeea91a5fcfb9b6a66a8c0b74cf68ff8d450ce17e0 /freebsd/sys/netinet6
parentDisable or make static kern_* functions (diff)
downloadrtems-libbsd-e0b4edbdcc3558d3f38af8398f995c2e9f019f07.tar.bz2
Update to FreeBSD head 2018-11-15
Git mirror commit a18b0830c4be01b39489a891b63d6023ada6358a. Update #3472.
Diffstat (limited to 'freebsd/sys/netinet6')
-rw-r--r--freebsd/sys/netinet6/in6_gif.c5
-rw-r--r--freebsd/sys/netinet6/in6_ifattach.c13
-rw-r--r--freebsd/sys/netinet6/in6_pcb.c6
-rw-r--r--freebsd/sys/netinet6/nd6.h3
-rw-r--r--freebsd/sys/netinet6/nd6_rtr.c38
-rw-r--r--freebsd/sys/netinet6/raw_ip6.c86
6 files changed, 102 insertions, 49 deletions
diff --git a/freebsd/sys/netinet6/in6_gif.c b/freebsd/sys/netinet6/in6_gif.c
index 66c2cfb4..d7396bb1 100644
--- a/freebsd/sys/netinet6/in6_gif.c
+++ b/freebsd/sys/netinet6/in6_gif.c
@@ -155,7 +155,8 @@ in6_gif_srcaddr(void *arg __unused, const struct sockaddr *sa, int event)
const struct sockaddr_in6 *sin;
struct gif_softc *sc;
- if (V_ipv6_srchashtbl == NULL)
+ /* Check that VNET is ready */
+ if (V_ipv6_hashtbl == NULL)
return;
MPASS(in_epoch(net_epoch_preempt));
@@ -482,6 +483,8 @@ in6_gif_uninit(void)
}
if (V_ipv6_hashtbl != NULL) {
gif_hashdestroy(V_ipv6_hashtbl);
+ V_ipv6_hashtbl = NULL;
+ GIF_WAIT();
gif_hashdestroy(V_ipv6_srchashtbl);
}
}
diff --git a/freebsd/sys/netinet6/in6_ifattach.c b/freebsd/sys/netinet6/in6_ifattach.c
index 1cab31d1..6af4b557 100644
--- a/freebsd/sys/netinet6/in6_ifattach.c
+++ b/freebsd/sys/netinet6/in6_ifattach.c
@@ -487,9 +487,16 @@ in6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp)
return (-1);
}
- ia = in6ifa_ifpforlinklocal(ifp, 0); /* ia must not be NULL */
- KASSERT(ia != NULL, ("%s: ia == NULL, ifp=%p", __func__, ifp));
-
+ ia = in6ifa_ifpforlinklocal(ifp, 0);
+ if (ia == NULL) {
+ /*
+ * Another thread removed the address that we just added.
+ * This should be rare, but it happens.
+ */
+ nd6log((LOG_NOTICE, "%s: %s: new link-local address "
+ "disappeared\n", __func__, if_name(ifp)));
+ return (-1);
+ }
ifa_free(&ia->ia_ifa);
/*
diff --git a/freebsd/sys/netinet6/in6_pcb.c b/freebsd/sys/netinet6/in6_pcb.c
index 53102764..f5b22db7 100644
--- a/freebsd/sys/netinet6/in6_pcb.c
+++ b/freebsd/sys/netinet6/in6_pcb.c
@@ -1175,13 +1175,11 @@ in6_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in6_addr *faddr,
/*
* Then look in lb group (for wildcard match).
*/
- if (pcbinfo->ipi_lbgrouphashbase != NULL &&
- (lookupflags & INPLOOKUP_WILDCARD)) {
+ if ((lookupflags & INPLOOKUP_WILDCARD) != 0) {
inp = in6_pcblookup_lbgroup(pcbinfo, laddr, lport, faddr,
fport, lookupflags);
- if (inp != NULL) {
+ if (inp != NULL)
return (inp);
- }
}
/*
diff --git a/freebsd/sys/netinet6/nd6.h b/freebsd/sys/netinet6/nd6.h
index cabfeec0..7544d23c 100644
--- a/freebsd/sys/netinet6/nd6.h
+++ b/freebsd/sys/netinet6/nd6.h
@@ -90,6 +90,9 @@ struct nd_ifinfo {
#define ND6_IFF_NO_RADR 0x40
#define ND6_IFF_NO_PREFER_IFACE 0x80 /* XXX: not related to ND. */
#define ND6_IFF_NO_DAD 0x100
+#ifdef EXPERIMENTAL
+#define ND6_IFF_IPV6_ONLY 0x200 /* draft-ietf-6man-ipv6only-flag */
+#endif
#ifdef _KERNEL
#define ND_IFINFO(ifp) \
diff --git a/freebsd/sys/netinet6/nd6_rtr.c b/freebsd/sys/netinet6/nd6_rtr.c
index a60e7c66..59868383 100644
--- a/freebsd/sys/netinet6/nd6_rtr.c
+++ b/freebsd/sys/netinet6/nd6_rtr.c
@@ -206,6 +206,37 @@ nd6_rs_input(struct mbuf *m, int off, int icmp6len)
m_freem(m);
}
+#ifdef EXPERIMENTAL
+/*
+ * An initial update routine for draft-ietf-6man-ipv6only-flag.
+ * We need to iterate over all default routers for the given
+ * interface to see whether they are all advertising the "6"
+ * (IPv6-Only) flag. If they do set, otherwise unset, the
+ * interface flag we later use to filter on.
+ */
+static void
+defrtr_ipv6_only_ifp(struct ifnet *ifp)
+{
+ struct nd_defrouter *dr;
+ bool ipv6_only;
+
+ ipv6_only = true;
+ ND6_RLOCK();
+ TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry)
+ if (dr->ifp == ifp &&
+ (dr->raflags & ND_RA_FLAG_IPV6_ONLY) == 0)
+ ipv6_only = false;
+ ND6_RUNLOCK();
+
+ IF_AFDATA_WLOCK(ifp);
+ if (ipv6_only)
+ ND_IFINFO(ifp)->flags |= ND6_IFF_IPV6_ONLY;
+ else
+ ND_IFINFO(ifp)->flags &= ~ND6_IFF_IPV6_ONLY;
+ IF_AFDATA_WUNLOCK(ifp);
+}
+#endif
+
/*
* Receive Router Advertisement Message.
*
@@ -321,6 +352,9 @@ nd6_ra_input(struct mbuf *m, int off, int icmp6len)
}
}
dr = defrtrlist_update(&dr0);
+#ifdef EXPERIMENTAL
+ defrtr_ipv6_only_ifp(ifp);
+#endif
}
/*
@@ -694,6 +728,10 @@ defrouter_del(struct nd_defrouter *dr)
if (ND_IFINFO(dr->ifp)->flags & ND6_IFF_ACCEPT_RTADV)
rt6_flush(&dr->rtaddr, dr->ifp);
+#ifdef EXPERIMENTAL
+ defrtr_ipv6_only_ifp(dr->ifp);
+#endif
+
if (dr->installed) {
deldr = dr;
defrouter_delreq(dr);
diff --git a/freebsd/sys/netinet6/raw_ip6.c b/freebsd/sys/netinet6/raw_ip6.c
index 9c3d7a61..73d0832a 100644
--- a/freebsd/sys/netinet6/raw_ip6.c
+++ b/freebsd/sys/netinet6/raw_ip6.c
@@ -189,6 +189,45 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&
!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src))
continue;
+ if (last != NULL) {
+ struct mbuf *n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
+
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
+ /*
+ * Check AH/ESP integrity.
+ */
+ if (IPSEC_ENABLED(ipv6)) {
+ if (n != NULL &&
+ IPSEC_CHECK_POLICY(ipv6, n, last) != 0) {
+ m_freem(n);
+ /* Do not inject data into pcb. */
+ n = NULL;
+ }
+ }
+#endif /* IPSEC */
+ if (n) {
+ if (last->inp_flags & INP_CONTROLOPTS ||
+ last->inp_socket->so_options & SO_TIMESTAMP)
+ ip6_savecontrol(last, n, &opts);
+ /* strip intermediate headers */
+ m_adj(n, *offp);
+ if (sbappendaddr(&last->inp_socket->so_rcv,
+ (struct sockaddr *)&fromsa,
+ n, opts) == 0) {
+ m_freem(n);
+ if (opts)
+ m_freem(opts);
+ RIP6STAT_INC(rip6s_fullsock);
+ } else
+ sorwakeup(last->inp_socket);
+ opts = NULL;
+ }
+ INP_RUNLOCK(last);
+ last = NULL;
+ }
+ INP_RLOCK(in6p);
+ if (__predict_false(in6p->inp_flags2 & INP_FREED))
+ goto skip_2;
if (jailed_without_vnet(in6p->inp_cred)) {
/*
* Allow raw socket in jail to receive multicast;
@@ -198,16 +237,14 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) &&
prison_check_ip6(in6p->inp_cred,
&ip6->ip6_dst) != 0)
- continue;
+ goto skip_2;
}
- INP_RLOCK(in6p);
if (in6p->in6p_cksum != -1) {
RIP6STAT_INC(rip6s_isum);
if (in6_cksum(m, proto, *offp,
m->m_pkthdr.len - *offp)) {
- INP_RUNLOCK(in6p);
RIP6STAT_INC(rip6s_badsum);
- continue;
+ goto skip_2;
}
}
/*
@@ -253,46 +290,13 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
}
if (blocked != MCAST_PASS) {
IP6STAT_INC(ip6s_notmember);
- INP_RUNLOCK(in6p);
- continue;
- }
- }
- if (last != NULL) {
- struct mbuf *n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
-
-#if defined(IPSEC) || defined(IPSEC_SUPPORT)
- /*
- * Check AH/ESP integrity.
- */
- if (IPSEC_ENABLED(ipv6)) {
- if (n != NULL &&
- IPSEC_CHECK_POLICY(ipv6, n, last) != 0) {
- m_freem(n);
- /* Do not inject data into pcb. */
- n = NULL;
- }
- }
-#endif /* IPSEC */
- if (n) {
- if (last->inp_flags & INP_CONTROLOPTS ||
- last->inp_socket->so_options & SO_TIMESTAMP)
- ip6_savecontrol(last, n, &opts);
- /* strip intermediate headers */
- m_adj(n, *offp);
- if (sbappendaddr(&last->inp_socket->so_rcv,
- (struct sockaddr *)&fromsa,
- n, opts) == 0) {
- m_freem(n);
- if (opts)
- m_freem(opts);
- RIP6STAT_INC(rip6s_fullsock);
- } else
- sorwakeup(last->inp_socket);
- opts = NULL;
+ goto skip_2;
}
- INP_RUNLOCK(last);
}
last = in6p;
+ continue;
+skip_2:
+ INP_RUNLOCK(in6p);
}
INP_INFO_RUNLOCK_ET(&V_ripcbinfo, et);
#if defined(IPSEC) || defined(IPSEC_SUPPORT)