]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 2597] fixed loose ends: changed/unified logging for leapfile related actions
authorJuergen Perlinger <perlinger@ntp.org>
Tue, 22 Apr 2014 19:40:54 +0000 (21:40 +0200)
committerJuergen Perlinger <perlinger@ntp.org>
Tue, 22 Apr 2014 19:40:54 +0000 (21:40 +0200)
bk: 5356c5c65m_L0hkr9ZkGieWhebULmA

ChangeLog
include/ntpd.h
ntpd/ntp_leapsec.c
ntpd/ntp_leapsec.h
ntpd/ntp_timer.c
ntpd/ntp_util.c

index 8fc2f9d9e92f88acc0ceb596e9273f5ec25df164..455580c1b5e5e796d11eda7c1272b1e6e3a8c0f0 100644 (file)
--- 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 <stenn@ntp.org>
 * [Bug 2536] ntpd sandboxing support (libseccomp2) cleanup.
 * [Bug 2570] cleanup: fix log format for successful leapfile load
index 52a0433aaf27ba0545dfc03fb87d0b710d055933..0a8a93186c5aac86507627de8bcfde984a4e1969 100644 (file)
@@ -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 *);
index 59fa034e5a0411098fcbc797048c2daef08af8f1..d85c75e439ffbbe3d61e804302e8e0b92de483e7 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <config.h>
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <ctype.h>
 
 #include "ntp_types.h"
 #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 = "<unknown>";
@@ -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! -*- */
index 5e9fc60d3f3288204f72ace86065254188e0d56f..472790db856d1fa04c9cad8684f738caa8be53ab 100644 (file)
@@ -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
index 74cde9e820d47f43305d37b65994fca33345d9e2..b51aa37d174a4c9e98b968ab2f66cd1706fd9a98 100644 (file)
@@ -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);
                }
        }
 }
index 3082f6218c7d7e2ecdf3468e409092fa9145328b..76a2239d9814a95c6a279e255d44a97fd5ed1053 100644 (file)
@@ -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;
 }