Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 20 Jun 2025 16:17:02 GMT
From:      Dag-Erling =?utf-8?Q?Sm=C3=B8rgrav?= <des@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 0daa334c5633 - main - inet6: RFC 8981 SLAAC Temporary Address Extensions
Message-ID:  <202506201617.55KGH2we024789@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by des:

URL: https://cgit.FreeBSD.org/src/commit/?id=0daa334c56334661ec68a514a95fa1d92c483e8e

commit 0daa334c56334661ec68a514a95fa1d92c483e8e
Author:     Fernando Gont <fernando@gont.com.ar>
AuthorDate: 2020-04-03 01:56:17 +0000
Commit:     Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2025-06-20 16:16:14 +0000

    inet6: RFC 8981 SLAAC Temporary Address Extensions
    
    Initial implementation of SLAAC temporary address extensions back when
    they were still draft-ietf-6man-rfc4941bis.
    
    PR:             245103
    MFC after:      1 month
---
 sys/netinet6/in6_ifattach.c | 124 --------------------------------------------
 sys/netinet6/in6_ifattach.h |   1 -
 sys/netinet6/nd6.h          |   2 +-
 sys/netinet6/nd6_rtr.c      |  58 ++++++++++++++++++---
 4 files changed, 52 insertions(+), 133 deletions(-)

diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c
index 1b5a38ba412a..f284f7fa5ffc 100644
--- a/sys/netinet6/in6_ifattach.c
+++ b/sys/netinet6/in6_ifattach.c
@@ -83,7 +83,6 @@ VNET_DECLARE(struct inpcbinfo, ripcbinfo);
 #define	V_ripcbinfo			VNET(ripcbinfo)
 
 static int get_rand_ifid(struct ifnet *, struct in6_addr *);
-static int generate_tmp_ifid(u_int8_t *, const u_int8_t *, u_int8_t *);
 static int get_ifid(struct ifnet *, struct ifnet *, struct in6_addr *);
 static int in6_ifattach_linklocal(struct ifnet *, struct ifnet *);
 static int in6_ifattach_loopback(struct ifnet *);
@@ -148,84 +147,6 @@ get_rand_ifid(struct ifnet *ifp, struct in6_addr *in6)
 	return 0;
 }
 
-static int
-generate_tmp_ifid(u_int8_t *seed0, const u_int8_t *seed1, u_int8_t *ret)
-{
-	MD5_CTX ctxt;
-	u_int8_t seed[16], digest[16], nullbuf[8];
-	u_int32_t val32;
-
-	/* If there's no history, start with a random seed. */
-	bzero(nullbuf, sizeof(nullbuf));
-	if (bcmp(nullbuf, seed0, sizeof(nullbuf)) == 0) {
-		int i;
-
-		for (i = 0; i < 2; i++) {
-			val32 = arc4random();
-			bcopy(&val32, seed + sizeof(val32) * i, sizeof(val32));
-		}
-	} else
-		bcopy(seed0, seed, 8);
-
-	/* copy the right-most 64-bits of the given address */
-	/* XXX assumption on the size of IFID */
-	bcopy(seed1, &seed[8], 8);
-
-	if (0) {		/* for debugging purposes only */
-		int i;
-
-		printf("generate_tmp_ifid: new randomized ID from: ");
-		for (i = 0; i < 16; i++)
-			printf("%02x", seed[i]);
-		printf(" ");
-	}
-
-	/* generate 16 bytes of pseudo-random value. */
-	bzero(&ctxt, sizeof(ctxt));
-	MD5Init(&ctxt);
-	MD5Update(&ctxt, seed, sizeof(seed));
-	MD5Final(digest, &ctxt);
-
-	/*
-	 * RFC 3041 3.2.1. (3)
-	 * Take the left-most 64-bits of the MD5 digest and set bit 6 (the
-	 * left-most bit is numbered 0) to zero.
-	 */
-	bcopy(digest, ret, 8);
-	ret[0] &= ~EUI64_UBIT;
-
-	/*
-	 * XXX: we'd like to ensure that the generated value is not zero
-	 * for simplicity.  If the caclculated digest happens to be zero,
-	 * use a random non-zero value as the last resort.
-	 */
-	if (bcmp(nullbuf, ret, sizeof(nullbuf)) == 0) {
-		nd6log((LOG_INFO,
-		    "generate_tmp_ifid: computed MD5 value is zero.\n"));
-
-		val32 = arc4random();
-		val32 = 1 + (val32 % (0xffffffff - 1));
-	}
-
-	/*
-	 * RFC 3041 3.2.1. (4)
-	 * Take the rightmost 64-bits of the MD5 digest and save them in
-	 * stable storage as the history value to be used in the next
-	 * iteration of the algorithm.
-	 */
-	bcopy(&digest[8], seed0, 8);
-
-	if (0) {		/* for debugging purposes only */
-		int i;
-
-		printf("to: ");
-		for (i = 0; i < 16; i++)
-			printf("%02x", digest[i]);
-		printf("\n");
-	}
-
-	return 0;
-}
 
 /*
  * Get interface identifier for the specified interface.
@@ -791,60 +712,15 @@ in6_ifdetach_destroy(struct ifnet *ifp)
 	_in6_ifdetach(ifp, 0);
 }
 
-int
-in6_get_tmpifid(struct ifnet *ifp, u_int8_t *retbuf,
-    const u_int8_t *baseid, int generate)
-{
-	u_int8_t nullbuf[8];
-	struct nd_ifinfo *ndi = ND_IFINFO(ifp);
-
-	bzero(nullbuf, sizeof(nullbuf));
-	if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) == 0) {
-		/* we've never created a random ID.  Create a new one. */
-		generate = 1;
-	}
-
-	if (generate) {
-		bcopy(baseid, ndi->randomseed1, sizeof(ndi->randomseed1));
-
-		/* generate_tmp_ifid will update seedn and buf */
-		(void)generate_tmp_ifid(ndi->randomseed0, ndi->randomseed1,
-		    ndi->randomid);
-	}
-	bcopy(ndi->randomid, retbuf, 8);
-
-	return (0);
-}
-
 void
 in6_tmpaddrtimer(void *arg)
 {
 	CURVNET_SET((struct vnet *) arg);
-	struct epoch_tracker et;
-	struct nd_ifinfo *ndi;
-	u_int8_t nullbuf[8];
-	struct ifnet *ifp;
 
 	callout_reset(&V_in6_tmpaddrtimer_ch,
 	    (V_ip6_temp_preferred_lifetime - V_ip6_desync_factor -
 	    V_ip6_temp_regen_advance) * hz, in6_tmpaddrtimer, curvnet);
 
-	bzero(nullbuf, sizeof(nullbuf));
-	NET_EPOCH_ENTER(et);
-	CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
-		if (ifp->if_afdata[AF_INET6] == NULL)
-			continue;
-		ndi = ND_IFINFO(ifp);
-		if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) {
-			/*
-			 * We've been generating a random ID on this interface.
-			 * Create a new one.
-			 */
-			(void)generate_tmp_ifid(ndi->randomseed0,
-			    ndi->randomseed1, ndi->randomid);
-		}
-	}
-	NET_EPOCH_EXIT(et);
 	CURVNET_RESTORE();
 }
 
diff --git a/sys/netinet6/in6_ifattach.h b/sys/netinet6/in6_ifattach.h
index b614019091f6..897926e90078 100644
--- a/sys/netinet6/in6_ifattach.h
+++ b/sys/netinet6/in6_ifattach.h
@@ -39,7 +39,6 @@ void in6_ifattach(struct ifnet *, struct ifnet *);
 void in6_ifattach_destroy(void);
 void in6_ifdetach(struct ifnet *);
 void in6_ifdetach_destroy(struct ifnet *);
-int in6_get_tmpifid(struct ifnet *, u_int8_t *, const u_int8_t *, int);
 void in6_tmpaddrtimer(void *);
 int in6_get_hw_ifid(struct ifnet *, struct in6_addr *);
 int in6_nigroup(struct ifnet *, const char *, int, struct in6_addr *);
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
index d0cbacff29d2..f8cf99cf09ac 100644
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -184,7 +184,7 @@ struct	in6_ndifreq {
 #define RETRANS_TIMER			1000	/* msec */
 #define MIN_RANDOM_FACTOR		512	/* 1024 * 0.5 */
 #define MAX_RANDOM_FACTOR		1536	/* 1024 * 1.5 */
-#define DEF_TEMP_VALID_LIFETIME		604800	/* 1 week */
+#define DEF_TEMP_VALID_LIFETIME		172800	/* 2 days */
 #define DEF_TEMP_PREFERRED_LIFETIME	86400	/* 1 day */
 #define TEMPADDR_REGEN_ADVANCE		5	/* sec */
 #define MAX_TEMP_DESYNC_FACTOR		600	/* 10 min */
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
index 927c7895305a..d9edb0d3e930 100644
--- a/sys/netinet6/nd6_rtr.c
+++ b/sys/netinet6/nd6_rtr.c
@@ -51,6 +51,7 @@
 #include <sys/sysctl.h>
 #include <sys/syslog.h>
 #include <sys/queue.h>
+#include <sys/random.h>
 
 #include <net/if.h>
 #include <net/if_var.h>
@@ -77,6 +78,7 @@ static struct nd_defrouter *defrtrlist_update(struct nd_defrouter *);
 static int prelist_update(struct nd_prefixctl *, struct nd_defrouter *,
     struct mbuf *, int);
 static int nd6_prefix_onlink(struct nd_prefix *);
+static int in6_get_tmp_ifid(struct in6_aliasreq *);
 
 TAILQ_HEAD(nd6_drhead, nd_defrouter);
 VNET_DEFINE_STATIC(struct nd6_drhead, nd6_defrouter);
@@ -2225,6 +2227,54 @@ restart:
 	return (error);
 }
 
+/*
+ * Get a randomized interface identifier for a temporary address
+ * <draft-ietf-6man-rfc4941bis-08.txt>, Section 3.3.1.
+ */
+static int
+in6_get_tmp_ifid(struct in6_aliasreq *ifra)
+{
+	struct in6_addr *addr;
+
+	if(!is_random_seeded()){
+		return 1;
+	}
+
+	addr = &(ifra->ifra_addr.sin6_addr);
+regen:
+	ifra->ifra_addr.sin6_addr.s6_addr32[2] |=
+	    (arc4random() & ~(ifra->ifra_prefixmask.sin6_addr.s6_addr32[2]));
+	ifra->ifra_addr.sin6_addr.s6_addr32[3] |=
+	    (arc4random() & ~(ifra->ifra_prefixmask.sin6_addr.s6_addr32[3]));
+
+	/*
+	 * Check if generated address is not inappropriate:
+	 *
+	 * - Reserved IPv6 Interface aIdentifers
+	 *   (https://www.iana.org/assignments/ipv6-interface-ids/)
+	 */
+
+	/* Subnet-router anycast: 0000:0000:0000:0000 */
+	if (!(addr->s6_addr32[2] | addr->s6_addr32[3]))
+		goto regen;
+
+	/*
+	 * IANA Ethernet block: 0200:5EFF:FE00:0000-0200:5EFF:FE00:5212
+	 * Proxy Mobile IPv6:   0200:5EFF:FE00:5213
+	 * IANA Ethernet block: 0200:5EFF:FE00:5214-0200:5EFF:FEFF:FFFF
+	 */
+	if (ntohl(addr->s6_addr32[2]) == 0x02005eff &&
+	    (ntohl(addr->s6_addr32[3]) & 0Xff000000) == 0xfe000000)
+		goto regen;
+
+	/* Reserved subnet anycast addresses */
+	if (ntohl(addr->s6_addr32[2]) == 0xfdffffff &&
+	    ntohl(addr->s6_addr32[3]) >= 0Xffffff80)
+		goto regen;
+
+	return 0;
+}
+
 /*
  * ia0 - corresponding public address
  */
@@ -2237,7 +2287,6 @@ in6_tmpifadd(const struct in6_ifaddr *ia0, int forcegen, int delay)
 	int error;
 	int trylimit = 3;	/* XXX: adhoc value */
 	int updateflags;
-	u_int32_t randid[2];
 	time_t vltime0, pltime0;
 
 	in6_prepare_ifra(&ifra, &ia0->ia_addr.sin6_addr,
@@ -2249,16 +2298,11 @@ in6_tmpifadd(const struct in6_ifaddr *ia0, int forcegen, int delay)
 	    &ifra.ifra_prefixmask.sin6_addr);
 
   again:
-	if (in6_get_tmpifid(ifp, (u_int8_t *)randid,
-	    (const u_int8_t *)&ia0->ia_addr.sin6_addr.s6_addr[8], forcegen)) {
+	if (in6_get_tmp_ifid(&ifra) != 0) {
 		nd6log((LOG_NOTICE, "%s: failed to find a good random IFID\n",
 		    __func__));
 		return (EINVAL);
 	}
-	ifra.ifra_addr.sin6_addr.s6_addr32[2] |=
-	    (randid[0] & ~(ifra.ifra_prefixmask.sin6_addr.s6_addr32[2]));
-	ifra.ifra_addr.sin6_addr.s6_addr32[3] |=
-	    (randid[1] & ~(ifra.ifra_prefixmask.sin6_addr.s6_addr32[3]));
 
 	/*
 	 * in6_get_tmpifid() quite likely provided a unique interface ID.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202506201617.55KGH2we024789>