diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2013-04-27 17:54:25 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2013-04-27 17:54:25 +0000 |
commit | 62113b7821ed39b3688315aee033a07ea1c43970 (patch) | |
tree | 2f99e33afc79fbca07041722e2df69674c77a42d /sbin/dhclient/parse.c | |
parent | 565994089555a60531c0a9fe27a5b650528984c9 (diff) |
Use same parse_date() and date writing logic as in dhcpd. i.e.
strptime() rather than handrolling parsing. Change date format
in leases to same as dhcpd, fixing 'u' vs 'w' error made in
initial strftime() introduction.
Diffstat (limited to 'sbin/dhclient/parse.c')
-rw-r--r-- | sbin/dhclient/parse.c | 185 |
1 files changed, 47 insertions, 138 deletions
diff --git a/sbin/dhclient/parse.c b/sbin/dhclient/parse.c index 2c71eeaa5e9..f9b4b22f077 100644 --- a/sbin/dhclient/parse.c +++ b/sbin/dhclient/parse.c @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.c,v 1.22 2013/04/02 02:37:41 guenther Exp $ */ +/* $OpenBSD: parse.c,v 1.23 2013/04/27 17:54:24 krw Exp $ */ /* Common parser code for dhcpd and dhclient. */ @@ -339,160 +339,69 @@ convert_num(unsigned char *buf, char *str, int base, int size) /* * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER - * NUMBER COLON NUMBER COLON NUMBER SEMI + * NUMBER COLON NUMBER COLON NUMBER UTC SEMI * - * Dates are always in GMT; first number is day of week; next is + * Dates are always in UTC; first number is day of week; next is * year/month/day; next is hours:minutes:seconds on a 24-hour * clock. */ time_t parse_date(FILE *cfile) { - static int months[11] = { 31, 59, 90, 120, 151, 181, - 212, 243, 273, 304, 334 }; - int guess, token; struct tm tm; - char *val; - - /* Day of week... */ - token = next_token(&val, cfile); - if (token != TOK_NUMBER) { - parse_warn("numeric day of week expected."); - if (token != ';') - skip_to_semi(cfile); - return (0); - } - tm.tm_wday = atoi(val); - - /* Year... */ - token = next_token(&val, cfile); - if (token != TOK_NUMBER) { - parse_warn("numeric year expected."); - if (token != ';') - skip_to_semi(cfile); - return (0); - } - tm.tm_year = atoi(val); - if (tm.tm_year > 1900) - tm.tm_year -= 1900; - - /* Slash separating year from month... */ - token = next_token(&val, cfile); - if (token != '/') { - parse_warn("expected slash separating year from month."); - if (token != ';') - skip_to_semi(cfile); - return (0); - } - - /* Month... */ - token = next_token(&val, cfile); - if (token != TOK_NUMBER) { - parse_warn("numeric month expected."); - if (token != ';') - skip_to_semi(cfile); - return (0); - } - tm.tm_mon = atoi(val) - 1; - - /* Slash separating month from day... */ - token = next_token(&val, cfile); - if (token != '/') { - parse_warn("expected slash separating month from day."); - if (token != ';') - skip_to_semi(cfile); - return (0); - } - - /* Day... */ - token = next_token(&val, cfile); - if (token != TOK_NUMBER) { - parse_warn("numeric day of month expected."); - if (token != ';') - skip_to_semi(cfile); - return (0); - } - tm.tm_mday = atoi(val); - - /* Hour... */ - token = next_token(&val, cfile); - if (token != TOK_NUMBER) { - parse_warn("numeric hour expected."); - if (token != ';') - skip_to_semi(cfile); - return (0); - } - tm.tm_hour = atoi(val); + char timestr[26]; /* "w yyyy/mm/dd hh:mm:ss UTC" */ + char *val, *p; + size_t n; + time_t guess; + int token; - /* Colon separating hour from minute... */ - token = next_token(&val, cfile); - if (token != ':') { - parse_warn("expected colon separating hour from minute."); - if (token != ';') - skip_to_semi(cfile); - return (0); - } + memset(timestr, 0, sizeof(timestr)); - /* Minute... */ - token = next_token(&val, cfile); - if (token != TOK_NUMBER) { - parse_warn("numeric minute expected."); - if (token != ';') + do { + token = peek_token(NULL, cfile); + switch (token) { + case TOK_NAME: + case TOK_NUMBER: + case '/': + case ':': + token = next_token(&val, cfile); + n = strlcat(timestr, val, sizeof(timestr)); + if (n >= sizeof(timestr)) { + /* XXX Will break after year 9999! */ + parse_warn("time string too long"); + skip_to_semi(cfile); + return (0); + } + break; + case';': + break; + default: + parse_warn("invalid time string"); skip_to_semi(cfile); - return (0); - } - tm.tm_min = atoi(val); + return (0); + } + } while (token != ';'); - /* Colon separating minute from second... */ - token = next_token(&val, cfile); - if (token != ':') { - parse_warn("expected colon separating minute from second."); - if (token != ';') - skip_to_semi(cfile); - return (0); - } + parse_semi(cfile); - /* Second... */ - token = next_token(&val, cfile); - if (token != TOK_NUMBER) { - parse_warn("numeric second expected."); - if (token != ';') - skip_to_semi(cfile); - return (0); + memset(&tm, 0, sizeof(tm)); /* 'cuz strptime ignores tm_isdt. */ + p = strptime(timestr, DB_TIMEFMT, &tm); + if (p == NULL || *p != '\0') { + p = strptime(timestr, OLD_DB_TIMEFMT, &tm); + if (p == NULL || *p != '\0') { + p = strptime(timestr, BAD_DB_TIMEFMT, &tm); + if (p == NULL || *p != '\0') { + parse_warn("unparseable time string"); + return (0); + } + } } - tm.tm_sec = atoi(val); - tm.tm_isdst = 0; - - /* XXX: We assume that mktime does not use tm_yday. */ - tm.tm_yday = 0; - /* Make sure the date ends in a semicolon... */ - token = next_token(&val, cfile); - if (token != ';') { - parse_warn("semicolon expected."); - skip_to_semi(cfile); + guess = timegm(&tm); + if (guess == -1) { + parse_warn("time could not be represented"); return (0); } - /* Guess the time value... */ - guess = ((((((365 * (tm.tm_year - 70) + /* Days in years since '70 */ - (tm.tm_year - 69) / 4 + /* Leap days since '70 */ - (tm.tm_mon /* Days in months this year */ - ? months[tm.tm_mon - 1] : 0) + - (tm.tm_mon > 1 && /* Leap day this year */ - !((tm.tm_year - 72) & 3)) + - tm.tm_mday - 1) * 24) + /* Day of month */ - tm.tm_hour) * 60) + tm.tm_min) * 60) + tm.tm_sec; - - /* - * This guess could be wrong because of leap seconds or other - * weirdness we don't know about that the system does. For - * now, we're just going to accept the guess, but at some point - * it might be nice to do a successive approximation here to get - * an exact value. Even if the error is small, if the server - * is restarted frequently (and thus the lease database is - * reread), the error could accumulate into something - * significant. - */ return (guess); } |