diff options
Diffstat (limited to 'ntpd/ntp_util.c')
-rw-r--r-- | ntpd/ntp_util.c | 816 |
1 files changed, 574 insertions, 242 deletions
diff --git a/ntpd/ntp_util.c b/ntpd/ntp_util.c index 91ff8a6..8bc95d6 100644 --- a/ntpd/ntp_util.c +++ b/ntpd/ntp_util.c @@ -1,7 +1,6 @@ /* * ntp_util.c - stuff I didn't have any other place for */ - #ifdef HAVE_CONFIG_H # include <config.h> #endif @@ -12,6 +11,7 @@ #include "ntp_filegen.h" #include "ntp_if.h" #include "ntp_stdlib.h" +#include "ntp_assert.h" #include <stdio.h> #include <ctype.h> @@ -38,24 +38,29 @@ #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 */ +char *leapseconds_file_name; /* leapseconds file name */ +char *stats_drift_file; /* frequency file name */ +static char *stats_temp_file; /* temp frequency file name */ +double wander_resid; /* wander threshold */ +double wander_threshold = 1e-7; /* initial wander threshold */ +int drift_file_sw; /* clock update switch */ /* * Statistics file stuff @@ -64,7 +69,7 @@ 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 @@ -72,13 +77,6 @@ static double prev_drift_comp = 99999.; # define MAXPATHLEN 256 #endif -static char statsdir[MAXPATHLEN] = NTP_VAR; - -static FILEGEN peerstats; -static FILEGEN loopstats; -static FILEGEN clockstats; -static FILEGEN rawstats; -static FILEGEN sysstats; #ifdef DEBUG_TIMING static FILEGEN timingstats; #endif @@ -86,6 +84,14 @@ static FILEGEN timingstats; static FILEGEN cryptostats; #endif /* OPENSSL */ +static char statsdir[MAXPATHLEN] = NTP_VAR; +static FILEGEN peerstats; +static FILEGEN loopstats; +static FILEGEN clockstats; +static FILEGEN rawstats; +static FILEGEN sysstats; +static FILEGEN protostats; + /* * This controls whether stats are written to the fileset. Provided * so that ntpdc can turn off stats when the file system fills up. @@ -95,35 +101,87 @@ int stats_control; /* * Initial frequency offset later passed to the loopfilter. */ -double old_drift; +double old_drift = 1e9; /* current frequency */ +static double prev_drift_comp; /* last frequency update */ /* - * init_util - initialize the utilities + * Static prototypes */ -void -init_util(void) -{ - stats_drift_file = 0; - stats_temp_file = 0; - key_file_name = 0; +static int leap_file(FILE *); +static void record_sys_stats(void); - filegen_register(&statsdir[0], "peerstats", &peerstats); +/* + * Prototypes + */ +#ifdef DEBUG +void uninit_util(void); +#endif - filegen_register(&statsdir[0], "loopstats", &loopstats); - filegen_register(&statsdir[0], "clockstats", &clockstats); +/* + * 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 OPENSSL + filegen_unregister("cryptostats"); +#endif /* OPENSSL */ +#ifdef DEBUG_TIMING + filegen_unregister("timingstats"); +#endif /* DEBUG_TIMING */ - filegen_register(&statsdir[0], "rawstats", &rawstats); +#if defined(_MSC_VER) && defined (_DEBUG) + _CrtCheckMemory(); +#endif +} +#endif /* DEBUG */ - filegen_register(&statsdir[0], "sysstats", &sysstats); +/* + * init_util - initialize the utilities (ntpd included) + */ +void +init_util(void) +{ + stats_drift_file = NULL; + stats_temp_file = NULL; + key_file_name = NULL; + 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); #ifdef OPENSSL - filegen_register(&statsdir[0], "cryptostats", &cryptostats); + filegen_register(statsdir, "cryptostats", &cryptostats); #endif /* OPENSSL */ - #ifdef DEBUG_TIMING - filegen_register(&statsdir[0], "timingstats", &timingstats); -#endif + filegen_register(statsdir, "timingstats", &timingstats); +#endif /* DEBUG_TIMING */ +#ifdef DEBUG + atexit(uninit_util); +#endif /* DEBUG */ } @@ -133,17 +191,17 @@ init_util(void) void write_stats(void) { - FILE *fp; - + FILE *fp; + double ftemp; #ifdef DOSYNCTODR struct timeval tv; #if !defined(VMS) - int prio_set; + int prio_set; #endif #ifdef HAVE_GETCLOCK struct timespec ts; #endif - int o_prio; + int o_prio; /* * Sometimes having a Sun can be a drag. @@ -168,7 +226,8 @@ write_stats(void) */ #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. */ @@ -198,63 +257,87 @@ write_stats(void) #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; - } + ftemp = fabs(prev_drift_comp - drift_comp); prev_drift_comp = drift_comp; - if (stats_drift_file != 0) { - if ((fp = fopen(stats_temp_file, "w")) == NULL) { - msyslog(LOG_ERR, "can't open %s: %m", - stats_temp_file); - return; - } - fprintf(fp, "%.3f\n", drift_comp * 1e6); - (void)fclose(fp); - /* atomic */ + if (ftemp > clock_phi) + return; + + if (stats_drift_file != 0 && drift_file_sw) { + + /* + * When the frequency file is written, initialize the + * wander threshold to a configured initial value. + * Thereafter reduce it by a factor of 0.5. When it + * drops below the frequency wander, write the frequency + * file. This adapts to the prevailing wander yet + * minimizes the file writes. + */ + drift_file_sw = FALSE; + wander_resid *= 0.5; +#ifdef DEBUG + if (debug) + printf("write_stats: wander %.6lf thresh %.6lf, freq %.6lf\n", + clock_stability * 1e6, wander_resid * 1e6, + drift_comp * 1e6); +#endif + if (sys_leap != LEAP_NOTINSYNC && clock_stability > + wander_resid) { + wander_resid = wander_threshold; + if ((fp = fopen(stats_temp_file, "w")) == NULL) + { + msyslog(LOG_ERR, + "frequency file %s: %m", + stats_temp_file); + return; + } + fprintf(fp, "%.3f\n", drift_comp * 1e6); + (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", - stats_drift_file); - return; - } - + /* we have no rename NFS of ftp in use */ + if ((fp = fopen(stats_drift_file, "w")) == + NULL) { + msyslog(LOG_ERR, + "frequency file %s: %m", + stats_drift_file); + return; + } #endif #if defined(VMS) - /* PURGE */ - { - $DESCRIPTOR(oldvers,";-1"); - struct dsc$descriptor driftdsc = { - strlen(stats_drift_file),0,0,stats_drift_file }; - - while(lib$delete_file(&oldvers,&driftdsc) & 1) ; - } + /* PURGE */ + { + $DESCRIPTOR(oldvers,";-1"); + struct dsc$descriptor driftdsc = { + strlen(stats_drift_file), 0, 0, + stats_drift_file }; + while(lib$delete_file(&oldvers, + &driftdsc) & 1); + } #endif + } else { + /* XXX: Log a message at INFO level */ + } } } @@ -268,9 +351,16 @@ stats_config( const char *invalue /* only one type so far */ ) { - FILE *fp; + FILE *fp; const char *value; - int len; + int len; + char tbuf[80]; + char str1[20], str2[20]; +#ifndef VMS + const char temp_ext[] = ".TEMP"; +#else + const char temp_ext[] = "-TEMP"; +#endif /* * Expand environment strings under Windows NT, since the @@ -284,20 +374,27 @@ stats_config( case STATS_FREQ_FILE: strcpy(parameter,"STATS_FREQ_FILE"); break; + + case STATS_LEAP_FILE: + strcpy(parameter,"STATS_LEAP_FILE"); + break; + case STATS_STATSDIR: strcpy(parameter,"STATS_STATSDIR"); break; + case STATS_PID_FILE: strcpy(parameter,"STATS_PID_FILE"); break; + default: strcpy(parameter,"UNKNOWN"); break; } value = invalue; - msyslog(LOG_ERR, - "ExpandEnvironmentStrings(%s) failed: %m\n", parameter); + "ExpandEnvironmentStrings(%s) failed: %m\n", + parameter); } else { value = newvalue; } @@ -306,67 +403,77 @@ stats_config( #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; - } - 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, (unsigned)(len+1)); + memcpy(stats_temp_file, value, (unsigned)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); + old_drift /= 1e6; + prev_drift_comp = old_drift; break; - - case STATS_STATSDIR: + + /* + * Specify statistics directory. + */ + case STATS_STATSDIR: + + /* + * HMS: the following test is insufficient: + * - value may be missing the DIR_SEP + * - we still need the filename after it + */ if (strlen(value) >= sizeof(statsdir)) { msyslog(LOG_ERR, - "value for statsdir too long (>%d, sigh)", - (int)sizeof(statsdir)-1); + "statsdir too long (>%d, sigh)", + (int)sizeof(statsdir) - 1); } else { l_fp now; + int add_dir_sep; + int value_l = strlen(value); + + /* Add a DIR_SEP unless we already have one. */ + if (value_l == 0) + add_dir_sep = 0; + 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); get_systime(&now); - strcpy(statsdir,value); if(peerstats.prefix == &statsdir[0] && peerstats.fp != NULL) { fclose(peerstats.fp); @@ -397,6 +504,12 @@ stats_config( sysstats.fp = NULL; filegen_setup(&sysstats, now.l_ui); } + if(protostats.prefix == &statsdir[0] && + protostats.fp != NULL) { + fclose(protostats.fp); + protostats.fp = NULL; + filegen_setup(&protostats, now.l_ui); + } #ifdef OPENSSL if(cryptostats.prefix == &statsdir[0] && cryptostats.fp != NULL) { @@ -405,45 +518,83 @@ stats_config( filegen_setup(&cryptostats, now.l_ui); } #endif /* OPENSSL */ +#ifdef DEBUG_TIMING + if(timingstats.prefix == &statsdir[0] && + timingstats.fp != NULL) { + fclose(timingstats.fp); + timingstats.fp = NULL; + filegen_setup(&timingstats, now.l_ui); + } +#endif /* DEBUG_TIMING */ } 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()); + fprintf(fp, "%d", (int)getpid()); fclose(fp);; break; - default: + /* + * Read leapseconds file. + */ + case STATS_LEAP_FILE: + if ((fp = fopen(value, "r")) == NULL) { + msyslog(LOG_ERR, "leapseconds file %s: %m", + value); + break; + } + + if (leap_file(fp) < 0) { + msyslog(LOG_ERR, + "format error leapseconds file %s", + value); + } else { + strcpy(str1, fstostr(leap_sec)); + strcpy(str2, fstostr(leap_expire)); + snprintf(tbuf, sizeof(tbuf), + "%d leap %s expire %s", leap_tai, str1, + str2); + report_event(EVNT_TAI, NULL, tbuf); + } + fclose(fp); + break; + + 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 +609,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 +651,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 +683,31 @@ 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); } } + /* * 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 */ ) { l_fp now; @@ -565,10 +721,10 @@ 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\n", day, + ulfptoa(&now, 3), stoa(srcadr), dstadr ? + stoa(dstadr) : "-", ulfptoa(t1, 9), ulfptoa(t2, 9), + ulfptoa(t3, 9), ulfptoa(t4, 9)); fflush(rawstats.fp); } } @@ -578,17 +734,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,19 +762,50 @@ 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(); } } +/* + * 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 OPENSSL /* * record_crypto_stats - write crypto statistics to file @@ -624,13 +813,13 @@ record_sys_stats(void) * 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 +834,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", @@ -655,9 +844,10 @@ record_crypto_stats( } #endif /* OPENSSL */ + #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 +856,7 @@ record_crypto_stats( */ void record_timing_stats( - const char *text + const char *text /* text message */ ) { static unsigned int flshcnt; @@ -681,13 +871,140 @@ 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 + + +/* + * leap_file - read leapseconds file + * + * Read the ERTS leapsecond file in NIST text format and extract the + * NTP seconds of the latest leap and TAI offset after the leap. + */ +static int +leap_file( + FILE *fp /* file handle */ + ) +{ + char buf[NTP_MAXSTRLEN]; /* file line buffer */ + u_long leap; /* NTP time at leap */ + u_long expire; /* NTP time when file expires */ + int offset; /* TAI offset at leap (s) */ + int i; + + /* + * Read and parse the leapseconds file. Empty lines and comments + * are ignored. A line beginning with #@ contains the file + * expiration time in NTP seconds. Other lines begin with two + * integers followed by junk or comments. The first integer is + * the NTP seconds at the leap, the second is the TAI offset + * after the leap. + */ + offset = 0; + leap = 0; + expire = 0; + i = 10; + while (fgets(buf, NTP_MAXSTRLEN - 1, fp) != NULL) { + if (strlen(buf) < 1) + continue; + + if (buf[0] == '#') { + if (strlen(buf) < 3) + continue; + + /* + * Note the '@' flag was used only in the 2006 + * table; previious to that the flag was '$'. + */ + if (buf[1] == '@' || buf[1] == '$') { + if (sscanf(&buf[2], "%lu", &expire) != + 1) + return (-1); + + continue; + } + } + if (sscanf(buf, "%lu %d", &leap, &offset) == 2) { + + /* + * Valid offsets must increase by one for each + * leap. + */ + if (i++ != offset) + return (-1); + } + } + + /* + * There must be at least one leap. + */ + if (i == 10) + return (-1); + + leap_tai = offset; + leap_sec = leap; + leap_expire = expire; + return (0); +} + + +/* + * leap_month - returns seconds until the end of the month. + */ +u_long +leap_month( + u_long sec /* current NTP second */ + ) +{ + u_long ltemp; + u_long *ptr; + u_long year[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, + 31}; + u_long lyear[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, + 31}; + + /* + * Find current leap cycle. + */ + ltemp = sec; + while (ltemp >= L_CENT) + ltemp -= L_CENT; + while (ltemp >= L_4YEAR) + ltemp -= L_4YEAR; + + /* + * We are within four years of the target. If in leap year, use + * leap year month table; otherwise, use year month table. + */ + if (ltemp < L_LYEAR) { + ptr = lyear; + } else { + ptr = year; + ltemp -= L_LYEAR; + while (ltemp >= L_YEAR) + ltemp -= L_YEAR; + } + + /* + * We are within one year of the target. Find the month of the + * leap. + */ + while (ltemp >= *ptr * L_DAY) + ltemp -= *ptr++ * L_DAY; + + /* + * The result is the number of seconds until the end of the + * month when the leap is to occur. + */ + return (*ptr * L_DAY - ltemp - L_DAY); +} + + /* * getauthkeys - read the authentication keys from the specified file */ @@ -699,30 +1016,21 @@ 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); + memmove(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"); + strncpy(key_file_name, keyfile, _MAX_PATH); } #endif /* SYS_WINNT */ @@ -736,58 +1044,58 @@ getauthkeys( void rereadkeys(void) { - if (key_file_name != 0) - authreadkeys(key_file_name); + if (NULL != key_file_name) + authreadkeys(key_file_name); } + /* - * sock_hash - hash an sockaddr_storage structure + * sock_hash - hash a sockaddr_u structure */ -int +u_short sock_hash( - struct sockaddr_storage *addr + sockaddr_u *addr ) { - int hashVal; - int i; - int len; - char *ch; - + u_int hashVal; + u_int j; + size_t len; + u_char *pch; 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; + pch = (u_char *)&AF(addr); + hashVal = 37 * hashVal + *pch; + if (sizeof(AF(addr)) > 1) { + pch++; + hashVal = 37 * hashVal + *pch; } - switch(addr->ss_family) { + switch(AF(addr)) { case AF_INET: - ch = (char *)&((struct sockaddr_in *)addr)->sin_addr; - len = sizeof(struct in_addr); + pch = (u_char *)&SOCK_ADDR4(addr); + len = sizeof(SOCK_ADDR4(addr)); break; + case AF_INET6: - ch = (char *)&((struct sockaddr_in6 *)addr)->sin6_addr; - len = sizeof(struct in6_addr); + pch = (u_char *)&SOCK_ADDR6(addr); + len = sizeof(SOCK_ADDR6(addr)); break; } - for (i = 0; i < len ; i++) - hashVal = 37 * hashVal + (int)*(ch + i); - - hashVal = hashVal % 128; /* % MON_HASH_SIZE hardcoded */ + for (j = 0; j < len ; j++) + hashVal = 37 * hashVal + pch[j]; - if (hashVal < 0) - hashVal += 128; + hashVal = hashVal & NTP_HASH_MASK; - return hashVal; + return (u_short)hashVal; } + #if notyet /* * ntp_exit - document explicitly that ntpd has exited @@ -795,7 +1103,31 @@ sock_hash( void ntp_exit(int retval) { - msyslog(LOG_ERR, "EXITING with return code %d", retval); - exit(retval); + msyslog(LOG_ERR, "EXITING with return code %d", retval); + exit(retval); } #endif + +/* + * fstostr - prettyprint NTP seconds + */ +char * fstostr( + time_t ntp_stamp + ) +{ + static char str[20]; + struct tm * tm; + time_t unix_stamp; + + unix_stamp = ntp_stamp - JAN_1970; + tm = gmtime(&unix_stamp); + if (NULL != tm) + snprintf(str, sizeof(str), + "%04d%02d%02d%02d%02d", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min); + else + strcpy(str, "gmtime() error"); + + return str; +} |