Commit 5e864416 authored by David Hankins's avatar David Hankins

- 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]
parent d19e2cf7
......@@ -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
......
......@@ -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");
......
......@@ -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;
......
......@@ -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. */
......
......@@ -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;
}
......@@ -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) \
......
......@@ -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 && \
......
......@@ -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)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment