154359Sroberto/* 254359Sroberto * ntp_util.c - stuff I didn't have any other place for 354359Sroberto */ 482498Sroberto 554359Sroberto#ifdef HAVE_CONFIG_H 682498Sroberto# include <config.h> 754359Sroberto#endif 854359Sroberto 954359Sroberto#include "ntpd.h" 1054359Sroberto#include "ntp_io.h" 1154359Sroberto#include "ntp_unixtime.h" 1254359Sroberto#include "ntp_filegen.h" 1354359Sroberto#include "ntp_if.h" 1454359Sroberto#include "ntp_stdlib.h" 1554359Sroberto 1682498Sroberto#include <stdio.h> 1782498Sroberto#include <ctype.h> 1882498Sroberto#include <sys/types.h> 1982498Sroberto#ifdef HAVE_SYS_IOCTL_H 2082498Sroberto# include <sys/ioctl.h> 2182498Sroberto#endif 2282498Sroberto 2382498Sroberto#ifdef HAVE_IEEEFP_H 2482498Sroberto# include <ieeefp.h> 2582498Sroberto#endif 2682498Sroberto#ifdef HAVE_MATH_H 2782498Sroberto# include <math.h> 2882498Sroberto#endif 2982498Sroberto 3054359Sroberto#ifdef DOSYNCTODR 31182007Sroberto# if !defined(VMS) 32182007Sroberto# include <sys/resource.h> 33182007Sroberto# endif /* VMS */ 3454359Sroberto#endif 3554359Sroberto 3654359Sroberto#if defined(VMS) 37182007Sroberto# include <descrip.h> 3854359Sroberto#endif /* VMS */ 3954359Sroberto 4054359Sroberto/* 4154359Sroberto * This contains odds and ends. Right now the only thing you'll find 42132451Sroberto * in here is the hourly stats printer and some code to support 43132451Sroberto * rereading the keys file, but I may eventually put other things in 44132451Sroberto * here such as code to do something with the leap bits. 4554359Sroberto */ 4654359Sroberto/* 4754359Sroberto * Name of the keys file 4854359Sroberto */ 4954359Srobertostatic char *key_file_name; 5054359Sroberto 5154359Sroberto/* 5254359Sroberto * The name of the drift_comp file and the temporary. 5354359Sroberto */ 5454359Srobertostatic char *stats_drift_file; 5554359Srobertostatic char *stats_temp_file; 56182007Srobertoint stats_write_period = 3600; /* # of seconds between writes. */ 57182007Srobertodouble stats_write_tolerance = 0; 58182007Srobertostatic double prev_drift_comp = 99999.; 5954359Sroberto 6054359Sroberto/* 6154359Sroberto * Statistics file stuff 6254359Sroberto */ 6354359Sroberto#ifndef NTP_VAR 64182007Sroberto# ifndef SYS_WINNT 65182007Sroberto# define NTP_VAR "/var/NTP/" /* NOTE the trailing '/' */ 66182007Sroberto# else 67182007Sroberto# define NTP_VAR "c:\\var\\ntp\\" /* NOTE the trailing '\\' */ 68182007Sroberto# endif /* SYS_WINNT */ 6954359Sroberto#endif 7054359Sroberto 7154359Sroberto#ifndef MAXPATHLEN 72182007Sroberto# define MAXPATHLEN 256 7354359Sroberto#endif 7454359Sroberto 7554359Srobertostatic char statsdir[MAXPATHLEN] = NTP_VAR; 7654359Sroberto 7754359Srobertostatic FILEGEN peerstats; 7854359Srobertostatic FILEGEN loopstats; 7954359Srobertostatic FILEGEN clockstats; 8054359Srobertostatic FILEGEN rawstats; 81132451Srobertostatic FILEGEN sysstats; 82182007Sroberto#ifdef DEBUG_TIMING 83182007Srobertostatic FILEGEN timingstats; 84182007Sroberto#endif 85132451Sroberto#ifdef OPENSSL 86132451Srobertostatic FILEGEN cryptostats; 87132451Sroberto#endif /* OPENSSL */ 8854359Sroberto 8954359Sroberto/* 9054359Sroberto * This controls whether stats are written to the fileset. Provided 9154359Sroberto * so that ntpdc can turn off stats when the file system fills up. 9254359Sroberto */ 9354359Srobertoint stats_control; 9454359Sroberto 9554359Sroberto/* 96182007Sroberto * Initial frequency offset later passed to the loopfilter. 97182007Sroberto */ 98182007Srobertodouble old_drift; 99182007Sroberto 100182007Sroberto/* 10154359Sroberto * init_util - initialize the utilities 10254359Sroberto */ 10354359Srobertovoid 10454359Srobertoinit_util(void) 10554359Sroberto{ 10654359Sroberto stats_drift_file = 0; 10754359Sroberto stats_temp_file = 0; 10854359Sroberto key_file_name = 0; 10954359Sroberto 110182007Sroberto filegen_register(&statsdir[0], "peerstats", &peerstats); 111132451Sroberto 112182007Sroberto filegen_register(&statsdir[0], "loopstats", &loopstats); 11354359Sroberto 114182007Sroberto filegen_register(&statsdir[0], "clockstats", &clockstats); 11554359Sroberto 116182007Sroberto filegen_register(&statsdir[0], "rawstats", &rawstats); 11754359Sroberto 118182007Sroberto filegen_register(&statsdir[0], "sysstats", &sysstats); 119132451Sroberto 120132451Sroberto#ifdef OPENSSL 121182007Sroberto filegen_register(&statsdir[0], "cryptostats", &cryptostats); 122132451Sroberto#endif /* OPENSSL */ 123132451Sroberto 124182007Sroberto#ifdef DEBUG_TIMING 125182007Sroberto filegen_register(&statsdir[0], "timingstats", &timingstats); 126182007Sroberto#endif 12754359Sroberto} 12854359Sroberto 12954359Sroberto 13054359Sroberto/* 13154359Sroberto * hourly_stats - print some interesting stats 13254359Sroberto */ 13354359Srobertovoid 134182007Srobertowrite_stats(void) 13554359Sroberto{ 13654359Sroberto FILE *fp; 13754359Sroberto 13854359Sroberto#ifdef DOSYNCTODR 13954359Sroberto struct timeval tv; 14054359Sroberto#if !defined(VMS) 14154359Sroberto int prio_set; 14254359Sroberto#endif 14354359Sroberto#ifdef HAVE_GETCLOCK 14454359Sroberto struct timespec ts; 14554359Sroberto#endif 14654359Sroberto int o_prio; 14754359Sroberto 14854359Sroberto /* 14954359Sroberto * Sometimes having a Sun can be a drag. 15054359Sroberto * 15154359Sroberto * The kernel variable dosynctodr controls whether the system's 15254359Sroberto * soft clock is kept in sync with the battery clock. If it 15354359Sroberto * is zero, then the soft clock is not synced, and the battery 15454359Sroberto * clock is simply left to rot. That means that when the system 15554359Sroberto * reboots, the battery clock (which has probably gone wacky) 15654359Sroberto * sets the soft clock. That means ntpd starts off with a very 15754359Sroberto * confused idea of what time it is. It then takes a large 15854359Sroberto * amount of time to figure out just how wacky the battery clock 15954359Sroberto * has made things drift, etc, etc. The solution is to make the 16054359Sroberto * battery clock sync up to system time. The way to do THAT is 16154359Sroberto * to simply set the time of day to the current time of day, but 16254359Sroberto * as quickly as possible. This may, or may not be a sensible 16354359Sroberto * thing to do. 16454359Sroberto * 16554359Sroberto * CAVEAT: settimeofday() steps the sun clock by about 800 us, 16654359Sroberto * so setting DOSYNCTODR seems a bad idea in the 16754359Sroberto * case of us resolution 16854359Sroberto */ 16954359Sroberto 17054359Sroberto#if !defined(VMS) 17154359Sroberto /* (prr) getpriority returns -1 on error, but -1 is also a valid 172132451Sroberto * return value (!), so instead we have to zero errno before the 173132451Sroberto * call and check it for non-zero afterwards. 17454359Sroberto */ 17554359Sroberto errno = 0; 17654359Sroberto prio_set = 0; 17754359Sroberto o_prio = getpriority(PRIO_PROCESS,0); /* Save setting */ 17854359Sroberto 179132451Sroberto /* 180132451Sroberto * (prr) if getpriority succeeded, call setpriority to raise 18154359Sroberto * scheduling priority as high as possible. If that succeeds 18254359Sroberto * as well, set the prio_set flag so we remember to reset 183132451Sroberto * priority to its previous value below. Note that on Solaris 184132451Sroberto * 2.6 (and beyond?), both getpriority and setpriority will fail 185132451Sroberto * with ESRCH, because sched_setscheduler (called from main) put 186132451Sroberto * us in the real-time scheduling class which setpriority 187132451Sroberto * doesn't know about. Being in the real-time class is better 188132451Sroberto * than anything setpriority can do, anyhow, so this error is 189132451Sroberto * silently ignored. 19054359Sroberto */ 19154359Sroberto if ((errno == 0) && (setpriority(PRIO_PROCESS,0,-20) == 0)) 192132451Sroberto prio_set = 1; /* overdrive */ 19354359Sroberto#endif /* VMS */ 19454359Sroberto#ifdef HAVE_GETCLOCK 19554359Sroberto (void) getclock(TIMEOFDAY, &ts); 19654359Sroberto tv.tv_sec = ts.tv_sec; 19754359Sroberto tv.tv_usec = ts.tv_nsec / 1000; 19854359Sroberto#else /* not HAVE_GETCLOCK */ 19954359Sroberto GETTIMEOFDAY(&tv,(struct timezone *)NULL); 20054359Sroberto#endif /* not HAVE_GETCLOCK */ 201132451Sroberto if (ntp_set_tod(&tv,(struct timezone *)NULL) != 0) { 20254359Sroberto msyslog(LOG_ERR, "can't sync battery time: %m"); 20354359Sroberto } 20454359Sroberto#if !defined(VMS) 20554359Sroberto if (prio_set) 206132451Sroberto setpriority(PRIO_PROCESS, 0, o_prio); /* downshift */ 20754359Sroberto#endif /* VMS */ 20854359Sroberto#endif /* DOSYNCTODR */ 20954359Sroberto 21054359Sroberto NLOG(NLOG_SYSSTATIST) 21154359Sroberto msyslog(LOG_INFO, 21254359Sroberto "offset %.6f sec freq %.3f ppm error %.6f poll %d", 213132451Sroberto last_offset, drift_comp * 1e6, sys_jitter, 214132451Sroberto sys_poll); 21582498Sroberto 21654359Sroberto 217132451Sroberto record_sys_stats(); 218182007Sroberto if ((u_long)(fabs(prev_drift_comp - drift_comp) * 1e9) <= 219182007Sroberto (u_long)(fabs(stats_write_tolerance * drift_comp) * 1e9)) { 220182007Sroberto return; 221182007Sroberto } 222182007Sroberto prev_drift_comp = drift_comp; 22354359Sroberto if (stats_drift_file != 0) { 22454359Sroberto if ((fp = fopen(stats_temp_file, "w")) == NULL) { 22554359Sroberto msyslog(LOG_ERR, "can't open %s: %m", 22654359Sroberto stats_temp_file); 22754359Sroberto return; 22854359Sroberto } 22954359Sroberto fprintf(fp, "%.3f\n", drift_comp * 1e6); 23054359Sroberto (void)fclose(fp); 23154359Sroberto /* atomic */ 23254359Sroberto#ifdef SYS_WINNT 233132451Sroberto (void) _unlink(stats_drift_file); /* rename semantics differ under NT */ 23454359Sroberto#endif /* SYS_WINNT */ 23554359Sroberto 23654359Sroberto#ifndef NO_RENAME 23754359Sroberto (void) rename(stats_temp_file, stats_drift_file); 23854359Sroberto#else 239182007Sroberto /* we have no rename NFS of ftp in use */ 24054359Sroberto if ((fp = fopen(stats_drift_file, "w")) == NULL) { 24154359Sroberto msyslog(LOG_ERR, "can't open %s: %m", 24254359Sroberto stats_drift_file); 24354359Sroberto return; 24454359Sroberto } 24554359Sroberto 24654359Sroberto#endif 24754359Sroberto 24854359Sroberto#if defined(VMS) 24954359Sroberto /* PURGE */ 25054359Sroberto { 25154359Sroberto $DESCRIPTOR(oldvers,";-1"); 25254359Sroberto struct dsc$descriptor driftdsc = { 25354359Sroberto strlen(stats_drift_file),0,0,stats_drift_file }; 25454359Sroberto 25554359Sroberto while(lib$delete_file(&oldvers,&driftdsc) & 1) ; 25654359Sroberto } 25754359Sroberto#endif 25854359Sroberto } 25954359Sroberto} 26054359Sroberto 26154359Sroberto 26254359Sroberto/* 26354359Sroberto * stats_config - configure the stats operation 26454359Sroberto */ 26554359Srobertovoid 26654359Srobertostats_config( 26754359Sroberto int item, 268182007Sroberto const char *invalue /* only one type so far */ 26954359Sroberto ) 27054359Sroberto{ 27154359Sroberto FILE *fp; 272182007Sroberto const char *value; 27354359Sroberto int len; 27454359Sroberto 275132451Sroberto /* 276132451Sroberto * Expand environment strings under Windows NT, since the 277132451Sroberto * command interpreter doesn't do this, the program must. 27854359Sroberto */ 27954359Sroberto#ifdef SYS_WINNT 28054359Sroberto char newvalue[MAX_PATH], parameter[MAX_PATH]; 28154359Sroberto 282132451Sroberto if (!ExpandEnvironmentStrings(invalue, newvalue, MAX_PATH)) { 28354359Sroberto switch(item) { 28454359Sroberto case STATS_FREQ_FILE: 28554359Sroberto strcpy(parameter,"STATS_FREQ_FILE"); 28654359Sroberto break; 28754359Sroberto case STATS_STATSDIR: 28854359Sroberto strcpy(parameter,"STATS_STATSDIR"); 28954359Sroberto break; 29054359Sroberto case STATS_PID_FILE: 29154359Sroberto strcpy(parameter,"STATS_PID_FILE"); 29254359Sroberto break; 29354359Sroberto default: 29454359Sroberto strcpy(parameter,"UNKNOWN"); 29554359Sroberto break; 29654359Sroberto } 29754359Sroberto value = invalue; 29854359Sroberto 29954359Sroberto msyslog(LOG_ERR, 30054359Sroberto "ExpandEnvironmentStrings(%s) failed: %m\n", parameter); 301132451Sroberto } else { 302132451Sroberto value = newvalue; 30354359Sroberto } 30454359Sroberto#else 30554359Sroberto value = invalue; 30654359Sroberto#endif /* SYS_WINNT */ 30754359Sroberto 30854359Sroberto switch(item) { 30954359Sroberto case STATS_FREQ_FILE: 31054359Sroberto if (stats_drift_file != 0) { 31154359Sroberto (void) free(stats_drift_file); 31254359Sroberto (void) free(stats_temp_file); 31354359Sroberto stats_drift_file = 0; 31454359Sroberto stats_temp_file = 0; 31554359Sroberto } 31654359Sroberto 31754359Sroberto if (value == 0 || (len = strlen(value)) == 0) 31854359Sroberto break; 31954359Sroberto 32054359Sroberto stats_drift_file = (char*)emalloc((u_int)(len + 1)); 32154359Sroberto#if !defined(VMS) 322132451Sroberto stats_temp_file = (char*)emalloc((u_int)(len + 323132451Sroberto sizeof(".TEMP"))); 32454359Sroberto#else 325132451Sroberto stats_temp_file = (char*)emalloc((u_int)(len + 326132451Sroberto sizeof("-TEMP"))); 32754359Sroberto#endif /* VMS */ 32854359Sroberto memmove(stats_drift_file, value, (unsigned)(len+1)); 32954359Sroberto memmove(stats_temp_file, value, (unsigned)len); 33054359Sroberto#if !defined(VMS) 331132451Sroberto memmove(stats_temp_file + len, ".TEMP", 332132451Sroberto sizeof(".TEMP")); 33354359Sroberto#else 334132451Sroberto memmove(stats_temp_file + len, "-TEMP", 335132451Sroberto sizeof("-TEMP")); 33654359Sroberto#endif /* VMS */ 33754359Sroberto 33854359Sroberto /* 339132451Sroberto * Open drift file and read frequency. If the file is 340132451Sroberto * missing or contains errors, tell the loop to reset. 34154359Sroberto */ 34254359Sroberto if ((fp = fopen(stats_drift_file, "r")) == NULL) { 343182007Sroberto old_drift = 1e9; 34454359Sroberto break; 34554359Sroberto } 34654359Sroberto if (fscanf(fp, "%lf", &old_drift) != 1) { 347132451Sroberto msyslog(LOG_ERR, "Frequency format error in %s", 34854359Sroberto stats_drift_file); 349182007Sroberto old_drift = 1e9; 350132451Sroberto fclose(fp); 35154359Sroberto break; 35254359Sroberto } 353132451Sroberto fclose(fp); 354182007Sroberto prev_drift_comp = old_drift / 1e6; 355132451Sroberto msyslog(LOG_INFO, 356132451Sroberto "frequency initialized %.3f PPM from %s", 357132451Sroberto old_drift, stats_drift_file); 35854359Sroberto break; 35954359Sroberto 36054359Sroberto case STATS_STATSDIR: 36154359Sroberto if (strlen(value) >= sizeof(statsdir)) { 36254359Sroberto msyslog(LOG_ERR, 36354359Sroberto "value for statsdir too long (>%d, sigh)", 36454359Sroberto (int)sizeof(statsdir)-1); 36554359Sroberto } else { 36654359Sroberto l_fp now; 36754359Sroberto 36854359Sroberto get_systime(&now); 36954359Sroberto strcpy(statsdir,value); 37054359Sroberto if(peerstats.prefix == &statsdir[0] && 37154359Sroberto peerstats.fp != NULL) { 37254359Sroberto fclose(peerstats.fp); 37354359Sroberto peerstats.fp = NULL; 37454359Sroberto filegen_setup(&peerstats, now.l_ui); 37554359Sroberto } 37654359Sroberto if(loopstats.prefix == &statsdir[0] && 37754359Sroberto loopstats.fp != NULL) { 37854359Sroberto fclose(loopstats.fp); 37954359Sroberto loopstats.fp = NULL; 38054359Sroberto filegen_setup(&loopstats, now.l_ui); 38154359Sroberto } 38254359Sroberto if(clockstats.prefix == &statsdir[0] && 38354359Sroberto clockstats.fp != NULL) { 38454359Sroberto fclose(clockstats.fp); 38554359Sroberto clockstats.fp = NULL; 38654359Sroberto filegen_setup(&clockstats, now.l_ui); 38754359Sroberto } 38854359Sroberto if(rawstats.prefix == &statsdir[0] && 38954359Sroberto rawstats.fp != NULL) { 39054359Sroberto fclose(rawstats.fp); 39154359Sroberto rawstats.fp = NULL; 39254359Sroberto filegen_setup(&rawstats, now.l_ui); 39354359Sroberto } 394132451Sroberto if(sysstats.prefix == &statsdir[0] && 395132451Sroberto sysstats.fp != NULL) { 396132451Sroberto fclose(sysstats.fp); 397132451Sroberto sysstats.fp = NULL; 398132451Sroberto filegen_setup(&sysstats, now.l_ui); 399132451Sroberto } 400132451Sroberto#ifdef OPENSSL 401132451Sroberto if(cryptostats.prefix == &statsdir[0] && 402132451Sroberto cryptostats.fp != NULL) { 403132451Sroberto fclose(cryptostats.fp); 404132451Sroberto cryptostats.fp = NULL; 405132451Sroberto filegen_setup(&cryptostats, now.l_ui); 406132451Sroberto } 407132451Sroberto#endif /* OPENSSL */ 40854359Sroberto } 40954359Sroberto break; 41054359Sroberto 41154359Sroberto case STATS_PID_FILE: 41254359Sroberto if ((fp = fopen(value, "w")) == NULL) { 41354359Sroberto msyslog(LOG_ERR, "Can't open %s: %m", value); 41454359Sroberto break; 41554359Sroberto } 41654359Sroberto fprintf(fp, "%d", (int) getpid()); 41754359Sroberto fclose(fp);; 41854359Sroberto break; 41954359Sroberto 42054359Sroberto default: 42154359Sroberto /* oh well */ 42254359Sroberto break; 42354359Sroberto } 42454359Sroberto} 42554359Sroberto 42654359Sroberto/* 42754359Sroberto * record_peer_stats - write peer statistics to file 42854359Sroberto * 42954359Sroberto * file format: 43054359Sroberto * day (mjd) 43154359Sroberto * time (s past UTC midnight) 43254359Sroberto * peer (ip address) 43354359Sroberto * peer status word (hex) 43454359Sroberto * peer offset (s) 43554359Sroberto * peer delay (s) 43654359Sroberto * peer error bound (s) 43754359Sroberto * peer error (s) 43854359Sroberto*/ 43954359Srobertovoid 44054359Srobertorecord_peer_stats( 441132451Sroberto struct sockaddr_storage *addr, 442132451Sroberto int status, 443132451Sroberto double offset, 444132451Sroberto double delay, 445132451Sroberto double dispersion, 446132451Sroberto double skew 44754359Sroberto ) 44854359Sroberto{ 449132451Sroberto l_fp now; 450132451Sroberto u_long day; 45154359Sroberto 45254359Sroberto if (!stats_control) 45354359Sroberto return; 45454359Sroberto 455132451Sroberto get_systime(&now); 456132451Sroberto filegen_setup(&peerstats, now.l_ui); 457132451Sroberto day = now.l_ui / 86400 + MJD_1900; 458132451Sroberto now.l_ui %= 86400; 45954359Sroberto if (peerstats.fp != NULL) { 46054359Sroberto fprintf(peerstats.fp, 461132451Sroberto "%lu %s %s %x %.9f %.9f %.9f %.9f\n", 462132451Sroberto day, ulfptoa(&now, 3), stoa(addr), status, offset, 46354359Sroberto delay, dispersion, skew); 46454359Sroberto fflush(peerstats.fp); 46554359Sroberto } 46654359Sroberto} 467182007Sroberto 46854359Sroberto/* 46954359Sroberto * record_loop_stats - write loop filter statistics to file 47054359Sroberto * 47154359Sroberto * file format: 47254359Sroberto * day (mjd) 47354359Sroberto * time (s past midnight) 47454359Sroberto * offset (s) 47554359Sroberto * frequency (approx ppm) 47654359Sroberto * time constant (log base 2) 47754359Sroberto */ 47854359Srobertovoid 47982498Srobertorecord_loop_stats( 480132451Sroberto double offset, 481132451Sroberto double freq, 482132451Sroberto double jitter, 483132451Sroberto double stability, 484132451Sroberto int spoll 48582498Sroberto ) 48654359Sroberto{ 487132451Sroberto l_fp now; 488132451Sroberto u_long day; 48954359Sroberto 49054359Sroberto if (!stats_control) 49154359Sroberto return; 49254359Sroberto 493132451Sroberto get_systime(&now); 494132451Sroberto filegen_setup(&loopstats, now.l_ui); 495132451Sroberto day = now.l_ui / 86400 + MJD_1900; 496132451Sroberto now.l_ui %= 86400; 49754359Sroberto if (loopstats.fp != NULL) { 498182007Sroberto fprintf(loopstats.fp, "%lu %s %.9f %.3f %.9f %.6f %d\n", 499132451Sroberto day, ulfptoa(&now, 3), offset, freq * 1e6, jitter, 500132451Sroberto stability * 1e6, spoll); 50154359Sroberto fflush(loopstats.fp); 50254359Sroberto } 50354359Sroberto} 50454359Sroberto 50554359Sroberto/* 50654359Sroberto * record_clock_stats - write clock statistics to file 50754359Sroberto * 50854359Sroberto * file format: 50954359Sroberto * day (mjd) 51054359Sroberto * time (s past midnight) 51154359Sroberto * peer (ip address) 51254359Sroberto * text message 51354359Sroberto */ 51454359Srobertovoid 51554359Srobertorecord_clock_stats( 516132451Sroberto struct sockaddr_storage *addr, 51754359Sroberto const char *text 51854359Sroberto ) 51954359Sroberto{ 520132451Sroberto l_fp now; 521132451Sroberto u_long day; 52254359Sroberto 52354359Sroberto if (!stats_control) 52454359Sroberto return; 52554359Sroberto 526132451Sroberto get_systime(&now); 527132451Sroberto filegen_setup(&clockstats, now.l_ui); 528132451Sroberto day = now.l_ui / 86400 + MJD_1900; 529132451Sroberto now.l_ui %= 86400; 53054359Sroberto if (clockstats.fp != NULL) { 531132451Sroberto fprintf(clockstats.fp, "%lu %s %s %s\n", 532132451Sroberto day, ulfptoa(&now, 3), stoa(addr), text); 53354359Sroberto fflush(clockstats.fp); 53454359Sroberto } 53554359Sroberto} 53654359Sroberto 53754359Sroberto/* 53854359Sroberto * record_raw_stats - write raw timestamps to file 53954359Sroberto * 54054359Sroberto * 54154359Sroberto * file format 54254359Sroberto * time (s past midnight) 54354359Sroberto * peer ip address 54454359Sroberto * local ip address 54554359Sroberto * t1 t2 t3 t4 timestamps 54654359Sroberto */ 54754359Srobertovoid 54854359Srobertorecord_raw_stats( 549132451Sroberto struct sockaddr_storage *srcadr, 550132451Sroberto struct sockaddr_storage *dstadr, 551132451Sroberto l_fp *t1, 552132451Sroberto l_fp *t2, 553132451Sroberto l_fp *t3, 554132451Sroberto l_fp *t4 55554359Sroberto ) 55654359Sroberto{ 557132451Sroberto l_fp now; 558132451Sroberto u_long day; 55954359Sroberto 56054359Sroberto if (!stats_control) 56154359Sroberto return; 56254359Sroberto 563132451Sroberto get_systime(&now); 564132451Sroberto filegen_setup(&rawstats, now.l_ui); 565132451Sroberto day = now.l_ui / 86400 + MJD_1900; 566132451Sroberto now.l_ui %= 86400; 56754359Sroberto if (rawstats.fp != NULL) { 568132451Sroberto fprintf(rawstats.fp, "%lu %s %s %s %s %s %s %s\n", 569182007Sroberto day, ulfptoa(&now, 3), stoa(srcadr), dstadr ? stoa(dstadr) : "-", 570182007Sroberto ulfptoa(t1, 9), ulfptoa(t2, 9), ulfptoa(t3, 9), 571182007Sroberto ulfptoa(t4, 9)); 57254359Sroberto fflush(rawstats.fp); 57354359Sroberto } 57454359Sroberto} 57554359Sroberto 576132451Sroberto 57754359Sroberto/* 578132451Sroberto * record_sys_stats - write system statistics to file 579132451Sroberto * 580132451Sroberto * file format 581132451Sroberto * time (s past midnight) 582132451Sroberto * time since startup (hr) 583132451Sroberto * packets recieved 584132451Sroberto * packets processed 585132451Sroberto * current version 586132451Sroberto * previous version 587132451Sroberto * bad version 588132451Sroberto * access denied 589132451Sroberto * bad length or format 590132451Sroberto * bad authentication 591132451Sroberto * rate exceeded 592132451Sroberto */ 593132451Srobertovoid 594132451Srobertorecord_sys_stats(void) 595132451Sroberto{ 596132451Sroberto l_fp now; 597132451Sroberto u_long day; 598132451Sroberto 599132451Sroberto if (!stats_control) 600132451Sroberto return; 601132451Sroberto 602132451Sroberto get_systime(&now); 603132451Sroberto filegen_setup(&sysstats, now.l_ui); 604132451Sroberto day = now.l_ui / 86400 + MJD_1900; 605132451Sroberto now.l_ui %= 86400; 606132451Sroberto if (sysstats.fp != NULL) { 607132451Sroberto fprintf(sysstats.fp, 608132451Sroberto "%lu %s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n", 609132451Sroberto day, ulfptoa(&now, 3), sys_stattime / 3600, 610132451Sroberto sys_received, sys_processed, sys_newversionpkt, 611132451Sroberto sys_oldversionpkt, sys_unknownversion, 612132451Sroberto sys_restricted, sys_badlength, sys_badauth, 613132451Sroberto sys_limitrejected); 614132451Sroberto fflush(sysstats.fp); 615132451Sroberto proto_clr_stats(); 616132451Sroberto } 617132451Sroberto} 618132451Sroberto 619132451Sroberto 620132451Sroberto#ifdef OPENSSL 621132451Sroberto/* 622132451Sroberto * record_crypto_stats - write crypto statistics to file 623132451Sroberto * 624132451Sroberto * file format: 625132451Sroberto * day (mjd) 626132451Sroberto * time (s past midnight) 627132451Sroberto * peer (ip address) 628132451Sroberto * text message 629132451Sroberto */ 630132451Srobertovoid 631132451Srobertorecord_crypto_stats( 632132451Sroberto struct sockaddr_storage *addr, 633132451Sroberto const char *text 634132451Sroberto ) 635132451Sroberto{ 636132451Sroberto l_fp now; 637132451Sroberto u_long day; 638132451Sroberto 639132451Sroberto if (!stats_control) 640132451Sroberto return; 641132451Sroberto 642132451Sroberto get_systime(&now); 643132451Sroberto filegen_setup(&cryptostats, now.l_ui); 644132451Sroberto day = now.l_ui / 86400 + MJD_1900; 645132451Sroberto now.l_ui %= 86400; 646132451Sroberto if (cryptostats.fp != NULL) { 647132451Sroberto if (addr == NULL) 648132451Sroberto fprintf(cryptostats.fp, "%lu %s %s\n", 649132451Sroberto day, ulfptoa(&now, 3), text); 650132451Sroberto else 651132451Sroberto fprintf(cryptostats.fp, "%lu %s %s %s\n", 652132451Sroberto day, ulfptoa(&now, 3), stoa(addr), text); 653132451Sroberto fflush(cryptostats.fp); 654132451Sroberto } 655132451Sroberto} 656132451Sroberto#endif /* OPENSSL */ 657132451Sroberto 658182007Sroberto#ifdef DEBUG_TIMING 659182007Sroberto/* 660182007Sroberto * record_crypto_stats - write crypto statistics to file 661182007Sroberto * 662182007Sroberto * file format: 663182007Sroberto * day (mjd) 664182007Sroberto * time (s past midnight) 665182007Sroberto * text message 666182007Sroberto */ 667182007Srobertovoid 668182007Srobertorecord_timing_stats( 669182007Sroberto const char *text 670182007Sroberto ) 671182007Sroberto{ 672182007Sroberto static unsigned int flshcnt; 673182007Sroberto l_fp now; 674182007Sroberto u_long day; 675132451Sroberto 676182007Sroberto if (!stats_control) 677182007Sroberto return; 678182007Sroberto 679182007Sroberto get_systime(&now); 680182007Sroberto filegen_setup(&timingstats, now.l_ui); 681182007Sroberto day = now.l_ui / 86400 + MJD_1900; 682182007Sroberto now.l_ui %= 86400; 683182007Sroberto if (timingstats.fp != NULL) { 684182007Sroberto fprintf(timingstats.fp, "%lu %s %s\n", 685182007Sroberto day, lfptoa(&now, 3), text); 686182007Sroberto if (++flshcnt % 100 == 0) 687182007Sroberto fflush(timingstats.fp); 688182007Sroberto } 689182007Sroberto} 690182007Sroberto#endif 691132451Sroberto/* 69254359Sroberto * getauthkeys - read the authentication keys from the specified file 69354359Sroberto */ 69454359Srobertovoid 69554359Srobertogetauthkeys( 696182007Sroberto const char *keyfile 69754359Sroberto ) 69854359Sroberto{ 69954359Sroberto int len; 70054359Sroberto 70154359Sroberto len = strlen(keyfile); 70254359Sroberto if (len == 0) 70354359Sroberto return; 70454359Sroberto 70554359Sroberto if (key_file_name != 0) { 70654359Sroberto if (len > (int)strlen(key_file_name)) { 70754359Sroberto (void) free(key_file_name); 70854359Sroberto key_file_name = 0; 70954359Sroberto } 71054359Sroberto } 71154359Sroberto 71254359Sroberto if (key_file_name == 0) { 71354359Sroberto#ifndef SYS_WINNT 71454359Sroberto key_file_name = (char*)emalloc((u_int) (len + 1)); 71554359Sroberto#else 71654359Sroberto key_file_name = (char*)emalloc((u_int) (MAXPATHLEN)); 71754359Sroberto#endif 71854359Sroberto } 71954359Sroberto#ifndef SYS_WINNT 72054359Sroberto memmove(key_file_name, keyfile, (unsigned)(len+1)); 72154359Sroberto#else 72254359Sroberto if (!ExpandEnvironmentStrings(keyfile, key_file_name, MAXPATHLEN)) 72354359Sroberto { 72454359Sroberto msyslog(LOG_ERR, 72554359Sroberto "ExpandEnvironmentStrings(KEY_FILE) failed: %m\n"); 72654359Sroberto } 72754359Sroberto#endif /* SYS_WINNT */ 72854359Sroberto 72954359Sroberto authreadkeys(key_file_name); 73054359Sroberto} 73154359Sroberto 73254359Sroberto 73354359Sroberto/* 73454359Sroberto * rereadkeys - read the authentication key file over again. 73554359Sroberto */ 73654359Srobertovoid 73754359Srobertorereadkeys(void) 73854359Sroberto{ 73954359Sroberto if (key_file_name != 0) 74054359Sroberto authreadkeys(key_file_name); 74154359Sroberto} 742132451Sroberto 743132451Sroberto/* 744132451Sroberto * sock_hash - hash an sockaddr_storage structure 745132451Sroberto */ 746132451Srobertoint 747132451Srobertosock_hash( 748132451Sroberto struct sockaddr_storage *addr 749132451Sroberto ) 750132451Sroberto{ 751132451Sroberto int hashVal; 752132451Sroberto int i; 753132451Sroberto int len; 754132451Sroberto char *ch; 755132451Sroberto 756132451Sroberto hashVal = 0; 757132451Sroberto len = 0; 758132451Sroberto /* 759132451Sroberto * We can't just hash the whole thing because there are hidden 760132451Sroberto * fields in sockaddr_in6 that might be filled in by recvfrom(), 761132451Sroberto * so just use the family, port and address. 762132451Sroberto */ 763132451Sroberto ch = (char *)&addr->ss_family; 764132451Sroberto hashVal = 37 * hashVal + (int)*ch; 765132451Sroberto if (sizeof(addr->ss_family) > 1) { 766132451Sroberto ch++; 767132451Sroberto hashVal = 37 * hashVal + (int)*ch; 768132451Sroberto } 769132451Sroberto switch(addr->ss_family) { 770132451Sroberto case AF_INET: 771132451Sroberto ch = (char *)&((struct sockaddr_in *)addr)->sin_addr; 772132451Sroberto len = sizeof(struct in_addr); 773132451Sroberto break; 774132451Sroberto case AF_INET6: 775132451Sroberto ch = (char *)&((struct sockaddr_in6 *)addr)->sin6_addr; 776132451Sroberto len = sizeof(struct in6_addr); 777132451Sroberto break; 778132451Sroberto } 779132451Sroberto 780132451Sroberto for (i = 0; i < len ; i++) 781132451Sroberto hashVal = 37 * hashVal + (int)*(ch + i); 782132451Sroberto 783132451Sroberto hashVal = hashVal % 128; /* % MON_HASH_SIZE hardcoded */ 784132451Sroberto 785132451Sroberto if (hashVal < 0) 786132451Sroberto hashVal += 128; 787132451Sroberto 788132451Sroberto return hashVal; 789132451Sroberto} 790182007Sroberto 791182007Sroberto#if notyet 792182007Sroberto/* 793182007Sroberto * ntp_exit - document explicitly that ntpd has exited 794182007Sroberto */ 795182007Srobertovoid 796182007Srobertontp_exit(int retval) 797182007Sroberto{ 798182007Sroberto msyslog(LOG_ERR, "EXITING with return code %d", retval); 799182007Sroberto exit(retval); 800182007Sroberto} 801182007Sroberto#endif 802