diff options
Diffstat (limited to 'freebsd/sys/netinet6/in6_ifattach.c')
-rw-r--r-- | freebsd/sys/netinet6/in6_ifattach.c | 72 |
1 files changed, 32 insertions, 40 deletions
diff --git a/freebsd/sys/netinet6/in6_ifattach.c b/freebsd/sys/netinet6/in6_ifattach.c index c2134c6f..bb150eb1 100644 --- a/freebsd/sys/netinet6/in6_ifattach.c +++ b/freebsd/sys/netinet6/in6_ifattach.c @@ -249,7 +249,7 @@ in6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6) static u_int8_t allone[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - IF_ADDR_LOCK(ifp); + IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != AF_LINK) continue; @@ -261,7 +261,7 @@ in6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6) goto found; } - IF_ADDR_UNLOCK(ifp); + IF_ADDR_RUNLOCK(ifp); return -1; @@ -273,6 +273,7 @@ found: /* get EUI64 */ switch (ifp->if_type) { case IFT_ETHER: + case IFT_L2VLAN: case IFT_FDDI: case IFT_ISO88025: case IFT_ATM: @@ -287,7 +288,7 @@ found: /* look at IEEE802/EUI64 only */ if (addrlen != 8 && addrlen != 6) { - IF_ADDR_UNLOCK(ifp); + IF_ADDR_RUNLOCK(ifp); return -1; } @@ -297,11 +298,11 @@ found: * card insertion. */ if (bcmp(addr, allzero, addrlen) == 0) { - IF_ADDR_UNLOCK(ifp); + IF_ADDR_RUNLOCK(ifp); return -1; } if (bcmp(addr, allone, addrlen) == 0) { - IF_ADDR_UNLOCK(ifp); + IF_ADDR_RUNLOCK(ifp); return -1; } @@ -322,11 +323,11 @@ found: case IFT_ARCNET: if (addrlen != 1) { - IF_ADDR_UNLOCK(ifp); + IF_ADDR_RUNLOCK(ifp); return -1; } if (!addr[0]) { - IF_ADDR_UNLOCK(ifp); + IF_ADDR_RUNLOCK(ifp); return -1; } @@ -350,17 +351,17 @@ found: * identifier source (can be renumbered). * we don't do this. */ - IF_ADDR_UNLOCK(ifp); + IF_ADDR_RUNLOCK(ifp); return -1; default: - IF_ADDR_UNLOCK(ifp); + IF_ADDR_RUNLOCK(ifp); return -1; } /* sanity check: g bit must not indicate "group" */ if (EUI64_GROUP(in6)) { - IF_ADDR_UNLOCK(ifp); + IF_ADDR_RUNLOCK(ifp); return -1; } @@ -373,11 +374,11 @@ found: */ if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 && bcmp(&in6->s6_addr[9], allzero, 7) == 0) { - IF_ADDR_UNLOCK(ifp); + IF_ADDR_RUNLOCK(ifp); return -1; } - IF_ADDR_UNLOCK(ifp); + IF_ADDR_RUNLOCK(ifp); return 0; } @@ -410,7 +411,7 @@ get_ifid(struct ifnet *ifp0, struct ifnet *altifp, /* next, try to get it from some other hardware interface */ IFNET_RLOCK_NOSLEEP(); - for (ifp = V_ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) { + TAILQ_FOREACH(ifp, &V_ifnet, if_list) { if (ifp == ifp0) continue; if (in6_get_hw_ifid(ifp, in6) != 0) @@ -518,12 +519,8 @@ in6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp) } ia = in6ifa_ifpforlinklocal(ifp, 0); /* ia must not be NULL */ -#ifdef DIAGNOSTIC - if (!ia) { - panic("ia == NULL in in6_ifattach_linklocal"); - /* NOTREACHED */ - } -#endif + KASSERT(ia != NULL, ("%s: ia == NULL, ifp=%p", __func__, ifp)); + ifa_free(&ia->ia_ifa); /* @@ -798,7 +795,6 @@ in6_ifdetach(struct ifnet *ifp) struct ifaddr *ifa, *next; struct radix_node_head *rnh; struct rtentry *rt; - short rtflags; struct sockaddr_in6 sin6; struct in6_multi_mship *imm; @@ -824,26 +820,19 @@ in6_ifdetach(struct ifnet *ifp) /* * leave from multicast groups we have joined for the interface */ - while ((imm = ia->ia6_memberships.lh_first) != NULL) { + while ((imm = LIST_FIRST(&ia->ia6_memberships)) != NULL) { LIST_REMOVE(imm, i6mm_chain); in6_leavegroup(imm); } - /* remove from the routing table */ - if ((ia->ia_flags & IFA_ROUTE) && - (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0, 0UL))) { - rtflags = rt->rt_flags; - RTFREE_LOCKED(rt); - rtrequest(RTM_DELETE, (struct sockaddr *)&ia->ia_addr, - (struct sockaddr *)&ia->ia_addr, - (struct sockaddr *)&ia->ia_prefixmask, - rtflags, (struct rtentry **)0); - } + /* Remove link-local from the routing table. */ + if (ia->ia_flags & IFA_ROUTE) + (void)rtinit(&ia->ia_ifa, RTM_DELETE, ia->ia_flags); /* remove from the linked list */ - IF_ADDR_LOCK(ifp); + IF_ADDR_WLOCK(ifp); TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link); - IF_ADDR_UNLOCK(ifp); + IF_ADDR_WUNLOCK(ifp); ifa_free(ifa); /* if_addrhead */ IN6_IFADDR_WLOCK(); @@ -867,7 +856,10 @@ in6_ifdetach(struct ifnet *ifp) */ nd6_purge(ifp); - /* remove route to link-local allnodes multicast (ff02::1) */ + /* + * Remove route to link-local allnodes multicast (ff02::1). + * These only get automatically installed for the default FIB. + */ bzero(&sin6, sizeof(sin6)); sin6.sin6_len = sizeof(struct sockaddr_in6); sin6.sin6_family = AF_INET6; @@ -876,10 +868,11 @@ in6_ifdetach(struct ifnet *ifp) /* XXX: should not fail */ return; /* XXX grab lock first to avoid LOR */ - rnh = rt_tables_get_rnh(0, AF_INET6); + rnh = rt_tables_get_rnh(RT_DEFAULT_FIB, AF_INET6); if (rnh != NULL) { RADIX_NODE_HEAD_LOCK(rnh); - rt = rtalloc1((struct sockaddr *)&sin6, 0, RTF_RNH_LOCKED); + rt = in6_rtalloc1((struct sockaddr *)&sin6, 0, RTF_RNH_LOCKED, + RT_DEFAULT_FIB); if (rt) { if (rt->rt_ifp == ifp) rtexpunge(rt); @@ -927,8 +920,7 @@ in6_tmpaddrtimer(void *arg) V_ip6_temp_regen_advance) * hz, in6_tmpaddrtimer, curvnet); bzero(nullbuf, sizeof(nullbuf)); - for (ifp = TAILQ_FIRST(&V_ifnet); ifp; - ifp = TAILQ_NEXT(ifp, if_list)) { + TAILQ_FOREACH(ifp, &V_ifnet, if_list) { ndi = ND_IFINFO(ifp); if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) { /* @@ -959,7 +951,7 @@ in6_purgemaddrs(struct ifnet *ifp) * We need to do this as IF_ADDR_LOCK() may be re-acquired * by code further down. */ - IF_ADDR_LOCK(ifp); + IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_INET6 || ifma->ifma_protospec == NULL) @@ -967,7 +959,7 @@ in6_purgemaddrs(struct ifnet *ifp) inm = (struct in6_multi *)ifma->ifma_protospec; LIST_INSERT_HEAD(&purgeinms, inm, in6m_entry); } - IF_ADDR_UNLOCK(ifp); + IF_ADDR_RUNLOCK(ifp); LIST_FOREACH_SAFE(inm, &purgeinms, in6m_entry, tinm) { LIST_REMOVE(inm, in6m_entry); |