]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
- The server now limits clients that request multiple addresses to one
authorDavid Hankins <dhankins@isc.org>
Tue, 20 Nov 2007 18:34:37 +0000 (18:34 +0000)
committerDavid Hankins <dhankins@isc.org>
Tue, 20 Nov 2007 18:34:37 +0000 (18:34 +0000)
  address per IA by default, which can be adjusted through the
  "limit-addrs-per-ia" configuration option.  [ISC-Bugs #17271]

RELNOTES
includes/dhcpd.h
server/dhcpd.conf.5
server/dhcpv6.c
server/stables.c

index 7c131c59c82426e4af9f87465dcee867fb37b081..28a531bcab8c2b4547624bde73b2fc18476299e6 100644 (file)
--- a/RELNOTES
+++ b/RELNOTES
@@ -65,6 +65,10 @@ suggested fixes to <dhcp-users@isc.org>.
   order to avoid cascading renewals in the event a server elects not to
   extend one of multiple IAADDR leases.
 
+- The server now limits clients that request multiple addresses to one
+  address per IA by default, which can be adjusted through the
+  "limit-addrs-per-ia" configuration option.
+
                        Changes since 4.0.0b2
 
 - Clarified error message when lease limit exceeded
index 0d5de79894e3a4655555e359fa0233109c25f360..1b86b337062cb2fcd24050c657ef0f05a1060d87 100644 (file)
@@ -620,6 +620,7 @@ struct lease_state {
 #define SV_PREFER_LIFETIME             53
 #define SV_DHCPV6_LEASE_FILE_NAME       54
 #define SV_DHCPV6_PID_FILE_NAME         55
+#define SV_LIMIT_ADDRS_PER_IA          56
 
 #if !defined (DEFAULT_PING_TIMEOUT)
 # define DEFAULT_PING_TIMEOUT 1
index 1ed8b65ac3f1bb2935c43d892281336e4ba0767d..15e4e0104cdf0b54430fdbd8b8d1a4926f654051 100644 (file)
@@ -28,7 +28,7 @@
 .\" see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
 .\" ``http://www.nominum.com''.
 .\"
-.\" $Id: dhcpd.conf.5,v 1.90 2007/10/31 19:13:33 dhankins Exp $
+.\" $Id: dhcpd.conf.5,v 1.91 2007/11/20 18:34:37 dhankins Exp $
 .\"
 .TH dhcpd.conf 5
 .SH NAME
@@ -2251,6 +2251,22 @@ environment variable.
 .RE
 .PP
 The
+.I limit-addrs-per-ia
+statement
+.RS 0.25i
+.PP
+.B limit-addrs-per-ia \fInumber\fB;\fR
+.PP
+By default, the DHCPv6 server will limit clients to one IAADDR per IA
+option, meaning one address.  If you wish to permit clients to hang onto
+multiple addresses at a time, configure a larger \fInumber\fR here.
+.PP
+Note that there is no present method to configure the server to forcibly
+configure the client with one IP address per each subnet on a shared network.
+This is left to future work.
+.RE
+.PP
+The
 .I dhcpv6-lease-file-name
 statement
 .RS 0.25i
index c501e622f5ce4f0c400a56633531ef7a203c9a3e..f8e2797f28563df3451fdac71f9c27e36538693a 100644 (file)
@@ -49,7 +49,8 @@ struct reply_state {
 
        /* IA level persistent state */
        unsigned ia_count;
-       isc_boolean_t client_addressed, static_lease;
+       unsigned client_addresses;
+       isc_boolean_t static_lease;
        struct ia_na *ia_na;
        struct ia_na *old_ia;
        struct option_state *reply_ia;
@@ -1244,7 +1245,7 @@ reply_process_ia(struct reply_state *reply, struct option_cache *ia) {
        oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAADDR);
        reply->valid = reply->prefer = 0xffffffff;
        reply->client_valid = reply->client_prefer = 0;
-       reply->client_addressed = ISC_FALSE;
+       reply->client_addresses = 0;
        for (; oc != NULL ; oc = oc->next) {
                status = reply_process_addr(reply, oc);
 
@@ -1267,7 +1268,7 @@ reply_process_ia(struct reply_state *reply, struct option_cache *ia) {
         * If we fell through the above and never gave the client
         * an address, give it one now.
         */
-       if ((status != ISC_R_CANCELED) && !reply->client_addressed) {
+       if ((status != ISC_R_CANCELED) && (reply->client_addresses == 0)) {
                status = find_client_address(reply);
 
                /*
@@ -1482,6 +1483,7 @@ reply_process_addr(struct reply_state *reply, struct option_cache *addr) {
        struct group *group;
        struct subnet *subnet;
        struct iaddr tmp_addr;
+       struct option_cache *oc;
        struct data_string iaaddr, data;
        isc_result_t status = ISC_R_SUCCESS;
 
@@ -1689,6 +1691,47 @@ reply_process_addr(struct reply_state *reply, struct option_cache *addr) {
                group = reply->shared->group;
        }
 
+       /*
+        * If client_addresses is nonzero, then the reply_process_is_addressed
+        * function has executed configuration state into the reply option
+        * cache.  We will use that valid cache to derive configuration for
+        * whether or not to engage in additional addresses, and similar.
+        */
+       if (reply->client_addresses != 0) {
+               unsigned limit = 1;
+
+               /*
+                * Does this client have "enough" addresses already?  Default
+                * to one.  Everybody gets one, and one should be enough for
+                * anybody.
+                */
+               oc = lookup_option(&server_universe, reply->opt_state,
+                                  SV_LIMIT_ADDRS_PER_IA);
+               if (oc != NULL) {
+                       if (!evaluate_option_cache(&data, reply->packet,
+                                                  NULL, NULL,
+                                                  reply->packet->options,
+                                                  reply->opt_state,
+                                                  scope, oc, MDL) ||
+                           (data.len != 4)) {
+                               log_error("reply_process_ia: unable to "
+                                         "evaluate addrs-per-ia value.");
+                               status = ISC_R_FAILURE;
+                               goto cleanup;
+                       }
+
+                       limit = getULong(data.data);
+                       data_string_forget(&data, MDL);
+               }
+
+               /*
+                * If we wish to limit the client to a certain number of
+                * addresses, then omit the address from the reply.
+                */
+               if (reply->client_addresses >= limit)
+                       goto cleanup;
+       }
+
        status = reply_process_is_addressed(reply, scope, group);
        if (status != ISC_R_SUCCESS)
                goto cleanup;
@@ -1889,12 +1932,10 @@ reply_process_is_addressed(struct reply_state *reply,
        oc = lookup_option(&server_universe, reply->opt_state,
                           SV_DEFAULT_LEASE_TIME);
        if (oc != NULL) {
-               if (!evaluate_option_cache(&data, reply->packet, NULL,
-                                          NULL,
+               if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
                                           reply->packet->options,
                                           reply->opt_state,
-                                          &reply->lease->scope,
-                                          oc, MDL) ||
+                                          scope, oc, MDL) ||
                    (data.len != 4)) {
                        log_error("reply_process_ia: uanble to "
                                  "evaluate default lease time");
@@ -1918,12 +1959,10 @@ reply_process_is_addressed(struct reply_state *reply,
        oc = lookup_option(&server_universe, reply->opt_state,
                           SV_PREFER_LIFETIME);
        if (oc != NULL) {
-               if (!evaluate_option_cache(&data, reply->packet, NULL,
-                                          NULL,
+               if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
                                           reply->packet->options,
                                           reply->opt_state,
-                                          &reply->lease->scope,
-                                          oc, MDL) ||
+                                          scope, oc, MDL) ||
                    (data.len != 4)) {
                        log_error("reply_process_ia: unable to "
                                  "evaluate preferred lease time");
@@ -1989,7 +2028,7 @@ reply_process_is_addressed(struct reply_state *reply,
                data_string_forget(&data, MDL);
 
        if (status == ISC_R_SUCCESS)
-               reply->client_addressed = ISC_TRUE;
+               reply->client_addresses++;
 
        return status;
 }
index ef50efb6c900ab11dd7e80f7ec1ffd6f6087a4a4..3e1dffdc8848d8f808deea731a81274695c4925c 100644 (file)
@@ -237,6 +237,7 @@ static struct option server_options[] = {
        { "preferred-lifetime", "T",            &server_universe,  53, 1 },
        { "dhcpv6-lease-file-name", "t",        &server_universe,  54, 1 },
        { "dhcpv6-pid-file-name", "t",          &server_universe,  55, 1 },
+       { "limit-addrs-per-ia", "L",            &server_universe,  56, 1 },
        { NULL, NULL, NULL, 0, 0 }
 };