summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorDavid Hankins <dhankins@isc.org>2009-09-30 20:59:59 +0000
committerDavid Hankins <dhankins@isc.org>2009-09-30 20:59:59 +0000
commit2267da8477b6659335c7ddfc2ac32afb91e1af43 (patch)
treeadd1525062d16a38abc99cafd8ad7e1d5dbd7c85 /server
parent29728510c5e28f0cd22a984c7e9396934ffacc13 (diff)
downloadisc-dhcp-2267da8477b6659335c7ddfc2ac32afb91e1af43.tar.gz
- Both host and subnet6 configuration groups are now included whether a
fixed-address6 (DHCPv6) is in use or not. Host scoped configuration takes precedence. This fixes two bugs, one where host scoped configuration would not be included from a non-fixed-address6 host record, and the equal and opposite bug where subnet6 scoped configuration would not be used when over-riding vlaues were not present in a matching fixed-address6 host configuration. [ISC-Bugs #20069]
Diffstat (limited to 'server')
-rw-r--r--server/dhcpv6.c94
1 files changed, 78 insertions, 16 deletions
diff --git a/server/dhcpv6.c b/server/dhcpv6.c
index b5472b0f..7c029b0e 100644
--- a/server/dhcpv6.c
+++ b/server/dhcpv6.c
@@ -43,6 +43,7 @@ struct reply_state {
/* root level persistent state */
struct shared_network *shared;
struct host_decl *host;
+ struct subnet *subnet; /* Used to match fixed-addrs to subnet scopes. */
struct option_state *opt_state;
struct packet *packet;
struct data_string client_id;
@@ -1386,6 +1387,15 @@ lease_to_client(struct data_string *reply_ret,
reply.packet->options,
reply.opt_state, &global_scope,
reply.shared->group, root_group);
+
+ /* Bring in any configuration from a host record. */
+ if (reply.host != NULL)
+ execute_statements_in_scope(NULL, reply.packet, NULL,
+ NULL, reply.packet->options,
+ reply.opt_state,
+ &global_scope,
+ reply.host->group,
+ reply.shared->group);
}
/*
@@ -1576,6 +1586,8 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) {
/* Check & cache the fixed host record. */
if ((reply->host != NULL) && (reply->host->fixed_addr != NULL)) {
+ struct iaddr tmp_addr;
+
if (!evaluate_option_cache(&reply->fixed, NULL, NULL, NULL,
NULL, NULL, &global_scope,
reply->host->fixed_addr, MDL)) {
@@ -1591,6 +1603,14 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) {
goto cleanup;
}
+ /* Find the static lease's subnet. */
+ tmp_addr.len = 16;
+ memcpy(tmp_addr.iabuf, reply->fixed.data, 16);
+
+ if (find_grouped_subnet(&reply->subnet, reply->shared,
+ tmp_addr, MDL) == 0)
+ log_fatal("Impossible condition at %s:%d.", MDL);
+
reply->static_lease = ISC_TRUE;
} else
reply->static_lease = ISC_FALSE;
@@ -1870,6 +1890,8 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) {
iasubopt_dereference(&reply->lease, MDL);
if (reply->fixed.data != NULL)
data_string_forget(&reply->fixed, MDL);
+ if (reply->subnet != NULL)
+ subnet_dereference(&reply->subnet, MDL);
/*
* ISC_R_CANCELED is a status code used by the addr processing to
@@ -2111,7 +2133,7 @@ reply_process_addr(struct reply_state *reply, struct option_cache *addr) {
log_fatal("Impossible condition at %s:%d.", MDL);
scope = &global_scope;
- group = reply->host->group;
+ group = reply->subnet->group;
} else {
if (reply->lease == NULL)
log_fatal("Impossible condition at %s:%d.", MDL);
@@ -2721,7 +2743,7 @@ find_client_address(struct reply_state *reply) {
status = ISC_R_SUCCESS;
scope = &global_scope;
- group = reply->host->group;
+ group = reply->subnet->group;
goto send_addr;
}
@@ -2794,11 +2816,26 @@ reply_process_is_addressed(struct reply_state *reply,
/* Initialize values we will cleanup. */
memset(&data, 0, sizeof(data));
- /* Execute relevant options into root scope. */
+ /*
+ * Bring configured options into the root packet level cache - start
+ * with the lease's closest enclosing group (passed in by the caller
+ * as 'group').
+ */
execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
reply->packet->options, reply->opt_state,
scope, group, root_group);
+ /*
+ * If there is a host record, over-ride with values configured there,
+ * without re-evaluating configuration from the previously executed
+ * group or its common enclosers.
+ */
+ if (reply->host != NULL)
+ execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
+ reply->packet->options,
+ reply->opt_state, scope,
+ reply->host->group, group);
+
/* Determine valid lifetime. */
if (reply->client_valid == 0)
reply->send_valid = DEFAULT_DEFAULT_LEASE_TIME;
@@ -2905,6 +2942,16 @@ reply_process_is_addressed(struct reply_state *reply,
reply->packet->options, reply->reply_ia,
scope, group, root_group);
+ /*
+ * And bring in host record configuration, if any, but not to overlap
+ * the previous group or its common enclosers.
+ */
+ if (reply->host != NULL)
+ execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
+ reply->packet->options,
+ reply->reply_ia, scope,
+ reply->host->group, group);
+
cleanup:
if (data.data != NULL)
data_string_forget(&data, MDL);
@@ -3356,7 +3403,6 @@ static isc_result_t
reply_process_prefix(struct reply_state *reply, struct option_cache *pref) {
u_int32_t pref_life, valid_life;
struct binding_scope **scope;
- struct group *group;
struct iaddrcidrnet tmp_pref;
struct option_cache *oc;
struct data_string iapref, data;
@@ -3501,13 +3547,11 @@ reply_process_prefix(struct reply_state *reply, struct option_cache *pref) {
log_fatal("Impossible condition at %s:%d.", MDL);
scope = &global_scope;
- group = reply->host->group;
} else {
if (reply->lease == NULL)
log_fatal("Impossible condition at %s:%d.", MDL);
scope = &reply->lease->scope;
- group = reply->shared->group;
}
/*
@@ -3551,7 +3595,7 @@ reply_process_prefix(struct reply_state *reply, struct option_cache *pref) {
goto cleanup;
}
- status = reply_process_is_prefixed(reply, scope, group);
+ status = reply_process_is_prefixed(reply, scope, reply->shared->group);
if (status != ISC_R_SUCCESS)
goto cleanup;
@@ -3663,14 +3707,8 @@ find_client_prefix(struct reply_state *reply) {
isc_result_t status = ISC_R_NORESOURCES;
struct iasubopt *prefix, *best_prefix = NULL;
struct binding_scope **scope;
- struct group *group;
int i;
- if (reply->host != NULL)
- group = reply->host->group;
- else
- group = reply->shared->group;
-
if (reply->static_prefixes > 0) {
struct iaddrcidrnetlist *l;
@@ -3732,14 +3770,13 @@ find_client_prefix(struct reply_state *reply) {
log_fatal("Impossible condition at %s:%d.", MDL);
scope = &reply->lease->scope;
- group = reply->shared->group;
send_pref.lo_addr.len = 16;
memcpy(send_pref.lo_addr.iabuf, &reply->lease->addr, 16);
send_pref.bits = (int) reply->lease->plen;
send_pref:
- status = reply_process_is_prefixed(reply, scope, group);
+ status = reply_process_is_prefixed(reply, scope, reply->shared->group);
if (status != ISC_R_SUCCESS)
return status;
@@ -3762,11 +3799,26 @@ reply_process_is_prefixed(struct reply_state *reply,
/* Initialize values we will cleanup. */
memset(&data, 0, sizeof(data));
- /* Execute relevant options into root scope. */
+ /*
+ * Bring configured options into the root packet level cache - start
+ * with the lease's closest enclosing group (passed in by the caller
+ * as 'group').
+ */
execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
reply->packet->options, reply->opt_state,
scope, group, root_group);
+ /*
+ * If there is a host record, over-ride with values configured there,
+ * without re-evaluating configuration from the previously executed
+ * group or its common enclosers.
+ */
+ if (reply->host != NULL)
+ execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
+ reply->packet->options,
+ reply->opt_state, scope,
+ reply->host->group, group);
+
/* Determine valid lifetime. */
if (reply->client_valid == 0)
reply->send_valid = DEFAULT_DEFAULT_LEASE_TIME;
@@ -3858,6 +3910,16 @@ reply_process_is_prefixed(struct reply_state *reply,
reply->packet->options, reply->reply_ia,
scope, group, root_group);
+ /*
+ * And bring in host record configuration, if any, but not to overlap
+ * the previous group or its common enclosers.
+ */
+ if (reply->host != NULL)
+ execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
+ reply->packet->options,
+ reply->reply_ia, scope,
+ reply->host->group, group);
+
cleanup:
if (data.data != NULL)
data_string_forget(&data, MDL);