summaryrefslogtreecommitdiffstats
path: root/sys/netinet6
diff options
context:
space:
mode:
authorLuiz Otavio O Souza <luiz@netgate.com>2016-07-02 18:35:17 -0500
committerLuiz Otavio O Souza <luiz@netgate.com>2016-07-02 18:35:17 -0500
commit7aa502721fb5918b709ae7595537705faf38408f (patch)
tree30415c6cc6c3459cd83d9760112ca3b2b6c75c2f /sys/netinet6
parent13d9c0c302a9efbf93724bd23c4b86a757e45348 (diff)
parentd08d8c2ff3af6ce2ba65f9805f1f061373e78a82 (diff)
downloadFreeBSD-src-7aa502721fb5918b709ae7595537705faf38408f.zip
FreeBSD-src-7aa502721fb5918b709ae7595537705faf38408f.tar.gz
Merge remote-tracking branch 'origin/master' into devel-11
Diffstat (limited to 'sys/netinet6')
-rw-r--r--sys/netinet6/in6.c12
-rw-r--r--sys/netinet6/in6_ifattach.c48
-rw-r--r--sys/netinet6/in6_ifattach.h1
-rw-r--r--sys/netinet6/ip6_input.c26
-rw-r--r--sys/netinet6/ip6_mroute.c2
-rw-r--r--sys/netinet6/mld6.c17
-rw-r--r--sys/netinet6/nd6.c13
-rw-r--r--sys/netinet6/nd6.h2
-rw-r--r--sys/netinet6/sctp6_usrreq.c3
9 files changed, 94 insertions, 30 deletions
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index e972ac7..4191782 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -2322,10 +2322,16 @@ in6_lltable_dump_entry(struct lltable *llt, struct llentry *lle,
sdl = &ndpc.sdl;
sdl->sdl_family = AF_LINK;
sdl->sdl_len = sizeof(*sdl);
- sdl->sdl_alen = ifp->if_addrlen;
sdl->sdl_index = ifp->if_index;
sdl->sdl_type = ifp->if_type;
- bcopy(lle->ll_addr, LLADDR(sdl), ifp->if_addrlen);
+ if ((lle->la_flags & LLE_VALID) == LLE_VALID) {
+ sdl->sdl_alen = ifp->if_addrlen;
+ bcopy(lle->ll_addr, LLADDR(sdl),
+ ifp->if_addrlen);
+ } else {
+ sdl->sdl_alen = 0;
+ bzero(LLADDR(sdl), ifp->if_addrlen);
+ }
if (lle->la_expire != 0)
ndpc.rtm.rtm_rmx.rmx_expire = lle->la_expire +
lle->lle_remtime / hz +
@@ -2419,7 +2425,7 @@ in6_domifdetach(struct ifnet *ifp, void *aux)
mld_domifdetach(ifp);
scope6_ifdetach(ext->scope6_id);
- nd6_ifdetach(ext->nd_ifinfo);
+ nd6_ifdetach(ifp, ext->nd_ifinfo);
lltable_free(ext->lltable);
COUNTER_ARRAY_FREE(ext->in6_ifstat,
sizeof(struct in6_ifstat) / sizeof(uint64_t));
diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c
index 471dd82..6c69399 100644
--- a/sys/netinet6/in6_ifattach.c
+++ b/sys/netinet6/in6_ifattach.c
@@ -761,19 +761,30 @@ in6_ifattach(struct ifnet *ifp, struct ifnet *altifp)
/*
* NOTE: in6_ifdetach() does not support loopback if at this moment.
- * We don't need this function in bsdi, because interfaces are never removed
- * from the ifnet list in bsdi.
+ *
+ * When shutting down a VNET we clean up layers top-down. In that case
+ * upper layer protocols (ulp) are cleaned up already and locks are destroyed
+ * and we must not call into these cleanup functions anymore, thus purgeulp
+ * is set to 0 in that case by in6_ifdetach_destroy().
+ * The normal case of destroying a (cloned) interface still needs to cleanup
+ * everything related to the interface and will have purgeulp set to 1.
*/
-void
-in6_ifdetach(struct ifnet *ifp)
+static void
+_in6_ifdetach(struct ifnet *ifp, int purgeulp)
{
struct ifaddr *ifa, *next;
if (ifp->if_afdata[AF_INET6] == NULL)
return;
- /* remove neighbor management table */
- nd6_purge(ifp);
+ /*
+ * Remove neighbor management table.
+ * Enabling the nd6_purge will panic on vmove for interfaces on VNET
+ * teardown as the IPv6 layer is cleaned up already and the locks
+ * are destroyed.
+ */
+ if (purgeulp)
+ nd6_purge(ifp);
/*
* nuke any of IPv6 addresses we have
@@ -784,9 +795,11 @@ in6_ifdetach(struct ifnet *ifp)
continue;
in6_purgeaddr(ifa);
}
- in6_pcbpurgeif0(&V_udbinfo, ifp);
- in6_pcbpurgeif0(&V_ulitecbinfo, ifp);
- in6_pcbpurgeif0(&V_ripcbinfo, ifp);
+ if (purgeulp) {
+ in6_pcbpurgeif0(&V_udbinfo, ifp);
+ in6_pcbpurgeif0(&V_ulitecbinfo, ifp);
+ in6_pcbpurgeif0(&V_ripcbinfo, ifp);
+ }
/* leave from all multicast groups joined */
in6_purgemaddrs(ifp);
@@ -798,7 +811,22 @@ in6_ifdetach(struct ifnet *ifp)
* prefixes after removing all addresses above.
* (Or can we just delay calling nd6_purge until at this point?)
*/
- nd6_purge(ifp);
+ if (purgeulp)
+ nd6_purge(ifp);
+}
+
+void
+in6_ifdetach(struct ifnet *ifp)
+{
+
+ _in6_ifdetach(ifp, 1);
+}
+
+void
+in6_ifdetach_destroy(struct ifnet *ifp)
+{
+
+ _in6_ifdetach(ifp, 0);
}
int
diff --git a/sys/netinet6/in6_ifattach.h b/sys/netinet6/in6_ifattach.h
index a5a82c0..a34530d 100644
--- a/sys/netinet6/in6_ifattach.h
+++ b/sys/netinet6/in6_ifattach.h
@@ -37,6 +37,7 @@
void in6_ifattach(struct ifnet *, struct ifnet *);
void in6_ifattach_destroy(void);
void in6_ifdetach(struct ifnet *);
+void in6_ifdetach_destroy(struct ifnet *);
int in6_get_tmpifid(struct ifnet *, u_int8_t *, const u_int8_t *, int);
void in6_tmpaddrtimer(void *);
int in6_get_hw_ifid(struct ifnet *, struct in6_addr *);
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index 9802c49..6b0fd2d 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -113,6 +113,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/icmp6.h>
#include <netinet6/scope6_var.h>
#include <netinet6/in6_ifattach.h>
+#include <netinet6/mld6_var.h>
#include <netinet6/nd6.h>
#include <netinet6/in6_rss.h>
@@ -318,6 +319,8 @@ ip6proto_unregister(short ip6proto)
static void
ip6_destroy(void *unused __unused)
{
+ struct ifaddr *ifa, *nifa;
+ struct ifnet *ifp;
int error;
#ifdef RSS
@@ -340,9 +343,30 @@ ip6_destroy(void *unused __unused)
"type HHOOK_TYPE_IPSEC_OUT, id HHOOK_IPSEC_INET6: "
"error %d returned\n", __func__, error);
}
- hashdestroy(V_in6_ifaddrhashtbl, M_IFADDR, V_in6_ifaddrhmask);
+
+ /* Cleanup addresses. */
+ IFNET_RLOCK();
+ TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
+ /* Cannot lock here - lock recursion. */
+ /* IF_ADDR_LOCK(ifp); */
+ TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, nifa) {
+
+ if (ifa->ifa_addr->sa_family != AF_INET6)
+ continue;
+ in6_purgeaddr(ifa);
+ }
+ /* IF_ADDR_UNLOCK(ifp); */
+ in6_ifdetach_destroy(ifp);
+ mld_domifdetach(ifp);
+ /* Make sure any routes are gone as well. */
+ rt_flushifroutes_af(ifp, AF_INET6);
+ }
+ IFNET_RUNLOCK();
+
nd6_destroy();
in6_ifattach_destroy();
+
+ hashdestroy(V_in6_ifaddrhashtbl, M_IFADDR, V_in6_ifaddrhmask);
}
VNET_SYSUNINIT(inet6, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, ip6_destroy, NULL);
diff --git a/sys/netinet6/ip6_mroute.c b/sys/netinet6/ip6_mroute.c
index f560dc5..3ae900d 100644
--- a/sys/netinet6/ip6_mroute.c
+++ b/sys/netinet6/ip6_mroute.c
@@ -1966,4 +1966,4 @@ static moduledata_t ip6_mroutemod = {
0
};
-DECLARE_MODULE(ip6_mroute, ip6_mroutemod, SI_SUB_PSEUDO, SI_ORDER_ANY);
+DECLARE_MODULE(ip6_mroute, ip6_mroutemod, SI_SUB_PROTO_MC, SI_ORDER_ANY);
diff --git a/sys/netinet6/mld6.c b/sys/netinet6/mld6.c
index dcae9f8..c7ad5a2 100644
--- a/sys/netinet6/mld6.c
+++ b/sys/netinet6/mld6.c
@@ -612,9 +612,6 @@ mli_delete_locked(const struct ifnet *ifp)
return;
}
}
-#ifdef INVARIANTS
- panic("%s: mld_ifsoftc not found for ifp %p\n", __func__, ifp);
-#endif
}
/*
@@ -3265,7 +3262,7 @@ mld_init(void *unused __unused)
mld_po.ip6po_prefer_tempaddr = IP6PO_TEMPADDR_NOTPREFER;
mld_po.ip6po_flags = IP6PO_DONTFRAG;
}
-SYSINIT(mld_init, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, mld_init, NULL);
+SYSINIT(mld_init, SI_SUB_PROTO_MC, SI_ORDER_MIDDLE, mld_init, NULL);
static void
mld_uninit(void *unused __unused)
@@ -3274,7 +3271,7 @@ mld_uninit(void *unused __unused)
CTR1(KTR_MLD, "%s: tearing down", __func__);
MLD_LOCK_DESTROY();
}
-SYSUNINIT(mld_uninit, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, mld_uninit, NULL);
+SYSUNINIT(mld_uninit, SI_SUB_PROTO_MC, SI_ORDER_MIDDLE, mld_uninit, NULL);
static void
vnet_mld_init(const void *unused __unused)
@@ -3284,19 +3281,17 @@ vnet_mld_init(const void *unused __unused)
LIST_INIT(&V_mli_head);
}
-VNET_SYSINIT(vnet_mld_init, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_mld_init,
+VNET_SYSINIT(vnet_mld_init, SI_SUB_PROTO_MC, SI_ORDER_ANY, vnet_mld_init,
NULL);
static void
vnet_mld_uninit(const void *unused __unused)
{
+ /* This can happen if we shutdown the network stack. */
CTR1(KTR_MLD, "%s: tearing down", __func__);
-
- KASSERT(LIST_EMPTY(&V_mli_head),
- ("%s: mli list not empty; ifnets not detached?", __func__));
}
-VNET_SYSUNINIT(vnet_mld_uninit, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_mld_uninit,
+VNET_SYSUNINIT(vnet_mld_uninit, SI_SUB_PROTO_MC, SI_ORDER_ANY, vnet_mld_uninit,
NULL);
static int
@@ -3318,4 +3313,4 @@ static moduledata_t mld_mod = {
mld_modevent,
0
};
-DECLARE_MODULE(mld, mld_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
+DECLARE_MODULE(mld, mld_mod, SI_SUB_PROTO_MC, SI_ORDER_ANY);
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index a75d588..8fc229f 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -292,8 +292,19 @@ nd6_ifattach(struct ifnet *ifp)
}
void
-nd6_ifdetach(struct nd_ifinfo *nd)
+nd6_ifdetach(struct ifnet *ifp, struct nd_ifinfo *nd)
{
+ struct ifaddr *ifa, *next;
+
+ IF_ADDR_RLOCK(ifp);
+ TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) {
+ if (ifa->ifa_addr->sa_family != AF_INET6)
+ continue;
+
+ /* stop DAD processing */
+ nd6_dad_stop(ifa);
+ }
+ IF_ADDR_RUNLOCK(ifp);
free(nd, M_IP6NDP);
}
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
index ce98975..33ac438 100644
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -414,7 +414,7 @@ void nd6_init(void);
void nd6_destroy(void);
#endif
struct nd_ifinfo *nd6_ifattach(struct ifnet *);
-void nd6_ifdetach(struct nd_ifinfo *);
+void nd6_ifdetach(struct ifnet *, struct nd_ifinfo *);
int nd6_is_addr_neighbor(const struct sockaddr_in6 *, struct ifnet *);
void nd6_option_init(void *, int, union nd_opts *);
struct nd_opt_hdr *nd6_option(union nd_opts *);
diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c
index 647107d..cbe50d9 100644
--- a/sys/netinet6/sctp6_usrreq.c
+++ b/sys/netinet6/sctp6_usrreq.c
@@ -341,8 +341,7 @@ sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d)
&inp, &net, 1, SCTP_DEFAULT_VRFID);
if ((stcb != NULL) &&
(net != NULL) &&
- (inp != NULL) &&
- (inp->sctp_socket != NULL)) {
+ (inp != NULL)) {
/* Check the verification tag */
if (ntohl(sh.v_tag) != 0) {
/*
OpenPOWER on IntegriCloud