]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
- Relative time may now be used as a qualifier for 'allow' and 'deny' access
authorDavid Hankins <dhankins@isc.org>
Wed, 31 Oct 2007 19:13:33 +0000 (19:13 +0000)
committerDavid Hankins <dhankins@isc.org>
Wed, 31 Oct 2007 19:13:33 +0000 (19:13 +0000)
  control lists.  These directives may be used to assist in re-addressing
  address pools without having to constantly reconfigure the server.  Please
  see 'man dhcpd.conf' for more information on allow/deny 'after time' syntax.
  Thanks to a patch from Christof Chen.  [ISC-Bugs #17110]

RELNOTES
common/conflex.c
common/parse.c
includes/dhcpd.h
includes/dhctoken.h
server/confpars.c
server/dhcp.c
server/dhcpd.conf.5

index a8e0b47cde56f75436c1a2e77ab631b6b474700e..55c7d9868859a0cbf614133cfa44f2472ba25780 100644 (file)
--- a/RELNOTES
+++ b/RELNOTES
@@ -59,6 +59,12 @@ suggested fixes to <dhcp-users@isc.org>.
   them, if advertised by the client.  It still only seeks to allocate one
   new address.
 
+- Relative time may now be used as a qualifier for 'allow' and 'deny' access
+  control lists.  These directives may be used to assist in re-addressing
+  address pools without having to constantly reconfigure the server.  Please
+  see 'man dhcpd.conf' for more information on allow/deny 'after time' syntax.
+  Thanks to a patch from Christof Chen.
+
                        Changes since 4.0.0b1
 
 - Use different paths for PID and lease files when running in DHCPv4
index fc32a15a44783fd0b3a08e93f63efb99f038bec4..18a840d140227c6f536c4943bc6a9f305ea6ae95 100644 (file)
@@ -732,6 +732,8 @@ intern(char *atom, enum dhcp_token dfv) {
                        return TOKEN_ACTIVE;
                if (!strcasecmp (atom + 1, "tsfp"))
                        return ATSFP;
+                if (!strcasecmp (atom + 1, "fter"))
+                        return AFTER;
                break;
              case 'b':
                if (!strcasecmp (atom + 1, "ackup"))
index 01eced4ee8c433b00068f1e8b534c1e9bee8a48f..6171cd3802488092458c4fb17fb6bb8f8abd7b13 100644 (file)
@@ -843,13 +843,15 @@ void convert_num (cfile, buf, str, base, size)
  *             NUMBER COLON NUMBER COLON NUMBER NUMBER SEMI |
  *         NEVER
  *
- * Dates are stored in GMT or with a timezone offset; first number is day
+ * Dates are stored in UTC or with a timezone offset; first number is day
  * of week; next is year/month/day; next is hours:minutes:seconds on a
  * 24-hour clock, followed by the timezone offset in seconds, which is
  * optional.
  */
 
-TIME parse_date (cfile)
+/* just parse the date */
+TIME 
+parse_date_core(cfile)
        struct parse *cfile;
 {
        int guess;
@@ -1008,10 +1010,6 @@ TIME parse_date (cfile)
        } else
                tzoff = 0;
 
-       /* Make sure the date ends in a semicolon... */
-       if (!parse_semi (cfile))
-               return 0;
-
        /* Guess the time value... */
        guess = ((((((365 * (year - 70) +       /* Days in years since '70 */
                      (year - 69) / 4 +         /* Leap days since '70 */
@@ -1036,6 +1034,22 @@ TIME parse_date (cfile)
        return guess;
 }
 
+/* Wrapper to consume the semicolon after the date */
+TIME 
+parse_date(cfile)
+       struct parse *cfile;
+{
+       int guess;
+       guess = parse_date_core(cfile);
+
+       /* Make sure the date ends in a semicolon... */
+       if (!parse_semi(cfile))
+               return 0;
+       return guess;
+}
+
+
+
 /*
  * option-name :== IDENTIFIER |
                   IDENTIFIER . IDENTIFIER
index ab1675659e80e3261211e885343dad1851e4a760..0d5de79894e3a4655555e359fa0233109c25f360 100644 (file)
@@ -752,9 +752,11 @@ struct permit {
                permit_unauthenticated_clients,
                permit_all_clients,
                permit_dynamic_bootp_clients,
-               permit_class
+               permit_class,
+               permit_after
        } type;
        struct class *class;
+       TIME after;     /* date after which this clause applies */
 };
 
 struct pool {
@@ -775,6 +777,9 @@ struct pool {
        int free_leases;
        int backup_leases;
        int index;
+       TIME valid_from;        /* deny pool use before this date */
+       TIME valid_until;       /* deny pool use after this date */
+
 #if defined (FAILOVER_PROTOCOL)
        dhcp_failover_state_t *failover_peer;
 #endif
@@ -1691,6 +1696,7 @@ unsigned char *parse_numeric_aggregate PROTO ((struct parse *,
 void convert_num PROTO ((struct parse *, unsigned char *, const char *,
                         int, unsigned));
 TIME parse_date PROTO ((struct parse *));
+TIME parse_date_core(struct parse *);
 isc_result_t parse_option_name PROTO ((struct parse *, int, int *,
                                       struct option **));
 void parse_option_space_decl PROTO ((struct parse *));
index 5baea1c49e8341668fca71fdcbcb861e15004197..80ad0b3d52eec0a1a537e75201ecb3bf9e692681 100644 (file)
@@ -344,7 +344,8 @@ enum dhcp_token {
        LL = 647,
        RANGE6 = 648,
        WHITESPACE = 649,
-       TOKEN_ALSO = 650
+       TOKEN_ALSO = 650,
+       AFTER = 651
 };
 
 #define is_identifier(x)       ((x) >= FIRST_TOKEN &&  \
index 5b850ade6d70e72746140d3e8d0f4f6d1b006473..f6101b3b1756b82f181ff47d0293212cbd5512a8 100644 (file)
@@ -1344,6 +1344,8 @@ void parse_pool_statement (cfile, group, type)
        int declaration = 0;
        isc_result_t status;
        struct lease *lpchain = (struct lease *)0, *lp;
+       TIME t;
+       int is_allow = 0;
 
        pool = (struct pool *)0;
        status = pool_allocate (&pool, MDL);
@@ -1440,6 +1442,8 @@ void parse_pool_statement (cfile, group, type)
                        break;
                      case ALLOW:
                        permit_head = &pool -> permit_list;
+                       /* remember the clause which leads to get_permit */
+                       is_allow = 1;
                      get_permit:
                        permit = new_permit (MDL);
                        if (!permit)
@@ -1522,6 +1526,24 @@ void parse_pool_statement (cfile, group, type)
                                                    "no such class: %s", val);
                                break;
 
+                             case AFTER:
+                               if (pool->valid_from || pool->valid_until) {
+                                       parse_warn(cfile,
+                                                   "duplicate \"after\" clause.");
+                                       skip_to_semi(cfile);
+                                       free_permit(permit, MDL);
+                                       continue;
+                               }
+                               t = parse_date_core(cfile);
+                               permit->type = permit_after;
+                               permit->after = t;
+                               if (is_allow) {
+                                       pool->valid_from = t;
+                               } else {
+                                       pool->valid_until = t;
+                               }
+                               break;
+
                              default:
                                parse_warn (cfile, "expecting permit type.");
                                skip_to_semi (cfile);
@@ -1535,6 +1557,8 @@ void parse_pool_statement (cfile, group, type)
 
                      case DENY:
                        permit_head = &pool -> prohibit_list;
+                       /* remember the clause which leads to get_permit */
+                       is_allow = 0; 
                        goto get_permit;
                        
                      case RBRACE:
index a27000b999faf959ec27ba8115841f16832ffde6..b1ec39266db70743396f4136a634b4491aae3eb6 100644 (file)
@@ -1451,6 +1451,8 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
        TIME ping_timeout;
        TIME lease_cltt;
        struct in_addr from;
+       TIME remaining_time;
+       struct iaddr cip;
 
        unsigned i, j;
        int s1;
@@ -2072,6 +2074,54 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
                        data_string_forget(&d1, MDL);
                }
 
+               /* a client requests an address which is not yet active*/
+               if (lease->pool && lease->pool->valid_from && 
+                    cur_time < lease->pool->valid_from) {
+                       /* NAK leases before pool activation date */
+                       cip.len = 4;
+                       memcpy (cip.iabuf, &lt->ip_addr.iabuf, 4);
+                       nak_lease(packet, &cip);
+                       free_lease_state (state, MDL);
+                       lease_dereference (&lt, MDL);
+                       if (host)
+                               host_dereference (&host, MDL);
+                       return;
+                       
+               }
+
+               /* CC:
+               a) NAK current lease if past the expiration date
+               b) extend lease only up to the expiration date, but not
+               below min-lease-time
+               Setting min-lease-time is essential for this to work!
+               The value of min-lease-time determines the lenght
+               of the transition window:
+               A client renewing a second before the deadline will
+               get a min-lease-time lease. Since the current ip might not
+               be routable after the deadline, the client will
+               be offline until it DISCOVERS again. Otherwise it will
+               receive a NAK at T/2.
+               A min-lease-time of 6 seconds effectively switches over
+               all clients in this pool very quickly.
+                       */
+               if (lease->pool && lease->pool->valid_until) {
+                       if (cur_time >= lease->pool->valid_until) {
+                               /* NAK leases after pool expiration date */
+                               cip.len = 4;
+                               memcpy (cip.iabuf, &lt->ip_addr.iabuf, 4);
+                               nak_lease(packet, &cip);
+                               free_lease_state (state, MDL);
+                               lease_dereference (&lt, MDL);
+                               if (host)
+                                       host_dereference (&host, MDL);
+                               return;
+                       }
+                       remaining_time = lease->pool->valid_until - cur_time;
+                       if (lease_time > remaining_time)
+                               lease_time = remaining_time;
+               }
                if (lease_time < min_lease_time) {
                        if (min_lease_time)
                                lease_time = min_lease_time;
@@ -2079,6 +2129,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
                                lease_time = default_lease_time;
                }
 
+
 #if defined (FAILOVER_PROTOCOL)
                /* Okay, we know the lease duration.   Now check the
                   failover state, if any. */
@@ -3839,6 +3890,11 @@ int permitted (packet, permit_list)
                                        return 1;
                        }
                        break;
+
+                     case permit_after:
+                       if (cur_time > p->after)
+                               return 1;
+                       break;
                }
        }
        return 0;
index f34eef5512a51936262386f779a7a1c512a851f8..1ed8b65ac3f1bb2935c43d892281336e4ba0767d 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.89 2007/10/27 19:15:36 each Exp $
+.\" $Id: dhcpd.conf.5,v 1.90 2007/10/31 19:13:33 dhankins Exp $
 .\"
 .TH dhcpd.conf 5
 .SH NAME
@@ -1831,6 +1831,18 @@ pool declaration for some reason, but hold it in reserve, or when you
 want to renumber your network quickly, and thus want the server to
 force all clients that have been allocated addresses from this pool to
 obtain new addresses immediately when they next renew.
+.PP
+ \fBafter \fItime\fR\fB;\fR
+.PP
+If specified, this statement either allows or prevents allocation from
+this pool after a given date. This can be used when you want to move
+clients from one pool to another. The server adjusts the regular lease
+time so that the latest expiry time is at the given time+min-lease-time.
+A short min-lease-time enforces a step change, whereas a longer
+min-lease-time allows for a gradual change.
+\fItime\fR is either second since epoch, or a UTC time string e.g.
+4 2007/08/24 09:14:32 or a string with time zone offset in seconds
+e.g. 4 2007/08/24 11:14:32 -7200
 .SH REFERENCE: PARAMETERS
 The
 .I adaptive-lease-time-threshold