DHCPv6 address allocation - same DUID, two IAIDs

This commit is contained in:
Simon Kelley
2013-01-09 19:51:04 +00:00
parent 71c73ac17c
commit 37c9ccebd1
3 changed files with 49 additions and 32 deletions

View File

@@ -328,6 +328,7 @@ int address6_allocate(struct dhcp_context *context, unsigned char *clid, int cl
return 0; return 0;
} }
/* can dynamically allocate addr */
struct dhcp_context *address6_available(struct dhcp_context *context, struct dhcp_context *address6_available(struct dhcp_context *context,
struct in6_addr *taddr, struct in6_addr *taddr,
struct dhcp_netid *netids) struct dhcp_netid *netids)
@@ -352,6 +353,22 @@ struct dhcp_context *address6_available(struct dhcp_context *context,
return NULL; return NULL;
} }
/* address OK if configured */
struct dhcp_context *address6_valid(struct dhcp_context *context,
struct in6_addr *taddr,
struct dhcp_netid *netids)
{
struct dhcp_context *tmp;
for (tmp = context; tmp; tmp = tmp->current)
if ((tmp->flags & CONTEXT_STATIC) &&
is_same_net6(&tmp->start6, taddr, tmp->prefix) &&
match_netid(tmp->filter, netids, 1))
return tmp;
return NULL;
}
struct dhcp_context *narrow_context6(struct dhcp_context *context, struct dhcp_context *narrow_context6(struct dhcp_context *context,
struct in6_addr *taddr, struct in6_addr *taddr,
struct dhcp_netid *netids) struct dhcp_netid *netids)
@@ -366,21 +383,12 @@ struct dhcp_context *narrow_context6(struct dhcp_context *context,
struct dhcp_context *tmp; struct dhcp_context *tmp;
if (!(tmp = address6_available(context, taddr, netids))) if (!(tmp = address6_available(context, taddr, netids)) &&
{ !(tmp = address6_valid(context, taddr, netids)))
for (tmp = context; tmp; tmp = tmp->current) for (tmp = context; tmp; tmp = tmp->current)
if (match_netid(tmp->filter, netids, 1) && if (match_netid(tmp->filter, netids, 1) &&
is_same_net6(taddr, &tmp->start6, tmp->prefix) && is_same_net6(taddr, &tmp->start6, tmp->prefix))
(tmp->flags & CONTEXT_STATIC)) break;
break;
if (!tmp)
for (tmp = context; tmp; tmp = tmp->current)
if (match_netid(tmp->filter, netids, 1) &&
is_same_net6(taddr, &tmp->start6, tmp->prefix) &&
!(tmp->flags & CONTEXT_PROXY))
break;
}
/* Only one context allowed now */ /* Only one context allowed now */
if (tmp) if (tmp)

View File

@@ -1149,6 +1149,9 @@ int is_addr_in_context6(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,
struct in6_addr *taddr, struct in6_addr *taddr,
struct dhcp_netid *netids); struct dhcp_netid *netids);
struct dhcp_context *address6_valid(struct dhcp_context *context,
struct in6_addr *taddr,
struct dhcp_netid *netids);
struct dhcp_context *narrow_context6(struct dhcp_context *context, struct dhcp_context *narrow_context6(struct dhcp_context *context,
struct in6_addr *taddr, struct in6_addr *taddr,
struct dhcp_netid *netids); struct dhcp_netid *netids);

View File

@@ -525,32 +525,38 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
{ {
struct in6_addr *req_addr = opt6_ptr(ia_option, 0); struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
requested_time = opt6_uint(ia_option, 16, 4); requested_time = opt6_uint(ia_option, 16, 4);
struct dhcp_context *dynamic;
if (!address6_available(context, req_addr, tags) && if ((dynamic = address6_available(context, req_addr, tags)) || address6_valid(context, req_addr, tags))
(!have_config(config, CONFIG_ADDR6) || memcmp(&config->addr6, req_addr, IN6ADDRSZ) != 0))
{ {
if (msg_type == DHCP6REQUEST) if (!dynamic && !(have_config(config, CONFIG_ADDR6) && memcmp(&config->addr6, req_addr, IN6ADDRSZ) == 0))
{ {
/* host has a lease, but it's not on the correct link */ /* Static range, not configured. */
o1 = new_opt6(OPTION6_STATUS_CODE); o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOTONLINK); put_opt6_short(DHCP6UNSPEC);
put_opt6_string("Not on link"); put_opt6_string("Address unavailable");
end_opt6(o1); end_opt6(o1);
} }
else if (lease6_find_by_addr(req_addr, 128, 0) &&
!(lease = lease6_find(clid, clid_len, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, req_addr)))
{
/* Address leased to another DUID/IAID */
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6UNSPEC);
put_opt6_string("Address in use");
end_opt6(o1);
}
else
addrp = req_addr;
} }
else if ((lease = lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, else if (msg_type == DHCP6REQUEST)
iaid, req_addr)) &&
(clid_len != lease->clid_len ||
memcmp(clid, lease->clid, clid_len) != 0))
{ {
/* Address leased to another DUID */ /* requested address not on the correct link */
o1 = new_opt6(OPTION6_STATUS_CODE); o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6UNSPEC); put_opt6_short(DHCP6NOTONLINK);
put_opt6_string("Address in use"); put_opt6_string("Not on link");
end_opt6(o1); end_opt6(o1);
} }
else
addrp = req_addr;
} }
else else
{ {