summaryrefslogtreecommitdiffstats
path: root/sys/netinet6
diff options
context:
space:
mode:
authormelifaro <melifaro@FreeBSD.org>2016-01-04 15:03:20 +0000
committermelifaro <melifaro@FreeBSD.org>2016-01-04 15:03:20 +0000
commit31d78f6810b70b03dcf590bdcd1f8520d199099d (patch)
tree97043b0fe5b60ef63af4661bdd61f9c954d3bf5b /sys/netinet6
parentff9e83788d7ed52342dcba4dff1e62fdf3cc985c (diff)
downloadFreeBSD-src-31d78f6810b70b03dcf590bdcd1f8520d199099d.zip
FreeBSD-src-31d78f6810b70b03dcf590bdcd1f8520d199099d.tar.gz
Add rib_lookup_info() to provide API for retrieving individual route
entries data in unified format. There are control plane functions that require information other than just next-hop data (e.g. individual rtentry fields like flags or prefix/mask). Given that the goal is to avoid rte reference/refcounting, re-use rt_addrinfo structure to store most rte fields. If caller wants to retrieve key/mask or gateway (which are sockaddrs and are allocated separately), it needs to provide sufficient-sized sockaddrs structures w/ ther pointers saved in passed rt_addrinfo. Convert: * lltable new records checks (in_lltable_rtcheck(), nd6_is_new_addr_neighbor(). * rtsock pre-add/change route check. * IPv6 NS ND-proxy check (RADIX_MPATH code was eliminated because 1) we don't support RTF_ANNOUNCE ND-proxy for networks and there should not be multiple host routes for such hosts 2) if we have multiple routes we should inspect them (which is not done). 3) the entire idea of abusing KRT as storage for ND proxy seems odd. Userland programs should be used for that purpose).
Diffstat (limited to 'sys/netinet6')
-rw-r--r--sys/netinet6/nd6.c25
-rw-r--r--sys/netinet6/nd6_nbr.c54
2 files changed, 43 insertions, 36 deletions
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index fbbf421..4371a02 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -1210,6 +1210,10 @@ nd6_is_new_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp)
{
struct nd_prefix *pr;
struct ifaddr *dstaddr;
+ struct rt_addrinfo info;
+ struct sockaddr_in6 rt_key;
+ struct sockaddr *dst6;
+ int fibnum;
/*
* A link-local address is always a neighbor.
@@ -1234,6 +1238,13 @@ nd6_is_new_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp)
return (0);
}
+ bzero(&rt_key, sizeof(rt_key));
+ 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.
@@ -1245,12 +1256,13 @@ nd6_is_new_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp)
continue;
if (!(pr->ndpr_stateflags & NDPRF_ONLINK)) {
- struct rtentry *rt;
/* Always use the default FIB here. */
- rt = in6_rtalloc1((struct sockaddr *)&pr->ndpr_prefix,
- 0, 0, RT_DEFAULT_FIB);
- if (rt == NULL)
+ dst6 = (struct sockaddr *)&pr->ndpr_prefix;
+
+ /* Restore length field before retrying lookup */
+ rt_key.sin6_len = sizeof(rt_key);
+ if (rib_lookup_info(fibnum, dst6, 0, 0, &info) != 0)
continue;
/*
* This is the case where multiple interfaces
@@ -1263,11 +1275,8 @@ nd6_is_new_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp)
* differ.
*/
if (!IN6_ARE_ADDR_EQUAL(&pr->ndpr_prefix.sin6_addr,
- &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr)) {
- RTFREE_LOCKED(rt);
+ &rt_key.sin6_addr))
continue;
- }
- RTFREE_LOCKED(rt);
}
if (IN6_ARE_MASKED_ADDR_EQUAL(&pr->ndpr_prefix.sin6_addr,
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
index 407c6e5..b7ba0b2 100644
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -248,37 +248,35 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
/* (2) check. */
if (ifa == NULL) {
- struct route_in6 ro;
- int need_proxy;
+ struct sockaddr_dl rt_gateway;
+ struct rt_addrinfo info;
+ struct sockaddr_in6 dst6;
- bzero(&ro, sizeof(ro));
- ro.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
- ro.ro_dst.sin6_family = AF_INET6;
- ro.ro_dst.sin6_addr = taddr6;
+ bzero(&dst6, sizeof(dst6));
+ dst6.sin6_len = sizeof(struct sockaddr_in6);
+ dst6.sin6_family = AF_INET6;
+ dst6.sin6_addr = taddr6;
+
+ bzero(&rt_gateway, sizeof(rt_gateway));
+ rt_gateway.sdl_len = sizeof(rt_gateway);
+ bzero(&info, sizeof(info));
+ info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&rt_gateway;
/* Always use the default FIB. */
-#ifdef RADIX_MPATH
- rtalloc_mpath_fib((struct route *)&ro, ntohl(taddr6.s6_addr32[3]),
- RT_DEFAULT_FIB);
-#else
- in6_rtalloc(&ro, RT_DEFAULT_FIB);
-#endif
- need_proxy = (ro.ro_rt &&
- (ro.ro_rt->rt_flags & RTF_ANNOUNCE) != 0 &&
- ro.ro_rt->rt_gateway->sa_family == AF_LINK);
- if (ro.ro_rt != NULL) {
- if (need_proxy)
- proxydl = *SDL(ro.ro_rt->rt_gateway);
- RTFREE(ro.ro_rt);
- }
- if (need_proxy) {
- /*
- * proxy NDP for single entry
- */
- ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp,
- IN6_IFF_NOTREADY|IN6_IFF_ANYCAST);
- if (ifa)
- proxy = 1;
+ if (rib_lookup_info(RT_DEFAULT_FIB, (struct sockaddr *)&dst6,
+ 0, 0, &info) == 0) {
+ if ((info.rti_flags & RTF_ANNOUNCE) != 0 &&
+ rt_gateway.sdl_family == AF_LINK) {
+
+ /*
+ * proxy NDP for single entry
+ */
+ proxydl = *SDL(&rt_gateway);
+ ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(
+ ifp, IN6_IFF_NOTREADY|IN6_IFF_ANYCAST);
+ if (ifa)
+ proxy = 1;
+ }
}
}
if (ifa == NULL) {
OpenPOWER on IntegriCloud