]> git.ipfire.org Git - people/ms/dnsmasq.git/commitdiff
Use random address allocation for DHCPv6 temporary addresses.
authorSimon Kelley <simon@thekelleys.org.uk>
Thu, 7 Nov 2013 14:20:13 +0000 (14:20 +0000)
committerSimon Kelley <simon@thekelleys.org.uk>
Thu, 7 Nov 2013 14:20:13 +0000 (14:20 +0000)
src/dhcp6.c
src/dnsmasq.h
src/rfc3315.c
src/util.c

index 7c72872d120a20778014bc4cf771435ef16f0df6..5da2d0f19613742de5e7481d91a28ee92cac70a1 100644 (file)
@@ -394,7 +394,7 @@ struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct
   return NULL;
 }
 
-struct dhcp_context *address6_allocate(struct dhcp_context *context,  unsigned char *clid, int clid_len, 
+struct dhcp_context *address6_allocate(struct dhcp_context *context,  unsigned char *clid, int clid_len, int temp_addr,
                                       int iaid, int serial, struct dhcp_netid *netids, int plain_range, struct in6_addr *ans)   
 {
   /* Find a free address: exclude anything in use and anything allocated to
@@ -411,9 +411,13 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context,  unsigned c
   u64 j; 
 
   /* hash hwaddr: use the SDBM hashing algorithm.  This works
-     for MAC addresses, let's see how it manages with client-ids! */
-  for (j = iaid, i = 0; i < clid_len; i++)
-    j += clid[i] + (j << 6) + (j << 16) - j;
+     for MAC addresses, let's see how it manages with client-ids! 
+     For temporary addresses, we generate a new random one each time. */
+  if (temp_addr)
+    j = rand64();
+  else
+    for (j = iaid, i = 0; i < clid_len; i++)
+      j += clid[i] + (j << 6) + (j << 16) - j;
   
   for (pass = 0; pass <= plain_range ? 1 : 0; pass++)
     for (c = context; c; c = c->current)
@@ -423,7 +427,7 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context,  unsigned c
        continue;
       else
        { 
-         if (option_bool(OPT_CONSEC_ADDR))
+         if (!temp_addr && option_bool(OPT_CONSEC_ADDR))
            /* seed is largest extant lease addr in this context */
            start = lease_find_max_addr6(c) + serial;
          else
index 62b1d68cd848be2cfd50f859debc093da8786590..98266c6661fa0517ae70e3b12a32dea82ab11560 100644 (file)
@@ -1000,6 +1000,7 @@ int in_zone(struct auth_zone *zone, char *name, char **cut);
 /* util.c */
 void rand_init(void);
 unsigned short rand16(void);
+u64 rand64(void);
 int legal_hostname(char *c);
 char *canonicalise(char *s, int *nomem);
 unsigned char *do_rfc1035_name(unsigned char *p, char *sval);
@@ -1221,7 +1222,7 @@ int get_incoming_mark(union mysockaddr *peer_addr, struct all_addr *local_addr,
 #ifdef HAVE_DHCP6
 void dhcp6_init(void);
 void dhcp6_packet(time_t now);
-struct dhcp_context *address6_allocate(struct dhcp_context *context,  unsigned char *clid, int clid_len, 
+struct dhcp_context *address6_allocate(struct dhcp_context *context,  unsigned char *clid, int clid_len, int temp_addr,
                                       int iaid, int serial, struct dhcp_netid *netids, int plain_range, struct in6_addr *ans);
 int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr);
 struct dhcp_context *address6_available(struct dhcp_context *context, 
index bf3bacf2e8e6170fc062188c3c1cd6f4e2b1c6ff..8a2660f195d30ba11f08515796e7f028b409935e 100644 (file)
@@ -764,7 +764,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
              }
                           
            /* Return addresses for all valid contexts which don't yet have one */
-           while ((c = address6_allocate(state->context, state->clid, state->clid_len, state->iaid, ia_counter, solicit_tags, plain_range, &addr)))
+           while ((c = address6_allocate(state->context, state->clid, state->clid_len, state->ia_type == OPTION6_IA_TA,
+                                         state->iaid, ia_counter, solicit_tags, plain_range, &addr)))
              {
 #ifdef OPTION6_PREFIX_CLASS
                if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
index 94cc570ad1447a5c8490e649ad2df022d3e073b8..b2675585bb67c0bd136d9732ba7608adeeff3f91 100644 (file)
@@ -39,6 +39,15 @@ unsigned short rand16(void)
    return (unsigned short) (arc4random() >> 15);
 }
 
+u64 rand64(void)
+{
+  u64 ret;
+
+  arc4random_buf(&ret, sizeof(ret));
+
+  return ret;
+}
+
 #else
 
 /* SURF random number generator */
@@ -46,6 +55,7 @@ unsigned short rand16(void)
 static u32 seed[32];
 static u32 in[12];
 static u32 out[8];
+static int outleft = 0;
 
 void rand_init()
 {
@@ -82,16 +92,31 @@ static void surf(void)
 }
 
 unsigned short rand16(void)
+{
+  if (!outleft) 
+    {
+      if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
+      surf();
+      outleft = 8;
+    }
+  
+  return (unsigned short) out[--outleft];
+}
+
+u64 rand64(void)
 {
   static int outleft = 0;
 
-  if (!outleft) {
-    if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
-    surf();
-    outleft = 8;
-  }
+  if (outleft < 2)
+    {
+      if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
+      surf();
+      outleft = 8;
+    }
+  
+  outleft -= 2;
 
-  return (unsigned short) out[--outleft];
+  return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
 }
 
 #endif