mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 18:28:25 +00:00
Massive refactor of stateful DHCPv6. Lease multiple prefixes per client.
This commit is contained in:
44
src/dhcp6.c
44
src/dhcp6.c
@@ -265,8 +265,8 @@ struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int 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 serial, struct dhcp_netid *netids, struct in6_addr *ans)
|
int iaid, struct dhcp_netid *netids, 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
|
||||||
a particular hwaddr/clientid/hostname in our configuration.
|
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
|
/* 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 (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;
|
j += clid[i] + (j << 6) + (j << 16) - j;
|
||||||
|
|
||||||
for (pass = 0; pass <= 1; pass++)
|
for (pass = 0; pass <= 1; pass++)
|
||||||
for (c = context; c; c = c->current)
|
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;
|
continue;
|
||||||
else if (!match_netid(c->filter, netids, pass))
|
else if (!match_netid(c->filter, netids, pass))
|
||||||
continue;
|
continue;
|
||||||
@@ -296,9 +296,9 @@ int address6_allocate(struct dhcp_context *context, unsigned char *clid, int cl
|
|||||||
{
|
{
|
||||||
if (option_bool(OPT_CONSEC_ADDR))
|
if (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);
|
||||||
else
|
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. */
|
/* iterate until we find a free address. */
|
||||||
addr = start;
|
addr = start;
|
||||||
@@ -315,7 +315,7 @@ int address6_allocate(struct dhcp_context *context, unsigned char *clid, int cl
|
|||||||
{
|
{
|
||||||
*ans = c->start6;
|
*ans = c->start6;
|
||||||
setaddr6part (ans, addr);
|
setaddr6part (ans, addr);
|
||||||
return 1;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
addr++;
|
addr++;
|
||||||
@@ -325,7 +325,7 @@ int address6_allocate(struct dhcp_context *context, unsigned char *clid, int cl
|
|||||||
|
|
||||||
} while (addr != start);
|
} while (addr != start);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,34 +369,6 @@ struct dhcp_context *address6_valid(struct dhcp_context *context,
|
|||||||
return NULL;
|
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)
|
static int is_config_in_context6(struct dhcp_context *context, struct dhcp_config *config)
|
||||||
{
|
{
|
||||||
/* expand wildcard on contructed contexts */
|
/* expand wildcard on contructed contexts */
|
||||||
|
|||||||
@@ -681,6 +681,14 @@ struct cond_domain {
|
|||||||
struct cond_domain *next;
|
struct cond_domain *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef OPTION6_PREFIX_CLASS
|
||||||
|
struct prefix_class {
|
||||||
|
int class;
|
||||||
|
struct dhcp_netid netid;
|
||||||
|
struct prefix_class *next;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
struct dhcp_context {
|
struct dhcp_context {
|
||||||
unsigned int lease_time, addr_epoch;
|
unsigned int lease_time, addr_epoch;
|
||||||
struct in_addr netmask, broadcast;
|
struct in_addr netmask, broadcast;
|
||||||
@@ -714,6 +722,7 @@ struct dhcp_context {
|
|||||||
#define CONTEXT_GC 4096
|
#define CONTEXT_GC 4096
|
||||||
#define CONTEXT_RA 8192
|
#define CONTEXT_RA 8192
|
||||||
#define CONTEXT_WILDCARD 16384
|
#define CONTEXT_WILDCARD 16384
|
||||||
|
#define CONTEXT_USED 32768
|
||||||
|
|
||||||
struct ping_result {
|
struct ping_result {
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
@@ -1055,7 +1064,8 @@ struct dhcp_lease *lease4_allocate(struct in_addr addr);
|
|||||||
struct dhcp_lease *lease6_allocate(struct in6_addr *addrp, int lease_type);
|
struct dhcp_lease *lease6_allocate(struct in6_addr *addrp, int lease_type);
|
||||||
struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len,
|
struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len,
|
||||||
int lease_type, int iaid, struct in6_addr *addr);
|
int lease_type, int iaid, struct in6_addr *addr);
|
||||||
void lease6_filter(int lease_type, int iaid, struct dhcp_context *context);
|
void lease6_reset(void);
|
||||||
|
struct dhcp_lease *lease6_find_by_client(struct dhcp_lease *first, int lease_type, unsigned char *clid, int clid_len, int iaid);
|
||||||
struct dhcp_lease *lease6_find_by_addr(struct in6_addr *net, int prefix, u64 addr);
|
struct dhcp_lease *lease6_find_by_addr(struct in6_addr *net, int prefix, u64 addr);
|
||||||
u64 lease_find_max_addr6(struct dhcp_context *context);
|
u64 lease_find_max_addr6(struct dhcp_context *context);
|
||||||
void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface);
|
void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface);
|
||||||
@@ -1160,8 +1170,8 @@ 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);
|
||||||
int 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 serial, struct dhcp_netid *netids, struct in6_addr *ans);
|
int iaid, struct dhcp_netid *netids, struct in6_addr *ans);
|
||||||
int is_addr_in_context6(struct dhcp_context *context, struct in6_addr *addr);
|
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,
|
||||||
@@ -1169,9 +1179,6 @@ struct dhcp_context *address6_available(struct dhcp_context *context,
|
|||||||
struct dhcp_context *address6_valid(struct dhcp_context *context,
|
struct dhcp_context *address6_valid(struct dhcp_context *context,
|
||||||
struct in6_addr *taddr,
|
struct in6_addr *taddr,
|
||||||
struct dhcp_netid *netids);
|
struct dhcp_netid *netids);
|
||||||
struct dhcp_context *narrow_context6(struct dhcp_context *context,
|
|
||||||
struct in6_addr *taddr,
|
|
||||||
struct dhcp_netid *netids);
|
|
||||||
struct dhcp_config *find_config6(struct dhcp_config *configs,
|
struct dhcp_config *find_config6(struct dhcp_config *configs,
|
||||||
struct dhcp_context *context,
|
struct dhcp_context *context,
|
||||||
unsigned char *duid, int duid_len,
|
unsigned char *duid, int duid_len,
|
||||||
|
|||||||
45
src/lease.c
45
src/lease.c
@@ -555,8 +555,7 @@ struct dhcp_lease *lease_find_by_addr(struct in_addr addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
/* addr or clid may be NULL for "don't care, both NULL resets "USED" flags both
|
/* find address for {CLID, IAID, address} */
|
||||||
set activates USED check */
|
|
||||||
struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len,
|
struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len,
|
||||||
int lease_type, int iaid, struct in6_addr *addr)
|
int lease_type, int iaid, struct in6_addr *addr)
|
||||||
{
|
{
|
||||||
@@ -567,40 +566,52 @@ struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len,
|
|||||||
if (!(lease->flags & lease_type) || lease->hwaddr_type != iaid)
|
if (!(lease->flags & lease_type) || lease->hwaddr_type != iaid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (clid && addr && (lease->flags & LEASE_USED))
|
if (memcmp(lease->hwaddr, addr, IN6ADDRSZ) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (addr && memcmp(lease->hwaddr, addr, IN6ADDRSZ) != 0)
|
if ((clid_len != lease->clid_len ||
|
||||||
continue;
|
|
||||||
|
|
||||||
if (clid &&
|
|
||||||
(clid_len != lease->clid_len ||
|
|
||||||
memcmp(clid, lease->clid, clid_len) != 0))
|
memcmp(clid, lease->clid, clid_len) != 0))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
lease->flags |= LEASE_USED;
|
|
||||||
return lease;
|
return lease;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lease6_filter(int lease_type, int iaid, struct dhcp_context *context)
|
/* reset "USED flags */
|
||||||
|
void lease6_reset(void)
|
||||||
{
|
{
|
||||||
struct dhcp_lease *lease;
|
struct dhcp_lease *lease;
|
||||||
|
|
||||||
for (lease = leases; lease; lease = lease->next)
|
for (lease = leases; lease; lease = lease->next)
|
||||||
|
lease->flags &= ~LEASE_USED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* enumerate all leases belonging to {CLID, IAID} */
|
||||||
|
struct dhcp_lease *lease6_find_by_client(struct dhcp_lease *first, int lease_type, unsigned char *clid, int clid_len, int iaid)
|
||||||
|
{
|
||||||
|
struct dhcp_lease *lease;
|
||||||
|
|
||||||
|
if (!first)
|
||||||
|
first = leases;
|
||||||
|
|
||||||
|
for (lease = first; lease; lease = lease->next)
|
||||||
{
|
{
|
||||||
/* reset "USED flag */
|
if (lease->flags & LEASE_USED)
|
||||||
lease->flags &= ~LEASE_USED;
|
continue;
|
||||||
|
|
||||||
if (!(lease->flags & lease_type) || lease->hwaddr_type != iaid)
|
if (!(lease->flags & lease_type) || lease->hwaddr_type != iaid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* leases on the wrong interface get filtered out here */
|
if ((clid_len != lease->clid_len ||
|
||||||
if (!is_addr_in_context6(context, (struct in6_addr *)&lease->hwaddr))
|
memcmp(clid, lease->clid, clid_len) != 0))
|
||||||
lease->flags |= LEASE_USED;
|
continue;
|
||||||
|
|
||||||
|
return lease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dhcp_lease *lease6_find_by_addr(struct in6_addr *net, int prefix, u64 addr)
|
struct dhcp_lease *lease6_find_by_addr(struct in6_addr *net, int prefix, u64 addr)
|
||||||
|
|||||||
1243
src/rfc3315.c
1243
src/rfc3315.c
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user