diff options
author | delphij <delphij@FreeBSD.org> | 2015-07-15 19:21:26 +0000 |
---|---|---|
committer | delphij <delphij@FreeBSD.org> | 2015-07-15 19:21:26 +0000 |
commit | 2a25cee78ab1d37e7d2bc40ae675646974d99f56 (patch) | |
tree | b0302ac4be59e104f4e1e54014561a1389397192 /contrib/ntp/ntpd/ntp_util.c | |
parent | a0741a75537b2e0514472ac3b28afc55a7846c30 (diff) | |
download | FreeBSD-src-2a25cee78ab1d37e7d2bc40ae675646974d99f56.zip FreeBSD-src-2a25cee78ab1d37e7d2bc40ae675646974d99f56.tar.gz |
MFC r280849,280915-280916,281015-281016,282097,282408,282415,283542,
284864,285169-285170,285435:
ntp 4.2.8p3.
Relnotes: yes
Approved by: re (?)
Diffstat (limited to 'contrib/ntp/ntpd/ntp_util.c')
-rw-r--r-- | contrib/ntp/ntpd/ntp_util.c | 878 |
1 files changed, 554 insertions, 324 deletions
diff --git a/contrib/ntp/ntpd/ntp_util.c b/contrib/ntp/ntpd/ntp_util.c index 91ff8a6..c4bc901 100644 --- a/contrib/ntp/ntpd/ntp_util.c +++ b/contrib/ntp/ntpd/ntp_util.c @@ -1,17 +1,19 @@ /* * ntp_util.c - stuff I didn't have any other place for */ - #ifdef HAVE_CONFIG_H # include <config.h> #endif #include "ntpd.h" -#include "ntp_io.h" #include "ntp_unixtime.h" #include "ntp_filegen.h" #include "ntp_if.h" #include "ntp_stdlib.h" +#include "ntp_assert.h" +#include "ntp_calendar.h" +#include "ntp_leapsec.h" +#include "lib_strbuf.h" #include <stdio.h> #include <ctype.h> @@ -19,6 +21,10 @@ #ifdef HAVE_SYS_IOCTL_H # include <sys/ioctl.h> #endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#include <sys/stat.h> #ifdef HAVE_IEEEFP_H # include <ieeefp.h> @@ -27,35 +33,35 @@ # include <math.h> #endif -#ifdef DOSYNCTODR -# if !defined(VMS) -# include <sys/resource.h> -# endif /* VMS */ -#endif - #if defined(VMS) # include <descrip.h> #endif /* VMS */ /* - * This contains odds and ends. Right now the only thing you'll find - * in here is the hourly stats printer and some code to support - * rereading the keys file, but I may eventually put other things in - * here such as code to do something with the leap bits. + * Defines used by the leapseconds stuff */ +#define MAX_TAI 100 /* max TAI offset (s) */ +#define L_DAY 86400UL /* seconds per day */ +#define L_YEAR (L_DAY * 365) /* days per year */ +#define L_LYEAR (L_YEAR + L_DAY) /* days per leap year */ +#define L_4YEAR (L_LYEAR + 3 * L_YEAR) /* days per leap cycle */ +#define L_CENT (L_4YEAR * 25) /* days per century */ + /* - * Name of the keys file + * This contains odds and ends, including the hourly stats, various + * configuration items, leapseconds stuff, etc. */ -static char *key_file_name; - /* - * The name of the drift_comp file and the temporary. + * File names */ -static char *stats_drift_file; -static char *stats_temp_file; -int stats_write_period = 3600; /* # of seconds between writes. */ -double stats_write_tolerance = 0; -static double prev_drift_comp = 99999.; +static char *key_file_name; /* keys file name */ +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 */ +double wander_threshold = 1e-7; /* initial frequency threshold */ /* * Statistics file stuff @@ -64,27 +70,20 @@ static double prev_drift_comp = 99999.; # ifndef SYS_WINNT # define NTP_VAR "/var/NTP/" /* NOTE the trailing '/' */ # else -# define NTP_VAR "c:\\var\\ntp\\" /* NOTE the trailing '\\' */ +# define NTP_VAR "c:\\var\\ntp\\" /* NOTE the trailing '\\' */ # endif /* SYS_WINNT */ #endif -#ifndef MAXPATHLEN -# define MAXPATHLEN 256 -#endif - -static char statsdir[MAXPATHLEN] = NTP_VAR; +char statsdir[MAXFILENAME] = NTP_VAR; static FILEGEN peerstats; static FILEGEN loopstats; static FILEGEN clockstats; static FILEGEN rawstats; static FILEGEN sysstats; -#ifdef DEBUG_TIMING -static FILEGEN timingstats; -#endif -#ifdef OPENSSL +static FILEGEN protostats; static FILEGEN cryptostats; -#endif /* OPENSSL */ +static FILEGEN timingstats; /* * This controls whether stats are written to the fileset. Provided @@ -93,37 +92,86 @@ static FILEGEN cryptostats; int stats_control; /* - * Initial frequency offset later passed to the loopfilter. + * Last frequency written to file. */ -double old_drift; +static double prev_drift_comp; /* last frequency update */ /* - * init_util - initialize the utilities + * Function prototypes */ -void -init_util(void) -{ - stats_drift_file = 0; - stats_temp_file = 0; - key_file_name = 0; - - filegen_register(&statsdir[0], "peerstats", &peerstats); +static void record_sys_stats(void); + void ntpd_time_stepped(void); +static void check_leap_expiration(int, uint32_t, const time_t*); - filegen_register(&statsdir[0], "loopstats", &loopstats); - - filegen_register(&statsdir[0], "clockstats", &clockstats); +/* + * Prototypes + */ +#ifdef DEBUG +void uninit_util(void); +#endif - filegen_register(&statsdir[0], "rawstats", &rawstats); +/* + * uninit_util - free memory allocated by init_util + */ +#ifdef DEBUG +void +uninit_util(void) +{ +#if defined(_MSC_VER) && defined (_DEBUG) + _CrtCheckMemory(); +#endif + if (stats_drift_file) { + free(stats_drift_file); + free(stats_temp_file); + stats_drift_file = NULL; + stats_temp_file = NULL; + } + if (key_file_name) { + free(key_file_name); + key_file_name = NULL; + } + filegen_unregister("peerstats"); + filegen_unregister("loopstats"); + filegen_unregister("clockstats"); + filegen_unregister("rawstats"); + filegen_unregister("sysstats"); + filegen_unregister("protostats"); +#ifdef AUTOKEY + filegen_unregister("cryptostats"); +#endif /* AUTOKEY */ +#ifdef DEBUG_TIMING + filegen_unregister("timingstats"); +#endif /* DEBUG_TIMING */ - filegen_register(&statsdir[0], "sysstats", &sysstats); +#if defined(_MSC_VER) && defined (_DEBUG) + _CrtCheckMemory(); +#endif +} +#endif /* DEBUG */ -#ifdef OPENSSL - filegen_register(&statsdir[0], "cryptostats", &cryptostats); -#endif /* OPENSSL */ -#ifdef DEBUG_TIMING - filegen_register(&statsdir[0], "timingstats", &timingstats); -#endif +/* + * init_util - initialize the util module of ntpd + */ +void +init_util(void) +{ + filegen_register(statsdir, "peerstats", &peerstats); + filegen_register(statsdir, "loopstats", &loopstats); + filegen_register(statsdir, "clockstats", &clockstats); + filegen_register(statsdir, "rawstats", &rawstats); + filegen_register(statsdir, "sysstats", &sysstats); + filegen_register(statsdir, "protostats", &protostats); + filegen_register(statsdir, "cryptostats", &cryptostats); + filegen_register(statsdir, "timingstats", &timingstats); + /* + * register with libntp ntp_set_tod() to call us back + * when time is stepped. + */ + step_callback = &ntpd_time_stepped; +#ifdef DEBUG + atexit(&uninit_util); +#endif /* DEBUG */ } @@ -133,17 +181,16 @@ init_util(void) void write_stats(void) { - FILE *fp; - + FILE *fp; #ifdef DOSYNCTODR struct timeval tv; #if !defined(VMS) - int prio_set; + int prio_set; #endif #ifdef HAVE_GETCLOCK - struct timespec ts; + struct timespec ts; #endif - int o_prio; + int o_prio; /* * Sometimes having a Sun can be a drag. @@ -163,12 +210,13 @@ write_stats(void) * thing to do. * * CAVEAT: settimeofday() steps the sun clock by about 800 us, - * so setting DOSYNCTODR seems a bad idea in the - * case of us resolution + * so setting DOSYNCTODR seems a bad idea in the + * case of us resolution */ #if !defined(VMS) - /* (prr) getpriority returns -1 on error, but -1 is also a valid + /* + * (prr) getpriority returns -1 on error, but -1 is also a valid * return value (!), so instead we have to zero errno before the * call and check it for non-zero afterwards. */ @@ -192,37 +240,45 @@ write_stats(void) prio_set = 1; /* overdrive */ #endif /* VMS */ #ifdef HAVE_GETCLOCK - (void) getclock(TIMEOFDAY, &ts); - tv.tv_sec = ts.tv_sec; - tv.tv_usec = ts.tv_nsec / 1000; + (void) getclock(TIMEOFDAY, &ts); + tv.tv_sec = ts.tv_sec; + tv.tv_usec = ts.tv_nsec / 1000; #else /* not HAVE_GETCLOCK */ GETTIMEOFDAY(&tv,(struct timezone *)NULL); #endif /* not HAVE_GETCLOCK */ - if (ntp_set_tod(&tv,(struct timezone *)NULL) != 0) { + if (ntp_set_tod(&tv,(struct timezone *)NULL) != 0) msyslog(LOG_ERR, "can't sync battery time: %m"); - } #if !defined(VMS) if (prio_set) setpriority(PRIO_PROCESS, 0, o_prio); /* downshift */ #endif /* VMS */ #endif /* DOSYNCTODR */ - - NLOG(NLOG_SYSSTATIST) - msyslog(LOG_INFO, - "offset %.6f sec freq %.3f ppm error %.6f poll %d", - last_offset, drift_comp * 1e6, sys_jitter, - sys_poll); - - record_sys_stats(); - if ((u_long)(fabs(prev_drift_comp - drift_comp) * 1e9) <= - (u_long)(fabs(stats_write_tolerance * drift_comp) * 1e9)) { - return; - } - prev_drift_comp = drift_comp; if (stats_drift_file != 0) { + + /* + * When the frequency file is written, initialize the + * prev_drift_comp and wander_resid. Thereafter, + * reduce the wander_resid by half each hour. When + * the difference between the prev_drift_comp and + * drift_comp is less than the wander_resid, update + * the frequncy file. This minimizes the file writes to + * nonvolaile storage. + */ +#ifdef DEBUG + if (debug) + printf("write_stats: frequency %.6lf thresh %.6lf, freq %.6lf\n", + (prev_drift_comp - drift_comp) * 1e6, wander_resid * + 1e6, drift_comp * 1e6); +#endif + if (fabs(prev_drift_comp - drift_comp) < wander_resid) { + wander_resid *= 0.5; + return; + } + prev_drift_comp = drift_comp; + wander_resid = wander_threshold; if ((fp = fopen(stats_temp_file, "w")) == NULL) { - msyslog(LOG_ERR, "can't open %s: %m", + msyslog(LOG_ERR, "frequency file %s: %m", stats_temp_file); return; } @@ -230,19 +286,26 @@ write_stats(void) (void)fclose(fp); /* atomic */ #ifdef SYS_WINNT - (void) _unlink(stats_drift_file); /* rename semantics differ under NT */ + if (_unlink(stats_drift_file)) /* rename semantics differ under NT */ + msyslog(LOG_WARNING, + "Unable to remove prior drift file %s, %m", + stats_drift_file); #endif /* SYS_WINNT */ #ifndef NO_RENAME - (void) rename(stats_temp_file, stats_drift_file); + if (rename(stats_temp_file, stats_drift_file)) + msyslog(LOG_WARNING, + "Unable to rename temp drift file %s to %s, %m", + stats_temp_file, stats_drift_file); #else /* we have no rename NFS of ftp in use */ - if ((fp = fopen(stats_drift_file, "w")) == NULL) { - msyslog(LOG_ERR, "can't open %s: %m", + if ((fp = fopen(stats_drift_file, "w")) == + NULL) { + msyslog(LOG_ERR, + "frequency file %s: %m", stats_drift_file); return; } - #endif #if defined(VMS) @@ -250,9 +313,10 @@ write_stats(void) { $DESCRIPTOR(oldvers,";-1"); struct dsc$descriptor driftdsc = { - strlen(stats_drift_file),0,0,stats_drift_file }; - - while(lib$delete_file(&oldvers,&driftdsc) & 1) ; + strlen(stats_drift_file), 0, 0, + stats_drift_file }; + while(lib$delete_file(&oldvers, + &driftdsc) & 1); } #endif } @@ -268,9 +332,17 @@ stats_config( const char *invalue /* only one type so far */ ) { - FILE *fp; + FILE *fp; const char *value; - int len; + int len; + double old_drift; + l_fp now; + time_t ttnow; +#ifndef VMS + const char temp_ext[] = ".TEMP"; +#else + const char temp_ext[] = "-TEMP"; +#endif /* * Expand environment strings under Windows NT, since the @@ -280,170 +352,192 @@ stats_config( char newvalue[MAX_PATH], parameter[MAX_PATH]; if (!ExpandEnvironmentStrings(invalue, newvalue, MAX_PATH)) { - switch(item) { - case STATS_FREQ_FILE: - strcpy(parameter,"STATS_FREQ_FILE"); + switch (item) { + case STATS_FREQ_FILE: + strlcpy(parameter, "STATS_FREQ_FILE", + sizeof(parameter)); break; - case STATS_STATSDIR: - strcpy(parameter,"STATS_STATSDIR"); + + case STATS_LEAP_FILE: + strlcpy(parameter, "STATS_LEAP_FILE", + sizeof(parameter)); + break; + + case STATS_STATSDIR: + strlcpy(parameter, "STATS_STATSDIR", + sizeof(parameter)); break; - case STATS_PID_FILE: - strcpy(parameter,"STATS_PID_FILE"); + + case STATS_PID_FILE: + strlcpy(parameter, "STATS_PID_FILE", + sizeof(parameter)); break; - default: - strcpy(parameter,"UNKNOWN"); + + default: + strlcpy(parameter, "UNKNOWN", + sizeof(parameter)); break; } value = invalue; - msyslog(LOG_ERR, - "ExpandEnvironmentStrings(%s) failed: %m\n", parameter); + "ExpandEnvironmentStrings(%s) failed: %m\n", + parameter); } else { value = newvalue; } -#else +#else value = invalue; #endif /* SYS_WINNT */ - switch(item) { - case STATS_FREQ_FILE: - if (stats_drift_file != 0) { - (void) free(stats_drift_file); - (void) free(stats_temp_file); - stats_drift_file = 0; - stats_temp_file = 0; - } + switch (item) { - if (value == 0 || (len = strlen(value)) == 0) - break; + /* + * Open and read frequency file. + */ + case STATS_FREQ_FILE: + if (!value || (len = strlen(value)) == 0) + break; - stats_drift_file = (char*)emalloc((u_int)(len + 1)); -#if !defined(VMS) - stats_temp_file = (char*)emalloc((u_int)(len + - sizeof(".TEMP"))); -#else - stats_temp_file = (char*)emalloc((u_int)(len + - sizeof("-TEMP"))); -#endif /* VMS */ - memmove(stats_drift_file, value, (unsigned)(len+1)); - memmove(stats_temp_file, value, (unsigned)len); -#if !defined(VMS) - memmove(stats_temp_file + len, ".TEMP", - sizeof(".TEMP")); -#else - memmove(stats_temp_file + len, "-TEMP", - sizeof("-TEMP")); -#endif /* VMS */ + stats_drift_file = erealloc(stats_drift_file, len + 1); + stats_temp_file = erealloc(stats_temp_file, + len + sizeof(".TEMP")); + memcpy(stats_drift_file, value, (size_t)(len+1)); + memcpy(stats_temp_file, value, (size_t)len); + memcpy(stats_temp_file + len, temp_ext, sizeof(temp_ext)); /* * Open drift file and read frequency. If the file is * missing or contains errors, tell the loop to reset. */ - if ((fp = fopen(stats_drift_file, "r")) == NULL) { - old_drift = 1e9; + if ((fp = fopen(stats_drift_file, "r")) == NULL) break; - } + if (fscanf(fp, "%lf", &old_drift) != 1) { - msyslog(LOG_ERR, "Frequency format error in %s", - stats_drift_file); - old_drift = 1e9; + msyslog(LOG_ERR, + "format error frequency file %s", + stats_drift_file); fclose(fp); break; + } fclose(fp); - prev_drift_comp = old_drift / 1e6; - msyslog(LOG_INFO, - "frequency initialized %.3f PPM from %s", - old_drift, stats_drift_file); + loop_config(LOOP_FREQ, old_drift); + prev_drift_comp = drift_comp; break; - - case STATS_STATSDIR: - if (strlen(value) >= sizeof(statsdir)) { + + /* + * Specify statistics directory. + */ + case STATS_STATSDIR: + + /* - 1 since value may be missing the DIR_SEP. */ + if (strlen(value) >= sizeof(statsdir) - 1) { msyslog(LOG_ERR, - "value for statsdir too long (>%d, sigh)", - (int)sizeof(statsdir)-1); + "statsdir too long (>%d, sigh)", + (int)sizeof(statsdir) - 2); } else { - l_fp now; - - get_systime(&now); - strcpy(statsdir,value); - if(peerstats.prefix == &statsdir[0] && - peerstats.fp != NULL) { - fclose(peerstats.fp); - peerstats.fp = NULL; - filegen_setup(&peerstats, now.l_ui); - } - if(loopstats.prefix == &statsdir[0] && - loopstats.fp != NULL) { - fclose(loopstats.fp); - loopstats.fp = NULL; - filegen_setup(&loopstats, now.l_ui); - } - if(clockstats.prefix == &statsdir[0] && - clockstats.fp != NULL) { - fclose(clockstats.fp); - clockstats.fp = NULL; - filegen_setup(&clockstats, now.l_ui); - } - if(rawstats.prefix == &statsdir[0] && - rawstats.fp != NULL) { - fclose(rawstats.fp); - rawstats.fp = NULL; - filegen_setup(&rawstats, now.l_ui); - } - if(sysstats.prefix == &statsdir[0] && - sysstats.fp != NULL) { - fclose(sysstats.fp); - sysstats.fp = NULL; - filegen_setup(&sysstats, now.l_ui); - } -#ifdef OPENSSL - if(cryptostats.prefix == &statsdir[0] && - cryptostats.fp != NULL) { - fclose(cryptostats.fp); - cryptostats.fp = NULL; - filegen_setup(&cryptostats, now.l_ui); - } -#endif /* OPENSSL */ + int add_dir_sep; + int value_l; + + /* Add a DIR_SEP unless we already have one. */ + value_l = strlen(value); + if (0 == value_l) + add_dir_sep = FALSE; + else + add_dir_sep = (DIR_SEP != + value[value_l - 1]); + + if (add_dir_sep) + snprintf(statsdir, sizeof(statsdir), + "%s%c", value, DIR_SEP); + else + snprintf(statsdir, sizeof(statsdir), + "%s", value); + filegen_statsdir(); } break; - case STATS_PID_FILE: + /* + * Open pid file. + */ + case STATS_PID_FILE: if ((fp = fopen(value, "w")) == NULL) { - msyslog(LOG_ERR, "Can't open %s: %m", value); + msyslog(LOG_ERR, "pid file %s: %m", + value); + break; + } + fprintf(fp, "%d", (int)getpid()); + fclose(fp); + break; + + /* + * Read leapseconds file. + * + * Note: Currently a leap file without SHA1 signature is + * accepted, but if there is a signature line, the signature + * must be valid or the file is rejected. + */ + case STATS_LEAP_FILE: + if (!value || (len = strlen(value)) == 0) break; + + leapfile_name = erealloc(leapfile_name, len + 1); + memcpy(leapfile_name, value, len + 1); + + if (leapsec_load_file( + leapfile_name, &leapfile_stat, TRUE, TRUE)) + { + leap_signature_t lsig; + + get_systime(&now); + time(&ttnow); + leapsec_getsig(&lsig); + mprintf_event(EVNT_TAI, NULL, + "%d leap %s %s %s", + lsig.taiof, + fstostr(lsig.ttime), + leapsec_expired(now.l_ui, NULL) + ? "expired" + : "expires", + fstostr(lsig.etime)); + + have_leapfile = TRUE; + + /* force an immediate daily expiration check of + * the leap seconds table + */ + check_leap_expiration(TRUE, now.l_ui, &ttnow); } - fprintf(fp, "%d", (int) getpid()); - fclose(fp);; break; - default: + default: /* oh well */ break; } } + /* * record_peer_stats - write peer statistics to file * * file format: - * day (mjd) + * day (MJD) * time (s past UTC midnight) - * peer (ip address) - * peer status word (hex) - * peer offset (s) - * peer delay (s) - * peer error bound (s) - * peer error (s) + * IP address + * status word (hex) + * offset + * delay + * dispersion + * jitter */ void record_peer_stats( - struct sockaddr_storage *addr, + sockaddr_u *addr, int status, - double offset, - double delay, - double dispersion, - double skew + double offset, /* offset */ + double delay, /* delay */ + double dispersion, /* dispersion */ + double jitter /* jitter */ ) { l_fp now; @@ -458,29 +552,32 @@ record_peer_stats( now.l_ui %= 86400; if (peerstats.fp != NULL) { fprintf(peerstats.fp, - "%lu %s %s %x %.9f %.9f %.9f %.9f\n", - day, ulfptoa(&now, 3), stoa(addr), status, offset, - delay, dispersion, skew); + "%lu %s %s %x %.9f %.9f %.9f %.9f\n", day, + ulfptoa(&now, 3), stoa(addr), status, offset, + delay, dispersion, jitter); fflush(peerstats.fp); } } + /* * record_loop_stats - write loop filter statistics to file * * file format: - * day (mjd) + * day (MJD) * time (s past midnight) - * offset (s) - * frequency (approx ppm) - * time constant (log base 2) + * offset + * frequency (PPM) + * jitter + * wnder (PPM) + * time constant (log2) */ void record_loop_stats( - double offset, - double freq, - double jitter, - double stability, + double offset, /* offset */ + double freq, /* frequency (PPM) */ + double jitter, /* jitter */ + double wander, /* wander (PPM) */ int spoll ) { @@ -497,24 +594,25 @@ record_loop_stats( if (loopstats.fp != NULL) { fprintf(loopstats.fp, "%lu %s %.9f %.3f %.9f %.6f %d\n", day, ulfptoa(&now, 3), offset, freq * 1e6, jitter, - stability * 1e6, spoll); + wander * 1e6, spoll); fflush(loopstats.fp); } } + /* * record_clock_stats - write clock statistics to file * * file format: - * day (mjd) + * day (MJD) * time (s past midnight) - * peer (ip address) + * IP address * text message */ void record_clock_stats( - struct sockaddr_storage *addr, - const char *text + sockaddr_u *addr, + const char *text /* timecode string */ ) { l_fp now; @@ -528,30 +626,64 @@ record_clock_stats( day = now.l_ui / 86400 + MJD_1900; now.l_ui %= 86400; if (clockstats.fp != NULL) { - fprintf(clockstats.fp, "%lu %s %s %s\n", - day, ulfptoa(&now, 3), stoa(addr), text); + fprintf(clockstats.fp, "%lu %s %s %s\n", day, + ulfptoa(&now, 3), stoa(addr), text); fflush(clockstats.fp); } } + +/* + * mprintf_clock_stats - write clock statistics to file with + * msnprintf-style formatting. + */ +int +mprintf_clock_stats( + sockaddr_u *addr, + const char *fmt, + ... + ) +{ + va_list ap; + int rc; + char msg[512]; + + va_start(ap, fmt); + rc = mvsnprintf(msg, sizeof(msg), fmt, ap); + va_end(ap); + if (stats_control) + record_clock_stats(addr, msg); + + return rc; +} + /* * record_raw_stats - write raw timestamps to file * - * * file format + * day (MJD) * time (s past midnight) * peer ip address - * local ip address + * IP address * t1 t2 t3 t4 timestamps */ void record_raw_stats( - struct sockaddr_storage *srcadr, - struct sockaddr_storage *dstadr, - l_fp *t1, - l_fp *t2, - l_fp *t3, - l_fp *t4 + sockaddr_u *srcadr, + sockaddr_u *dstadr, + l_fp *t1, /* originate timestamp */ + l_fp *t2, /* receive timestamp */ + l_fp *t3, /* transmit timestamp */ + l_fp *t4, /* destination timestamp */ + int leap, + int version, + int mode, + int stratum, + int ppoll, + int precision, + double root_delay, /* seconds */ + double root_dispersion,/* seconds */ + u_int32 refid ) { l_fp now; @@ -565,10 +697,13 @@ record_raw_stats( day = now.l_ui / 86400 + MJD_1900; now.l_ui %= 86400; if (rawstats.fp != NULL) { - fprintf(rawstats.fp, "%lu %s %s %s %s %s %s %s\n", - day, ulfptoa(&now, 3), stoa(srcadr), dstadr ? stoa(dstadr) : "-", - ulfptoa(t1, 9), ulfptoa(t2, 9), ulfptoa(t3, 9), - ulfptoa(t4, 9)); + fprintf(rawstats.fp, "%lu %s %s %s %s %s %s %s %d %d %d %d %d %d %.6f %.6f %s\n", + day, ulfptoa(&now, 3), + stoa(srcadr), dstadr ? stoa(dstadr) : "-", + ulfptoa(t1, 9), ulfptoa(t2, 9), + ulfptoa(t3, 9), ulfptoa(t4, 9), + leap, version, mode, stratum, ppoll, precision, + root_delay, root_dispersion, refid_str(refid, stratum)); fflush(rawstats.fp); } } @@ -578,17 +713,19 @@ record_raw_stats( * record_sys_stats - write system statistics to file * * file format + * day (MJD) * time (s past midnight) - * time since startup (hr) + * time since reset * packets recieved - * packets processed + * packets for this host * current version - * previous version - * bad version + * old version * access denied * bad length or format * bad authentication + * declined * rate exceeded + * KoD sent */ void record_sys_stats(void) @@ -604,33 +741,64 @@ record_sys_stats(void) day = now.l_ui / 86400 + MJD_1900; now.l_ui %= 86400; if (sysstats.fp != NULL) { - fprintf(sysstats.fp, - "%lu %s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n", - day, ulfptoa(&now, 3), sys_stattime / 3600, - sys_received, sys_processed, sys_newversionpkt, - sys_oldversionpkt, sys_unknownversion, - sys_restricted, sys_badlength, sys_badauth, - sys_limitrejected); + fprintf(sysstats.fp, + "%lu %s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n", + day, ulfptoa(&now, 3), current_time - sys_stattime, + sys_received, sys_processed, sys_newversion, + sys_oldversion, sys_restricted, sys_badlength, + sys_badauth, sys_declined, sys_limitrejected, + sys_kodsent); fflush(sysstats.fp); proto_clr_stats(); } } -#ifdef OPENSSL +/* + * record_proto_stats - write system statistics to file + * + * file format + * day (MJD) + * time (s past midnight) + * text message + */ +void +record_proto_stats( + char *str /* text string */ + ) +{ + l_fp now; + u_long day; + + if (!stats_control) + return; + + get_systime(&now); + filegen_setup(&protostats, now.l_ui); + day = now.l_ui / 86400 + MJD_1900; + now.l_ui %= 86400; + if (protostats.fp != NULL) { + fprintf(protostats.fp, "%lu %s %s\n", day, + ulfptoa(&now, 3), str); + fflush(protostats.fp); + } +} + + +#ifdef AUTOKEY /* * record_crypto_stats - write crypto statistics to file * * file format: * day (mjd) * time (s past midnight) - * peer (ip address) + * peer ip address * text message */ void record_crypto_stats( - struct sockaddr_storage *addr, - const char *text + sockaddr_u *addr, + const char *text /* text message */ ) { l_fp now; @@ -645,7 +813,7 @@ record_crypto_stats( now.l_ui %= 86400; if (cryptostats.fp != NULL) { if (addr == NULL) - fprintf(cryptostats.fp, "%lu %s %s\n", + fprintf(cryptostats.fp, "%lu %s 0.0.0.0 %s\n", day, ulfptoa(&now, 3), text); else fprintf(cryptostats.fp, "%lu %s %s %s\n", @@ -653,11 +821,12 @@ record_crypto_stats( fflush(cryptostats.fp); } } -#endif /* OPENSSL */ +#endif /* AUTOKEY */ + #ifdef DEBUG_TIMING /* - * record_crypto_stats - write crypto statistics to file + * record_timing_stats - write timing statistics to file * * file format: * day (mjd) @@ -666,7 +835,7 @@ record_crypto_stats( */ void record_timing_stats( - const char *text + const char *text /* text message */ ) { static unsigned int flshcnt; @@ -681,13 +850,81 @@ record_timing_stats( day = now.l_ui / 86400 + MJD_1900; now.l_ui %= 86400; if (timingstats.fp != NULL) { - fprintf(timingstats.fp, "%lu %s %s\n", - day, lfptoa(&now, 3), text); + fprintf(timingstats.fp, "%lu %s %s\n", day, lfptoa(&now, + 3), text); if (++flshcnt % 100 == 0) fflush(timingstats.fp); } } #endif + + +/* + * check_leap_file - See if the leapseconds file has been updated. + * + * Returns: n/a + * + * Note: This loads a new leapfile on the fly. Currently a leap file + * without SHA1 signature is accepted, but if there is a signature line, + * the signature must be valid or the file is rejected. + */ +void +check_leap_file( + int is_daily_check, + uint32_t ntptime , + const time_t *systime + ) +{ + /* 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, is_daily_check)) + have_leapfile = TRUE; + else if (!have_leapfile) + return; + + check_leap_expiration(is_daily_check, ntptime, systime); +} + +/* + * check expiration of a loaded leap table + */ +static void +check_leap_expiration( + int is_daily_check, + uint32_t ntptime , + const time_t *systime + ) +{ + static const char * const logPrefix = "leapsecond file"; + int rc; + + /* 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, + "%s ('%s'): expired less than %d day%s ago", + logPrefix, leapfile_name, -rc, (rc == -1 ? "" : "s")); + else + msyslog(LOG_WARNING, + "%s ('%s'): will expire in less than %d days", + logPrefix, leapfile_name, 1+rc); + } +} + + /* * getauthkeys - read the authentication keys from the specified file */ @@ -699,31 +936,24 @@ getauthkeys( int len; len = strlen(keyfile); - if (len == 0) + if (!len) return; - if (key_file_name != 0) { - if (len > (int)strlen(key_file_name)) { - (void) free(key_file_name); - key_file_name = 0; - } - } - - if (key_file_name == 0) { #ifndef SYS_WINNT - key_file_name = (char*)emalloc((u_int) (len + 1)); + key_file_name = erealloc(key_file_name, len + 1); + memcpy(key_file_name, keyfile, len + 1); #else - key_file_name = (char*)emalloc((u_int) (MAXPATHLEN)); -#endif - } -#ifndef SYS_WINNT - memmove(key_file_name, keyfile, (unsigned)(len+1)); -#else - if (!ExpandEnvironmentStrings(keyfile, key_file_name, MAXPATHLEN)) - { + key_file_name = erealloc(key_file_name, _MAX_PATH); + if (len + 1 > _MAX_PATH) + return; + if (!ExpandEnvironmentStrings(keyfile, key_file_name, + _MAX_PATH)) { msyslog(LOG_ERR, - "ExpandEnvironmentStrings(KEY_FILE) failed: %m\n"); + "ExpandEnvironmentStrings(KEY_FILE) failed: %m"); + strlcpy(key_file_name, keyfile, _MAX_PATH); } + key_file_name = erealloc(key_file_name, + 1 + strlen(key_file_name)); #endif /* SYS_WINNT */ authreadkeys(key_file_name); @@ -736,66 +966,66 @@ getauthkeys( void rereadkeys(void) { - if (key_file_name != 0) - authreadkeys(key_file_name); + if (NULL != key_file_name) + authreadkeys(key_file_name); } + +#if notyet /* - * sock_hash - hash an sockaddr_storage structure + * ntp_exit - document explicitly that ntpd has exited */ -int -sock_hash( - struct sockaddr_storage *addr - ) +void +ntp_exit(int retval) { - int hashVal; - int i; - int len; - char *ch; - - hashVal = 0; - len = 0; - /* - * We can't just hash the whole thing because there are hidden - * fields in sockaddr_in6 that might be filled in by recvfrom(), - * so just use the family, port and address. - */ - ch = (char *)&addr->ss_family; - hashVal = 37 * hashVal + (int)*ch; - if (sizeof(addr->ss_family) > 1) { - ch++; - hashVal = 37 * hashVal + (int)*ch; - } - switch(addr->ss_family) { - case AF_INET: - ch = (char *)&((struct sockaddr_in *)addr)->sin_addr; - len = sizeof(struct in_addr); - break; - case AF_INET6: - ch = (char *)&((struct sockaddr_in6 *)addr)->sin6_addr; - len = sizeof(struct in6_addr); - break; - } - - for (i = 0; i < len ; i++) - hashVal = 37 * hashVal + (int)*(ch + i); - - hashVal = hashVal % 128; /* % MON_HASH_SIZE hardcoded */ - - if (hashVal < 0) - hashVal += 128; + msyslog(LOG_ERR, "EXITING with return code %d", retval); + exit(retval); +} +#endif - return hashVal; +/* + * fstostr - prettyprint NTP seconds + */ +char * fstostr( + time_t ntp_stamp + ) +{ + char * buf; + struct calendar tm; + + LIB_GETBUF(buf); + if (ntpcal_ntp_to_date(&tm, (u_int32)ntp_stamp, NULL) < 0) + snprintf(buf, LIB_BUFLENGTH, "ntpcal_ntp_to_date: %ld: range error", + (long)ntp_stamp); + else + snprintf(buf, LIB_BUFLENGTH, "%04d%02d%02d%02d%02d", + tm.year, tm.month, tm.monthday, + tm.hour, tm.minute); + return buf; } -#if notyet + /* - * ntp_exit - document explicitly that ntpd has exited + * ntpd_time_stepped is called back by step_systime(), allowing ntpd + * to do any one-time processing necessitated by the step. */ void -ntp_exit(int retval) +ntpd_time_stepped(void) { - msyslog(LOG_ERR, "EXITING with return code %d", retval); - exit(retval); -} + u_int saved_mon_enabled; + + /* + * flush the monitor MRU list which contains l_fp timestamps + * which should not be compared across the step. + */ + if (MON_OFF != mon_enabled) { + saved_mon_enabled = mon_enabled; + mon_stop(MON_OFF); + mon_start(saved_mon_enabled); + } + + /* inform interpolating Windows code to allow time to go back */ +#ifdef SYS_WINNT + win_time_stepped(); #endif +} |