mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-09-04 00:05:30 +00:00
Prefix pools are attached to shared network scopes
This commit is contained in:
2
RELNOTES
2
RELNOTES
@@ -69,6 +69,8 @@ work on other platforms. Please report any problems and suggested fixes to
|
|||||||
- Shared network selection should be done from the innermost relay
|
- Shared network selection should be done from the innermost relay
|
||||||
valid link-address field, rather than the outermost.
|
valid link-address field, rather than the outermost.
|
||||||
|
|
||||||
|
- Prefix pools are attached to shared network scopes.
|
||||||
|
|
||||||
Changes since 4.0.0 (new features)
|
Changes since 4.0.0 (new features)
|
||||||
|
|
||||||
- Added DHCPv6 rapid commit support.
|
- Added DHCPv6 rapid commit support.
|
||||||
|
@@ -813,6 +813,7 @@ struct shared_network {
|
|||||||
struct ipv6_pool **ipv6_pools; /* NULL-terminated array */
|
struct ipv6_pool **ipv6_pools; /* NULL-terminated array */
|
||||||
int last_ipv6_pool; /* offset of last IPv6 pool
|
int last_ipv6_pool; /* offset of last IPv6 pool
|
||||||
used to issue a lease */
|
used to issue a lease */
|
||||||
|
struct ipv6_ppool **ipv6_ppools; /* NULL-terminated array */
|
||||||
struct group *group;
|
struct group *group;
|
||||||
#if defined (FAILOVER_PROTOCOL)
|
#if defined (FAILOVER_PROTOCOL)
|
||||||
dhcp_failover_state_t *failover_peer;
|
dhcp_failover_state_t *failover_peer;
|
||||||
@@ -1427,6 +1428,8 @@ struct ipv6_ppool {
|
|||||||
int num_inactive; /* count of inactive IAADDR */
|
int num_inactive; /* count of inactive IAADDR */
|
||||||
isc_heap_t *inactive_timeouts; /* timeouts for expired or
|
isc_heap_t *inactive_timeouts; /* timeouts for expired or
|
||||||
released leases */
|
released leases */
|
||||||
|
struct shared_network *shared_network; /* shared_network for
|
||||||
|
this pool */
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct ipv6_ppool **ppools;
|
extern struct ipv6_ppool **ppools;
|
||||||
|
@@ -627,7 +627,7 @@ int parse_statement (cfile, group, type, host_decl, declaration)
|
|||||||
|
|
||||||
case PREFIX6:
|
case PREFIX6:
|
||||||
next_token(NULL, NULL, cfile);
|
next_token(NULL, NULL, cfile);
|
||||||
if (type != ROOT_GROUP) {
|
if ((type != SUBNET_DECL) || (group->subnet == NULL)) {
|
||||||
parse_warn (cfile,
|
parse_warn (cfile,
|
||||||
"prefix6 definitions may not be scoped.");
|
"prefix6 definitions may not be scoped.");
|
||||||
skip_to_semi(cfile);
|
skip_to_semi(cfile);
|
||||||
@@ -3817,11 +3817,14 @@ parse_address_range6(struct parse *cfile, struct group *group) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_ipv6_ppool_to_global(struct iaddr *start_addr,
|
add_ipv6_ppool_to_shared_network(struct shared_network *share,
|
||||||
|
struct iaddr *start_addr,
|
||||||
int pool_bits,
|
int pool_bits,
|
||||||
int alloc_bits) {
|
int alloc_bits) {
|
||||||
struct ipv6_ppool *ppool;
|
struct ipv6_ppool *ppool;
|
||||||
struct in6_addr tmp_in6_addr;
|
struct in6_addr tmp_in6_addr;
|
||||||
|
int num_ppools;
|
||||||
|
struct ipv6_ppool **tmp;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create our prefix pool.
|
* Create our prefix pool.
|
||||||
@@ -3843,6 +3846,43 @@ add_ipv6_ppool_to_global(struct iaddr *start_addr,
|
|||||||
if (add_ipv6_ppool(ppool) != ISC_R_SUCCESS) {
|
if (add_ipv6_ppool(ppool) != ISC_R_SUCCESS) {
|
||||||
log_fatal ("Out of memory");
|
log_fatal ("Out of memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Link our prefix pool to our shared_network.
|
||||||
|
*/
|
||||||
|
ppool->shared_network = NULL;
|
||||||
|
shared_network_reference(&ppool->shared_network, share, MDL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Increase our array size for ipv6_ppools in the shared_network.
|
||||||
|
*/
|
||||||
|
if (share->ipv6_ppools == NULL) {
|
||||||
|
num_ppools = 0;
|
||||||
|
} else {
|
||||||
|
num_ppools = 0;
|
||||||
|
while (share->ipv6_ppools[num_ppools] != NULL) {
|
||||||
|
num_ppools++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tmp = dmalloc(sizeof(struct ipv6_ppool *) * (num_ppools + 2), MDL);
|
||||||
|
if (tmp == NULL) {
|
||||||
|
log_fatal("Out of memory");
|
||||||
|
}
|
||||||
|
if (num_ppools > 0) {
|
||||||
|
memcpy(tmp, share->ipv6_ppools,
|
||||||
|
sizeof(struct ipv6_ppool *) * num_ppools);
|
||||||
|
}
|
||||||
|
if (share->ipv6_ppools != NULL) {
|
||||||
|
dfree(share->ipv6_ppools, MDL);
|
||||||
|
}
|
||||||
|
share->ipv6_ppools = tmp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Record this prefix pool in our array of prefix pools
|
||||||
|
* for this shared network.
|
||||||
|
*/
|
||||||
|
ipv6_ppool_reference(&share->ipv6_ppools[num_ppools], ppool, MDL);
|
||||||
|
share->ipv6_ppools[num_ppools+1] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* prefix6-declaration :== ip-address6 ip-address6 SLASH number SEMI */
|
/* prefix6-declaration :== ip-address6 ip-address6 SLASH number SEMI */
|
||||||
@@ -3853,9 +3893,25 @@ parse_prefix6(struct parse *cfile, struct group *group) {
|
|||||||
int bits;
|
int bits;
|
||||||
enum dhcp_token token;
|
enum dhcp_token token;
|
||||||
const char *val;
|
const char *val;
|
||||||
|
struct shared_network *share;
|
||||||
struct iaddrcidrnetlist *nets;
|
struct iaddrcidrnetlist *nets;
|
||||||
struct iaddrcidrnetlist *p;
|
struct iaddrcidrnetlist *p;
|
||||||
|
|
||||||
|
if (local_family != AF_INET6) {
|
||||||
|
parse_warn(cfile, "prefix6 statement is only supported "
|
||||||
|
"in DHCPv6 mode.");
|
||||||
|
skip_to_semi(cfile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We'll use the shared_network from our group.
|
||||||
|
*/
|
||||||
|
share = group->shared_network;
|
||||||
|
if (share == NULL) {
|
||||||
|
share = group->subnet->shared_network;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read starting and ending address.
|
* Read starting and ending address.
|
||||||
*/
|
*/
|
||||||
@@ -3900,7 +3956,6 @@ parse_prefix6(struct parse *cfile, struct group *group) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert our range to a set of CIDR networks.
|
* Convert our range to a set of CIDR networks.
|
||||||
*/
|
*/
|
||||||
@@ -3918,7 +3973,8 @@ parse_prefix6(struct parse *cfile, struct group *group) {
|
|||||||
parse_warn(cfile, "impossible mask length");
|
parse_warn(cfile, "impossible mask length");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
add_ipv6_ppool_to_global(&p->cidrnet.lo_addr,
|
add_ipv6_ppool_to_shared_network(share,
|
||||||
|
&p->cidrnet.lo_addr,
|
||||||
p->cidrnet.bits, bits);
|
p->cidrnet.bits, bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -103,7 +103,7 @@ static int get_encapsulated_IA_state(struct option_state **enc_opt_state,
|
|||||||
struct option_cache *oc,
|
struct option_cache *oc,
|
||||||
int offset);
|
int offset);
|
||||||
static void build_dhcpv6_reply(struct data_string *, struct packet *);
|
static void build_dhcpv6_reply(struct data_string *, struct packet *);
|
||||||
static void shared_network_from_packet6(struct shared_network **shared,
|
static isc_result_t shared_network_from_packet6(struct shared_network **shared,
|
||||||
struct packet *packet);
|
struct packet *packet);
|
||||||
static void seek_shared_host(struct host_decl **hp,
|
static void seek_shared_host(struct host_decl **hp,
|
||||||
struct shared_network *shared);
|
struct shared_network *shared);
|
||||||
@@ -1143,6 +1143,7 @@ try_client_v6_prefix(struct iaprefix **pref,
|
|||||||
*/
|
*/
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
pick_v6_prefix(struct iaprefix **pref, int plen,
|
pick_v6_prefix(struct iaprefix **pref, int plen,
|
||||||
|
struct shared_network *shared_network,
|
||||||
const struct data_string *client_id)
|
const struct data_string *client_id)
|
||||||
{
|
{
|
||||||
struct ipv6_ppool *p;
|
struct ipv6_ppool *p;
|
||||||
@@ -1153,19 +1154,19 @@ pick_v6_prefix(struct iaprefix **pref, int plen,
|
|||||||
/*
|
/*
|
||||||
* No prefix pools, we're done.
|
* No prefix pools, we're done.
|
||||||
*/
|
*/
|
||||||
if (!num_ppools) {
|
if (shared_network->ipv6_ppools == NULL) {
|
||||||
log_debug("Unable to pick client prefix: "
|
log_debug("Unable to pick client prefix: "
|
||||||
"no IPv6 prefix pools");
|
"no IPv6 prefix pools on this shared network");
|
||||||
return ISC_R_NORESOURCES;
|
return ISC_R_NORESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Otherwise try to get a prefix.
|
* Otherwise try to get a prefix.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < num_ppools; i++) {
|
for (i = 0;; i++) {
|
||||||
p = ppools[i];
|
p = shared_network->ipv6_ppools[i];
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1229,7 +1230,9 @@ lease_to_client(struct data_string *reply_ret,
|
|||||||
isc_boolean_t no_resources_avail;
|
isc_boolean_t no_resources_avail;
|
||||||
|
|
||||||
/* Locate the client. */
|
/* Locate the client. */
|
||||||
shared_network_from_packet6(&reply.shared, packet);
|
if (shared_network_from_packet6(&reply.shared,
|
||||||
|
packet) != ISC_R_SUCCESS)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the reply.
|
* Initialize the reply.
|
||||||
@@ -1264,18 +1267,14 @@ lease_to_client(struct data_string *reply_ret,
|
|||||||
* valid for the shared network the client is on.
|
* valid for the shared network the client is on.
|
||||||
*/
|
*/
|
||||||
if (find_hosts_by_option(&reply.host, packet, packet->options, MDL)) {
|
if (find_hosts_by_option(&reply.host, packet, packet->options, MDL)) {
|
||||||
if (reply.shared != NULL) {
|
|
||||||
seek_shared_host(&reply.host, reply.shared);
|
seek_shared_host(&reply.host, reply.shared);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ((reply.host == NULL) &&
|
if ((reply.host == NULL) &&
|
||||||
find_hosts_by_uid(&reply.host, client_id->data, client_id->len,
|
find_hosts_by_uid(&reply.host, client_id->data, client_id->len,
|
||||||
MDL)) {
|
MDL)) {
|
||||||
if (reply.shared != NULL) {
|
|
||||||
seek_shared_host(&reply.host, reply.shared);
|
seek_shared_host(&reply.host, reply.shared);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Process the client supplied IA's onto the reply buffer. */
|
/* Process the client supplied IA's onto the reply buffer. */
|
||||||
reply.ia_count = 0;
|
reply.ia_count = 0;
|
||||||
@@ -1284,10 +1283,6 @@ lease_to_client(struct data_string *reply_ret,
|
|||||||
for (; oc != NULL ; oc = oc->next) {
|
for (; oc != NULL ; oc = oc->next) {
|
||||||
isc_result_t status;
|
isc_result_t status;
|
||||||
|
|
||||||
/* A shared network is required. */
|
|
||||||
if (reply.shared == NULL)
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
/* Start counting resources (addresses) offered. */
|
/* Start counting resources (addresses) offered. */
|
||||||
reply.client_resources = 0;
|
reply.client_resources = 0;
|
||||||
reply.ia_resources_included = ISC_FALSE;
|
reply.ia_resources_included = ISC_FALSE;
|
||||||
@@ -1313,10 +1308,6 @@ lease_to_client(struct data_string *reply_ret,
|
|||||||
for (; oc != NULL ; oc = oc->next) {
|
for (; oc != NULL ; oc = oc->next) {
|
||||||
isc_result_t status;
|
isc_result_t status;
|
||||||
|
|
||||||
/* A shared network is required. */
|
|
||||||
if (reply.shared == NULL)
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
/* Start counting resources (addresses) offered. */
|
/* Start counting resources (addresses) offered. */
|
||||||
reply.client_resources = 0;
|
reply.client_resources = 0;
|
||||||
reply.ia_resources_included = ISC_FALSE;
|
reply.ia_resources_included = ISC_FALSE;
|
||||||
@@ -3373,7 +3364,7 @@ reply_process_prefix(struct reply_state *reply, struct option_cache *pref) {
|
|||||||
log_fatal("Impossible condition at %s:%d.", MDL);
|
log_fatal("Impossible condition at %s:%d.", MDL);
|
||||||
|
|
||||||
scope = &reply->prefix->scope;
|
scope = &reply->prefix->scope;
|
||||||
group = root_group;
|
group = reply->shared->group;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3490,7 +3481,9 @@ reply_process_try_prefix(struct reply_state *reply,
|
|||||||
int i;
|
int i;
|
||||||
struct data_string data_pref;
|
struct data_string data_pref;
|
||||||
|
|
||||||
if ((reply == NULL) || (pref == NULL) || (reply->prefix != NULL))
|
if ((reply == NULL) || (reply->shared == NULL) ||
|
||||||
|
(reply->shared->ipv6_ppools == NULL) || (pref == NULL) ||
|
||||||
|
(reply->prefix != NULL))
|
||||||
return ISC_R_INVALIDARG;
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
memset(&data_pref, 0, sizeof(data_pref));
|
memset(&data_pref, 0, sizeof(data_pref));
|
||||||
@@ -3503,10 +3496,10 @@ reply_process_try_prefix(struct reply_state *reply,
|
|||||||
data_pref.buffer->data[0] = (u_int8_t) pref->bits;
|
data_pref.buffer->data[0] = (u_int8_t) pref->bits;
|
||||||
memcpy(data_pref.buffer->data + 1, pref->lo_addr.iabuf, 16);
|
memcpy(data_pref.buffer->data + 1, pref->lo_addr.iabuf, 16);
|
||||||
|
|
||||||
for (i = 0 ; i < num_ppools ; i++) {
|
for (i = 0 ;; i++) {
|
||||||
ppool = ppools[i];
|
ppool = reply->shared->ipv6_ppools[i];
|
||||||
if (ppool == NULL)
|
if (ppool == NULL)
|
||||||
continue;
|
break;
|
||||||
status = try_client_v6_prefix(&reply->prefix, ppool,
|
status = try_client_v6_prefix(&reply->prefix, ppool,
|
||||||
&data_pref);
|
&data_pref);
|
||||||
if (status == ISC_R_SUCCESS)
|
if (status == ISC_R_SUCCESS)
|
||||||
@@ -3533,10 +3526,8 @@ find_client_prefix(struct reply_state *reply) {
|
|||||||
|
|
||||||
if (reply->host != NULL)
|
if (reply->host != NULL)
|
||||||
group = reply->host->group;
|
group = reply->host->group;
|
||||||
else if (reply->shared != NULL)
|
|
||||||
group = reply->shared->group;
|
|
||||||
else
|
else
|
||||||
group = root_group;
|
group = reply->shared->group;
|
||||||
|
|
||||||
if (reply->static_prefixes > 0) {
|
if (reply->static_prefixes > 0) {
|
||||||
struct iaddrcidrnetlist *l;
|
struct iaddrcidrnetlist *l;
|
||||||
@@ -3576,7 +3567,7 @@ find_client_prefix(struct reply_state *reply) {
|
|||||||
*/
|
*/
|
||||||
if ((best_prefix == NULL) || (best_prefix->state == FTS_ABANDONED)) {
|
if ((best_prefix == NULL) || (best_prefix->state == FTS_ABANDONED)) {
|
||||||
status = pick_v6_prefix(&reply->prefix, reply->preflen,
|
status = pick_v6_prefix(&reply->prefix, reply->preflen,
|
||||||
&reply->client_id);
|
reply->shared, &reply->client_id);
|
||||||
} else if (best_prefix != NULL) {
|
} else if (best_prefix != NULL) {
|
||||||
iaprefix_reference(&reply->prefix, best_prefix, MDL);
|
iaprefix_reference(&reply->prefix, best_prefix, MDL);
|
||||||
status = ISC_R_SUCCESS;
|
status = ISC_R_SUCCESS;
|
||||||
@@ -3599,11 +3590,7 @@ find_client_prefix(struct reply_state *reply) {
|
|||||||
log_fatal("Impossible condition at %s:%d.", MDL);
|
log_fatal("Impossible condition at %s:%d.", MDL);
|
||||||
|
|
||||||
scope = &reply->prefix->scope;
|
scope = &reply->prefix->scope;
|
||||||
if (reply->shared != NULL) {
|
|
||||||
group = reply->shared->group;
|
group = reply->shared->group;
|
||||||
} else {
|
|
||||||
group = root_group;
|
|
||||||
}
|
|
||||||
|
|
||||||
send_pref.lo_addr.len = 16;
|
send_pref.lo_addr.len = 16;
|
||||||
memcpy(send_pref.lo_addr.iabuf, &reply->prefix->pref, 16);
|
memcpy(send_pref.lo_addr.iabuf, &reply->prefix->pref, 16);
|
||||||
@@ -3929,7 +3916,7 @@ dhcpv6_request(struct data_string *reply_ret, struct packet *packet) {
|
|||||||
|
|
||||||
/* Find a DHCPv6 packet's shared network from hints in the packet.
|
/* Find a DHCPv6 packet's shared network from hints in the packet.
|
||||||
*/
|
*/
|
||||||
static void
|
static isc_result_t
|
||||||
shared_network_from_packet6(struct shared_network **shared,
|
shared_network_from_packet6(struct shared_network **shared,
|
||||||
struct packet *packet)
|
struct packet *packet)
|
||||||
{
|
{
|
||||||
@@ -3937,11 +3924,10 @@ shared_network_from_packet6(struct shared_network **shared,
|
|||||||
const struct in6_addr *link_addr, *first_link_addr;
|
const struct in6_addr *link_addr, *first_link_addr;
|
||||||
struct iaddr tmp_addr;
|
struct iaddr tmp_addr;
|
||||||
struct subnet *subnet;
|
struct subnet *subnet;
|
||||||
|
isc_result_t status;
|
||||||
|
|
||||||
if ((shared == NULL) || (*shared != NULL) || (packet == NULL)) {
|
if ((shared == NULL) || (*shared != NULL) || (packet == NULL))
|
||||||
log_error("shared_network_from_packet6: invalid arg.");
|
return ISC_R_INVALIDARG;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First, find the link address where the packet from the client
|
* First, find the link address where the packet from the client
|
||||||
@@ -3972,9 +3958,10 @@ shared_network_from_packet6(struct shared_network **shared,
|
|||||||
if (!find_subnet(&subnet, tmp_addr, MDL)) {
|
if (!find_subnet(&subnet, tmp_addr, MDL)) {
|
||||||
log_debug("No subnet found for link-address %s.",
|
log_debug("No subnet found for link-address %s.",
|
||||||
piaddr(tmp_addr));
|
piaddr(tmp_addr));
|
||||||
return;
|
return ISC_R_NOTFOUND;
|
||||||
}
|
}
|
||||||
shared_network_reference(shared, subnet->shared_network, MDL);
|
status = shared_network_reference(shared,
|
||||||
|
subnet->shared_network, MDL);
|
||||||
subnet_dereference(&subnet, MDL);
|
subnet_dereference(&subnet, MDL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3982,10 +3969,12 @@ shared_network_from_packet6(struct shared_network **shared,
|
|||||||
* that this packet came in on to pick the shared_network.
|
* that this packet came in on to pick the shared_network.
|
||||||
*/
|
*/
|
||||||
} else {
|
} else {
|
||||||
shared_network_reference(shared,
|
status = shared_network_reference(shared,
|
||||||
packet->interface->shared_network,
|
packet->interface->shared_network,
|
||||||
MDL);
|
MDL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -4054,8 +4043,8 @@ dhcpv6_confirm(struct data_string *reply_ret, struct packet *packet) {
|
|||||||
* network the client is on.
|
* network the client is on.
|
||||||
*/
|
*/
|
||||||
shared = NULL;
|
shared = NULL;
|
||||||
shared_network_from_packet6(&shared, packet);
|
if ((shared_network_from_packet6(&shared, packet) != ISC_R_SUCCESS) ||
|
||||||
if (shared == NULL)
|
(shared == NULL))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
/* If there are no recorded subnets, then we have no
|
/* If there are no recorded subnets, then we have no
|
||||||
@@ -5651,8 +5640,9 @@ seek_shared_host(struct host_decl **hp, struct shared_network *shared) {
|
|||||||
struct host_decl *seek, *hold = NULL;
|
struct host_decl *seek, *hold = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Seek forward through fixed addresses for the right broadcast
|
* Seek forward through fixed addresses for the right link.
|
||||||
* domain.
|
*
|
||||||
|
* Note: how to do this for fixed prefixes???
|
||||||
*/
|
*/
|
||||||
host_reference(&hold, *hp, MDL);
|
host_reference(&hold, *hp, MDL);
|
||||||
host_dereference(hp, MDL);
|
host_dereference(hp, MDL);
|
||||||
|
Reference in New Issue
Block a user