Page MenuHomeFreeBSD

D50108.id154805.diff
No OneTemporary

D50108.id154805.diff

diff --git a/sys/netinet6/in6_ifattach.h b/sys/netinet6/in6_ifattach.h
--- a/sys/netinet6/in6_ifattach.h
+++ b/sys/netinet6/in6_ifattach.h
@@ -39,7 +39,6 @@
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/in6_ifattach.c b/sys/netinet6/in6_ifattach.c
--- a/sys/netinet6/in6_ifattach.c
+++ b/sys/netinet6/in6_ifattach.c
@@ -85,7 +85,6 @@
#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 *);
@@ -150,84 +149,6 @@
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.
@@ -797,60 +718,15 @@
_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_proto.c b/sys/netinet6/in6_proto.c
--- a/sys/netinet6/in6_proto.c
+++ b/sys/netinet6/in6_proto.c
@@ -217,15 +217,18 @@
static int
sysctl_ip6_temppltime(SYSCTL_HANDLER_ARGS)
{
- int error, val;
+ int error, val, ndf;
val = V_ip6_temp_preferred_lifetime;
error = sysctl_handle_int(oidp, &val, 0, req);
if (error != 0 || !req->newptr)
return (error);
- if (val < V_ip6_desync_factor + V_ip6_temp_regen_advance)
+ ndf = MAX_TEMP_DESYNC_FACTOR_LIMIT + (val >> 5);
+ if (val < ndf + V_ip6_temp_regen_advance || val > V_ip6_temp_valid_lifetime)
return (EINVAL);
V_ip6_temp_preferred_lifetime = val;
+ V_ip6_temp_max_desync_factor = ndf;
+ V_ip6_desync_factor = arc4random() % ndf;
return (0);
}
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -173,6 +173,11 @@
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_sav), true,
"Drop incoming packets with source address that is a local address");
+SYSCTL_UINT(_net_inet6_ip6, OID_AUTO, temp_max_desync_factor,
+ CTLFLAG_RD | CTLFLAG_VNET,
+ &VNET_NAME(ip6_temp_max_desync_factor), 0,
+ "RFC 8981 max desync factor");
+
#ifdef RSS
static struct netisr_handler ip6_direct_nh = {
.nh_name = "ip6_direct",
@@ -262,7 +267,9 @@
nd6_init();
frag6_init();
- V_ip6_desync_factor = arc4random() % MAX_TEMP_DESYNC_FACTOR;
+ V_ip6_temp_max_desync_factor = (V_ip6_temp_preferred_lifetime >> 5) +
+ MAX_TEMP_DESYNC_FACTOR_LIMIT;
+ V_ip6_desync_factor = arc4random() % V_ip6_temp_max_desync_factor;
/* Skip global initialization stuff for non-default instances. */
#ifdef VIMAGE
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -184,10 +184,10 @@
#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_PREFERRED_LIFETIME 86400 /* 1 day */
+#define DEF_TEMP_VALID_LIFETIME 172800 /* 2 days */
+#define DEF_TEMP_PREFERRED_LIFETIME 88200 /* 1 day and 1/2 hour */
#define TEMPADDR_REGEN_ADVANCE 5 /* sec */
-#define MAX_TEMP_DESYNC_FACTOR 600 /* 10 min */
+#define MAX_TEMP_DESYNC_FACTOR_LIMIT 600 /* 10 min */
#define ND_COMPUTE_RTIME(x) \
(((MIN_RANDOM_FACTOR * (x >> 10)) + (arc4random() & \
((MAX_RANDOM_FACTOR - MIN_RANDOM_FACTOR) * (x >> 10)))) /1000)
@@ -293,11 +293,13 @@
/* nd6_rtr.c */
VNET_DECLARE(int, nd6_defifindex);
VNET_DECLARE(int, ip6_desync_factor); /* seconds */
+VNET_DECLARE(u_int32_t, ip6_temp_max_desync_factor); /* seconds */
VNET_DECLARE(u_int32_t, ip6_temp_preferred_lifetime); /* seconds */
VNET_DECLARE(u_int32_t, ip6_temp_valid_lifetime); /* seconds */
VNET_DECLARE(int, ip6_temp_regen_advance); /* seconds */
#define V_nd6_defifindex VNET(nd6_defifindex)
#define V_ip6_desync_factor VNET(ip6_desync_factor)
+#define V_ip6_temp_max_desync_factor VNET(ip6_temp_max_desync_factor)
#define V_ip6_temp_preferred_lifetime VNET(ip6_temp_preferred_lifetime)
#define V_ip6_temp_valid_lifetime VNET(ip6_temp_valid_lifetime)
#define V_ip6_temp_regen_advance VNET(ip6_temp_regen_advance)
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
--- 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 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);
@@ -94,6 +96,7 @@
VNET_DEFINE(int, ip6_desync_factor);
VNET_DEFINE(u_int32_t, ip6_temp_preferred_lifetime) = DEF_TEMP_PREFERRED_LIFETIME;
VNET_DEFINE(u_int32_t, ip6_temp_valid_lifetime) = DEF_TEMP_VALID_LIFETIME;
+VNET_DEFINE(u_int32_t, ip6_temp_max_desync_factor) = MAX_TEMP_DESYNC_FACTOR_LIMIT;
VNET_DEFINE(int, ip6_temp_regen_advance) = TEMPADDR_REGEN_ADVANCE;
@@ -2230,6 +2233,51 @@
return (error);
}
+/*
+ * Get a randomized interface identifier for a temporary address
+ * Based on RFC 8981, 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
*/
@@ -2242,7 +2290,6 @@
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,
@@ -2254,16 +2301,11 @@
&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.

File Metadata

Mime Type
text/plain
Expires
Sat, Oct 25, 5:20 AM (6 h, 47 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24162111
Default Alt Text
D50108.id154805.diff (10 KB)

Event Timeline