diff options
author | Luiz Otavio O Souza <luiz@netgate.com> | 2016-07-02 18:35:17 -0500 |
---|---|---|
committer | Luiz Otavio O Souza <luiz@netgate.com> | 2016-07-02 18:35:17 -0500 |
commit | 7aa502721fb5918b709ae7595537705faf38408f (patch) | |
tree | 30415c6cc6c3459cd83d9760112ca3b2b6c75c2f /sys/netinet6 | |
parent | 13d9c0c302a9efbf93724bd23c4b86a757e45348 (diff) | |
parent | d08d8c2ff3af6ce2ba65f9805f1f061373e78a82 (diff) | |
download | FreeBSD-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.c | 12 | ||||
-rw-r--r-- | sys/netinet6/in6_ifattach.c | 48 | ||||
-rw-r--r-- | sys/netinet6/in6_ifattach.h | 1 | ||||
-rw-r--r-- | sys/netinet6/ip6_input.c | 26 | ||||
-rw-r--r-- | sys/netinet6/ip6_mroute.c | 2 | ||||
-rw-r--r-- | sys/netinet6/mld6.c | 17 | ||||
-rw-r--r-- | sys/netinet6/nd6.c | 13 | ||||
-rw-r--r-- | sys/netinet6/nd6.h | 2 | ||||
-rw-r--r-- | sys/netinet6/sctp6_usrreq.c | 3 |
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) { /* |