From: Shawn Routhier Date: Fri, 26 Jun 2015 20:15:59 +0000 (-0700) Subject: [master] Be more liberal when trying to find a group for a host prefix X-Git-Tag: v4_3_3b1~16 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=34711bb79b2afb3987b738150dc3ce2e4675e602;p=thirdparty%2Fdhcp.git [master] Be more liberal when trying to find a group for a host prefix When trying to find the group to use as a scope boundary for a prefix from a host declaration relax the requirement that the prefix be within a subnet. We now look for the subnet based on the prefix, if that fails we look for a subnet based on the host address if it exists and if that fails we use the one from the shared network we found for the client. --- diff --git a/RELNOTES b/RELNOTES index aa51fff3f..bec9bc2f2 100644 --- a/RELNOTES +++ b/RELNOTES @@ -148,6 +148,15 @@ by Eric Young (eay@cryptsoft.com). with the next entry in the lease file. [ISC-Bugs #39314] +- Be more liberal in finding a subnet group associated with a static + prefix. When we added the class matching code for v6 we also added + a requirement that the static prefix must be within a subnet the + client was in, in order to find the proper statements. We now + look for a subnet based on the prefix, failing that on the static + address for the client and failing that on the shared network + itself. + [ISC-Bugs #38329] + Changes since 4.3.2rc2 - None diff --git a/server/dhcpd.conf.5 b/server/dhcpd.conf.5 index 4c3491f38..1e0aedca4 100644 --- a/server/dhcpd.conf.5 +++ b/server/dhcpd.conf.5 @@ -1540,18 +1540,25 @@ This statement is currently global but it should have a shared-network scope. .PP The .B host -declaration provides a scope in which to provide configuration information about -a specific client, and also provides a way to assign a client a fixed address. -The host declaration provides a way for the DHCP server to identify a DHCP or -BOOTP client, and also a way to assign the client a static IP address. +declaration provides a way for the DHCP server to identify a DHCP or +BOOTP client. This allows the server to provide configuration +information including fixed addresses or, in DHCPv6, fixed prefixes +for a specific client. .PP If it is desirable to be able to boot a DHCP or BOOTP client on more than one -subnet with fixed addresses, more than one address may be specified in the +subnet with fixed v4 addresses, more than one address may be specified in the .I fixed-address declaration, or more than one .B host statement may be specified matching the same client. .PP +The +.I fixed-address6 +delcaration is used for v6 addresses. At this time it only works with a single +address. For multiple addresses specify multiple +.B host +statements. +.PP If client-specific boot parameters must change based on the network to which the client is attached, then multiple .B host @@ -1724,19 +1731,20 @@ allocations. .PP Currently, abandoned IPv6 addresses are reclaimed in one of two ways: a) Client renews a specific address: - If a client using a given DUID submits a DHCP REQUEST containing the - last address abandoned by that DUID, the address will be reassigned to - that client. + If a client using a given DUID submits a DHCP REQUEST containing + the last address abandoned by that DUID, the address will be + reassigned to that client. - b) Upon the second restart following an address abandonment. When an - address is abandoned it is both recorded as such in the lease file and - retained as abandoned in server memory until the server is restarted. Upon - restart, the server will process the lease file and all addresses whose - last known state is abandoned will be retained as such in memory but not - rewritten to the lease file. This means that a subsequent restart of the - server will not see the abandoned addresses in the lease file and - therefore have no record of them as abandoned in memory and as such - perceive them as free for assignment. + b) Upon the second restart following an address abandonment. When + an address is abandoned it is both recorded as such in the lease + file and retained as abandoned in server memory until the server + is restarted. Upon restart, the server will process the lease file + and all addresses whose last known state is abandoned will be + retained as such in memory but not rewritten to the lease file. + This means that a subsequent restart of the server will not see the + abandoned addresses in the lease file and therefore have no record + of them as abandoned in memory and as such perceive them as free + for assignment. .PP The total number addresses in a pool, available for a given DUID value, is internally limited by the server's address generation mechanism. If @@ -1747,11 +1755,11 @@ of activity such that address range is not exhausted for other DUID values. The appearance of the following error log, can be an indication of this condition: - "Best match for DUID is an abandoned address, This may be a result of - multiple clients attempting to use this DUID" + "Best match for DUID is an abandoned address, This may be a + result of multiple clients attempting to use this DUID" - where is an actual DUID value depicted as colon separated string of - bytes in hexadecimal values. + where is an actual DUID value depicted as colon separated + string of bytes in hexadecimal values. .PP The \fBdeclines\fR flag tells the DHCP server whether or not to honor DHCPDECLINE messages. If it is set to \fBdeny\fR or \fBignore\fR in @@ -2313,6 +2321,36 @@ declaration. .RE .PP The +.I fixed-prefix6 +declaration +.RS 0.25i +.PP +.B fixed-prefix6\fR \fIlow-address\fR \fB/\fR \fIbits\fR\fB;\fR +.PP +The \fIfixed-prefix6\fR declaration is used to assign a fixed +IPv6 prefix to a client. It should only appear in a \fIhost\fR +declaration, but multiple \fIfixed-prefix6\fR statements may appear +in a single \fIhost\fR declaration. +.PP +The \fIlow-address\fR specifies the start of the prefix and the \fIbits\fR +specifies the size of the prefix in bits. +.PP +If there are multiple prefixes for a given host entry the server will +choose one that matches the requested prefix size or, if none match, +the first one. +.PP +If there are multiple \fIhost\fR delcarations the server will try to +choose a declaration where the \fIfixed-address6\fR matches the client's +subnet. If none match it will choose one that doesn't have a \fIfixed-address6\fR +statement. +.PP +Note Well: Unlike the fixed address the fixed prefix does not need to match +a subnet in order to be served. This allows you to provide a prefix to +a client that is outside of the subnet on which the client makes the request +to the the server. +.RE +.PP +The .I get-lease-hostnames statement .RS 0.25i diff --git a/server/dhcpv6.c b/server/dhcpv6.c index a9cab1fea..ec9c9bf76 100644 --- a/server/dhcpv6.c +++ b/server/dhcpv6.c @@ -131,6 +131,7 @@ static struct iasubopt *lease_compare(struct iasubopt *alpha, struct iasubopt *beta); static isc_result_t reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia_pd); +static struct group *find_group_by_prefix(struct reply_state *reply); static isc_result_t reply_process_prefix(struct reply_state *reply, struct option_cache *pref); static isc_boolean_t prefix_is_owned(struct reply_state *reply, @@ -4079,6 +4080,66 @@ reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia) { return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status); } +/*! + * + * \brief Find the proper scoping group for use with a v6 static prefix. + * + * We start by trying to find a subnet based on the given prefix and + * the shared network. If we don't find one then the prefix has been + * declared outside of any subnets. If there is a static address + * associated with the host we use it to try and find a subnet (this + * should succeed). If there isn't a static address we fall back + * to the shared subnet itself. + * Once we have a subnet we extract the group from it and return it. + * + * \param reply - the reply structure we use to collect information + * we will use the fields shared, fixed_pref and host + * from the structure + * + * \return a pointer to the group structure to use for scoping + */ + +static struct group * +find_group_by_prefix(struct reply_state *reply) { + /* default group if we don't find anything better */ + struct group *group = reply->shared->group; + struct subnet *subnet = NULL; + struct iaddr tmp_addr; + struct data_string fixed_addr; + + /* Try with the prefix first */ + if (find_grouped_subnet(&subnet, reply->shared, + reply->fixed_pref.lo_addr, MDL) != 0) { + group = subnet->group; + subnet_dereference(&subnet, MDL); + return (group); + } + + /* Didn't find a subnet via prefix, what about fixed address */ + /* The caller has already tested reply->host != NULL */ + + memset(&fixed_addr, 0, sizeof(fixed_addr)); + + if ((reply->host->fixed_addr != NULL) && + (evaluate_option_cache(&fixed_addr, NULL, NULL, NULL, + NULL, NULL, &global_scope, + reply->host->fixed_addr, MDL))) { + if (fixed_addr.len >= 16) { + tmp_addr.len = 16; + memcpy(tmp_addr.iabuf, fixed_addr.data, 16); + if (find_grouped_subnet(&subnet, reply->shared, + tmp_addr, MDL) != 0) { + group = subnet->group; + subnet_dereference(&subnet, MDL); + } + } + data_string_forget(&fixed_addr, MDL); + } + + /* return whatever we got */ + return (group); +} + /* * Process an IAPREFIX within a given IA_PD, storing any IAPREFIX reply * contents into the reply's current ia_pd-scoped option cache. Returns @@ -4236,15 +4297,11 @@ reply_process_prefix(struct reply_state *reply, struct option_cache *pref) { scope = &global_scope; - /* Find the static prefixe's subnet. */ - if (find_grouped_subnet(&reply->subnet, reply->shared, - tmp_pref.lo_addr, MDL) == 0) - log_fatal("Impossible condition at %s:%d.", MDL); - group = reply->subnet->group; - subnet_dereference(&reply->subnet, MDL); - - /* Copy the static prefix for logging purposes */ + /* Copy the static prefix for logging and finding the group */ memcpy(&reply->fixed_pref, &tmp_pref, sizeof(tmp_pref)); + + /* Try to find a group for the static prefix */ + group = find_group_by_prefix(reply); } else { if (reply->lease == NULL) log_fatal("Impossible condition at %s:%d.", MDL); @@ -4485,16 +4542,12 @@ find_client_prefix(struct reply_state *reply) { scope = &global_scope; - /* Find the static prefixe's subnet. */ - if (find_grouped_subnet(&reply->subnet, reply->shared, - send_pref.lo_addr, MDL) == 0) - log_fatal("Impossible condition at %s:%d.", MDL); - group = reply->subnet->group; - subnet_dereference(&reply->subnet, MDL); - /* Copy the prefix for logging purposes */ memcpy(&reply->fixed_pref, &l->cidrnet, sizeof(send_pref)); + /* Try to find a group for the static prefix */ + group = find_group_by_prefix(reply); + goto send_pref; }