summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorqingli <qingli@FreeBSD.org>2009-12-30 21:51:23 +0000
committerqingli <qingli@FreeBSD.org>2009-12-30 21:51:23 +0000
commit5357cdf4a4c9bdda64cf6bb28e925542b2461320 (patch)
tree75a349f27cba9c6fe76580cd905b6439d74ee4e9
parent1200ca53ee6bdb87095040b33feeb3d30efbb351 (diff)
downloadFreeBSD-src-5357cdf4a4c9bdda64cf6bb28e925542b2461320.zip
FreeBSD-src-5357cdf4a4c9bdda64cf6bb28e925542b2461320.tar.gz
Multiple IPv6 addresses of the same prefix can be installed on the
same interface. The first address will install the prefix route into the kernel routing table and that prefix will be marked as on-link. Without RADIX_MPATH enabled, the other address aliases of the same prefix will update the prefix reference count but no other routes will be installed. Consequently the prefixes associated with these addresses would not be marked as on-link. As such, incoming packets destined to these address aliases will fail the ND6 on-link check on input. This patch fixes the above problem by searching the kernel routing table and try to find an on-link prefix on the given interface. MFC after: 5 days
-rw-r--r--sys/netinet6/nd6.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index 575ff25..d90520e 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -935,8 +935,28 @@ nd6_is_new_addr_neighbor(struct sockaddr_in6 *addr, struct ifnet *ifp)
if (pr->ndpr_ifp != ifp)
continue;
- if (!(pr->ndpr_stateflags & NDPRF_ONLINK))
- continue;
+ if (!(pr->ndpr_stateflags & NDPRF_ONLINK)) {
+ struct rtentry *rt;
+ rt = rtalloc1((struct sockaddr *)&pr->ndpr_prefix, 0, 0);
+ if (rt == NULL)
+ continue;
+ /*
+ * This is the case where multiple interfaces
+ * have the same prefix, but only one is installed
+ * into the routing table and that prefix entry
+ * is not the one being examined here. In the case
+ * where RADIX_MPATH is enabled, multiple route
+ * entries (of the same rt_key value) will be
+ * installed because the interface addresses all
+ * differ.
+ */
+ if (!IN6_ARE_ADDR_EQUAL(&pr->ndpr_prefix.sin6_addr,
+ &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr)) {
+ RTFREE_LOCKED(rt);
+ continue;
+ }
+ RTFREE_LOCKED(rt);
+ }
if (IN6_ARE_MASKED_ADDR_EQUAL(&pr->ndpr_prefix.sin6_addr,
&addr->sin6_addr, &pr->ndpr_mask))
OpenPOWER on IntegriCloud