]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
[master] Be more liberal when trying to find a group for a host prefix
authorShawn Routhier <sar@isc.org>
Fri, 26 Jun 2015 20:15:59 +0000 (13:15 -0700)
committerShawn Routhier <sar@isc.org>
Fri, 26 Jun 2015 20:15:59 +0000 (13:15 -0700)
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.

RELNOTES
server/dhcpd.conf.5
server/dhcpv6.c

index aa51fff3f433e8a1815d8b0047566925db493fc8..bec9bc2f2bbd22173da6a2433213848d679a8428 100644 (file)
--- 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
 
index 4c3491f38b54a83766affcb482a53903e478e40b..1e0aedca4255f8d8d56376dc68a91c2574459654 100644 (file)
@@ -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 <XX> is an abandoned address, This may be a result of
-     multiple clients attempting to use this DUID"
+    "Best match for DUID <XX> is an abandoned address, This may be a
+     result of multiple clients attempting to use this DUID"
 
-    where <XX> is an actual DUID value depicted as colon separated string of
-    bytes in hexadecimal values.
+    where <XX> 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
index a9cab1feafe5f01106f1d2a75265b5fb7588e172..ec9c9bf7694a29a16f393804a239daad6b5fa2bd 100644 (file)
@@ -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;
        }