diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2017-04-04 09:36:57 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2017-04-04 14:46:23 +0200 |
commit | de8a76da2f374792594ce03a203b3f30e4889f6f (patch) | |
tree | 12b5e1e59358005c3c522955c08aee4795e4829c /freebsd/sys/netinet6/nd6.c | |
parent | Enable bridging by default (diff) | |
download | rtems-libbsd-de8a76da2f374792594ce03a203b3f30e4889f6f.tar.bz2 |
Update to FreeBSD head 2017-04-04
Git mirror commit 642b174daddbd0efd9bb5f242c43f4ab4db6869f.
Diffstat (limited to 'freebsd/sys/netinet6/nd6.c')
-rw-r--r-- | freebsd/sys/netinet6/nd6.c | 74 |
1 files changed, 44 insertions, 30 deletions
diff --git a/freebsd/sys/netinet6/nd6.c b/freebsd/sys/netinet6/nd6.c index 757130b8..cb626e5a 100644 --- a/freebsd/sys/netinet6/nd6.c +++ b/freebsd/sys/netinet6/nd6.c @@ -159,6 +159,7 @@ nd6_lle_event(void *arg __unused, struct llentry *lle, int evt) struct sockaddr_dl gw; struct ifnet *ifp; int type; + int fibnum; LLE_WLOCK_ASSERT(lle); @@ -196,8 +197,9 @@ nd6_lle_event(void *arg __unused, struct llentry *lle, int evt) rtinfo.rti_info[RTAX_DST] = (struct sockaddr *)&dst; rtinfo.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&gw; rtinfo.rti_addrs = RTA_DST | RTA_GATEWAY; + fibnum = V_rt_add_addr_allfibs ? RT_ALL_FIBS : ifp->if_fib; rt_missmsg_fib(type, &rtinfo, RTF_HOST | RTF_LLDATA | ( - type == RTM_ADD ? RTF_UP: 0), 0, RT_DEFAULT_FIB); + type == RTM_ADD ? RTF_UP: 0), 0, fibnum); } /* @@ -1202,7 +1204,7 @@ nd6_purge(struct ifnet *ifp) if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV) { /* Refresh default router list. */ - defrouter_select(); + defrouter_select_fib(ifp->if_fib); } } @@ -1255,7 +1257,7 @@ static int nd6_is_new_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp) { struct nd_prefix *pr; - struct ifaddr *dstaddr; + struct ifaddr *ifa; struct rt_addrinfo info; struct sockaddr_in6 rt_key; const struct sockaddr *dst6; @@ -1289,9 +1291,6 @@ nd6_is_new_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp) bzero(&info, sizeof(info)); info.rti_info[RTAX_DST] = (struct sockaddr *)&rt_key; - /* Always use the default FIB here. XXME - why? */ - fibnum = RT_DEFAULT_FIB; - /* * If the address matches one of our addresses, * it should be a neighbor. @@ -1305,19 +1304,31 @@ restart: continue; if ((pr->ndpr_stateflags & NDPRF_ONLINK) == 0) { - /* Always use the default FIB here. */ dst6 = (const struct sockaddr *)&pr->ndpr_prefix; - genid = V_nd6_list_genid; - ND6_RUNLOCK(); - - /* Restore length field before retrying lookup */ - rt_key.sin6_len = sizeof(rt_key); - error = rib_lookup_info(fibnum, dst6, 0, 0, &info); + /* + * We only need to check all FIBs if add_addr_allfibs + * is unset. If set, checking any FIB will suffice. + */ + fibnum = V_rt_add_addr_allfibs ? rt_numfibs - 1 : 0; + for (; fibnum < rt_numfibs; fibnum++) { + genid = V_nd6_list_genid; + ND6_RUNLOCK(); - ND6_RLOCK(); - if (genid != V_nd6_list_genid) - goto restart; + /* + * Restore length field before + * retrying lookup + */ + rt_key.sin6_len = sizeof(rt_key); + error = rib_lookup_info(fibnum, dst6, 0, 0, + &info); + + ND6_RLOCK(); + if (genid != V_nd6_list_genid) + goto restart; + if (error == 0) + break; + } if (error != 0) continue; @@ -1348,13 +1359,18 @@ restart: * If the address is assigned on the node of the other side of * a p2p interface, the address should be a neighbor. */ - dstaddr = ifa_ifwithdstaddr((const struct sockaddr *)addr, RT_ALL_FIBS); - if (dstaddr != NULL) { - if (dstaddr->ifa_ifp == ifp) { - ifa_free(dstaddr); - return (1); + if (ifp->if_flags & IFF_POINTOPOINT) { + IF_ADDR_RLOCK(ifp); + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + if (ifa->ifa_addr->sa_family != addr->sin6_family) + continue; + if (ifa->ifa_dstaddr != NULL && + sa_equal(addr, ifa->ifa_dstaddr)) { + IF_ADDR_RUNLOCK(ifp); + return 1; + } } - ifa_free(dstaddr); + IF_ADDR_RUNLOCK(ifp); } /* @@ -1487,7 +1503,7 @@ nd6_free(struct llentry **lnp, int gc) /* * We need to unlock to avoid a LOR with rt6_flush() with the * rnh and for the calls to pfxlist_onlink_check() and - * defrouter_select() in the block further down for calls + * defrouter_select_fib() in the block further down for calls * into nd6_lookup(). We still hold a ref. */ LLE_WUNLOCK(ln); @@ -1502,7 +1518,7 @@ nd6_free(struct llentry **lnp, int gc) if (dr) { /* - * Since defrouter_select() does not affect the + * Since defrouter_select_fib() does not affect the * on-link determination and MIP6 needs the check * before the default router selection, we perform * the check now. @@ -1512,7 +1528,7 @@ nd6_free(struct llentry **lnp, int gc) /* * Refresh default router list. */ - defrouter_select(); + defrouter_select_fib(dr->ifp->if_fib); } /* @@ -2106,11 +2122,11 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr, * Question: can we restrict the first condition to the "is_newentry" * case? * XXX: when we hear an RA from a new router with the link-layer - * address option, defrouter_select() is called twice, since + * address option, defrouter_select_fib() is called twice, since * defrtrlist_update called the function as well. However, I believe * we can compromise the overhead, since it only happens the first * time. - * XXX: although defrouter_select() should not have a bad effect + * XXX: although defrouter_select_fib() should not have a bad effect * for those are not autoconfigured hosts, we explicitly avoid such * cases for safety. */ @@ -2119,7 +2135,7 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr, /* * guaranteed recursion */ - defrouter_select(); + defrouter_select_fib(ifp->if_fib); } } @@ -2261,7 +2277,6 @@ nd6_resolve(struct ifnet *ifp, int is_gw, struct mbuf *m, case IFT_ETHER: case IFT_FDDI: case IFT_L2VLAN: - case IFT_IEEE80211: case IFT_BRIDGE: case IFT_ISO88025: ETHER_MAP_IPV6_MULTICAST(&dst6->sin6_addr, @@ -2529,7 +2544,6 @@ nd6_need_cache(struct ifnet *ifp) case IFT_FDDI: case IFT_IEEE1394: case IFT_L2VLAN: - case IFT_IEEE80211: case IFT_INFINIBAND: case IFT_BRIDGE: case IFT_PROPVIRTUAL: |