Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / bsd / ntp / dist / ntpd / ntp_util.c
blobf6c9a0f8ad8abbe68a174140dd2fb447aca50884
1 /* $NetBSD$ */
3 /*
4 * ntp_util.c - stuff I didn't have any other place for
5 */
6 #ifdef HAVE_CONFIG_H
7 # include <config.h>
8 #endif
10 #include "ntpd.h"
11 #include "ntp_io.h"
12 #include "ntp_unixtime.h"
13 #include "ntp_filegen.h"
14 #include "ntp_if.h"
15 #include "ntp_stdlib.h"
16 #include "ntp_assert.h"
18 #include <stdio.h>
19 #include <ctype.h>
20 #include <sys/types.h>
21 #ifdef HAVE_SYS_IOCTL_H
22 # include <sys/ioctl.h>
23 #endif
25 #ifdef HAVE_IEEEFP_H
26 # include <ieeefp.h>
27 #endif
28 #ifdef HAVE_MATH_H
29 # include <math.h>
30 #endif
32 #ifdef DOSYNCTODR
33 # if !defined(VMS)
34 # include <sys/resource.h>
35 # endif /* VMS */
36 #endif
38 #if defined(VMS)
39 # include <descrip.h>
40 #endif /* VMS */
43 * Defines used by the leapseconds stuff
45 #define MAX_TAI 100 /* max TAI offset (s) */
46 #define L_DAY 86400UL /* seconds per day */
47 #define L_YEAR (L_DAY * 365) /* days per year */
48 #define L_LYEAR (L_YEAR + L_DAY) /* days per leap year */
49 #define L_4YEAR (L_LYEAR + 3 * L_YEAR) /* days per leap cycle */
50 #define L_CENT (L_4YEAR * 25) /* days per century */
53 * This contains odds and ends, including the hourly stats, various
54 * configuration items, leapseconds stuff, etc.
57 * File names
59 static char *key_file_name; /* keys file name */
60 char *leapseconds_file_name; /* leapseconds file name */
61 char *stats_drift_file; /* frequency file name */
62 static char *stats_temp_file; /* temp frequency file name */
63 double wander_resid; /* wander threshold */
64 double wander_threshold = 1e-7; /* initial wander threshold */
65 int drift_file_sw; /* clock update switch */
68 * Statistics file stuff
70 #ifndef NTP_VAR
71 # ifndef SYS_WINNT
72 # define NTP_VAR "/var/NTP/" /* NOTE the trailing '/' */
73 # else
74 # define NTP_VAR "c:\\var\\ntp\\" /* NOTE the trailing '\\' */
75 # endif /* SYS_WINNT */
76 #endif
78 #ifndef MAXPATHLEN
79 # define MAXPATHLEN 256
80 #endif
82 #ifdef DEBUG_TIMING
83 static FILEGEN timingstats;
84 #endif
85 #ifdef OPENSSL
86 static FILEGEN cryptostats;
87 #endif /* OPENSSL */
89 static char statsdir[MAXPATHLEN] = NTP_VAR;
90 static FILEGEN peerstats;
91 static FILEGEN loopstats;
92 static FILEGEN clockstats;
93 static FILEGEN rawstats;
94 static FILEGEN sysstats;
95 static FILEGEN protostats;
98 * This controls whether stats are written to the fileset. Provided
99 * so that ntpdc can turn off stats when the file system fills up.
101 int stats_control;
104 * Initial frequency offset later passed to the loopfilter.
106 double old_drift = 1e9; /* current frequency */
107 static double prev_drift_comp; /* last frequency update */
110 * Static prototypes
112 static int leap_file(FILE *);
113 static void record_sys_stats(void);
116 * Prototypes
118 #ifdef DEBUG
119 void uninit_util(void);
120 #endif
124 * uninit_util - free memory allocated by init_util
126 #ifdef DEBUG
127 void
128 uninit_util(void)
130 #if defined(_MSC_VER) && defined (_DEBUG)
131 _CrtCheckMemory();
132 #endif
133 if (stats_drift_file) {
134 free(stats_drift_file);
135 free(stats_temp_file);
136 stats_drift_file = NULL;
137 stats_temp_file = NULL;
139 if (key_file_name) {
140 free(key_file_name);
141 key_file_name = NULL;
143 filegen_unregister("peerstats");
144 filegen_unregister("loopstats");
145 filegen_unregister("clockstats");
146 filegen_unregister("rawstats");
147 filegen_unregister("sysstats");
148 filegen_unregister("protostats");
149 #ifdef OPENSSL
150 filegen_unregister("cryptostats");
151 #endif /* OPENSSL */
152 #ifdef DEBUG_TIMING
153 filegen_unregister("timingstats");
154 #endif /* DEBUG_TIMING */
156 #if defined(_MSC_VER) && defined (_DEBUG)
157 _CrtCheckMemory();
158 #endif
160 #endif /* DEBUG */
164 * init_util - initialize the utilities (ntpd included)
166 void
167 init_util(void)
169 stats_drift_file = NULL;
170 stats_temp_file = NULL;
171 key_file_name = NULL;
172 filegen_register(statsdir, "peerstats", &peerstats);
173 filegen_register(statsdir, "loopstats", &loopstats);
174 filegen_register(statsdir, "clockstats", &clockstats);
175 filegen_register(statsdir, "rawstats", &rawstats);
176 filegen_register(statsdir, "sysstats", &sysstats);
177 filegen_register(statsdir, "protostats", &protostats);
178 #ifdef OPENSSL
179 filegen_register(statsdir, "cryptostats", &cryptostats);
180 #endif /* OPENSSL */
181 #ifdef DEBUG_TIMING
182 filegen_register(statsdir, "timingstats", &timingstats);
183 #endif /* DEBUG_TIMING */
184 #ifdef DEBUG
185 atexit(uninit_util);
186 #endif /* DEBUG */
191 * hourly_stats - print some interesting stats
193 void
194 write_stats(void)
196 FILE *fp;
197 double ftemp;
198 #ifdef DOSYNCTODR
199 struct timeval tv;
200 #if !defined(VMS)
201 int prio_set;
202 #endif
203 #ifdef HAVE_GETCLOCK
204 struct timespec ts;
205 #endif
206 int o_prio;
209 * Sometimes having a Sun can be a drag.
211 * The kernel variable dosynctodr controls whether the system's
212 * soft clock is kept in sync with the battery clock. If it
213 * is zero, then the soft clock is not synced, and the battery
214 * clock is simply left to rot. That means that when the system
215 * reboots, the battery clock (which has probably gone wacky)
216 * sets the soft clock. That means ntpd starts off with a very
217 * confused idea of what time it is. It then takes a large
218 * amount of time to figure out just how wacky the battery clock
219 * has made things drift, etc, etc. The solution is to make the
220 * battery clock sync up to system time. The way to do THAT is
221 * to simply set the time of day to the current time of day, but
222 * as quickly as possible. This may, or may not be a sensible
223 * thing to do.
225 * CAVEAT: settimeofday() steps the sun clock by about 800 us,
226 * so setting DOSYNCTODR seems a bad idea in the
227 * case of us resolution
230 #if !defined(VMS)
232 * (prr) getpriority returns -1 on error, but -1 is also a valid
233 * return value (!), so instead we have to zero errno before the
234 * call and check it for non-zero afterwards.
236 errno = 0;
237 prio_set = 0;
238 o_prio = getpriority(PRIO_PROCESS,0); /* Save setting */
241 * (prr) if getpriority succeeded, call setpriority to raise
242 * scheduling priority as high as possible. If that succeeds
243 * as well, set the prio_set flag so we remember to reset
244 * priority to its previous value below. Note that on Solaris
245 * 2.6 (and beyond?), both getpriority and setpriority will fail
246 * with ESRCH, because sched_setscheduler (called from main) put
247 * us in the real-time scheduling class which setpriority
248 * doesn't know about. Being in the real-time class is better
249 * than anything setpriority can do, anyhow, so this error is
250 * silently ignored.
252 if ((errno == 0) && (setpriority(PRIO_PROCESS,0,-20) == 0))
253 prio_set = 1; /* overdrive */
254 #endif /* VMS */
255 #ifdef HAVE_GETCLOCK
256 (void) getclock(TIMEOFDAY, &ts);
257 tv.tv_sec = ts.tv_sec;
258 tv.tv_usec = ts.tv_nsec / 1000;
259 #else /* not HAVE_GETCLOCK */
260 GETTIMEOFDAY(&tv,(struct timezone *)NULL);
261 #endif /* not HAVE_GETCLOCK */
262 if (ntp_set_tod(&tv,(struct timezone *)NULL) != 0)
263 msyslog(LOG_ERR, "can't sync battery time: %m");
264 #if !defined(VMS)
265 if (prio_set)
266 setpriority(PRIO_PROCESS, 0, o_prio); /* downshift */
267 #endif /* VMS */
268 #endif /* DOSYNCTODR */
269 record_sys_stats();
270 ftemp = fabs(prev_drift_comp - drift_comp);
271 prev_drift_comp = drift_comp;
272 if (ftemp > clock_phi)
273 return;
275 if (stats_drift_file != 0 && drift_file_sw) {
278 * When the frequency file is written, initialize the
279 * wander threshold to a configured initial value.
280 * Thereafter reduce it by a factor of 0.5. When it
281 * drops below the frequency wander, write the frequency
282 * file. This adapts to the prevailing wander yet
283 * minimizes the file writes.
285 drift_file_sw = FALSE;
286 wander_resid *= 0.5;
287 #ifdef DEBUG
288 if (debug)
289 printf("write_stats: wander %.6lf thresh %.6lf, freq %.6lf\n",
290 clock_stability * 1e6, wander_resid * 1e6,
291 drift_comp * 1e6);
292 #endif
293 if (sys_leap != LEAP_NOTINSYNC && clock_stability >
294 wander_resid) {
295 wander_resid = wander_threshold;
296 if ((fp = fopen(stats_temp_file, "w")) == NULL)
298 msyslog(LOG_ERR,
299 "frequency file %s: %m",
300 stats_temp_file);
301 return;
303 fprintf(fp, "%.3f\n", drift_comp * 1e6);
304 (void)fclose(fp);
305 /* atomic */
306 #ifdef SYS_WINNT
307 if (_unlink(stats_drift_file)) /* rename semantics differ under NT */
308 msyslog(LOG_WARNING,
309 "Unable to remove prior drift file %s, %m",
310 stats_drift_file);
311 #endif /* SYS_WINNT */
313 #ifndef NO_RENAME
314 if (rename(stats_temp_file, stats_drift_file))
315 msyslog(LOG_WARNING,
316 "Unable to rename temp drift file %s to %s, %m",
317 stats_temp_file, stats_drift_file);
318 #else
319 /* we have no rename NFS of ftp in use */
320 if ((fp = fopen(stats_drift_file, "w")) ==
321 NULL) {
322 msyslog(LOG_ERR,
323 "frequency file %s: %m",
324 stats_drift_file);
325 return;
327 #endif
329 #if defined(VMS)
330 /* PURGE */
332 $DESCRIPTOR(oldvers,";-1");
333 struct dsc$descriptor driftdsc = {
334 strlen(stats_drift_file), 0, 0,
335 stats_drift_file };
336 while(lib$delete_file(&oldvers,
337 &driftdsc) & 1);
339 #endif
340 } else {
341 /* XXX: Log a message at INFO level */
348 * stats_config - configure the stats operation
350 void
351 stats_config(
352 int item,
353 const char *invalue /* only one type so far */
356 FILE *fp;
357 const char *value;
358 int len;
359 char tbuf[80];
360 char str1[20], str2[20];
363 * Expand environment strings under Windows NT, since the
364 * command interpreter doesn't do this, the program must.
366 #ifdef SYS_WINNT
367 char newvalue[MAX_PATH], parameter[MAX_PATH];
369 if (!ExpandEnvironmentStrings(invalue, newvalue, MAX_PATH)) {
370 switch(item) {
371 case STATS_FREQ_FILE:
372 strcpy(parameter,"STATS_FREQ_FILE");
373 break;
375 case STATS_LEAP_FILE:
376 strcpy(parameter,"STATS_LEAP_FILE");
377 break;
379 case STATS_STATSDIR:
380 strcpy(parameter,"STATS_STATSDIR");
381 break;
383 case STATS_PID_FILE:
384 strcpy(parameter,"STATS_PID_FILE");
385 break;
387 default:
388 strcpy(parameter,"UNKNOWN");
389 break;
391 value = invalue;
392 msyslog(LOG_ERR,
393 "ExpandEnvironmentStrings(%s) failed: %m\n",
394 parameter);
395 } else {
396 value = newvalue;
398 #else
399 value = invalue;
400 #endif /* SYS_WINNT */
402 switch(item) {
405 * Open and read frequency file.
407 case STATS_FREQ_FILE:
408 if (!value || (len = strlen(value)) == 0)
409 break;
411 stats_drift_file = erealloc(stats_drift_file, len + 1);
412 stats_temp_file = erealloc(stats_temp_file,
413 len + sizeof(".TEMP"));
415 memmove(stats_drift_file, value, (unsigned)(len+1));
416 memmove(stats_temp_file, value, (unsigned)len);
417 memmove(stats_temp_file + len,
418 #if !defined(VMS)
419 ".TEMP", sizeof(".TEMP"));
420 #else
421 "-TEMP", sizeof("-TEMP"));
422 #endif /* VMS */
425 * Open drift file and read frequency. If the file is
426 * missing or contains errors, tell the loop to reset.
428 if ((fp = fopen(stats_drift_file, "r")) == NULL)
429 break;
431 if (fscanf(fp, "%lf", &old_drift) != 1) {
432 msyslog(LOG_ERR,
433 "format error frequency file %s",
434 stats_drift_file);
435 fclose(fp);
436 break;
439 fclose(fp);
440 old_drift /= 1e6;
441 prev_drift_comp = old_drift;
442 break;
445 * Specify statistics directory.
447 case STATS_STATSDIR:
450 * HMS: the following test is insufficient:
451 * - value may be missing the DIR_SEP
452 * - we still need the filename after it
454 if (strlen(value) >= sizeof(statsdir)) {
455 msyslog(LOG_ERR,
456 "statsdir too long (>%d, sigh)",
457 (int)sizeof(statsdir) - 1);
458 } else {
459 l_fp now;
460 int add_dir_sep;
461 int value_l = strlen(value);
463 /* Add a DIR_SEP unless we already have one. */
464 if (value_l == 0)
465 add_dir_sep = 0;
466 else
467 add_dir_sep = (DIR_SEP !=
468 value[value_l - 1]);
470 if (add_dir_sep)
471 snprintf(statsdir, sizeof(statsdir),
472 "%s%c", value, DIR_SEP);
473 else
474 snprintf(statsdir, sizeof(statsdir),
475 "%s", value);
477 get_systime(&now);
478 if(peerstats.prefix == &statsdir[0] &&
479 peerstats.fp != NULL) {
480 fclose(peerstats.fp);
481 peerstats.fp = NULL;
482 filegen_setup(&peerstats, now.l_ui);
484 if(loopstats.prefix == &statsdir[0] &&
485 loopstats.fp != NULL) {
486 fclose(loopstats.fp);
487 loopstats.fp = NULL;
488 filegen_setup(&loopstats, now.l_ui);
490 if(clockstats.prefix == &statsdir[0] &&
491 clockstats.fp != NULL) {
492 fclose(clockstats.fp);
493 clockstats.fp = NULL;
494 filegen_setup(&clockstats, now.l_ui);
496 if(rawstats.prefix == &statsdir[0] &&
497 rawstats.fp != NULL) {
498 fclose(rawstats.fp);
499 rawstats.fp = NULL;
500 filegen_setup(&rawstats, now.l_ui);
502 if(sysstats.prefix == &statsdir[0] &&
503 sysstats.fp != NULL) {
504 fclose(sysstats.fp);
505 sysstats.fp = NULL;
506 filegen_setup(&sysstats, now.l_ui);
508 if(protostats.prefix == &statsdir[0] &&
509 protostats.fp != NULL) {
510 fclose(protostats.fp);
511 protostats.fp = NULL;
512 filegen_setup(&protostats, now.l_ui);
514 #ifdef OPENSSL
515 if(cryptostats.prefix == &statsdir[0] &&
516 cryptostats.fp != NULL) {
517 fclose(cryptostats.fp);
518 cryptostats.fp = NULL;
519 filegen_setup(&cryptostats, now.l_ui);
521 #endif /* OPENSSL */
522 #ifdef DEBUG_TIMING
523 if(timingstats.prefix == &statsdir[0] &&
524 timingstats.fp != NULL) {
525 fclose(timingstats.fp);
526 timingstats.fp = NULL;
527 filegen_setup(&timingstats, now.l_ui);
529 #endif /* DEBUG_TIMING */
531 break;
534 * Open pid file.
536 case STATS_PID_FILE:
537 if ((fp = fopen(value, "w")) == NULL) {
538 msyslog(LOG_ERR, "pid file %s: %m",
539 value);
540 break;
542 fprintf(fp, "%d", (int)getpid());
543 fclose(fp);;
544 break;
547 * Read leapseconds file.
549 case STATS_LEAP_FILE:
550 if ((fp = fopen(value, "r")) == NULL) {
551 msyslog(LOG_ERR, "leapseconds file %s: %m",
552 value);
553 break;
556 if (leap_file(fp) < 0) {
557 msyslog(LOG_ERR,
558 "format error leapseconds file %s",
559 value);
560 } else {
561 strcpy(str1, fstostr(leap_sec));
562 strcpy(str2, fstostr(leap_expire));
563 snprintf(tbuf, sizeof(tbuf),
564 "%d leap %s expire %s", leap_tai, str1,
565 str2);
566 report_event(EVNT_TAI, NULL, tbuf);
568 fclose(fp);
569 break;
571 default:
572 /* oh well */
573 break;
579 * record_peer_stats - write peer statistics to file
581 * file format:
582 * day (MJD)
583 * time (s past UTC midnight)
584 * IP address
585 * status word (hex)
586 * offset
587 * delay
588 * dispersion
589 * jitter
591 void
592 record_peer_stats(
593 sockaddr_u *addr,
594 int status,
595 double offset, /* offset */
596 double delay, /* delay */
597 double dispersion, /* dispersion */
598 double jitter /* jitter */
601 l_fp now;
602 u_long day;
604 if (!stats_control)
605 return;
607 get_systime(&now);
608 filegen_setup(&peerstats, now.l_ui);
609 day = now.l_ui / 86400 + MJD_1900;
610 now.l_ui %= 86400;
611 if (peerstats.fp != NULL) {
612 fprintf(peerstats.fp,
613 "%lu %s %s %x %.9f %.9f %.9f %.9f\n", day,
614 ulfptoa(&now, 3), stoa(addr), status, offset,
615 delay, dispersion, jitter);
616 fflush(peerstats.fp);
622 * record_loop_stats - write loop filter statistics to file
624 * file format:
625 * day (MJD)
626 * time (s past midnight)
627 * offset
628 * frequency (PPM)
629 * jitter
630 * wnder (PPM)
631 * time constant (log2)
633 void
634 record_loop_stats(
635 double offset, /* offset */
636 double freq, /* frequency (PPM) */
637 double jitter, /* jitter */
638 double wander, /* wander (PPM) */
639 int spoll
642 l_fp now;
643 u_long day;
645 if (!stats_control)
646 return;
648 get_systime(&now);
649 filegen_setup(&loopstats, now.l_ui);
650 day = now.l_ui / 86400 + MJD_1900;
651 now.l_ui %= 86400;
652 if (loopstats.fp != NULL) {
653 fprintf(loopstats.fp, "%lu %s %.9f %.3f %.9f %.6f %d\n",
654 day, ulfptoa(&now, 3), offset, freq * 1e6, jitter,
655 wander * 1e6, spoll);
656 fflush(loopstats.fp);
662 * record_clock_stats - write clock statistics to file
664 * file format:
665 * day (MJD)
666 * time (s past midnight)
667 * IP address
668 * text message
670 void
671 record_clock_stats(
672 sockaddr_u *addr,
673 const char *text /* timecode string */
676 l_fp now;
677 u_long day;
679 if (!stats_control)
680 return;
682 get_systime(&now);
683 filegen_setup(&clockstats, now.l_ui);
684 day = now.l_ui / 86400 + MJD_1900;
685 now.l_ui %= 86400;
686 if (clockstats.fp != NULL) {
687 fprintf(clockstats.fp, "%lu %s %s %s\n", day,
688 ulfptoa(&now, 3), stoa(addr), text);
689 fflush(clockstats.fp);
695 * record_raw_stats - write raw timestamps to file
697 * file format
698 * day (MJD)
699 * time (s past midnight)
700 * peer ip address
701 * IP address
702 * t1 t2 t3 t4 timestamps
704 void
705 record_raw_stats(
706 sockaddr_u *srcadr,
707 sockaddr_u *dstadr,
708 l_fp *t1, /* originate timestamp */
709 l_fp *t2, /* receive timestamp */
710 l_fp *t3, /* transmit timestamp */
711 l_fp *t4 /* destination timestamp */
714 l_fp now;
715 u_long day;
717 if (!stats_control)
718 return;
720 get_systime(&now);
721 filegen_setup(&rawstats, now.l_ui);
722 day = now.l_ui / 86400 + MJD_1900;
723 now.l_ui %= 86400;
724 if (rawstats.fp != NULL) {
725 fprintf(rawstats.fp, "%lu %s %s %s %s %s %s %s\n", day,
726 ulfptoa(&now, 3), stoa(srcadr), dstadr ?
727 stoa(dstadr) : "-", ulfptoa(t1, 9), ulfptoa(t2, 9),
728 ulfptoa(t3, 9), ulfptoa(t4, 9));
729 fflush(rawstats.fp);
735 * record_sys_stats - write system statistics to file
737 * file format
738 * day (MJD)
739 * time (s past midnight)
740 * time since reset
741 * packets recieved
742 * packets for this host
743 * current version
744 * old version
745 * access denied
746 * bad length or format
747 * bad authentication
748 * declined
749 * rate exceeded
750 * KoD sent
752 void
753 record_sys_stats(void)
755 l_fp now;
756 u_long day;
758 if (!stats_control)
759 return;
761 get_systime(&now);
762 filegen_setup(&sysstats, now.l_ui);
763 day = now.l_ui / 86400 + MJD_1900;
764 now.l_ui %= 86400;
765 if (sysstats.fp != NULL) {
766 fprintf(sysstats.fp,
767 "%lu %s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
768 day, ulfptoa(&now, 3), current_time - sys_stattime,
769 sys_received, sys_processed, sys_newversion,
770 sys_oldversion, sys_restricted, sys_badlength,
771 sys_badauth, sys_declined, sys_limitrejected,
772 sys_kodsent);
773 fflush(sysstats.fp);
774 proto_clr_stats();
780 * record_proto_stats - write system statistics to file
782 * file format
783 * day (MJD)
784 * time (s past midnight)
785 * text message
787 void
788 record_proto_stats(
789 char *str /* text string */
792 l_fp now;
793 u_long day;
795 if (!stats_control)
796 return;
798 get_systime(&now);
799 filegen_setup(&protostats, now.l_ui);
800 day = now.l_ui / 86400 + MJD_1900;
801 now.l_ui %= 86400;
802 if (protostats.fp != NULL) {
803 fprintf(protostats.fp, "%lu %s %s\n", day,
804 ulfptoa(&now, 3), str);
805 fflush(protostats.fp);
810 #ifdef OPENSSL
812 * record_crypto_stats - write crypto statistics to file
814 * file format:
815 * day (mjd)
816 * time (s past midnight)
817 * peer ip address
818 * text message
820 void
821 record_crypto_stats(
822 sockaddr_u *addr,
823 const char *text /* text message */
826 l_fp now;
827 u_long day;
829 if (!stats_control)
830 return;
832 get_systime(&now);
833 filegen_setup(&cryptostats, now.l_ui);
834 day = now.l_ui / 86400 + MJD_1900;
835 now.l_ui %= 86400;
836 if (cryptostats.fp != NULL) {
837 if (addr == NULL)
838 fprintf(cryptostats.fp, "%lu %s 0.0.0.0 %s\n",
839 day, ulfptoa(&now, 3), text);
840 else
841 fprintf(cryptostats.fp, "%lu %s %s %s\n",
842 day, ulfptoa(&now, 3), stoa(addr), text);
843 fflush(cryptostats.fp);
846 #endif /* OPENSSL */
849 #ifdef DEBUG_TIMING
851 * record_timing_stats - write timing statistics to file
853 * file format:
854 * day (mjd)
855 * time (s past midnight)
856 * text message
858 void
859 record_timing_stats(
860 const char *text /* text message */
863 static unsigned int flshcnt;
864 l_fp now;
865 u_long day;
867 if (!stats_control)
868 return;
870 get_systime(&now);
871 filegen_setup(&timingstats, now.l_ui);
872 day = now.l_ui / 86400 + MJD_1900;
873 now.l_ui %= 86400;
874 if (timingstats.fp != NULL) {
875 fprintf(timingstats.fp, "%lu %s %s\n", day, lfptoa(&now,
876 3), text);
877 if (++flshcnt % 100 == 0)
878 fflush(timingstats.fp);
881 #endif
885 * leap_file - read leapseconds file
887 * Read the ERTS leapsecond file in NIST text format and extract the
888 * NTP seconds of the latest leap and TAI offset after the leap.
890 static int
891 leap_file(
892 FILE *fp /* file handle */
895 char buf[NTP_MAXSTRLEN]; /* file line buffer */
896 u_long leap; /* NTP time at leap */
897 u_long expire; /* NTP time when file expires */
898 int offset; /* TAI offset at leap (s) */
899 int i;
902 * Read and parse the leapseconds file. Empty lines and comments
903 * are ignored. A line beginning with #@ contains the file
904 * expiration time in NTP seconds. Other lines begin with two
905 * integers followed by junk or comments. The first integer is
906 * the NTP seconds at the leap, the second is the TAI offset
907 * after the leap.
909 offset = 0;
910 leap = 0;
911 expire = 0;
912 i = 10;
913 while (fgets(buf, NTP_MAXSTRLEN - 1, fp) != NULL) {
914 if (strlen(buf) < 1)
915 continue;
917 if (buf[0] == '#') {
918 if (strlen(buf) < 3)
919 continue;
922 * Note the '@' flag was used only in the 2006
923 * table; previious to that the flag was '$'.
925 if (buf[1] == '@' || buf[1] == '$') {
926 if (sscanf(&buf[2], "%lu", &expire) !=
928 return (-1);
930 continue;
933 if (sscanf(buf, "%lu %d", &leap, &offset) == 2) {
936 * Valid offsets must increase by one for each
937 * leap.
939 if (i++ != offset)
940 return (-1);
945 * There must be at least one leap.
947 if (i == 10)
948 return (-1);
950 leap_tai = offset;
951 leap_sec = leap;
952 leap_expire = expire;
953 return (0);
958 * leap_month - returns seconds until the end of the month.
960 u_long
961 leap_month(
962 u_long sec /* current NTP second */
965 u_long ltemp;
966 u_long *ptr;
967 u_long year[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30,
968 31};
969 u_long lyear[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30,
970 31};
973 * Find current leap cycle.
975 ltemp = sec;
976 while (ltemp >= L_CENT)
977 ltemp -= L_CENT;
978 while (ltemp >= L_4YEAR)
979 ltemp -= L_4YEAR;
982 * We are within four years of the target. If in leap year, use
983 * leap year month table; otherwise, use year month table.
985 if (ltemp < L_LYEAR) {
986 ptr = lyear;
987 } else {
988 ptr = year;
989 ltemp -= L_LYEAR;
990 while (ltemp >= L_YEAR)
991 ltemp -= L_YEAR;
995 * We are within one year of the target. Find the month of the
996 * leap.
998 while (ltemp >= *ptr * L_DAY)
999 ltemp -= *ptr++ * L_DAY;
1002 * The result is the number of seconds until the end of the
1003 * month when the leap is to occur.
1005 return (*ptr * L_DAY - ltemp - L_DAY);
1010 * getauthkeys - read the authentication keys from the specified file
1012 void
1013 getauthkeys(
1014 const char *keyfile
1017 int len;
1019 len = strlen(keyfile);
1020 if (!len)
1021 return;
1023 #ifndef SYS_WINNT
1024 key_file_name = erealloc(key_file_name, len + 1);
1025 memmove(key_file_name, keyfile, len + 1);
1026 #else
1027 key_file_name = erealloc(key_file_name, _MAX_PATH);
1028 if (len + 1 > _MAX_PATH)
1029 return;
1030 if (!ExpandEnvironmentStrings(keyfile, key_file_name,
1031 _MAX_PATH)) {
1032 msyslog(LOG_ERR,
1033 "ExpandEnvironmentStrings(KEY_FILE) failed: %m");
1034 strncpy(key_file_name, keyfile, _MAX_PATH);
1036 #endif /* SYS_WINNT */
1038 authreadkeys(key_file_name);
1043 * rereadkeys - read the authentication key file over again.
1045 void
1046 rereadkeys(void)
1048 if (NULL != key_file_name)
1049 authreadkeys(key_file_name);
1054 * sock_hash - hash a sockaddr_u structure
1056 u_short
1057 sock_hash(
1058 sockaddr_u *addr
1061 u_int hashVal;
1062 u_int j;
1063 size_t len;
1064 u_char *pch;
1065 hashVal = 0;
1066 len = 0;
1069 * We can't just hash the whole thing because there are hidden
1070 * fields in sockaddr_in6 that might be filled in by recvfrom(),
1071 * so just use the family, port and address.
1073 pch = (u_char *)&AF(addr);
1074 hashVal = 37 * hashVal + *pch;
1075 if (sizeof(AF(addr)) > 1) {
1076 pch++;
1077 hashVal = 37 * hashVal + *pch;
1079 switch(AF(addr)) {
1080 case AF_INET:
1081 pch = (u_char *)&SOCK_ADDR4(addr);
1082 len = sizeof(SOCK_ADDR4(addr));
1083 break;
1085 case AF_INET6:
1086 pch = (u_char *)&SOCK_ADDR6(addr);
1087 len = sizeof(SOCK_ADDR6(addr));
1088 break;
1091 for (j = 0; j < len ; j++)
1092 hashVal = 37 * hashVal + pch[j];
1094 hashVal = hashVal & NTP_HASH_MASK;
1096 return (u_short)hashVal;
1100 #if notyet
1102 * ntp_exit - document explicitly that ntpd has exited
1104 void
1105 ntp_exit(int retval)
1107 msyslog(LOG_ERR, "EXITING with return code %d", retval);
1108 exit(retval);
1110 #endif
1113 * fstostr - prettyprint NTP seconds
1115 char * fstostr(
1116 time_t ntp_stamp
1119 static char str[20];
1120 struct tm * tm;
1121 time_t unix_stamp;
1123 unix_stamp = ntp_stamp - JAN_1970;
1124 tm = gmtime(&unix_stamp);
1125 if (NULL != tm)
1126 snprintf(str, sizeof(str),
1127 "%04d%02d%02d%02d%02d",
1128 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
1129 tm->tm_hour, tm->tm_min);
1130 else
1131 strcpy(str, "gmtime() error");
1133 return str;