From nobody Thu Apr 2 11:11:49 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4fmfLs1KCGz6YGHT for ; Thu, 02 Apr 2026 11:11:49 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R12" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4fmfLs0Wxmz3HK9 for ; Thu, 02 Apr 2026 11:11:49 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1775128309; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=UNj543iYIHYBJhIyvRtNVU4XRUDHHj4MftroVQ8ikp8=; b=IhUfSptGnYLFKGpUjGrTnwlAcY3FzEaeMshGZz7cQWpGeoj8xEs7iNR/D4tVObK8KyjQyo nYHei7JvreNIRrgyraoTta7A/OlbrwCmc52hjFSAgy+p6GB5xbMlwjZ78xMBQ2OJLG45eQ 843PS+ANHdVaJZPd5QGK9UNl1iKqtRNzynPjNVLqopKPqXzyHPptroIOC0239FvBzcMzTe jZbJs0U3XtltdL8ps6AbiM0YC+akgURCEDpm9NMHNyv3xy7ja1F/qGWnlXXQVjwMd8LMgS W2D2Zk68wEtyTHZTy7GyYgz3hR7I0syIA8t0zy/DuejebXiiw9MHZWn29JsBHw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1775128309; a=rsa-sha256; cv=none; b=PiRMogTWVcO/9JYOe0N2g3B/uLOJ/xRkTLYLpjZ8i9Lvl21qcnXIOGsrMn1kUuPme4U7ZZ Qcz62kV3eAHcRaTdhSKXxna5Cy7lv8ugaSeKAgPRuWOH2u+dadBYIkYnpR/FxwB9ii+DdN YF01lbXzh7OZ7QeXESrK7b5BgE2wgeaZ6zqjZiw64nTOcjcKY0EcJSD9icj+L0TcsD1NwY B8OscagR2ptLihuY8vcmYcDciHdvOVX8lhqfwhs1mfsBs0KKEcaJGXkHV3vH9d00wEEhUh ldDHp94uXDHKXVc4CXKKK5HW7mCcsxmXDGFsmvO2Td1ung5Ft/6vtA1hfqEQjw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1775128309; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=UNj543iYIHYBJhIyvRtNVU4XRUDHHj4MftroVQ8ikp8=; b=OmcUQZtjQrXWuQLvrF/+8bITiji8Cm9r6en0bzpVTmsFBFURc47fqy1NmEGTNFGhgsoSIZ f5odsaSYlTCZNLjbhcIlc2J2vj2CPxxNMTceXkSFz2FHMG3NCjLs6TetOelOeSoYZoynAg h5fz3I6UsjNur0DnaM97DMsKcefY3IwIh9zC3EkeJb021Yd/ZSM86tKCOMIO1Qm2ZUtc3U noKSl968jjDOH6hOy6SrfUc+tb4mUYH274YWqNV0FrxkvlpXGTMb1OivlIcu3pis5k8925 RoeUe1mxshKb1Zh4/OJroSNMHCA9YnbPUzOHuxz4JN0dPkgIiCQ7e9OIgFcIRA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4fmfLs06gxz10VQ for ; Thu, 02 Apr 2026 11:11:49 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 1bfe6 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 02 Apr 2026 11:11:49 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Pouria Mousavizadeh Tehrani Subject: git: cf275806b6ed - main - nd6: Fix delayed NA for proxy addresses List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: pouria X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: cf275806b6eddd66a3d82be56b3672dc5afab525 Auto-Submitted: auto-generated Date: Thu, 02 Apr 2026 11:11:49 +0000 Message-Id: <69ce4ef5.1bfe6.27412941@gitrepo.freebsd.org> The branch main has been updated by pouria: URL: https://cgit.FreeBSD.org/src/commit/?id=cf275806b6eddd66a3d82be56b3672dc5afab525 commit cf275806b6eddd66a3d82be56b3672dc5afab525 Author: Pouria Mousavizadeh Tehrani AuthorDate: 2026-03-13 14:25:01 +0000 Commit: Pouria Mousavizadeh Tehrani CommitDate: 2026-04-02 11:11:26 +0000 nd6: Fix delayed NA for proxy addresses Delayed proxy addresses need special handling, since they can use link-local ifa as their source address and have different link-layer data in their response. Fixes: f37fbe30f559 Reviewed by: glebius, markj Differential Revision: https://reviews.freebsd.org/D55850 --- sys/netinet6/nd6.h | 1 + sys/netinet6/nd6_nbr.c | 72 ++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 53 insertions(+), 20 deletions(-) diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h index 70cd6dfbdb62..8c069c294593 100644 --- a/sys/netinet6/nd6.h +++ b/sys/netinet6/nd6.h @@ -156,6 +156,7 @@ struct in6_ndifreq { #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 index 44677a9637bd..c345e96f8d3f 100644 --- a/sys/netinet6/nd6_nbr.c +++ b/sys/netinet6/nd6_nbr.c @@ -98,7 +98,8 @@ static void nd6_na_output_fib(struct ifnet *, const struct in6_addr *, 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 @@ SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_ONLINKNSRFC4861, 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 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len) 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 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len) 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 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len) */ 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 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len) * 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 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len) * 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 @@ nd6_queue_timer(void *arg) 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 @@ nd6_queue_timer(void *arg) 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,13 @@ nd6_queue_timer(void *arg) /* 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; + sdl = ndq->ndq_sdl; + proxy = true; + } /* * if it was GRAND, wait at least a RetransTimer @@ -1724,16 +1738,23 @@ nd6_queue_timer(void *arg) 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 +1796,17 @@ nd6_queue_add(struct ifaddr *ifa, struct in6_addr *daddr, } 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 + memcpy(&ndq->ndq_taddr, IFA_IN6(ifa), sizeof(struct in6_addr)); ndq->ndq_flags = flags; nd6log((LOG_DEBUG, "%s: delay IPv6 NA for %s\n", if_name(ifp), @@ -1842,7 +1874,7 @@ nd6_grand_start(struct ifaddr *ifa, uint32_t flags) 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); } /*