From owner-freebsd-net@freebsd.org Fri Apr 3 09:32:25 2020 Return-Path: Delivered-To: freebsd-net@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 0CB8327AED0 for ; Fri, 3 Apr 2020 09:32:25 +0000 (UTC) (envelope-from bzeeb-lists@lists.zabbadoz.net) Received: from mx1.sbone.de (mx1.sbone.de [IPv6:2a01:4f8:13b:39f::9f:25]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mx1.sbone.de", Issuer "SBone.DE" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 48tvpk74Bkz4VJ0; Fri, 3 Apr 2020 09:32:14 +0000 (UTC) (envelope-from bzeeb-lists@lists.zabbadoz.net) Received: from mail.sbone.de (mail.sbone.de [IPv6:fde9:577b:c1a9:31::2013:587]) (using TLSv1 with cipher ADH-CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by mx1.sbone.de (Postfix) with ESMTPS id C4D5F8D4A37C; Fri, 3 Apr 2020 09:32:03 +0000 (UTC) Received: from content-filter.sbone.de (content-filter.sbone.de [IPv6:fde9:577b:c1a9:31::2013:2742]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.sbone.de (Postfix) with ESMTPS id 4A1B2E70815; Fri, 3 Apr 2020 09:32:03 +0000 (UTC) X-Virus-Scanned: amavisd-new at sbone.de Received: from mail.sbone.de ([IPv6:fde9:577b:c1a9:31::2013:587]) by content-filter.sbone.de (content-filter.sbone.de [fde9:577b:c1a9:31::2013:2742]) (amavisd-new, port 10024) with ESMTP id HympdlzSzLiS; Fri, 3 Apr 2020 09:31:58 +0000 (UTC) Received: from [169.254.42.135] (unknown [IPv6:fde9:577b:c1a9:4902:151a:2590:828e:b991]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.sbone.de (Postfix) with ESMTPSA id 77157E70814; Fri, 3 Apr 2020 09:31:57 +0000 (UTC) From: "Bjoern A. Zeeb" To: "Fernando Gont" Cc: "FreeBSD Net" , "Hiroki Sato" Subject: Re: [PATCH] Implement the upcoming RFC4941bis (IPv6 SLAAC temporary addresses/privacy extensions) Date: Fri, 03 Apr 2020 09:31:55 +0000 X-Mailer: MailMate (2.0BETAr6146) Message-ID: <2C7AA4FD-CA20-4B53-8305-E279ACC2C5F2@lists.zabbadoz.net> In-Reply-To: <93726ba6-6d96-2b45-81c5-6fd8a83f95a9@gont.com.ar> References: <93726ba6-6d96-2b45-81c5-6fd8a83f95a9@gont.com.ar> MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8"; format=flowed Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: 48tvpk74Bkz4VJ0 X-Spamd-Bar: ---- Authentication-Results: mx1.freebsd.org; dkim=none; dmarc=none; spf=pass (mx1.freebsd.org: domain of bzeeb-lists@lists.zabbadoz.net designates 2a01:4f8:13b:39f::9f:25 as permitted sender) smtp.mailfrom=bzeeb-lists@lists.zabbadoz.net X-Spamd-Result: default: False [-4.85 / 15.00]; ARC_NA(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; RCVD_COUNT_FIVE(0.00)[5]; NEURAL_HAM_MEDIUM(-1.00)[-1.000,0]; FROM_HAS_DN(0.00)[]; RCPT_COUNT_THREE(0.00)[3]; R_SPF_ALLOW(-0.20)[+ip6:2a01:4f8:13b:39f::9f:25]; NEURAL_HAM_LONG(-1.00)[-1.000,0]; MIME_GOOD(-0.10)[text/plain]; RCVD_TLS_LAST(0.00)[]; DMARC_NA(0.00)[zabbadoz.net]; TO_MATCH_ENVRCPT_SOME(0.00)[]; TO_DN_ALL(0.00)[]; IP_SCORE(-2.55)[ip: (-8.58), ipnet: 2a01:4f8::/29(-2.59), asn: 24940(-1.57), country: DE(-0.02)]; FROM_EQ_ENVFROM(0.00)[]; R_DKIM_NA(0.00)[]; MIME_TRACE(0.00)[0:+]; ASN(0.00)[asn:24940, ipnet:2a01:4f8::/29, country:DE]; MID_RHS_MATCH_FROM(0.00)[] X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 03 Apr 2020 09:32:25 -0000 On 3 Apr 2020, at 1:55, Fernando Gont wrote: Hi Fernando, can you follow-up on https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=245103 with your more complete patch so this is properly tracked? I’ll be happy to deal with it the next days if no one else beats me to it. /bz > Folks/Hiroki, > > I've implemented the upcoming revision of RFC4941 > (https://tools.ietf.org/html/draft-ietf-6man-rfc4941bis-08) for > FreeBSD. > > The main changes are this: > > * Reduce the Valid Lifetime from 1 week to 2 days. This effectively > limits the number of concurrent temporary addresses per prefix to 2 > > * Use different interface-ids for each temporary address, to prevent > correlation of network activity among temporary addresses > corresponding to different prefixes. > > P.S.: The patch is also available here: > > > > ---- cut here ---- > diff --git sys/netinet6/in6_ifattach.c sys/netinet6/in6_ifattach.c > index 91ef544d8b2..c093b53974a 100644 > --- sys/netinet6/in6_ifattach.c > +++ sys/netinet6/in6_ifattach.c > @@ -87,7 +87,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 *); > @@ -152,84 +151,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. > @@ -798,58 +719,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 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)); > - 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); > - } > - } > - > CURVNET_RESTORE(); > } > > diff --git sys/netinet6/in6_ifattach.h sys/netinet6/in6_ifattach.h > index 1e038fa8319..b9983200447 100644 > --- sys/netinet6/in6_ifattach.h > +++ sys/netinet6/in6_ifattach.h > @@ -40,7 +40,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 sys/netinet6/nd6.h sys/netinet6/nd6.h > index 857657f6e20..c88f37288a2 100644 > --- sys/netinet6/nd6.h > +++ sys/netinet6/nd6.h > @@ -185,7 +185,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 sys/netinet6/nd6_rtr.c sys/netinet6/nd6_rtr.c > index d678a53233e..179238257bb 100644 > --- sys/netinet6/nd6_rtr.c > +++ sys/netinet6/nd6_rtr.c > @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); > #include > #include > #include > +#include > > #include > #include > @@ -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); > @@ -2248,6 +2250,51 @@ nd6_prefix_offlink(struct nd_prefix *pr) > return (error); > } > > +/* > + * Get a randomized interface identifier for a temporary address > + * , 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 Identifers > + * > (http://www.iana.org/assignments/ipv6-interface-ids/ipv6-interface-ids.xhtml) > + */ > + > + /* 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 > */ > @@ -2260,7 +2307,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, > @@ -2272,16 +2318,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. > @@ -2289,7 +2330,6 @@ in6_tmpifadd(const struct in6_ifaddr *ia0, int > forcegen, int delay) > * there may be a time lag between generation of the ID and > generation > * of the address. So, we'll do one more sanity check. > */ > - > if (in6_localip(&ifra.ifra_addr.sin6_addr) != 0) { > if (trylimit-- > 0) { > forcegen = 1; > ---- cut here ---- > > > Thanks! > > Cheers, > -- > Fernando Gont > e-mail: fernando@gont.com.ar || fgont@si6networks.com > PGP Fingerprint: 7809 84F5 322E 45C7 F1C9 3945 96EE A9EF D076 FFF1 > > > > _______________________________________________ > freebsd-net@freebsd.org mailing list > https://lists.freebsd.org/mailman/listinfo/freebsd-net > To unsubscribe, send any mail to "freebsd-net-unsubscribe@freebsd.org"