Use random address allocation for DHCPv6 temporary addresses.

This commit is contained in:
Simon Kelley
2013-11-07 14:20:13 +00:00
parent 3511a92869
commit 6586e8352a
4 changed files with 44 additions and 13 deletions

View File

@@ -394,7 +394,7 @@ struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct
return NULL; 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) 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 /* Find a free address: exclude anything in use and anything allocated to
@@ -411,7 +411,11 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
u64 j; u64 j;
/* hash hwaddr: use the SDBM hashing algorithm. This works /* hash hwaddr: use the SDBM hashing algorithm. This works
for MAC addresses, let's see how it manages with client-ids! */ 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++) for (j = iaid, i = 0; i < clid_len; i++)
j += clid[i] + (j << 6) + (j << 16) - j; j += clid[i] + (j << 6) + (j << 16) - j;
@@ -423,7 +427,7 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
continue; continue;
else else
{ {
if (option_bool(OPT_CONSEC_ADDR)) if (!temp_addr && option_bool(OPT_CONSEC_ADDR))
/* seed is largest extant lease addr in this context */ /* seed is largest extant lease addr in this context */
start = lease_find_max_addr6(c) + serial; start = lease_find_max_addr6(c) + serial;
else else

View File

@@ -1000,6 +1000,7 @@ int in_zone(struct auth_zone *zone, char *name, char **cut);
/* util.c */ /* util.c */
void rand_init(void); void rand_init(void);
unsigned short rand16(void); unsigned short rand16(void);
u64 rand64(void);
int legal_hostname(char *c); int legal_hostname(char *c);
char *canonicalise(char *s, int *nomem); char *canonicalise(char *s, int *nomem);
unsigned char *do_rfc1035_name(unsigned char *p, char *sval); 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 #ifdef HAVE_DHCP6
void dhcp6_init(void); void dhcp6_init(void);
void dhcp6_packet(time_t now); 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 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); int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr);
struct dhcp_context *address6_available(struct dhcp_context *context, struct dhcp_context *address6_available(struct dhcp_context *context,

View 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 */ /* 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 #ifdef OPTION6_PREFIX_CLASS
if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA) if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)

View File

@@ -39,6 +39,15 @@ unsigned short rand16(void)
return (unsigned short) (arc4random() >> 15); return (unsigned short) (arc4random() >> 15);
} }
u64 rand64(void)
{
u64 ret;
arc4random_buf(&ret, sizeof(ret));
return ret;
}
#else #else
/* SURF random number generator */ /* SURF random number generator */
@@ -46,6 +55,7 @@ unsigned short rand16(void)
static u32 seed[32]; static u32 seed[32];
static u32 in[12]; static u32 in[12];
static u32 out[8]; static u32 out[8];
static int outleft = 0;
void rand_init() void rand_init()
{ {
@@ -83,9 +93,8 @@ static void surf(void)
unsigned short rand16(void) unsigned short rand16(void)
{ {
static int outleft = 0; if (!outleft)
{
if (!outleft) {
if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3]; if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
surf(); surf();
outleft = 8; outleft = 8;
@@ -94,6 +103,22 @@ unsigned short rand16(void)
return (unsigned short) out[--outleft]; return (unsigned short) out[--outleft];
} }
u64 rand64(void)
{
static int outleft = 0;
if (outleft < 2)
{
if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
surf();
outleft = 8;
}
outleft -= 2;
return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
}
#endif #endif
static int check_name(char *in) static int check_name(char *in)