]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
- A new common (server or client) option, 'db-time-format local;', has
authorDavid Hankins <dhankins@isc.org>
Tue, 6 Jun 2006 16:35:18 +0000 (16:35 +0000)
committerDavid Hankins <dhankins@isc.org>
Tue, 6 Jun 2006 16:35:18 +0000 (16:35 +0000)
  been added which prints the local time in /var/db/dhcpd.leases rather
  than UTC.  Thanks to a patch from Ken Lalonde. [ISC-Bugs #2678]

RELNOTES
client/dhclient.c
common/conflex.c
common/parse.c
common/print.c
includes/dhcpd.h
includes/dhctoken.h
server/db.c

index d202be27e7384a137fb5c26318978ef0119b949f..bd3af2dd243dadbce678645fcfdd9c0ecf00db2e 100644 (file)
--- a/RELNOTES
+++ b/RELNOTES
@@ -99,6 +99,10 @@ and for prodding me into improving it.
   supported.  This is a milestone in acheiving RFC 3925 "VIVSO" and
   DHCPv6 support.
 
+- A new common (server or client) option, 'db-time-format local;', has
+  been added which prints the local time in /var/db/dhcpd.leases rather
+  than UTC.  Thanks to a patch from Ken Lalonde.
+
                        Changes since 3.0.4
 
 - A warning that host statements declared within subnet or shared-network
index b04598c113cf92d695be8f918c50edf78c866b77..094df7f1d37481c65d0d5a0d954ff546683f9a82 100644 (file)
@@ -32,7 +32,7 @@
 
 #ifndef lint
 static char ocopyright[] =
-"$Id: dhclient.c,v 1.139 2006/06/01 20:23:16 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: dhclient.c,v 1.140 2006/06/06 16:35:18 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -2285,6 +2285,7 @@ int write_client_lease (client, lease, rewrite, makesure)
        pair *hash;
        int errors = 0;
        char *s;
+       const char *tval;
 
        if (!rewrite) {
                if (leases_written++ > 20) {
@@ -2386,49 +2387,27 @@ int write_client_lease (client, lease, rewrite, makesure)
                                      client, write_lease_option);
        }
 
-       /* Note: the following is not a Y2K bug - it's a Y1.9K bug.   Until
-          somebody invents a time machine, I think we can safely disregard
-          it. */
-       t = gmtime (&lease -> renewal);
-       fprintf (leaseFile,
-                "  renew %d %d/%d/%d %02d:%02d:%02d;\n",
-                t -> tm_wday, t -> tm_year + 1900,
-                t -> tm_mon + 1, t -> tm_mday,
-                t -> tm_hour, t -> tm_min, t -> tm_sec);
-       if (errno != 0) {
+       tval = print_time(lease->renewal);
+       if (tval == NULL ||
+           fprintf(leaseFile, "  renew %s\n", tval) < 0)
                errors++;
-               errno = 0;
-       }
-       t = gmtime (&lease -> rebind);
-       fprintf (leaseFile,
-                "  rebind %d %d/%d/%d %02d:%02d:%02d;\n",
-                t -> tm_wday, t -> tm_year + 1900,
-                t -> tm_mon + 1, t -> tm_mday,
-                t -> tm_hour, t -> tm_min, t -> tm_sec);
-       if (errno != 0) {
+
+       tval = print_time(lease->rebind);
+       if (tval == NULL ||
+           fprintf(leaseFile, "  rebind %s\n", tval) < 0)
                errors++;
-               errno = 0;
-       }
-       t = gmtime (&lease -> expiry);
-       fprintf (leaseFile,
-                "  expire %d %d/%d/%d %02d:%02d:%02d;\n",
-                t -> tm_wday, t -> tm_year + 1900,
-                t -> tm_mon + 1, t -> tm_mday,
-                t -> tm_hour, t -> tm_min, t -> tm_sec);
-       if (errno != 0) {
+
+       tval = print_time(lease->expiry);
+       if (tval == NULL ||
+           fprintf(leaseFile, "  expire %s\n", tval) < 0)
                errors++;
-               errno = 0;
-       }
-       fprintf (leaseFile, "}\n");
-       if (errno != 0) {
+
+       if (fprintf(leaseFile, "}\n") < 0)
                errors++;
-               errno = 0;
-       }
-       fflush (leaseFile);
-       if (errno != 0) {
+
+       if (fflush(leaseFile) != 0)
                errors++;
-               errno = 0;
-       }
+
        if (!errors && makesure) {
                if (fsync (fileno (leaseFile)) < 0) {
                        log_info ("write_client_lease: %m");
index 5f744998d3a50ee4c670ebd37a0e0659976fec2f..db3de04505e0573cbb41e86d9b680b7c205d77e8 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: conflex.c,v 1.98 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: conflex.c,v 1.99 2006/06/06 16:35:18 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -647,6 +647,8 @@ static enum dhcp_token intern (atom, dfv)
                        return CLTT;
                break;
              case 'd':
+               if (!strcasecmp(atom + 1, "b-time-format"))
+                       return DB_TIME_FORMAT;
                if (!strcasecmp (atom + 1, "ns-update"))
                        return DNS_UPDATE;
                if (!strcasecmp (atom + 1, "ns-delete"))
@@ -711,6 +713,8 @@ static enum dhcp_token intern (atom, dfv)
                }
                if (!strcasecmp (atom + 1, "ncode-int"))
                        return ENCODE_INT;
+               if (!strcasecmp(atom + 1, "poch"))
+                       return EPOCH;
                if (!strcasecmp (atom + 1, "thernet"))
                        return ETHERNET;
                if (!strcasecmp (atom + 1, "nds"))
@@ -823,6 +827,8 @@ static enum dhcp_token intern (atom, dfv)
                        return LET;
                if (!strcasecmp (atom + 1, "oad"))
                        return LOAD;
+               if (!strcasecmp(atom + 1, "ocal"))
+                       return LOCAL;
                if (!strcasecmp (atom + 1, "og"))
                        return LOG;
                break;
index 33529a5b1bdb94fc15f45dcc6396f15bab94806e..e1b6b772dc579df1d9b22eecdc9eeff39c14a1f0 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: parse.c,v 1.111 2006/06/05 16:42:58 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: parse.c,v 1.112 2006/06/06 16:35:18 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -758,6 +758,25 @@ TIME parse_date (cfile)
                return MAX_TIME;
        }
 
+       /* This indicates 'local' time format. */
+       if (token == EPOCH) {
+               token = next_token(&val, NULL, cfile);
+
+               if (token != NUMBER) {
+                       parse_warn(cfile, "Seconds since epoch expected.");
+                       if (token != SEMI)
+                               skip_to_semi(cfile);
+                       return (TIME)0;
+               }
+
+               guess = atoi(val);
+
+               if (!parse_semi(cfile))
+                       return (TIME)0;
+
+               return guess;
+       }
+
        if (token != NUMBER) {
                parse_warn (cfile, "numeric day of week expected.");
                if (token != SEMI)
@@ -1754,6 +1773,32 @@ int parse_executable_statement (result, cfile, lose, case_context)
 
        token = peek_token (&val, (unsigned *)0, cfile);
        switch (token) {
+             case DB_TIME_FORMAT:
+               next_token(&val, NULL, cfile);
+
+               token = next_token(&val, NULL, cfile);
+               if (token == DEFAULT) {
+                       db_time_format = DEFAULT_TIME_FORMAT;
+               } else if (token == LOCAL) {
+                       db_time_format = LOCAL_TIME_FORMAT;
+               } else {
+                       parse_warn(cfile, "Expecting 'local' or 'default'.");
+                       if (token != SEMI)
+                               skip_to_semi(cfile);
+                       *lose = 1;
+                       return 0;
+               }
+
+               token = next_token(&val, NULL, cfile);
+               if (token != SEMI) {
+                       parse_warn(cfile, "Expecting a semicolon.");
+                       *lose = 1;
+                       return 0;
+               }
+
+               /* We're done here. */
+               return 1;
+
              case IF:
                next_token (&val, (unsigned *)0, cfile);
                return parse_if_statement (result, cfile, lose);
@@ -2188,7 +2233,7 @@ int parse_executable_statement (result, cfile, lose, case_context)
                        return 0;
                }
                break;
-                       
+
                /* Not really a statement, but we parse it here anyway
                   because it's appropriate for all DHCP agents with
                   parsers. */
index 67f2283793eb9de7a089266d8d3c8dc940ea518d..a1c748ad6ce1bc024d868348bc70e65b0802ce6a 100644 (file)
 
 #ifndef lint
 static char copyright[] =
-"$Id: print.c,v 1.59 2006/05/11 16:31:29 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: print.c,v 1.60 2006/06/06 16:35:18 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
 
+int db_time_format = DEFAULT_TIME_FORMAT;
+
 char *quotify_string (const char *s, const char *file, int line)
 {
        unsigned len = 0;
@@ -1427,3 +1429,48 @@ void print_dns_status (int status, ns_updque *uq)
                log_info ("%s", obuf);
 }
 #endif /* NSUPDATE */
+
+/* Format the given time as "A; # B", where A is the format
+ * used by the parser, and B is the local time, for humans.
+ */
+const char *
+print_time(TIME t)
+{
+       static char buf[sizeof("epoch 9223372036854775807; "
+                              "# Wed Jun 30 21:49:08 2147483647")];
+       /* The string:         "6 2147483647/12/31 23:59:60;"
+        * is smaller than the other, used to declare the buffer size, so
+        * we can use one buffer for both.
+        */
+
+       if (t == MAX_TIME)
+               return "never;";
+
+       if (t < 0)
+               return NULL;
+
+       /* For those lucky enough to have a 128-bit time_t, ensure that
+        * whatever (corrupt) value we're given doesn't exceed the static
+        * buffer.
+        */
+#if (MAX_TIME > 0x7fffffffffffffff)
+       if (t > 0x7fffffffffffffff)
+               return NULL;
+#endif
+
+       if (db_time_format == LOCAL_TIME_FORMAT) {
+               if (strftime(buf, sizeof(buf),
+                            "epoch %s; # %a %b %d %H:%M:%S %Y",
+                            localtime(&t)) == 0)
+                       return NULL;
+       } else {
+               /* No bounds check for the year is necessary - in this case,
+                * strftime() will run out of space and assert an error.
+                */
+               if (strftime(buf, sizeof(buf), "%w %Y/%m/%d %H:%M:%S;",
+                            gmtime(&t)) == 0)
+                       return NULL;
+       }
+
+       return buf;
+}
index bd6788591b56f77235d296ab431f129bf910383f..952edd29b3c074f1640b606cc2a213088f7c04a4 100644 (file)
@@ -1654,6 +1654,9 @@ int dns_zone_reference PROTO ((struct dns_zone **,
                               struct dns_zone *, const char *, int));
 
 /* print.c */
+#define DEFAULT_TIME_FORMAT 0
+#define LOCAL_TIME_FORMAT   1
+extern int db_time_format;
 char *quotify_string (const char *, const char *, int);
 char *quotify_buf (const unsigned char *, unsigned, const char *, int);
 char *print_base64 (const unsigned char *, unsigned, const char *, int);
@@ -1683,6 +1686,7 @@ void indent_spaces (FILE *, int);
 #if defined (NSUPDATE)
 void print_dns_status (int, ns_updque *);
 #endif
+const char *print_time(TIME);
 
 /* socket.c */
 #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_RECEIVE) \
index caa6f43146f10a98c4405326a99dcf76c62a6497..ea332c4b65e77d64bcaf9e6e2a259e8cab585ab9 100644 (file)
@@ -315,7 +315,10 @@ enum dhcp_token {
        WIDTH = 619,
        LENGTH = 620,
        HASH = 621,
-       SIZE = 622
+       SIZE = 622,
+       EPOCH = 623,
+       DB_TIME_FORMAT = 624,
+       LOCAL = 625
 };
 
 #define is_identifier(x)       ((x) >= FIRST_TOKEN &&  \
index fe8303526ee0be9bb2ea676485fc6eacaf90909e..7431fa7d78e406da28a1d29c8cab11b720d03643 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: db.c,v 1.72 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: db.c,v 1.73 2006/06/06 16:35:18 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -53,12 +53,11 @@ int lease_file_is_corrupt = 0;
 int write_lease (lease)
        struct lease *lease;
 {
-       struct tm *t;
-       char tbuf [64];
        int errors = 0;
        int i;
        struct binding *b;
        char *s;
+       const char *tval;
 
        /* If the lease file is corrupt, don't try to write any more leases
           until we've written a good lease file. */
@@ -74,84 +73,35 @@ int write_lease (lease)
                ++errors;
        }
 
-       /* Note: the following is not a Y2K bug - it's a Y1.9K bug.   Until
-          somebody invents a time machine, I think we can safely disregard
-          it. */
-       if (lease -> starts) {
-               if (lease -> starts != MAX_TIME) {
-                       t = gmtime (&lease -> starts);
-                       /* %Audit% Cannot exceed 59 bytes. %2004.06.17,Safe% */
-                       sprintf (tbuf, "%d %d/%02d/%02d %02d:%02d:%02d;",
-                                t -> tm_wday, t -> tm_year + 1900,
-                                t -> tm_mon + 1, t -> tm_mday,
-                                t -> tm_hour, t -> tm_min, t -> tm_sec);
-               } else
-                       strcpy (tbuf, "never;");
-               errno = 0;
-               fprintf (db_file, "\n  starts %s", tbuf);
-               if (errno) {
-                       ++errors;
-               }
-       }
+       if (lease->starts &&
+           ((tval = print_time(lease->starts)) == NULL ||
+            fprintf(db_file, "\n  starts %s", tval) < 0))
+               ++errors;
 
-       if (lease -> ends) {
-               if (lease -> ends != MAX_TIME) {
-                       t = gmtime (&lease -> ends);
-                       /* %Audit% Cannot exceed 59 bytes. %2004.06.17,Safe% */
-                       sprintf (tbuf, "%d %d/%02d/%02d %02d:%02d:%02d;",
-                                t -> tm_wday, t -> tm_year + 1900,
-                                t -> tm_mon + 1, t -> tm_mday,
-                                t -> tm_hour, t -> tm_min, t -> tm_sec);
-               } else
-                       strcpy (tbuf, "never;");
-               errno = 0;
-               fprintf (db_file, "\n  ends %s", tbuf);
-               if (errno) {
-                       ++errors;
-               }
-       }
+       if (lease->ends &&
+           ((tval = print_time(lease->ends)) == NULL ||
+            fprintf(db_file, "\n  ends %s", tval) < 0))
+               ++errors;
 
-       if (lease -> tstp) {
-               t = gmtime (&lease -> tstp);
-               errno = 0;
-               fprintf (db_file, "\n  tstp %d %d/%02d/%02d %02d:%02d:%02d;",
-                        t -> tm_wday, t -> tm_year + 1900,
-                        t -> tm_mon + 1, t -> tm_mday,
-                        t -> tm_hour, t -> tm_min, t -> tm_sec);
-               if (errno) {
-                       ++errors;
-               }
-       }
-       if (lease -> tsfp) {
-               t = gmtime (&lease -> tsfp);
-               errno = 0;
-               fprintf (db_file, "\n  tsfp %d %d/%02d/%02d %02d:%02d:%02d;",
-                        t -> tm_wday, t -> tm_year + 1900,
-                        t -> tm_mon + 1, t -> tm_mday,
-                        t -> tm_hour, t -> tm_min, t -> tm_sec);
-               if (errno) {
-                       ++errors;
-               }
-       }
-       if (lease->atsfp) {
-               t = gmtime(&lease->atsfp);
-               if (fprintf(db_file,
-                           "\n  atsfp %d %d/%02d/%02d %02d:%02d:%02d;",
-                           t->tm_wday, t->tm_year + 1900, t->tm_mon + 1,
-                           t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec) <= 0)
-                       ++errors;
-       }
-       if (lease -> cltt) {
-               t = gmtime (&lease -> cltt);
-               errno = 0;
-               fprintf (db_file, "\n  cltt %d %d/%02d/%02d %02d:%02d:%02d;",
-                        t -> tm_wday, t -> tm_year + 1900,
-                        t -> tm_mon + 1, t -> tm_mday,
-                        t -> tm_hour, t -> tm_min, t -> tm_sec);
-               if (errno) {
-                       ++errors;
-               }
-       }
+       if (lease->tstp &&
+           ((tval = print_time(lease->tstp)) == NULL ||
+            fprintf(db_file, "\n  tstp %s", tval) < 0))
+               ++errors;
+
+       if (lease->tsfp &&
+           ((tval = print_time(lease->tsfp)) == NULL ||
+            fprintf(db_file, "\n  tsfp %s", tval) < 0))
+               ++errors;
+
+       if (lease->atsfp &&
+           ((tval = print_time(lease->atsfp)) == NULL ||
+            fprintf(db_file, "\n  atsfp %s", tval) < 0))
+               ++errors;
+
+       if (lease->cltt &&
+           ((tval = print_time(lease->cltt)) == NULL ||
+            fprintf(db_file, "\n  cltt %s", tval) < 0))
+               ++errors;
 
        fprintf (db_file, "\n  binding state %s;",
                 ((lease -> binding_state > 0 &&
@@ -530,6 +480,7 @@ int write_failover_state (dhcp_failover_state_t *state)
 {
        struct tm *t;
        int errors = 0;
+       const char *tval;
 
        if (lease_file_is_corrupt)
                if (!new_lease_file ())
@@ -540,28 +491,20 @@ int write_failover_state (dhcp_failover_state_t *state)
        if (errno)
                ++errors;
 
-       t = gmtime (&state -> me.stos);
-       errno = 0;
-       fprintf (db_file, "\n  my state %s at %d %d/%02d/%02d %02d:%02d:%02d;",
-                /* Never record our state as "startup"! */
-                (state -> me.state == startup
-                 ? dhcp_failover_state_name_print (state -> saved_state)
-                 : dhcp_failover_state_name_print (state -> me.state)),
-                t -> tm_wday, t -> tm_year + 1900,
-                t -> tm_mon + 1, t -> tm_mday,
-                t -> tm_hour, t -> tm_min, t -> tm_sec);
-       if (errno)
+       tval = print_time(state->me.stos);
+       if (tval == NULL ||
+           fprintf(db_file, "\n  my state %s at %s",
+                   (state->me.state == startup) ?
+                   dhcp_failover_state_name_print(state->saved_state) :
+                   dhcp_failover_state_name_print(state->me.state),
+                   tval) < 0)
                ++errors;
 
-       t = gmtime (&state -> partner.stos);
-       errno = 0;
-       fprintf (db_file,
-                "\n  partner state %s at %d %d/%02d/%02d %02d:%02d:%02d;",
-                dhcp_failover_state_name_print (state -> partner.state),
-                t -> tm_wday, t -> tm_year + 1900,
-                t -> tm_mon + 1, t -> tm_mday,
-                t -> tm_hour, t -> tm_min, t -> tm_sec);
-       if (errno)
+       tval = print_time(state->partner.stos);
+       if (tval == NULL ||
+           fprintf(db_file, "\n  partner state %s at %s",
+                   dhcp_failover_state_name_print(state->partner.state),
+                   tval) < 0)
                ++errors;
 
        if (state -> i_am == secondary) {
@@ -882,28 +825,7 @@ int new_lease_file ()
                fclose(db_file);
        db_file = new_db_file;
 
-       /* Write an introduction so people don't complain about time
-          being off. */
        errno = 0;
-       fprintf (db_file, "# All times in this file are in UTC (GMT), not %s",
-                "your local timezone.   This is\n");
-       if (errno != 0)
-               goto fail;
-       fprintf (db_file, "# not a bug, so please don't ask about it.   %s",
-                "There is no portable way to\n");
-       if (errno != 0)
-               goto fail;
-       fprintf (db_file, "# store leases in the local timezone, so please %s",
-                "don't request this as a\n");
-       if (errno != 0)
-               goto fail;
-       fprintf (db_file, "# feature.   If this is inconvenient or %s",
-                "confusing to you, we sincerely\n");
-       if (errno != 0)
-               goto fail;
-       fprintf (db_file, "# apologize.   Seriously, though - don't ask.\n");
-       if (errno != 0)
-               goto fail;
        fprintf (db_file, "# The format of this file is documented in the %s",
                 "dhcpd.leases(5) manual page.\n");
        if (errno != 0)