Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F157685365
D55850.id174437.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D55850.id174437.diff
View Options
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -156,6 +156,7 @@
#define ND6_QUEUE_FLAG_NEWGUA 0x01 /* new global unicast address event */
#define ND6_QUEUE_FLAG_LLADDR 0x02 /* link-layer address change event */
#define ND6_QUEUE_FLAG_ANYCAST 0x04 /* delay NA for anycast address */
+#define ND6_QUEUE_FLAG_PROXY 0x08 /* delay NA for proxy address */
/* GRAND specific flags */
#define ND6_QUEUE_GRAND_MASK (ND6_QUEUE_FLAG_NEWGUA|ND6_QUEUE_FLAG_LLADDR)
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -98,7 +98,8 @@
const struct in6_addr *, u_long, int, struct sockaddr *, u_int);
static void nd6_ns_output_fib(struct ifnet *, const struct in6_addr *,
const struct in6_addr *, const struct in6_addr *, uint8_t *, u_int);
-static void nd6_queue_add(struct ifaddr *, struct in6_addr *, int, uint32_t);
+static void nd6_queue_add(struct ifaddr *, struct in6_addr *,
+ struct in6_addr *, struct sockaddr_dl *, int, uint32_t);
static struct ifaddr *nd6_proxy_fill_sdl(struct ifnet *,
const struct in6_addr *, struct sockaddr_dl *);
@@ -124,10 +125,12 @@
struct nd_queue {
TAILQ_ENTRY(nd_queue) ndq_list;
- struct ifaddr *ndq_ifa;
- struct in6_addr ndq_daddr;
- uint32_t ndq_flags;
- struct callout ndq_callout;
+ struct ifaddr *ndq_ifa;
+ struct in6_addr ndq_daddr;
+ struct in6_addr ndq_taddr;
+ struct sockaddr_dl ndq_sdl;
+ uint32_t ndq_flags;
+ struct callout ndq_callout;
};
/*
@@ -148,7 +151,8 @@
union nd_opts ndopts;
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
char *lladdr;
- int anycast, lladdrlen, proxy, rflag, tentative, tlladdr;
+ int lladdrlen, rflag, tentative, tlladdr;
+ uint32_t dflags;
ifa = NULL;
@@ -276,10 +280,10 @@
ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
/* (2) check. */
- proxy = 0;
+ dflags = 0;
if (ifa == NULL) {
if ((ifa = nd6_proxy_fill_sdl(ifp, &taddr6, &proxydl)) != NULL)
- proxy = 1;
+ dflags |= ND6_QUEUE_FLAG_PROXY;
}
if (ifa == NULL) {
/*
@@ -289,8 +293,9 @@
*/
goto freeit;
}
+ if ((((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST) != 0)
+ dflags |= ND6_QUEUE_FLAG_ANYCAST;
myaddr6 = *IFA_IN6(ifa);
- anycast = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST;
tentative = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE;
if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DUPLICATED)
goto freeit;
@@ -341,7 +346,7 @@
* Link-Layer Address option is not included, the Override flag SHOULD
* be set to zero. Otherwise, the Override flag SHOULD be set to one.
*/
- if (anycast == 0 && proxy == 0 && (tlladdr & ND6_NA_OPT_LLA) != 0)
+ if (dflags == 0 && (tlladdr & ND6_NA_OPT_LLA) != 0)
rflag |= ND_NA_FLAG_OVERRIDE;
/*
* If the source address is unspecified address, entries must not
@@ -362,12 +367,11 @@
* be delayed by a random time between 0 and MAX_ANYCAST_DELAY_TIME
* to reduce the probability of network congestion.
*/
- if (anycast == 0)
- nd6_na_output_fib(ifp, &saddr6, &taddr6, rflag, tlladdr,
- proxy ? (struct sockaddr *)&proxydl : NULL, M_GETFIB(m));
+ if (dflags == 0)
+ nd6_na_output_fib(ifp, &saddr6, &taddr6, rflag, tlladdr, NULL, M_GETFIB(m));
else
- nd6_queue_add(ifa, &saddr6, arc4random() %
- (MAX_ANYCAST_DELAY_TIME * hz), ND6_QUEUE_FLAG_ANYCAST);
+ nd6_queue_add(ifa, &saddr6, &taddr6, &proxydl, arc4random() %
+ (MAX_ANYCAST_DELAY_TIME * hz), dflags);
freeit:
if (ifa != NULL)
ifa_free(ifa);
@@ -1672,10 +1676,12 @@
struct nd_queue *ndq = arg;
struct ifaddr *ifa = ndq->ndq_ifa;
struct ifnet *ifp;
- struct in6_addr daddr;
+ struct in6_addr daddr, taddr;
+ struct sockaddr_dl sdl;
struct epoch_tracker et;
int delay, tlladdr;
u_long flags;
+ bool proxy;
KASSERT(ifa != NULL, ("ND6 queue entry %p with no address", ndq));
@@ -1684,6 +1690,7 @@
NET_EPOCH_ENTER(et);
daddr = ndq->ndq_daddr;
+ taddr = ndq->ndq_taddr;
tlladdr = ND6_NA_OPT_LLA;
flags = (V_ip6_forwarding) ? ND_NA_FLAG_ROUTER : 0;
if ((ifp->if_inet6->nd_flags & ND6_IFF_ACCEPT_RTADV) != 0 && V_ip6_norbit_raif)
@@ -1711,6 +1718,14 @@
/* anycast advertisement delay rule (RFC 4861 7.2.7, SHOULD) */
if ((ndq->ndq_flags & ND6_QUEUE_FLAG_ANYCAST) != 0)
flags |= ND_NA_FLAG_SOLICITED;
+ /* proxy advertisement delay rule (RFC 4861 7.2.8, SHOULD) */
+ proxy = false;
+ if ((ndq->ndq_flags & ND6_QUEUE_FLAG_PROXY) != 0) {
+ flags |= ND_NA_FLAG_SOLICITED;
+ tlladdr |= ND6_NA_OPT_LLA;
+ sdl = ndq->ndq_sdl;
+ proxy = true;
+ }
/*
* if it was GRAND, wait at least a RetransTimer
@@ -1724,16 +1739,23 @@
nd6_queue_rel(ndq);
if (__predict_true(in6_setscope(&daddr, ifp, NULL) == 0))
- nd6_na_output_fib(ifp, &daddr, IFA_IN6(ifa), flags, tlladdr,
- NULL, ifp->if_fib);
+ nd6_na_output_fib(ifp, &daddr, &taddr, flags, tlladdr,
+ proxy ? (struct sockaddr *)&sdl : NULL, ifp->if_fib);
NET_EPOCH_EXIT(et);
CURVNET_RESTORE();
}
+/*
+ * Queue a delayed IPv6 Neighbor Advertisement.
+ *
+ * daddr: destination address (who the NA is sent to)
+ * taddr: target address being advertised (used for proxy NAs)
+ * sdl: link-layer address (used for proxy NAs)
+ */
static void
nd6_queue_add(struct ifaddr *ifa, struct in6_addr *daddr,
- int delay, uint32_t flags)
+ struct in6_addr *taddr, struct sockaddr_dl *sdl, int delay, uint32_t flags)
{
struct nd_queue *ndq = NULL;
struct ifnet *ifp;
@@ -1775,6 +1797,17 @@
}
memcpy(&ndq->ndq_daddr, daddr, sizeof(struct in6_addr));
+ /*
+ * For proxy NAs, the target address (taddr) being advertised differs from
+ * the interface address (ifa), so we must explicitly store both the proxy
+ * target address and its link-layer address (sdl).
+ * For non-proxy NAs, use the interface address (ifa) itself as the target.
+ */
+ if ((flags & ND6_QUEUE_FLAG_PROXY) != 0) {
+ memcpy(&ndq->ndq_taddr, taddr, sizeof(struct in6_addr));
+ memcpy(&ndq->ndq_sdl, sdl, sizeof(struct sockaddr_dl));
+ } else
+ ndq->ndq_taddr = ((struct in6_ifaddr *)ifa)->ia_addr.sin6_addr;
ndq->ndq_flags = flags;
nd6log((LOG_DEBUG, "%s: delay IPv6 NA for %s\n", if_name(ifp),
@@ -1842,7 +1875,7 @@
daddr = in6addr_linklocal_allnodes;
delay = ext->nd_retrans * hz / 1000;
- nd6_queue_add(ifa, &daddr, count * delay, flags);
+ nd6_queue_add(ifa, &daddr, NULL, NULL, count * delay, flags);
}
/*
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, May 25, 1:58 AM (16 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33494280
Default Alt Text
D55850.id174437.diff (6 KB)
Attached To
Mode
D55850: nd6: Fix delayed proxy address
Attached
Detach File
Event Timeline
Log In to Comment