diff options
author | David Hankins <dhankins@isc.org> | 2009-09-30 20:59:59 +0000 |
---|---|---|
committer | David Hankins <dhankins@isc.org> | 2009-09-30 20:59:59 +0000 |
commit | 2267da8477b6659335c7ddfc2ac32afb91e1af43 (patch) | |
tree | add1525062d16a38abc99cafd8ad7e1d5dbd7c85 /server | |
parent | 29728510c5e28f0cd22a984c7e9396934ffacc13 (diff) | |
download | isc-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.c | 94 |
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); |