mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 18:28:25 +00:00
Support prefixed ranges of ipv6 addresses in dhcp-host.
When a request matching the clid or mac address is recieved the server will iterate over all candidate addresses until it find's one that is not already leased to a different clid/iaid and advertise this address. Using multiple reservations for a single host makes it possible to maintain a static leases only configuration which support network booting systems with UEFI firmware that request a new address (a new SOLICIT with a new IA_NA option using a new IAID) for different boot modes, for instance 'PXE over IPv6', and 'HTTP-Boot over IPv6'. Open Virtual Machine Firmware (OVMF) and most UEFI firmware build on the EDK2 code base exhibit this behaviour.
This commit is contained in:
@@ -49,6 +49,8 @@ static void end_ia(int t1cntr, unsigned int min_time, int do_fuzz);
|
||||
static void mark_context_used(struct state *state, struct in6_addr *addr);
|
||||
static void mark_config_used(struct dhcp_context *context, struct in6_addr *addr);
|
||||
static int check_address(struct state *state, struct in6_addr *addr);
|
||||
static int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr, struct state *state);
|
||||
static int config_implies(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr);
|
||||
static void add_address(struct state *state, struct dhcp_context *context, unsigned int lease_time, void *ia_option,
|
||||
unsigned int *min_time, struct in6_addr *addr, time_t now);
|
||||
static void update_leases(struct state *state, struct dhcp_context *context, struct in6_addr *addr, unsigned int lease_time, time_t now);
|
||||
@@ -675,7 +677,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
/* If the client asks for an address on the same network as a configured address,
|
||||
offer the configured address instead, to make moving to newly-configured
|
||||
addresses automatic. */
|
||||
if (!(c->flags & CONTEXT_CONF_USED) && config_valid(config, c, &addr) && check_address(state, &addr))
|
||||
if (!(c->flags & CONTEXT_CONF_USED) && config_valid(config, c, &addr, state))
|
||||
{
|
||||
req_addr = addr;
|
||||
mark_config_used(c, &addr);
|
||||
@@ -699,8 +701,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
for (c = state->context; c; c = c->current)
|
||||
if (!(c->flags & CONTEXT_CONF_USED) &&
|
||||
match_netid(c->filter, solicit_tags, plain_range) &&
|
||||
config_valid(config, c, &addr) &&
|
||||
check_address(state, &addr))
|
||||
config_valid(config, c, &addr, state))
|
||||
{
|
||||
mark_config_used(state->context, &addr);
|
||||
if (have_config(config, CONFIG_TIME))
|
||||
@@ -838,14 +839,13 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
struct in6_addr req_addr;
|
||||
struct dhcp_context *dynamic, *c;
|
||||
unsigned int lease_time;
|
||||
struct in6_addr addr;
|
||||
int config_ok = 0;
|
||||
|
||||
/* align. */
|
||||
memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
|
||||
|
||||
if ((c = address6_valid(state->context, &req_addr, tagif, 1)))
|
||||
config_ok = config_valid(config, c, &addr) && IN6_ARE_ADDR_EQUAL(&addr, &req_addr);
|
||||
config_ok = config_implies(config, c, &req_addr);
|
||||
|
||||
if ((dynamic = address6_available(state->context, &req_addr, tagif, 1)) || c)
|
||||
{
|
||||
@@ -971,12 +971,11 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
if ((this_context = address6_available(state->context, &req_addr, tagif, 1)) ||
|
||||
(this_context = address6_valid(state->context, &req_addr, tagif, 1)))
|
||||
{
|
||||
struct in6_addr addr;
|
||||
unsigned int lease_time;
|
||||
|
||||
get_context_tag(state, this_context);
|
||||
|
||||
if (config_valid(config, this_context, &addr) && IN6_ARE_ADDR_EQUAL(&addr, &req_addr) && have_config(config, CONFIG_TIME))
|
||||
if (config_implies(config, this_context, &req_addr) && have_config(config, CONFIG_TIME))
|
||||
lease_time = config->lease_time;
|
||||
else
|
||||
lease_time = this_context->lease_time;
|
||||
@@ -1667,6 +1666,75 @@ static int check_address(struct state *state, struct in6_addr *addr)
|
||||
}
|
||||
|
||||
|
||||
/* return true of *addr could have been generated from config. */
|
||||
static int config_implies(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr)
|
||||
{
|
||||
int prefix;
|
||||
struct in6_addr wild_addr;
|
||||
|
||||
if (!config || !(config->flags & CONFIG_ADDR6))
|
||||
return 0;
|
||||
|
||||
prefix = (config->flags & CONFIG_PREFIX) ? config->prefix : 128;
|
||||
wild_addr = config->addr6;
|
||||
|
||||
if (!is_same_net6(&context->start6, addr, context->prefix))
|
||||
return 0;
|
||||
|
||||
if ((config->flags & CONFIG_WILDCARD))
|
||||
{
|
||||
if (context->prefix != 64)
|
||||
return 0;
|
||||
|
||||
wild_addr = context->start6;
|
||||
setaddr6part(&wild_addr, addr6part(&config->addr6));
|
||||
}
|
||||
|
||||
if (is_same_net6(&wild_addr, addr, prefix))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr, struct state *state)
|
||||
{
|
||||
u64 addrpart;
|
||||
|
||||
if (!config || !(config->flags & CONFIG_ADDR6))
|
||||
return 0;
|
||||
|
||||
addrpart = addr6part(&config->addr6);
|
||||
|
||||
if ((config->flags & CONFIG_WILDCARD))
|
||||
{
|
||||
if (context->prefix != 64)
|
||||
return 0;
|
||||
|
||||
*addr = context->start6;
|
||||
setaddr6part(addr, addrpart);
|
||||
}
|
||||
else if (is_same_net6(&context->start6, &config->addr6, context->prefix))
|
||||
*addr = config->addr6;
|
||||
else
|
||||
return 0;
|
||||
|
||||
while(1) {
|
||||
if (check_address(state, addr))
|
||||
return 1;
|
||||
|
||||
if (!(config->flags & CONFIG_PREFIX))
|
||||
return 0;
|
||||
|
||||
/* config may specify a set of addresses, return first one not in use
|
||||
by another client */
|
||||
|
||||
addrpart++;
|
||||
setaddr6part(addr, addrpart);
|
||||
if (!is_same_net6(addr, &config->addr6, config->prefix))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate valid and preferred times to send in leases/renewals.
|
||||
|
||||
Inputs are:
|
||||
|
||||
Reference in New Issue
Block a user