From: David Hankins Date: Tue, 6 Jun 2006 16:35:18 +0000 (+0000) Subject: - A new common (server or client) option, 'db-time-format local;', has X-Git-Tag: DHCPv6_parsing_base~27 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5e864416367e93c148a709b34ae386f1539c4000;p=thirdparty%2Fdhcp.git - 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. [ISC-Bugs #2678] --- diff --git a/RELNOTES b/RELNOTES index d202be27e..bd3af2dd2 100644 --- 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 diff --git a/client/dhclient.c b/client/dhclient.c index b04598c11..094df7f1d 100644 --- a/client/dhclient.c +++ b/client/dhclient.c @@ -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"); diff --git a/common/conflex.c b/common/conflex.c index 5f744998d..db3de0450 100644 --- a/common/conflex.c +++ b/common/conflex.c @@ -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; diff --git a/common/parse.c b/common/parse.c index 33529a5b1..e1b6b772d 100644 --- a/common/parse.c +++ b/common/parse.c @@ -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. */ diff --git a/common/print.c b/common/print.c index 67f228379..a1c748ad6 100644 --- a/common/print.c +++ b/common/print.c @@ -34,11 +34,13 @@ #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; +} diff --git a/includes/dhcpd.h b/includes/dhcpd.h index bd6788591..952edd29b 100644 --- a/includes/dhcpd.h +++ b/includes/dhcpd.h @@ -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) \ diff --git a/includes/dhctoken.h b/includes/dhctoken.h index caa6f4314..ea332c4b6 100644 --- a/includes/dhctoken.h +++ b/includes/dhctoken.h @@ -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 && \ diff --git a/server/db.c b/server/db.c index fe8303526..7431fa7d7 100644 --- a/server/db.c +++ b/server/db.c @@ -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)