From: Juergen Perlinger Date: Tue, 22 Apr 2014 19:40:54 +0000 (+0200) Subject: [Bug 2597] fixed loose ends: changed/unified logging for leapfile related actions X-Git-Tag: NTP_4_2_7P441~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ea1c09461333802a35712d138244d48e16563eeb;p=thirdparty%2Fntp.git [Bug 2597] fixed loose ends: changed/unified logging for leapfile related actions bk: 5356c5c65m_L0hkr9ZkGieWhebULmA --- diff --git a/ChangeLog b/ChangeLog index 8fc2f9d9e..455580c1b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +* [Bug 2597] leap file processing -- loose ends + log daily warning when leap info less than 28 days to expiration or + already expired; nag hourly on last day before expiration; log when + leapfile name is invalid (4.2.7p440) 2014/04/09 Released by Harlan Stenn * [Bug 2536] ntpd sandboxing support (libseccomp2) cleanup. * [Bug 2570] cleanup: fix log format for successful leapfile load diff --git a/include/ntpd.h b/include/ntpd.h index 52a0433aa..0a8a93186 100644 --- a/include/ntpd.h +++ b/include/ntpd.h @@ -286,7 +286,7 @@ extern void record_clock_stats (sockaddr_u *, const char *); extern int mprintf_clock_stats(sockaddr_u *, const char *, ...) NTP_PRINTF(2, 3); extern void record_raw_stats (sockaddr_u *srcadr, sockaddr_u *dstadr, l_fp *t1, l_fp *t2, l_fp *t3, l_fp *t4, int leap, int version, int mode, int stratum, int poll, int precision, double root_delay, double root_dispersion, u_int32 refid); -extern int check_leap_file (void); +extern void check_leap_file (int is_daily_check, u_int32 ntptime, const time_t * systime); extern void record_crypto_stats (sockaddr_u *, const char *); #ifdef DEBUG extern void record_timing_stats (const char *); diff --git a/ntpd/ntp_leapsec.c b/ntpd/ntp_leapsec.c index 59fa034e5..d85c75e43 100644 --- a/ntpd/ntp_leapsec.c +++ b/ntpd/ntp_leapsec.c @@ -10,6 +10,7 @@ #include #include +#include #include #include "ntp_types.h" @@ -19,9 +20,12 @@ #include "ntp_leapsec.h" #include "ntp.h" #include "vint64ops.h" +#include "lib_strbuf.h" #include "isc/sha1.h" +static const char * const logPrefix = "leapsecond file"; + /* --------------------------------------------------------------------- * GCC is rather sticky with its 'const' attribute. We have to do it more * explicit than with a cast if we want to get rid of a CONST qualifier. @@ -89,6 +93,7 @@ static int betweenu32(uint32_t, uint32_t, uint32_t); static void reset_times(leap_table_t*); static int leapsec_add(leap_table_t*, const vint64*, int); static int leapsec_raw(leap_table_t*, const vint64 *, int, int); +static char * lstostr(const vint64 * ts); /* ===================================================================== * Get & Set the current leap table @@ -368,14 +373,12 @@ leapsec_reset_frame(void) * or this will fail. */ int/*BOOL*/ -leapsec_load_file( +leapsec_load_stream( FILE * ifp , const char * fname) { - static const char * const logPrefix = "leapsecond file"; - - leap_table_t * pt; - int rcheck; + leap_table_t *pt; + int rcheck; if (NULL == fname) fname = ""; @@ -389,7 +392,7 @@ leapsec_load_file( break; case LSVALID_NOHASH: - msyslog(LOG_INFO, "%s ('%s'): no hash signature", + msyslog(LOG_NOTICE, "%s ('%s'): no hash signature", logPrefix, fname); break; case LSVALID_BADHASH: @@ -427,10 +430,64 @@ leapsec_load_file( } return FALSE; } - msyslog(LOG_NOTICE, "%s ('%s'): loaded", logPrefix, fname); + + if (pt->head.size) + msyslog(LOG_NOTICE, "%s ('%s'): loaded, expire=%s last=%s ofs=%d", + logPrefix, fname, lstostr(&pt->head.expire), + lstostr(&pt->info[0].ttime), pt->info[0].taiof); + else + msyslog(LOG_NOTICE, + "%s ('%s'): loaded, expire=%s ofs=%d (no entries after build date)", + logPrefix, fname, lstostr(&pt->head.expire), + pt->head.base_tai); + return leapsec_set_table(pt); } +/* ------------------------------------------------------------------ */ +int/*BOOL*/ +leapsec_load_file( + const char * fname, + struct stat * sb_old, + int/*BOOL*/ force) +{ + FILE * fp; + struct stat sb_new; + int rc; + + /* just do nothing if there is no leap file */ + if ( ! (fname && *fname)) + return FALSE; + + /* try to stat the leapfile */ + if (0 != stat(fname, &sb_new)) { + msyslog(LOG_ERR, "%s ('%s'): stat failed: %m", + logPrefix, fname); + return FALSE; + } + + /* silently skip to postcheck if no new file found */ + if (NULL != sb_old) { + if (!force && + sb_old->st_mtime == sb_new.st_mtime && + sb_old->st_ctime == sb_new.st_ctime ) + return FALSE; + *sb_old = sb_new; + } + + /* try to open the leap file, complain if that fails */ + if ((fp = fopen(fname, "r")) == NULL) { + msyslog(LOG_ERR, + "%s ('%s'): open failed: %m", + logPrefix, fname); + return FALSE; + } + + rc = leapsec_load_stream(fp, fname); + fclose(fp); + return rc; +} + /* ------------------------------------------------------------------ */ void leapsec_getsig( @@ -907,4 +964,23 @@ leapsec_validate( return LSVALID_GOODHASH; } +/* + * lstostr - prettyprint NTP seconds + */ +static char * lstostr( + const vint64 * ts) +{ + char * buf; + struct calendar tm; + + LIB_GETBUF(buf); + ntpcal_ntp64_to_date(&tm, ts); + snprintf(buf, LIB_BUFLENGTH, "%04d-%02d-%02dT%02d:%02dZ", + tm.year, tm.month, tm.monthday, + tm.hour, tm.minute); + return buf; +} + + + /* -*- that's all folks! -*- */ diff --git a/ntpd/ntp_leapsec.h b/ntpd/ntp_leapsec.h index 5e9fc60d3..472790db8 100644 --- a/ntpd/ntp_leapsec.h +++ b/ntpd/ntp_leapsec.h @@ -11,6 +11,9 @@ #ifndef NTP_LEAPSEC_H #define NTP_LEAPSEC_H +struct stat; + + /* function pointer types. Note that 'fprintf' and 'getc' can be casted * to the dumper resp. reader type, provided the auxiliary argument is a * valid FILE pointer in hat case. @@ -128,10 +131,20 @@ extern int/*BOOL*/ leapsec_load(leap_table_t*, leapsec_reader, */ extern void leapsec_dump(const leap_table_t*, leapsec_dumper func, void *farg); -/* Read a leap second file. This is a convenience wrapper around the - * generic load function, 'leapsec_load()'. +/* Read a leap second file from stream. This is a convenience wrapper + * around the generic load function, 'leapsec_load()'. + */ +extern int/*BOOL*/ leapsec_load_stream(FILE * fp, const char * fname); + +/* Read a leap second file from file. It checks that the file exists and + * (if 'force' is not applied) the ctime/mtime has changed since the + * last load. If the file has to be loaded, either due to 'force' or + * changed time stamps, the 'stat()' results of the file are stored in + * '*sb' for the next cycle. Returns TRUE on successful load, FALSE + * otherwise. Uses 'leapsec_load_stream()' internally. */ -extern int/*BOOL*/ leapsec_load_file(FILE * fp, const char * fname); +extern int/*BOOL*/ leapsec_load_file(const char * fname, struct stat * sb, + int/*BOOL*/force); /* Get the current leap data signature. This consists of the last * ransition, the table expiration, and the total TAI difference at the diff --git a/ntpd/ntp_timer.c b/ntpd/ntp_timer.c index 74cde9e82..b51aa37d1 100644 --- a/ntpd/ntp_timer.c +++ b/ntpd/ntp_timer.c @@ -41,8 +41,6 @@ #define TC_ERR (-1) #endif -extern char *leapseconds_file; /* name of the leapseconds file */ - static void check_leapsec(u_int32, const time_t*, int/*BOOL*/); /* @@ -427,30 +425,11 @@ timer(void) if (stats_timer <= current_time) { stats_timer += SECSPERHR; write_stats(); - if (sys_tai != 0 && leapsec_expired(now.l_ui, &tnow)) { - int clf = check_leap_file(); - - /* - ** check_leap_file() returns -1 on a problem, - ** 0 on an expired leapsecond file, or the number - ** of days until the leapsecond file expires. - ** - ** We only want to log stuff once/day. - */ - if (check_leapfile < current_time) { - check_leapfile += SECSPERDAY; - if (-1 == clf) { - /* nothing to do */ - } else if (0 == clf) { - report_event(EVNT_LEAPVAL, NULL, NULL); - msyslog(LOG_WARNING, - "timer: leapseconds data file <%s> has expired!", - leapseconds_file); - } else if (clf < 31) { - msyslog(LOG_WARNING, - "timer: leapseconds data file <%s> will expire in less than %d days' time.", leapseconds_file, clf); - } - } + if (check_leapfile < current_time) { + check_leapfile += SECSPERDAY; + check_leap_file(TRUE, now.l_ui, &tnow); + } else { + check_leap_file(FALSE, now.l_ui, &tnow); } } } diff --git a/ntpd/ntp_util.c b/ntpd/ntp_util.c index 3082f6218..76a2239d9 100644 --- a/ntpd/ntp_util.c +++ b/ntpd/ntp_util.c @@ -55,9 +55,9 @@ * File names */ static char *key_file_name; /* keys file name */ -char *leapseconds_file; /* leapseconds file name */ -struct stat leapseconds_file_sb1; /* leapseconds file stat() buffer */ -struct stat leapseconds_file_sb2; /* leapseconds file stat() buffer */ +static char *leapfile_name; /* leapseconds file name */ +static struct stat leapfile_stat; /* leapseconds file stat() buffer */ +static int /*BOOL*/have_leapfile = FALSE; char *stats_drift_file; /* frequency file name */ static char *stats_temp_file; /* temp frequency file name */ static double wander_resid; /* last frequency update */ @@ -466,7 +466,7 @@ stats_config( break; } fprintf(fp, "%d", (int)getpid()); - fclose(fp);; + fclose(fp); break; /* @@ -480,20 +480,10 @@ stats_config( if (!value || (len = strlen(value)) == 0) break; - leapseconds_file = erealloc(leapseconds_file, len + 1); - memcpy(leapseconds_file, value, len + 1); + leapfile_name = erealloc(leapfile_name, len + 1); + memcpy(leapfile_name, value, len + 1); - if ((fp = fopen(leapseconds_file, "r")) == NULL) { - msyslog(LOG_ERR, "leapseconds file %s: %m", - leapseconds_file); - break; - } - - if (-1 == fstat(fileno(fp), &leapseconds_file_sb1)) { - msyslog(LOG_ERR, - "leapseconds: stat(%s) failed: %m", - leapseconds_file); - } else if (leapsec_load_file(fp, leapseconds_file)) { + if (leapsec_load_file(leapfile_name, &leapfile_stat, TRUE)) { leap_signature_t lsig; leapsec_getsig(&lsig); @@ -506,8 +496,8 @@ stats_config( ? "expired" : "expires", fstostr(lsig.etime)); + have_leapfile = TRUE; } - fclose(fp); break; default: @@ -871,46 +861,46 @@ record_timing_stats( * without SHA1 signature is accepted, but if there is a signature line, * the signature must be valid or the file is rejected. */ -int +void check_leap_file( - void + int is_daily_check, + uint32_t ntptime , + const time_t *systime ) { - FILE *fp; - struct stat *sp1 = &leapseconds_file_sb1; - struct stat *sp2 = &leapseconds_file_sb2; - int rc = INT_MAX; /* assume not expired for long a time */ - l_fp now; + static const char * const logPrefix = "leapsecond file"; + int rc; + /* just do nothing if there is no leap file */ + if ( ! (leapfile_name && *leapfile_name)) + return; + + /* try to load leapfile, force it if no leapfile loaded yet */ + if (leapsec_load_file( + leapfile_name, &leapfile_stat, !have_leapfile)) + have_leapfile = TRUE; + else if (!have_leapfile) + return; - if (leapseconds_file) { - get_systime(&now); - if ((fp = fopen(leapseconds_file, "r")) == NULL) { - msyslog(LOG_ERR, - "check_leap_file: fopen(%s): %m", - leapseconds_file); - rc = -1; - } else if (fstat(fileno(fp), &leapseconds_file_sb2)) { + /* test the expiration of the leap data and log with proper + * level and frequency (once/hour or once/day, depending on the + * state. + */ + rc = leapsec_daystolive(ntptime, systime); + if (rc == 0) { + msyslog(LOG_WARNING, + "%s ('%s'): will expire in less than one day", + logPrefix, leapfile_name); + } else if (is_daily_check && rc < 28) { + if (rc < 0) msyslog(LOG_ERR, - "check_leap_file: stat(%s): %m", - leapseconds_file); - rc = -1; - } else if ( (sp1->st_mtime != sp2->st_mtime) - || (sp1->st_ctime != sp2->st_ctime)) { - leapseconds_file_sb1 = leapseconds_file_sb2; - if (!leapsec_load_file(fp, leapseconds_file)) - rc = -1; - } - if (rc >= 0) { - rc = leapsec_daystolive(now.l_ui, NULL); - if (rc < 0) - rc = 0; - } - if (fp != NULL) - fclose(fp); + "%s ('%s'): expired (%d days)", + logPrefix, leapfile_name, -rc); + else + msyslog(LOG_WARNING, + "%s ('%s'): will expire in less than %d days", + logPrefix, leapfile_name, 1+rc); } - - return rc; }