Massive refactor of stateful DHCPv6. Lease multiple prefixes per client.

This commit is contained in:
Simon Kelley
2013-03-06 20:52:35 +00:00
parent c7961075c4
commit a6ebfacf7b
4 changed files with 713 additions and 638 deletions

View File

@@ -265,8 +265,8 @@ struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct
return NULL;
}
int address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len,
int serial, struct dhcp_netid *netids, struct in6_addr *ans)
struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len,
int iaid, struct dhcp_netid *netids, struct in6_addr *ans)
{
/* Find a free address: exclude anything in use and anything allocated to
a particular hwaddr/clientid/hostname in our configuration.
@@ -283,12 +283,12 @@ int address6_allocate(struct dhcp_context *context, unsigned char *clid, int cl
/* hash hwaddr: use the SDBM hashing algorithm. This works
for MAC addresses, let's see how it manages with client-ids! */
for (j = 0, i = 0; i < clid_len; i++)
for (j = iaid, i = 0; i < clid_len; i++)
j += clid[i] + (j << 6) + (j << 16) - j;
for (pass = 0; pass <= 1; pass++)
for (c = context; c; c = c->current)
if (c->flags & (CONTEXT_DEPRECATE | CONTEXT_STATIC | CONTEXT_RA_STATELESS))
if (c->flags & (CONTEXT_DEPRECATE | CONTEXT_STATIC | CONTEXT_RA_STATELESS | CONTEXT_USED))
continue;
else if (!match_netid(c->filter, netids, pass))
continue;
@@ -296,9 +296,9 @@ int address6_allocate(struct dhcp_context *context, unsigned char *clid, int cl
{
if (option_bool(OPT_CONSEC_ADDR))
/* seed is largest extant lease addr in this context */
start = lease_find_max_addr6(c) + serial;
start = lease_find_max_addr6(c);
else
start = addr6part(&c->start6) + ((j + c->addr_epoch + serial) % (1 + addr6part(&c->end6) - addr6part(&c->start6)));
start = addr6part(&c->start6) + ((j + c->addr_epoch) % (1 + addr6part(&c->end6) - addr6part(&c->start6)));
/* iterate until we find a free address. */
addr = start;
@@ -315,7 +315,7 @@ int address6_allocate(struct dhcp_context *context, unsigned char *clid, int cl
{
*ans = c->start6;
setaddr6part (ans, addr);
return 1;
return c;
}
addr++;
@@ -325,7 +325,7 @@ int address6_allocate(struct dhcp_context *context, unsigned char *clid, int cl
} while (addr != start);
}
return 0;
}
@@ -369,34 +369,6 @@ struct dhcp_context *address6_valid(struct dhcp_context *context,
return NULL;
}
struct dhcp_context *narrow_context6(struct dhcp_context *context,
struct in6_addr *taddr,
struct dhcp_netid *netids)
{
/* We start of with a set of possible contexts, all on the current physical interface.
These are chained on ->current.
Here we have an address, and return the actual context correponding to that
address. Note that none may fit, if the address came a dhcp-host and is outside
any dhcp-range. In that case we return a static range if possible, or failing that,
any context on the correct subnet. (If there's more than one, this is a dodgy
configuration: maybe there should be a warning.) */
struct dhcp_context *tmp;
if (!(tmp = address6_available(context, taddr, netids)) &&
!(tmp = address6_valid(context, taddr, netids)))
for (tmp = context; tmp; tmp = tmp->current)
if (match_netid(tmp->filter, netids, 1) &&
is_same_net6(taddr, &tmp->start6, tmp->prefix))
break;
/* Only one context allowed now */
if (tmp)
tmp->current = NULL;
return tmp;
}
static int is_config_in_context6(struct dhcp_context *context, struct dhcp_config *config)
{
/* expand wildcard on contructed contexts */