1: /*
2: * ntptimeset - get/set the time via ntp
3: *
4: * GOAL:
5: * The goal of ntptime is to set the current time on system startup
6: * to the best possible time using the network very wisely. It is assumed
7: * that after a resonable time has been sett then ntp daemon will
8: * maintain it.
9: *
10: * PROBLEM DOMAIN:
11: * We have three sets of issues related to acheiving the goal. The first
12: * issue is using the network when normal traffic is happening or when
13: * the entire network world is recovering from a campus wide power failure
14: * and is restarting. The second issue is the class of machine whether it
15: * is a user's office workstation being handled by an uneducated user or
16: * a server computer being handled by a trained operations staff. The third
17: * issue is whether the ratio of people to computers and whether the
18: * environment is stable and viable or not.
19: *
20: * NETWORK USAGE:
21: * The first issue of using the network wisely is a question of whether
22: * the network load and time server load and state are normal. If things
23: * are normal ntptime can do what ntpdate does of sending out 4 packets
24: * quickly to each server (new transmit done with each ack). However
25: * if network or time load is high then this scheme will simply contribute
26: * to problems. Given we have minimal state, we simply weight lost packets
27: * significantly and make sure we throttle output as much as possible
28: * without performance lost for quick startups.
29: *
30: * TRAINING AND KNOWLEDGE:
31: * The second issue of uneducated user of a office workstation versus a
32: * trained operation staff of a server machine translates into simply an
33: * issue of untrained and trained users.
34: *
35: * The training issue implies that for the sake of the users involved in the
36: * handling of their office workstation, problems and options should be
37: * communicated simply and effectively and not in terse expert related
38: * descriptions without possible options to be taken. The operator's training
39: * and education enables them to deal with either type of communication and
40: * control.
41: *
42: * AUTOMATION AND MANUAL CONTROL:
43: * The last issue boils down to a design problem. If the design tends to go
44: * into a manual mode when the environment is non-viable then one person
45: * handling many computers all at the same time will be heavily impacted. On
46: * the other hand, if the design tends to be automatic and does not indicate
47: * a way for the user to take over control then the computer will be
48: * unavailable for the user until the proble is resolved by someone else or
49: * the user.
50: *
51: * NOTE: Please do not have this program print out every minute some line,
52: * of output. If this happens and the environment is in trouble then
53: * many pages of paper on many different machines will be filled up.
54: * Save some tress in your lifetime.
55: *
56: * CONCLUSION:
57: * The behavior of the program derived from these three issues should be
58: * that during normal situations it quickly sets the time and allow the
59: * system to startup.
60: *
61: * However during abnormal conditions as detected by unresponsive servers,
62: * out-of-sync or bad responses and other detections, it should print out
63: * a simple but clear message and continue in a mellow way to get the best
64: * possible time. It may never get the time and if so should also indicate
65: * this.
66: *
67: * Rudy Nedved
68: * 18-May-1993
69: *
70: ****************************************************************
71: *
72: * Much of the above is confusing or no longer relevant. For example,
73: * it is rare these days for a machine's console to be a printing terminal,
74: * so the comment about saving trees doesn't mean much. Nonetheless,
75: * the basic principles still stand:
76: *
77: * - Work automatically, without human control or intervention. To
78: * this end, we use the same configuration file as ntpd itself, so
79: * you don't have to specify servers or other information on the
80: * command line. We also recognize that sometimes we won't be able
81: * to contact any servers, and give up in that event instead of
82: * hanging forever.
83: *
84: * - Behave in a sane way, both internally and externally, even in the
85: * face of insane conditions. That means we back off quickly when
86: * we don't hear a response, to avoid network congestion. Like
87: * ntpd, we verify responses from several servers before accepting
88: * the new time data.
89: *
90: * However, we don't assume that the local clock is right, or even
91: * close, because it might not be at boot time, and we want to catch
92: * and correct that situation. This behaviour has saved us in several
93: * instances. On HP-UX 9.0x, there used to be a bug in adjtimed which
94: * would cause the time to be set to some wild value, making the machine
95: * essentially unusable (we use Kerberos authentication pervasively,
96: * and it requires workstations and servers to have a time within five
97: * minutes of the Kerberos server). We also have problems on PC's
98: * running both Linux and some Microsoft OS -- they tend to disagree
99: * on what the BIOS clock should say, and who should update it, and
100: * when. On those systems, we not only run ntptimeset at boot, we
101: * also reset the BIOS clock based on the result, so the correct
102: * time will be retained across reboots.
103: *
104: * For these reasons, and others, we have continued to use this tool
105: * rather than ntpdate. It is run automatically at boot time on every
106: * workstation and server in our facility.
107: *
108: * In the past, we called this program 'ntptime'. Unfortunately, the
109: * ntp v4 distribution also includes a program with that name. In
110: * order to avoid confusion, we have renamed our program 'ntptimeset',
111: * which more accurately describes what it does.
112: *
113: * Jeffrey T. Hutzelman (N3NHS) <jhutz+@cmu.edu>
114: * School of Computer Science - Research Computing Facility
115: * Carnegie Mellon University - Pittsburgh, PA
116: * 16-Aug-1999
117: *
118: */
119:
120: #ifdef HAVE_CONFIG_H
121: # include <config.h>
122: #endif
123:
124: #include "ntp_machine.h"
125: #include "ntp_fp.h"
126: #include "ntp.h"
127: #include "ntp_io.h"
128: #include "iosignal.h"
129: #include "ntp_unixtime.h"
130: #include "ntpdate.h"
131: #include "ntp_string.h"
132: #include "ntp_syslog.h"
133: #include "ntp_select.h"
134: #include "ntp_stdlib.h"
135:
136: #ifdef HAVE_UNISTD_H
137: # include <unistd.h>
138: #endif
139:
140: #include <stdio.h>
141: #include <signal.h>
142: #include <ctype.h>
143: #ifndef SYS_WINNT
144: # ifdef HAVE_SYS_SIGNAL_H
145: # include <sys/signal.h>
146: # else
147: # include <signal.h>
148: # endif
149: # include <sys/ioctl.h>
150: #endif /* SYS_WINNT */
151:
152: #ifdef HAVE_SYS_RESOURCE_H
153: # include <sys/resource.h>
154: #endif /* HAVE_SYS_RESOURCE_H */
155:
156: #ifdef SYS_VXWORKS
157: # include "ioLib.h"
158: # include "sockLib.h"
159: # include "timers.h"
160: #endif
161:
162: #include "recvbuff.h"
163:
164: #ifdef SYS_WINNT
165: # define TARGET_RESOLUTION 1 /* Try for 1-millisecond accuracy
166: on Windows NT timers. */
167: #pragma comment(lib, "winmm")
168: #endif /* SYS_WINNT */
169:
170: /*
171: * Scheduling priority we run at
172: */
173: #ifndef SYS_VXWORKS
174: # define NTPDATE_PRIO (-12)
175: #else
176: # define NTPDATE_PRIO (100)
177: #endif
178:
179: #if defined(HAVE_TIMER_SETTIME) || defined (HAVE_TIMER_CREATE)
180: /* POSIX TIMERS - vxWorks doesn't have itimer - casey */
181: static timer_t ntpdate_timerid;
182: #endif
183:
184: /*
185: * Compatibility stuff for Version 2
186: */
187: #define NTP_MAXSKW 0x28f /* 0.01 sec in fp format */
188: #define NTP_MINDIST 0x51f /* 0.02 sec in fp format */
189: #define NTP_INFIN 15 /* max stratum, infinity a la Bellman-Ford */
190: #define NTP_MAXWGT (8*FP_SECOND) /* maximum select weight 8 seconds */
191: #define NTP_MAXLIST 5 /* maximum select list size */
192: #define PEER_SHIFT 8 /* 8 suitable for crystal time base */
193:
194: /*
195: * Debugging flag
196: */
197: volatile int debug = 0;
198:
199: /*
200: * File descriptor masks etc. for call to select
201: */
202: int fd;
203: fd_set fdmask;
204:
205: /*
206: * Initializing flag. All async routines watch this and only do their
207: * thing when it is clear.
208: */
209: int initializing = 1;
210:
211: /*
212: * Alarm flag. Set when an alarm occurs
213: */
214: volatile int alarm_flag = 0;
215:
216: /*
217: * Set the time if valid time determined
218: */
219: int set_time = 0;
220:
221: /*
222: * transmission rate control
223: */
224: #define MINTRANSMITS (3) /* minimum total packets per server */
225: #define MAXXMITCOUNT (2) /* maximum packets per time interrupt */
226:
227: /*
228: * time setting constraints
229: */
230: #define DESIREDDISP (4*FP_SECOND) /* desired dispersion, (fp 4) */
231: int max_period = DEFMAXPERIOD;
232: int min_servers = DEFMINSERVERS;
233: int min_valid = DEFMINVALID;
234:
235: /*
236: * counters related to time setting constraints
237: */
238: int contacted = 0; /* # of servers we have sent to */
239: int responding = 0; /* servers responding */
240: int validcount = 0; /* servers with valid time */
241: int valid_n_low = 0; /* valid time servers with low dispersion */
242:
243: /*
244: * Unpriviledged port flag.
245: */
246: int unpriv_port = 0;
247:
248: /*
249: * Program name.
250: */
251: char *progname;
252:
253: /*
254: * Systemwide parameters and flags
255: */
256: struct server **sys_servers; /* the server list */
257: int sys_numservers = 0; /* number of servers to poll */
258: int sys_authenticate = 0; /* true when authenticating */
259: u_int32 sys_authkey = 0; /* set to authentication key in use */
260: u_long sys_authdelay = 0; /* authentication delay */
261:
262: /*
263: * The current internal time
264: */
265: u_long current_time = 0;
266:
267: /*
268: * File of encryption keys
269: */
270:
271: #ifndef KEYFILE
272: # ifndef SYS_WINNT
273: #define KEYFILE "/etc/ntp.keys"
274: # else
275: #define KEYFILE "%windir%\\ntp.keys"
276: # endif /* SYS_WINNT */
277: #endif /* KEYFILE */
278:
279: #ifndef SYS_WINNT
280: const char *key_file = KEYFILE;
281: #else
282: char key_file_storage[MAX_PATH+1], *key_file ;
283: #endif /* SYS_WINNT */
284:
285: /*
286: * total packet counts
287: */
288: u_long total_xmit = 0;
289: u_long total_recv = 0;
290:
291: /*
292: * Miscellaneous flags
293: */
294: int verbose = 0;
295: #define HORRIBLEOK 3 /* how many packets to let out */
296: int horrible = 0; /* how many packets we drop for testing */
297: int secondhalf = 0; /* second half of timeout period */
298: int printmsg = 0; /* print time response analysis */
299:
300: /*
301: * The half time and finish time in internal time
302: */
303: u_long half_time = 0;
304: u_long finish_time = 0;
305:
306:
307: int ntptimesetmain P((int argc, char *argv[]));
308: static void analysis P((int final));
309: static int have_enough P((void));
310: static void transmit P((register struct server *server));
311: static void receive P((struct recvbuf *rbufp));
312: static void clock_filter P((register struct server *server, s_fp d, l_fp *c));
313: static void clock_count P((void));
314: static struct server *clock_select P((void));
315: static void set_local_clock P((void));
316: static struct server *findserver P((struct sockaddr_in *addr));
317: static void timer P((void));
318: #ifndef SYS_WINNT
319: static RETSIGTYPE alarming P((int sig));
320: #endif /* SYS_WINNT */
321: static void init_alarm P((void));
322: static void init_io P((void));
323: static int sendpkt P((struct sockaddr_in *dest, struct pkt *pkt, int len));
324: void input_handler P((l_fp *xts));
325: static void printserver P((register struct server *pp, FILE *fp));
326: #if !defined(HAVE_VSPRINTF)
327: int vsprintf P((char *str, const char *fmt, va_list ap));
328: #endif
329:
330: #ifdef HAVE_SIGNALED_IO
331: extern void wait_for_signal P((void));
332: extern void unblock_io_and_alarm P((void));
333: extern void block_io_and_alarm P((void));
334: #endif
335:
336:
337: #ifdef NO_MAIN_ALLOWED
338: CALL(ntptimeset,"ntptimeset",ntptimesetmain);
339:
340: void clear_globals()
341: {
342: /*
343: * Debugging flag
344: */
345: debug = 0;
346:
347: ntp_optind = 0;
348:
349: /*
350: * Initializing flag. All async routines watch this and only do their
351: * thing when it is clear.
352: */
353: initializing = 1;
354:
355: /*
356: * Alarm flag. Set when an alarm occurs
357: */
358: alarm_flag = 0;
359:
360: /*
361: * Unpriviledged port flag.
362: */
363: unpriv_port = 0;
364:
365: /*
366: * Systemwide parameters and flags
367: */
368: sys_numservers = 0; /* number of servers to poll */
369: sys_authenticate = 0; /* true when authenticating */
370: sys_authkey = 0; /* set to authentication key in use */
371: sys_authdelay = 0; /* authentication delay */
372:
373: /*
374: * The current internal time
375: */
376: current_time = 0;
377:
378: verbose = 0;
379: }
380: #endif /* NO_MAIN_ALLOWED */
381:
382: /*
383: * Main program. Initialize us and loop waiting for I/O and/or
384: * timer expiries.
385: */
386: #ifndef NO_MAIN_ALLOWED
387: int
388: main(
389: int argc,
390: char *argv[]
391: )
392: {
393: return ntptimesetmain(argc, argv);
394: }
395: #endif /* NO_MAIN_ALLOWED */
396:
397:
398: int
399: ntptimesetmain(
400: int argc,
401: char *argv[]
402: )
403: {
404: int was_alarmed;
405: int tot_recvbufs;
406: struct recvbuf *rbuf;
407: l_fp tmp;
408: int errflg;
409: int c;
410: extern char *ntp_optarg;
411: extern int ntp_optind;
412: int ltmp;
413: char *cfgpath;
414:
415: #ifdef SYS_WINNT
416: HANDLE process_handle;
417:
418: wVersionRequested = MAKEWORD(1,1);
419: if (WSAStartup(wVersionRequested, &wsaData)) {
420: msyslog(LOG_ERR, "No useable winsock.dll: %m");
421: exit(1);
422: }
423: #endif /* SYS_WINNT */
424:
425: #ifdef NO_MAIN_ALLOWED
426: clear_globals();
427: #endif
428:
429: errflg = 0;
430: cfgpath = 0;
431: progname = argv[0];
432: syslogit = 0;
433:
434: /*
435: * Decode argument list
436: */
437: while ((c = ntp_getopt(argc, argv, "a:c:de:slt:uvHS:V:")) != EOF)
438: switch (c)
439: {
440: case 'a':
441: c = atoi(ntp_optarg);
442: sys_authenticate = 1;
443: sys_authkey = c;
444: break;
445: case 'c':
446: cfgpath = ntp_optarg;
447: break;
448: case 'd':
449: ++debug;
450: break;
451: case 'e':
452: if (!atolfp(ntp_optarg, &tmp)
453: || tmp.l_ui != 0) {
454: (void) fprintf(stderr,
455: "%s: encryption delay %s is unlikely\n",
456: progname, ntp_optarg);
457: errflg++;
458: } else {
459: sys_authdelay = tmp.l_uf;
460: }
461: break;
462: case 's':
463: set_time = 1;
464: break;
465: case 'l':
466: syslogit = 1;
467: break;
468: case 't':
469: ltmp = atoi(ntp_optarg);
470: if (ltmp <= 0) {
471: (void) fprintf(stderr,
472: "%s: maximum time period (%d) is invalid\n",
473: progname, ltmp);
474: errflg++;
475: }
476: else
477: max_period = ltmp;
478: break;
479: case 'u':
480: unpriv_port = 1;
481: break;
482: case 'v':
483: ++verbose;
484: break;
485: case 'H':
486: horrible++;
487: break;
488: case 'S':
489: ltmp = atoi(ntp_optarg);
490: if (ltmp <= 0) {
491: (void) fprintf(stderr,
492: "%s: minimum responding (%d) is invalid\n",
493: progname, ltmp);
494: errflg++;
495: }
496: else
497: min_servers = ltmp;
498: break;
499: case 'V':
500: ltmp = atoi(ntp_optarg);
501: if (ltmp <= 0) {
502: (void) fprintf(stderr,
503: "%s: minimum valid (%d) is invalid\n",
504: progname, ltmp);
505: errflg++;
506: }
507: else
508: min_valid = ltmp;
509: break;
510: case '?':
511: ++errflg;
512: break;
513: default:
514: break;
515: }
516:
517:
518: if (errflg || ntp_optind < argc) {
519: fprintf(stderr,"usage: %s [switches...]\n",progname);
520: fprintf(stderr," -v (verbose)\n");
521: fprintf(stderr," -c path (set config file path)\n");
522: fprintf(stderr," -a key (authenticate using key)\n");
523: fprintf(stderr," -e delay (authentication delay)\n");
524: fprintf(stderr," -S num (# of servers that must respond)\n");
525: fprintf(stderr," -V num (# of servers that must valid)\n");
526: fprintf(stderr," -s (set the time based if okay)\n");
527: fprintf(stderr," -t secs (time period before ending)\n");
528: fprintf(stderr," -l (use syslog facility)\n");
529: fprintf(stderr," -u (use unprivileged port)\n");
530: fprintf(stderr," -H (drop packets for debugging)\n");
531: fprintf(stderr," -d (debug output)\n");
532: exit(2);
533: }
534:
535: /*
536: * Logging. Open the syslog if we have to
537: */
538: if (syslogit) {
539: #if !defined (SYS_WINNT) && !defined (SYS_VXWORKS) && !defined SYS_CYGWIN32
540: # ifndef LOG_DAEMON
541: openlog("ntptimeset", LOG_PID);
542: # else
543:
544: # ifndef LOG_NTP
545: # define LOG_NTP LOG_DAEMON
546: # endif
547: openlog("ntptimeset", LOG_PID | LOG_NDELAY, LOG_NTP);
548: if (debug)
549: setlogmask(LOG_UPTO(LOG_DEBUG));
550: else
551: setlogmask(LOG_UPTO(LOG_INFO));
552: # endif /* LOG_DAEMON */
553: #endif /* SYS_WINNT */
554: }
555:
556: if (debug || verbose)
557: msyslog(LOG_INFO, "%s", Version);
558:
559: if (horrible)
560: msyslog(LOG_INFO, "Dropping %d out of %d packets",
561: horrible,horrible+HORRIBLEOK);
562: /*
563: * Add servers we are going to be polling
564: */
565: loadservers(cfgpath);
566:
567: if (sys_numservers < min_servers) {
568: msyslog(LOG_ERR, "Found %d servers, require %d servers",
569: sys_numservers,min_servers);
570: exit(2);
571: }
572:
573: /*
574: * determine when we will end at least
575: */
576: finish_time = max_period * TIMER_HZ;
577: half_time = finish_time >> 1;
578:
579: /*
580: * Initialize the time of day routines and the I/O subsystem
581: */
582: if (sys_authenticate) {
583: init_auth();
584: #ifdef SYS_WINNT
585: if (!key_file) key_file = KEYFILE;
586: if (!ExpandEnvironmentStrings(key_file, key_file_storage, MAX_PATH))
587: {
588: msyslog(LOG_ERR, "ExpandEnvironmentStrings(%s) failed: %m\n",
589: key_file);
590: } else {
591: key_file = key_file_storage;
592: }
593: #endif /* SYS_WINNT */
594:
595: if (!authreadkeys(key_file)) {
596: msyslog(LOG_ERR, "no key file, exiting");
597: exit(1);
598: }
599: if (!authistrusted(sys_authkey)) {
600: char buf[10];
601:
602: (void) sprintf(buf, "%lu", (unsigned long)sys_authkey);
603: msyslog(LOG_ERR, "authentication key %s unknown", buf);
604: exit(1);
605: }
606: }
607: init_io();
608: init_alarm();
609:
610: /*
611: * Set the priority.
612: */
613: #ifdef SYS_VXWORKS
614: taskPrioritySet( taskIdSelf(), NTPDATE_PRIO);
615: #endif
616: #if defined(HAVE_ATT_NICE)
617: nice (NTPDATE_PRIO);
618: #endif
619: #if defined(HAVE_BSD_NICE)
620: (void) setpriority(PRIO_PROCESS, 0, NTPDATE_PRIO);
621: #endif
622: #ifdef SYS_WINNT
623: process_handle = GetCurrentProcess();
624: if (!SetPriorityClass(process_handle, (DWORD) REALTIME_PRIORITY_CLASS)) {
625: msyslog(LOG_ERR, "SetPriorityClass failed: %m");
626: }
627: #endif /* SYS_WINNT */
628:
629: initializing = 0;
630:
631: /*
632: * Use select() on all on all input fd's for unlimited
633: * time. select() will terminate on SIGALARM or on the
634: * reception of input. Using select() means we can't do
635: * robust signal handling and we get a potential race
636: * between checking for alarms and doing the select().
637: * Mostly harmless, I think.
638: * Keep going until we have enough information, or time is up.
639: */
640: /* On VMS, I suspect that select() can't be interrupted
641: * by a "signal" either, so I take the easy way out and
642: * have select() time out after one second.
643: * System clock updates really aren't time-critical,
644: * and - lacking a hardware reference clock - I have
645: * yet to learn about anything else that is.
646: */
647: was_alarmed = 0;
648: while (finish_time > current_time) {
649: #if !defined(HAVE_SIGNALED_IO)
650: fd_set rdfdes;
651: int nfound;
652: #elif defined(HAVE_SIGNALED_IO)
653: block_io_and_alarm();
654: #endif
655:
656: tot_recvbufs = full_recvbuffs(); /* get received buffers */
657: if (printmsg) {
658: printmsg = 0;
659: analysis(0);
660: }
661: if (alarm_flag) { /* alarmed? */
662: was_alarmed = 1;
663: alarm_flag = 0;
664: }
665:
666: if (!was_alarmed && tot_recvbufs > 0) {
667: /*
668: * Nothing to do. Wait for something.
669: */
670: #ifndef HAVE_SIGNALED_IO
671: rdfdes = fdmask;
672: # if defined(VMS) || defined(SYS_VXWORKS)
673: /* make select() wake up after one second */
674: {
675: struct timeval t1;
676:
677: t1.tv_sec = 1; t1.tv_usec = 0;
678: nfound = select(fd+1, &rdfdes, (fd_set *)0,
679: (fd_set *)0, &t1);
680: }
681: # else
682: nfound = select(fd+1, &rdfdes, (fd_set *)0,
683: (fd_set *)0, (struct timeval *)0);
684: # endif /* VMS */
685: if (nfound > 0) {
686: l_fp ts;
687: get_systime(&ts);
688: (void)input_handler(&ts);
689: }
690: else if (nfound == -1 && errno != EINTR)
691: msyslog(LOG_ERR, "select() error: %m");
692: else if (debug) {
693: # if !defined SYS_VXWORKS && !defined SYS_CYGWIN32 /* to unclutter log */
694: msyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound);
695: # endif
696: }
697: #else /* HAVE_SIGNALED_IO */
698:
699: wait_for_signal();
700: #endif /* HAVE_SIGNALED_IO */
701: if (alarm_flag) /* alarmed? */
702: {
703: was_alarmed = 1;
704: alarm_flag = 0;
705: }
706: tot_recvbufs = full_recvbuffs(); /* get received buffers */
707: }
708: #ifdef HAVE_SIGNALED_IO
709: unblock_io_and_alarm();
710: #endif /* HAVE_SIGNALED_IO */
711:
712: /*
713: * Out here, signals are unblocked. Call timer routine
714: * to process expiry.
715: */
716: if (was_alarmed)
717: {
718: timer();
719: was_alarmed = 0;
720: }
721:
722: /*
723: * Call the data procedure to handle each received
724: * packet.
725: */
726: rbuf = get_full_recv_buffer();
727: while (rbuf != NULL)
728: {
729: receive(rbuf);
730: freerecvbuf(rbuf);
731: rbuf = get_full_recv_buffer();
732: }
733:
734: /*
735: * Do we have enough information to stop now?
736: */
737: if (have_enough())
738: break; /* time to end */
739:
740: /*
741: * Go around again
742: */
743: }
744:
745: /*
746: * adjust the clock and exit accordingly
747: */
748: set_local_clock();
749:
750: /*
751: * if we get here then we are in trouble
752: */
753: return(1);
754: }
755:
756:
757: /*
758: * analysis - print a message indicating what is happening with time service
759: * must mimic have_enough() procedure.
760: */
761: static void
762: analysis(
763: int final
764: )
765: {
766: if (contacted < sys_numservers) {
767: printf("%d servers of %d have been probed with %d packets\n",
768: contacted,sys_numservers,MINTRANSMITS);
769: return;
770: }
771: if (!responding) {
772: printf("No response from any of %d servers, network problem?\n",
773: sys_numservers);
774: return;
775: }
776: else if (responding < min_servers) {
777: printf("%d servers out of %d responding, need at least %d.\n",
778: responding, sys_numservers, min_servers);
779: return;
780: }
781: if (!validcount) {
782: printf("%d servers responding but none have valid time\n",
783: responding);
784: return;
785: }
786: else if (validcount < min_valid) {
787: printf("%d servers responding, %d are valid, need %d valid\n",
788: responding,validcount,min_valid);
789: return;
790: }
791: if (!final && valid_n_low != validcount) {
792: printf("%d valid servers but only %d have low dispersion\n",
793: validcount,valid_n_low);
794: return;
795: }
796: }
797:
798:
799: /* have_enough - see if we have enough information to terminate probing
800: */
801: static int
802: have_enough(void)
803: {
804: /* have we contacted all servers yet? */
805: if (contacted < sys_numservers)
806: return 0; /* no...try some more */
807:
808: /* have we got at least minimum servers responding? */
809: if (responding < min_servers)
810: return 0; /* no...try some more */
811:
812: /* count the clocks */
813: (void) clock_count();
814:
815: /* have we got at least minimum valid clocks? */
816: if (validcount <= 0 || validcount < min_valid)
817: return 0; /* no...try some more */
818:
819: /* do we have all valid servers with low dispersion */
820: if (!secondhalf && valid_n_low != validcount)
821: return 0;
822:
823: /* if we get into the secondhalf then we ignore dispersion */
824:
825: /* all conditions have been met...end */
826: return 1;
827: }
828:
829:
830: /*
831: * transmit - transmit a packet to the given server, or mark it completed.
832: * This is called by the timeout routine and by the receive
833: * procedure.
834: */
835: static void
836: transmit(
837: register struct server *server
838: )
839: {
840: struct pkt xpkt;
841: int timeout;
842:
843: if (debug > 2)
844: printf("transmit(%s)\n", ntoa(&server->srcadr));
845:
846: if ((server->reach & 01) == 0) {
847: l_fp ts;
848: /*
849: * Last message to this server timed out. Shift
850: * zeros into the filter.
851: */
852: L_CLR(&ts);
853: clock_filter(server, 0, &ts);
854: }
855:
856: /*
857: * shift reachable register over
858: */
859: server->reach <<= 1;
860:
861: /*
862: * If we're here, send another message to the server. Fill in
863: * the packet and let 'er rip.
864: */
865: xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOTINSYNC,
866: server->version, MODE_CLIENT);
867: xpkt.stratum = STRATUM_TO_PKT(STRATUM_UNSPEC);
868: xpkt.ppoll = NTP_MINPOLL;
869: xpkt.precision = NTPDATE_PRECISION;
870: xpkt.rootdelay = htonl(NTPDATE_DISTANCE);
871: xpkt.rootdispersion = htonl(NTPDATE_DISP);
872: xpkt.refid = htonl(NTPDATE_REFID);
873: L_CLR(&xpkt.reftime);
874: L_CLR(&xpkt.org);
875: L_CLR(&xpkt.rec);
876:
877: /*
878: * Determine whether to authenticate or not. If so,
879: * fill in the extended part of the packet and do it.
880: * If not, just timestamp it and send it away.
881: */
882: if (sys_authenticate) {
883: int len;
884:
885: xpkt.exten[0] = htonl(sys_authkey);
886: get_systime(&server->xmt);
887: L_ADDUF(&server->xmt, sys_authdelay);
888: HTONL_FP(&server->xmt, &xpkt.xmt);
889: len = authencrypt(sys_authkey, (u_int32 *)&xpkt, LEN_PKT_NOMAC);
890: if (sendpkt(&(server->srcadr), &xpkt, (int)(LEN_PKT_NOMAC + len))) {
891: if (debug > 1)
892: printf("failed transmit auth to %s\n",
893: ntoa(&(server->srcadr)));
894: return;
895: }
896:
897: if (debug > 1)
898: printf("transmit auth to %s\n",
899: ntoa(&(server->srcadr)));
900: } else {
901: get_systime(&(server->xmt));
902: HTONL_FP(&server->xmt, &xpkt.xmt);
903: if (sendpkt(&(server->srcadr), &xpkt, LEN_PKT_NOMAC)) {
904: if (debug > 1)
905: printf("failed transmit to %s\n",
906: ntoa(&(server->srcadr)));
907: return;
908: }
909:
910: if (debug > 1)
911: printf("transmit to %s\n", ntoa(&(server->srcadr)));
912: }
913:
914: /*
915: * count transmits, record contacted count and set transmit time
916: */
917: if (++server->xmtcnt == MINTRANSMITS)
918: contacted++;
919: server->last_xmit = current_time;
920:
921: /*
922: * determine timeout for this packet. The more packets we send
923: * to the host, the slower we get. If the host indicates that
924: * it is not "sane" then we expect even less.
925: */
926: if (server->xmtcnt < MINTRANSMITS) {
927: /* we have not sent enough */
928: timeout = TIMER_HZ; /* 1 second probe */
929: }
930: else if (server->rcvcnt <= 0) {
931: /* we have heard nothing */
932: if (secondhalf)
933: timeout = TIMER_HZ<<4; /* 16 second probe */
934: else
935: timeout = TIMER_HZ<<3; /* 8 second probe */
936: }
937: else {
938: /* if we have low dispersion then probe infrequently */
939: if (server->dispersion <= DESIREDDISP)
940: timeout = TIMER_HZ<<4; /* 16 second probe */
941: /* if the server is not in sync then let it alone */
942: else if (server->leap == LEAP_NOTINSYNC)
943: timeout = TIMER_HZ<<4; /* 16 second probe */
944: /* if the server looks broken ignore it */
945: else if (server->org.l_ui < server->reftime.l_ui)
946: timeout = TIMER_HZ<<5; /* 32 second probe */
947: else if (secondhalf)
948: timeout = TIMER_HZ<<2; /* 4 second probe */
949: else
950: timeout = TIMER_HZ<<1; /* 2 second probe */
951: }
952:
953: /*
954: * set next transmit time based on timeout
955: */
956: server->event_time = current_time + timeout;
957: }
958:
959:
960: /*
961: * receive - receive and process an incoming frame
962: */
963: static void
964: receive(
965: struct recvbuf *rbufp
966: )
967: {
968: register struct pkt *rpkt;
969: register struct server *server;
970: register s_fp di;
971: l_fp t10, t23;
972: l_fp org;
973: l_fp rec;
974: l_fp ci;
975: int has_mac;
976: int is_authentic;
977:
978: if (debug > 2)
979: printf("receive(%s)\n", ntoa(&rbufp->srcadr));
980: /*
981: * Check to see if the packet basically looks like something
982: * intended for us.
983: */
984: if (rbufp->recv_length == LEN_PKT_NOMAC)
985: has_mac = 0;
986: else if (rbufp->recv_length >= LEN_PKT_NOMAC)
987: has_mac = 1;
988: else {
989: if (debug > 2)
990: printf("receive: packet length %d\n",
991: rbufp->recv_length);
992: return; /* funny length packet */
993: }
994:
995: rpkt = &(rbufp->recv_pkt);
996: if (PKT_VERSION(rpkt->li_vn_mode) < NTP_OLDVERSION ||
997: PKT_VERSION(rpkt->li_vn_mode) > NTP_VERSION) {
998: if (debug > 1)
999: printf("receive: bad version %d\n",
1000: PKT_VERSION(rpkt->li_vn_mode));
1001: return;
1002: }
1003:
1004: if ((PKT_MODE(rpkt->li_vn_mode) != MODE_SERVER
1005: && PKT_MODE(rpkt->li_vn_mode) != MODE_PASSIVE)
1006: || rpkt->stratum >=STRATUM_UNSPEC) {
1007: if (debug > 1)
1008: printf("receive: mode %d stratum %d\n",
1009: PKT_MODE(rpkt->li_vn_mode), rpkt->stratum);
1010: return;
1011: }
1012:
1013: /*
1014: * So far, so good. See if this is from a server we know.
1015: */
1016: server = findserver(&(rbufp->srcadr));
1017: if (server == NULL) {
1018: if (debug > 1)
1019: printf("receive: server not found\n");
1020: return;
1021: }
1022:
1023: /*
1024: * Decode the org timestamp and make sure we're getting a response
1025: * to our last request.
1026: */
1027: NTOHL_FP(&rpkt->org, &org);
1028: if (!L_ISEQU(&org, &server->xmt)) {
1029: if (debug > 1)
1030: printf("receive: pkt.org and peer.xmt differ\n");
1031: return;
1032: }
1033:
1034: /*
1035: * Check out the authenticity if we're doing that.
1036: */
1037: if (!sys_authenticate)
1038: is_authentic = 1;
1039: else {
1040: is_authentic = 0;
1041:
1042: if (debug > 3)
1043: printf("receive: rpkt keyid=%ld sys_authkey=%ld decrypt=%ld\n",
1044: (long int)ntohl(rpkt->exten[0]), (long int)sys_authkey,
1045: (long int)authdecrypt(sys_authkey, (u_int32 *)rpkt,
1046: LEN_PKT_NOMAC, (int)(rbufp->recv_length - LEN_PKT_NOMAC)));
1047:
1048: if (has_mac && ntohl(rpkt->exten[0]) == sys_authkey &&
1049: authdecrypt(sys_authkey, (u_int32 *)rpkt, LEN_PKT_NOMAC,
1050: (int)(rbufp->recv_length - LEN_PKT_NOMAC)))
1051: is_authentic = 1;
1052: if (debug)
1053: printf("receive: authentication %s\n",
1054: is_authentic ? "passed" : "failed");
1055: }
1056: server->trust <<= 1;
1057: if (!is_authentic)
1058: server->trust |= 1;
1059:
1060: /*
1061: * Looks good. Record info from the packet.
1062: */
1063: server->leap = PKT_LEAP(rpkt->li_vn_mode);
1064: server->stratum = PKT_TO_STRATUM(rpkt->stratum);
1065: server->precision = rpkt->precision;
1066: server->rootdelay = ntohl(rpkt->rootdelay);
1067: server->rootdispersion = ntohl(rpkt->rootdispersion);
1068: server->refid = rpkt->refid;
1069: NTOHL_FP(&rpkt->reftime, &server->reftime);
1070: NTOHL_FP(&rpkt->rec, &rec);
1071: NTOHL_FP(&rpkt->xmt, &server->org);
1072:
1073: /*
1074: * count this guy as responding
1075: */
1076: server->reach |= 1;
1077: if (server->rcvcnt++ == 0)
1078: responding++;
1079:
1080: /*
1081: * Make sure the server is at least somewhat sane. If not, ignore
1082: * it for later.
1083: */
1084: if (L_ISZERO(&rec) || !L_ISHIS(&server->org, &rec)) {
1085: if (debug > 1)
1086: printf("receive: pkt insane\n");
1087: return;
1088: }
1089:
1090: /*
1091: * Calculate the round trip delay (di) and the clock offset (ci).
1092: * We use the equations (reordered from those in the spec):
1093: *
1094: * d = (t2 - t3) - (t1 - t0)
1095: * c = ((t2 - t3) + (t1 - t0)) / 2
1096: */
1097: t10 = server->org; /* pkt.xmt == t1 */
1098: L_SUB(&t10, &rbufp->recv_time); /* recv_time == t0*/
1099:
1100: t23 = rec; /* pkt.rec == t2 */
1101: L_SUB(&t23, &org); /* pkt->org == t3 */
1102:
1103: /* now have (t2 - t3) and (t0 - t1). Calculate (ci) and (di) */
1104: ci = t10;
1105: L_ADD(&ci, &t23);
1106: L_RSHIFT(&ci);
1107:
1108: /*
1109: * Calculate di in t23 in full precision, then truncate
1110: * to an s_fp.
1111: */
1112: L_SUB(&t23, &t10);
1113: di = LFPTOFP(&t23);
1114:
1115: if (debug > 3)
1116: printf("offset: %s, delay %s\n", lfptoa(&ci, 6), fptoa(di, 5));
1117:
1118: di += (FP_SECOND >> (-(int)NTPDATE_PRECISION))
1119: + (FP_SECOND >> (-(int)server->precision)) + NTP_MAXSKW;
1120:
1121: if (di <= 0) { /* value still too raunchy to use? */
1122: L_CLR(&ci);
1123: di = 0;
1124: } else {
1125: di = max(di, NTP_MINDIST);
1126: }
1127:
1128:
1129: /*
1130: * This one is valid. Give it to clock_filter(),
1131: */
1132: clock_filter(server, di, &ci);
1133: if (debug > 1)
1134: printf("receive from %s\n", ntoa(&rbufp->srcadr));
1135:
1136: /*
1137: * See if we should goes the transmission. If not return now
1138: * otherwise have the next event time be shortened
1139: */
1140: if (server->stratum <= NTP_INFIN)
1141: return; /* server does not have a stratum */
1142: if (server->leap == LEAP_NOTINSYNC)
1143: return; /* just booted server or out of sync */
1144: if (!L_ISHIS(&server->org, &server->reftime))
1145: return; /* broken host */
1146: if (server->trust != 0)
1147: return; /* can not trust it */
1148:
1149: if (server->dispersion < DESIREDDISP)
1150: return; /* we have the desired dispersion */
1151:
1152: server->event_time -= (TIMER_HZ+1);
1153: }
1154:
1155:
1156: /*
1157: * clock_filter - add clock sample, determine a server's delay, dispersion
1158: * and offset
1159: */
1160: static void
1161: clock_filter(
1162: register struct server *server,
1163: s_fp di,
1164: l_fp *c
1165: )
1166: {
1167: register int i, j;
1168: int ord[NTP_SHIFT];
1169:
1170: /*
1171: * Insert sample and increment nextpt
1172: */
1173:
1174: i = server->filter_nextpt;
1175: server->filter_delay[i] = di;
1176: server->filter_offset[i] = *c;
1177: server->filter_soffset[i] = LFPTOFP(c);
1178: server->filter_nextpt++;
1179: if (server->filter_nextpt >= NTP_SHIFT)
1180: server->filter_nextpt = 0;
1181:
1182: /*
1183: * Sort indices into increasing delay order
1184: */
1185: for (i = 0; i < NTP_SHIFT; i++)
1186: ord[i] = i;
1187:
1188: for (i = 0; i < (NTP_SHIFT-1); i++) {
1189: for (j = i+1; j < NTP_SHIFT; j++) {
1190: if (server->filter_delay[ord[j]] == 0)
1191: continue;
1192: if (server->filter_delay[ord[i]] == 0
1193: || (server->filter_delay[ord[i]]
1194: > server->filter_delay[ord[j]])) {
1195: register int tmp;
1196:
1197: tmp = ord[i];
1198: ord[i] = ord[j];
1199: ord[j] = tmp;
1200: }
1201: }
1202: }
1203:
1204: /*
1205: * Now compute the dispersion, and assign values to delay and
1206: * offset. If there are no samples in the register, delay and
1207: * offset go to zero and dispersion is set to the maximum.
1208: */
1209: if (server->filter_delay[ord[0]] == 0) {
1210: server->delay = 0;
1211: L_CLR(&server->offset);
1212: server->soffset = 0;
1213: server->dispersion = PEER_MAXDISP;
1214: } else {
1215: register s_fp d;
1216:
1217: server->delay = server->filter_delay[ord[0]];
1218: server->offset = server->filter_offset[ord[0]];
1219: server->soffset = LFPTOFP(&server->offset);
1220: server->dispersion = 0;
1221: for (i = 1; i < NTP_SHIFT; i++) {
1222: if (server->filter_delay[ord[i]] == 0)
1223: d = PEER_MAXDISP;
1224: else {
1225: d = server->filter_soffset[ord[i]]
1226: - server->filter_soffset[ord[0]];
1227: if (d < 0)
1228: d = -d;
1229: if (d > PEER_MAXDISP)
1230: d = PEER_MAXDISP;
1231: }
1232: /*
1233: * XXX This *knows* PEER_FILTER is 1/2
1234: */
1235: server->dispersion += (u_fp)(d) >> i;
1236: }
1237: }
1238: /*
1239: * We're done
1240: */
1241: }
1242:
1243:
1244: /* clock_count - count the clock sources we have
1245: */
1246: static void
1247: clock_count(void)
1248: {
1249: register struct server *server;
1250: register int n;
1251:
1252: /* reset counts */
1253: validcount = valid_n_low = 0;
1254:
1255: /* go through the list of servers and count the clocks we believe
1256: * and that have low dispersion
1257: */
1258: for (n = 0; n < sys_numservers; n++) {
1259: server = sys_servers[n];
1260: if (server->delay == 0) {
1261: continue; /* no data */
1262: }
1263: if (server->stratum > NTP_INFIN) {
1264: continue; /* stratum no good */
1265: }
1266: if (server->delay > NTP_MAXWGT) {
1267: continue; /* too far away */
1268: }
1269: if (server->leap == LEAP_NOTINSYNC)
1270: continue; /* he's in trouble */
1271: if (!L_ISHIS(&server->org, &server->reftime)) {
1272: continue; /* very broken host */
1273: }
1274: if ((server->org.l_ui - server->reftime.l_ui) >= NTP_MAXAGE) {
1275: continue; /* too long without sync */
1276: }
1277: if (server->trust != 0) {
1278: continue;
1279: }
1280:
1281: /*
1282: * This one is a valid time source..
1283: */
1284: validcount++;
1285:
1286: /*
1287: * See if this one has a okay low dispersion
1288: */
1289: if (server->dispersion <= DESIREDDISP)
1290: valid_n_low++;
1291: }
1292:
1293: if (debug > 1)
1294: printf("have %d, valid %d, low %d\n",
1295: responding, validcount, valid_n_low);
1296: }
1297:
1298:
1299: /*
1300: * clock_select - select the pick-of-the-litter clock from the samples
1301: * we've got.
1302: */
1303: static struct server *
1304: clock_select(void)
1305: {
1306: register struct server *server;
1307: register int i;
1308: register int nlist;
1309: register s_fp d;
1310: register int j;
1311: register int n;
1312: s_fp local_threshold;
1313: struct server *server_list[NTP_MAXCLOCK];
1314: u_fp server_badness[NTP_MAXCLOCK];
1315: struct server *sys_server;
1316:
1317: /*
1318: * This first chunk of code is supposed to go through all
1319: * servers we know about to find the NTP_MAXLIST servers which
1320: * are most likely to succeed. We run through the list
1321: * doing the sanity checks and trying to insert anyone who
1322: * looks okay. We are at all times aware that we should
1323: * only keep samples from the top two strata and we only need
1324: * NTP_MAXLIST of them.
1325: */
1326: nlist = 0; /* none yet */
1327: for (n = 0; n < sys_numservers; n++) {
1328: server = sys_servers[n];
1329: if (server->delay == 0)
1330: continue; /* no data */
1331: if (server->stratum > NTP_INFIN)
1332: continue; /* stratum no good */
1333: if (server->delay > NTP_MAXWGT) {
1334: continue; /* too far away */
1335: }
1336: if (server->leap == LEAP_NOTINSYNC)
1337: continue; /* he's in trouble */
1338: if (!L_ISHIS(&server->org, &server->reftime)) {
1339: continue; /* very broken host */
1340: }
1341: if ((server->org.l_ui - server->reftime.l_ui)
1342: >= NTP_MAXAGE) {
1343: continue; /* too long without sync */
1344: }
1345: if (server->trust != 0) {
1346: continue;
1347: }
1348:
1349: /*
1350: * This one seems sane. Find where he belongs
1351: * on the list.
1352: */
1353: d = server->dispersion + server->dispersion;
1354: for (i = 0; i < nlist; i++)
1355: if (server->stratum <= server_list[i]->stratum)
1356: break;
1357: for ( ; i < nlist; i++) {
1358: if (server->stratum < server_list[i]->stratum)
1359: break;
1360: if (d < (s_fp) server_badness[i])
1361: break;
1362: }
1363:
1364: /*
1365: * If i points past the end of the list, this
1366: * guy is a loser, else stick him in.
1367: */
1368: if (i >= NTP_MAXLIST)
1369: continue;
1370: for (j = nlist; j > i; j--)
1371: if (j < NTP_MAXLIST) {
1372: server_list[j] = server_list[j-1];
1373: server_badness[j]
1374: = server_badness[j-1];
1375: }
1376:
1377: server_list[i] = server;
1378: server_badness[i] = d;
1379: if (nlist < NTP_MAXLIST)
1380: nlist++;
1381: }
1382:
1383: /*
1384: * Got the five-or-less best. Cut the list where the number of
1385: * strata exceeds two.
1386: */
1387: j = 0;
1388: for (i = 1; i < nlist; i++)
1389: if (server_list[i]->stratum > server_list[i-1]->stratum)
1390: if (++j == 2) {
1391: nlist = i;
1392: break;
1393: }
1394:
1395: /*
1396: * Whew! What we should have by now is 0 to 5 candidates for
1397: * the job of syncing us. If we have none, we're out of luck.
1398: * If we have one, he's a winner. If we have more, do falseticker
1399: * detection.
1400: */
1401:
1402: if (nlist == 0)
1403: sys_server = 0;
1404: else if (nlist == 1) {
1405: sys_server = server_list[0];
1406: } else {
1407: /*
1408: * Re-sort by stratum, bdelay estimate quality and
1409: * server.delay.
1410: */
1411: for (i = 0; i < nlist-1; i++)
1412: for (j = i+1; j < nlist; j++) {
1413: if (server_list[i]->stratum
1414: < server_list[j]->stratum)
1415: break; /* already sorted by stratum */
1416: if (server_list[i]->delay
1417: < server_list[j]->delay)
1418: continue;
1419: server = server_list[i];
1420: server_list[i] = server_list[j];
1421: server_list[j] = server;
1422: }
1423:
1424: /*
1425: * Calculate the fixed part of the dispersion limit
1426: */
1427: local_threshold = (FP_SECOND >> (-(int)NTPDATE_PRECISION))
1428: + NTP_MAXSKW;
1429:
1430: /*
1431: * Now drop samples until we're down to one.
1432: */
1433: while (nlist > 1) {
1434: for (n = 0; n < nlist; n++) {
1435: server_badness[n] = 0;
1436: for (j = 0; j < nlist; j++) {
1437: if (j == n) /* with self? */
1438: continue;
1439: d = server_list[j]->soffset
1440: - server_list[n]->soffset;
1441: if (d < 0) /* absolute value */
1442: d = -d;
1443: /*
1444: * XXX This code *knows* that
1445: * NTP_SELECT is 3/4
1446: */
1447: for (i = 0; i < j; i++)
1448: d = (d>>1) + (d>>2);
1449: server_badness[n] += d;
1450: }
1451: }
1452:
1453: /*
1454: * We now have an array of nlist badness
1455: * coefficients. Find the badest. Find
1456: * the minimum precision while we're at
1457: * it.
1458: */
1459: i = 0;
1460: n = server_list[0]->precision;;
1461: for (j = 1; j < nlist; j++) {
1462: if (server_badness[j] >= server_badness[i])
1463: i = j;
1464: if (n > server_list[j]->precision)
1465: n = server_list[j]->precision;
1466: }
1467:
1468: /*
1469: * i is the index of the server with the worst
1470: * dispersion. If his dispersion is less than
1471: * the threshold, stop now, else delete him and
1472: * continue around again.
1473: */
1474: if (server_badness[i] < (local_threshold
1475: + (FP_SECOND >> (-n))))
1476: break;
1477: for (j = i + 1; j < nlist; j++)
1478: server_list[j-1] = server_list[j];
1479: nlist--;
1480: }
1481:
1482: /*
1483: * What remains is a list of less than 5 servers. Take
1484: * the best.
1485: */
1486: sys_server = server_list[0];
1487: }
1488:
1489: /*
1490: * That's it. Return our server.
1491: */
1492: return sys_server;
1493: }
1494:
1495:
1496: /*
1497: * set_local_clock -- handle setting the local clock or displaying info.
1498: */
1499: static void
1500: set_local_clock(void)
1501: {
1502: register int i;
1503: register struct server *server;
1504: time_t tmp;
1505: double dtemp;
1506:
1507: /*
1508: * if setting time then print final analysis
1509: */
1510: if (set_time)
1511: analysis(1);
1512:
1513: /*
1514: * pick a clock
1515: */
1516: server = clock_select();
1517:
1518: /*
1519: * do some display of information
1520: */
1521: if (debug || verbose) {
1522: for (i = 0; i < sys_numservers; i++)
1523: printserver(sys_servers[i], stdout);
1524: if (debug)
1525: printf("packets sent %ld, received %ld\n",
1526: total_xmit, total_recv);
1527: }
1528:
1529: /*
1530: * see if we have a server to set the time with
1531: */
1532: if (server == 0) {
1533: if (!set_time || verbose)
1534: fprintf(stdout,"No servers available to sync time with\n");
1535: exit(1);
1536: }
1537:
1538: /*
1539: * we have a valid and selected time to use!!!!!
1540: */
1541:
1542: /*
1543: * if we are not setting the time then display offset and exit
1544: */
1545: if (!set_time) {
1546: fprintf(stdout,
1547: "Your clock is off by %s seconds. (%s) [%ld/%ld]\n",
1548: lfptoa(&server->offset, 7),
1549: ntoa(&server->srcadr),
1550: total_xmit, total_recv);
1551: exit(0);
1552: }
1553:
1554: /*
1555: * set the clock
1556: * XXX: Examine the more flexible approach used by ntpdate.
1557: * Note that a design consideration here is that we sometimes
1558: * _want_ to step the clock by a _huge_ amount in either
1559: * direction, because the local clock is completely bogus.
1560: * This condition must be recognized and dealt with, so
1561: * that we always get a good time when this completes.
1562: * -- jhutz+@cmu.edu, 16-Aug-1999
1563: */
1564: LFPTOD(&server->offset, dtemp);
1565: step_systime(dtemp);
1566: time(&tmp);
1567: fprintf(stdout,"Time set to %.20s [%s %s %ld/%ld]\n",
1568: ctime(&tmp)+4,
1569: ntoa(&server->srcadr),
1570: lfptoa(&server->offset, 7),
1571: total_xmit, total_recv);
1572: exit(0);
1573: }
1574:
1575:
1576: /*
1577: * findserver - find a server in the list given its address
1578: */
1579: static struct server *
1580: findserver(
1581: struct sockaddr_in *addr
1582: )
1583: {
1584: register int i;
1585: register u_int32 netnum;
1586:
1587: if (htons(addr->sin_port) != NTP_PORT)
1588: return 0;
1589: netnum = addr->sin_addr.s_addr;
1590:
1591: for (i = 0; i < sys_numservers; i++) {
1592: if (netnum == sys_servers[i]->srcadr.sin_addr.s_addr)
1593: return sys_servers[i];
1594: }
1595: return 0;
1596: }
1597:
1598:
1599: /*
1600: * timer - process a timer interrupt
1601: */
1602: static void
1603: timer(void)
1604: {
1605: register int k;
1606:
1607: /*
1608: * Bump the current idea of the time
1609: */
1610: current_time++;
1611:
1612: /*
1613: * see if we have reached half time
1614: */
1615: if (current_time >= half_time && !secondhalf) {
1616: secondhalf++;
1617: if (debug)
1618: printf("\nSecond Half of Timeout!\n");
1619: printmsg++;
1620: }
1621:
1622: /*
1623: * We only want to send a few packets per transmit interrupt
1624: * to throttle things
1625: */
1626: for(k = 0;k < MAXXMITCOUNT;k++) {
1627: register int i, oldi;
1628: register u_long oldxtime;
1629:
1630: /*
1631: * We want to send a packet out for a server that has an
1632: * expired event time. However to be mellow about this, we only
1633: * use one expired event timer and to avoid starvation we use
1634: * the one with the oldest last transmit time.
1635: */
1636: oldi = -1;
1637: oldxtime = 0;
1638: for (i = 0; i < sys_numservers; i++) {
1639: if (sys_servers[i]->event_time <= current_time) {
1640: if (oldi < 0 || oldxtime > sys_servers[i]->last_xmit) {
1641: oldxtime = sys_servers[i]->last_xmit;
1642: oldi = i;
1643: }
1644: }
1645: }
1646: if (oldi >= 0)
1647: transmit(sys_servers[oldi]);
1648: else
1649: break; /* no expired event */
1650: } /* end of transmit loop */
1651: }
1652:
1653:
1654: #ifndef SYS_WINNT
1655: /*
1656: * alarming - record the occurance of an alarm interrupt
1657: */
1658: static RETSIGTYPE
1659: alarming(
1660: int sig
1661: )
1662: #else
1663: void CALLBACK
1664: alarming(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
1665: #endif /* SYS_WINNT */
1666: {
1667: alarm_flag++;
1668: }
1669:
1670:
1671: /*
1672: * init_alarm - set up the timer interrupt
1673: */
1674: static void
1675: init_alarm(void)
1676: {
1677: #ifndef SYS_WINNT
1678: # ifndef HAVE_TIMER_SETTIME
1679: struct itimerval itimer;
1680: # else
1681: struct itimerspec ntpdate_itimer;
1682: # endif
1683: #else
1684: TIMECAPS tc;
1685: UINT wTimerRes, wTimerID;
1686: # endif /* SYS_WINNT */
1687: #if defined SYS_CYGWIN32 || defined SYS_WINNT
1688: HANDLE hToken;
1689: TOKEN_PRIVILEGES tkp;
1690: DWORD dwUser = 0;
1691: #endif /* SYS_WINNT */
1692:
1693: alarm_flag = 0;
1694:
1695: #ifndef SYS_WINNT
1696: # if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME)
1697: alarm_flag = 0;
1698: /* this code was put in as setitimer() is non existant this us the
1699: * POSIX "equivalents" setup - casey
1700: */
1701: /* ntpdate_timerid is global - so we can kill timer later */
1702: if (timer_create (CLOCK_REALTIME, NULL, &ntpdate_timerid) ==
1703: # ifdef SYS_VXWORKS
1704: ERROR
1705: # else
1706: -1
1707: # endif
1708: )
1709: {
1710: fprintf (stderr, "init_alarm(): timer_create (...) FAILED\n");
1711: return;
1712: }
1713:
1714: /* TIMER_HZ = (5)
1715: * Set up the alarm interrupt. The first comes 1/(2*TIMER_HZ)
1716: * seconds from now and they continue on every 1/TIMER_HZ seconds.
1717: */
1718: (void) signal_no_reset(SIGALRM, alarming);
1719: ntpdate_itimer.it_interval.tv_sec = ntpdate_itimer.it_value.tv_sec = 0;
1720: ntpdate_itimer.it_interval.tv_nsec = 1000000000/TIMER_HZ;
1721: ntpdate_itimer.it_value.tv_nsec = 1000000000/(TIMER_HZ<<1);
1722: timer_settime(ntpdate_timerid, 0 /* !TIMER_ABSTIME */, &ntpdate_itimer, NULL);
1723: # else
1724: /*
1725: * Set up the alarm interrupt. The first comes 1/(2*TIMER_HZ)
1726: * seconds from now and they continue on every 1/TIMER_HZ seconds.
1727: */
1728: (void) signal_no_reset(SIGALRM, alarming);
1729: itimer.it_interval.tv_sec = itimer.it_value.tv_sec = 0;
1730: itimer.it_interval.tv_usec = 1000000/TIMER_HZ;
1731: itimer.it_value.tv_usec = 1000000/(TIMER_HZ<<1);
1732: setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
1733: # endif
1734: #if defined SYS_CYGWIN32
1735: /*
1736: * Get previleges needed for fiddling with the clock
1737: */
1738:
1739: /* get the current process token handle */
1740: if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
1741: msyslog(LOG_ERR, "OpenProcessToken failed: %m");
1742: exit(1);
1743: }
1744: /* get the LUID for system-time privilege. */
1745: LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid);
1746: tkp.PrivilegeCount = 1; /* one privilege to set */
1747: tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
1748: /* get set-time privilege for this process. */
1749: AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES) NULL, 0);
1750: /* cannot test return value of AdjustTokenPrivileges. */
1751: if (GetLastError() != ERROR_SUCCESS)
1752: msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m");
1753: #endif
1754: #else /* SYS_WINNT */
1755: _tzset();
1756:
1757: /*
1758: * Get previleges needed for fiddling with the clock
1759: */
1760:
1761: /* get the current process token handle */
1762: if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
1763: msyslog(LOG_ERR, "OpenProcessToken failed: %m");
1764: exit(1);
1765: }
1766: /* get the LUID for system-time privilege. */
1767: LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid);
1768: tkp.PrivilegeCount = 1; /* one privilege to set */
1769: tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
1770: /* get set-time privilege for this process. */
1771: AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES) NULL, 0);
1772: /* cannot test return value of AdjustTokenPrivileges. */
1773: if (GetLastError() != ERROR_SUCCESS)
1774: msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m");
1775:
1776: /*
1777: * Set up timer interrupts for every 2**EVENT_TIMEOUT seconds
1778: * Under Win/NT, expiry of timer interval leads to invocation
1779: * of a callback function (on a different thread) rather than
1780: * generating an alarm signal
1781: */
1782:
1783: /* determine max and min resolution supported */
1784: if(timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
1785: msyslog(LOG_ERR, "timeGetDevCaps failed: %m");
1786: exit(1);
1787: }
1788: wTimerRes = min(max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax);
1789: /* establish the minimum timer resolution that we'll use */
1790: timeBeginPeriod(wTimerRes);
1791:
1792: /* start the timer event */
1793: wTimerID = timeSetEvent(
1794: (UINT) (1000/TIMER_HZ), /* Delay */
1795: wTimerRes, /* Resolution */
1796: (LPTIMECALLBACK) alarming, /* Callback function */
1797: (DWORD) dwUser, /* User data */
1798: TIME_PERIODIC); /* Event type (periodic) */
1799: if (wTimerID == 0) {
1800: msyslog(LOG_ERR, "timeSetEvent failed: %m");
1801: exit(1);
1802: }
1803: #endif /* SYS_WINNT */
1804: }
1805:
1806:
1807: /*
1808: * init_io - initialize I/O data and open socket
1809: */
1810: static void
1811: init_io(void)
1812: {
1813: #ifdef SYS_WINNT
1814: WORD wVersionRequested;
1815: WSADATA wsaData;
1816: init_transmitbuff();
1817: #endif /* SYS_WINNT */
1818:
1819: /*
1820: * Init buffer free list and stat counters
1821: */
1822: init_recvbuff(sys_numservers + 2);
1823:
1824: #if defined(HAVE_SIGNALED_IO)
1825: set_signal();
1826: #endif
1827:
1828: #ifdef SYS_WINNT
1829: wVersionRequested = MAKEWORD(1,1);
1830: if (WSAStartup(wVersionRequested, &wsaData))
1831: {
1832: msyslog(LOG_ERR, "No useable winsock.dll: %m");
1833: exit(1);
1834: }
1835: #endif /* SYS_WINNT */
1836:
1837: BLOCKIO();
1838:
1839: /* create a datagram (UDP) socket */
1840: if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1841: msyslog(LOG_ERR, "socket() failed: %m");
1842: exit(1);
1843: /*NOTREACHED*/
1844: }
1845:
1846: /*
1847: * bind the socket to the NTP port
1848: */
1849: if (!debug && set_time && !unpriv_port) {
1850: struct sockaddr_in addr;
1851:
1852: memset((char *)&addr, 0, sizeof addr);
1853: addr.sin_family = AF_INET;
1854: addr.sin_port = htons(NTP_PORT);
1855: addr.sin_addr.s_addr = htonl(INADDR_ANY);
1856: if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
1857: #ifndef SYS_WINNT
1858: if (errno == EADDRINUSE)
1859: #else
1860: if (WSAGetLastError() == WSAEADDRINUSE)
1861: #endif
1862: msyslog(LOG_ERR,
1863: "the NTP socket is in use, exiting");
1864: else
1865: msyslog(LOG_ERR, "bind() fails: %m");
1866: exit(1);
1867: }
1868: }
1869:
1870: FD_ZERO(&fdmask);
1871: FD_SET(fd, &fdmask);
1872:
1873: /*
1874: * set non-blocking,
1875: */
1876:
1877: #ifdef USE_FIONBIO
1878: /* in vxWorks we use FIONBIO, but the others are defined for old systems, so
1879: * all hell breaks loose if we leave them defined
1880: */
1881: #undef O_NONBLOCK
1882: #undef FNDELAY
1883: #undef O_NDELAY
1884: #endif
1885:
1886: #if defined(O_NONBLOCK) /* POSIX */
1887: if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
1888: {
1889: msyslog(LOG_ERR, "fcntl(O_NONBLOCK) fails: %m");
1890: exit(1);
1891: /*NOTREACHED*/
1892: }
1893: #elif defined(FNDELAY)
1894: if (fcntl(fd, F_SETFL, FNDELAY) < 0)
1895: {
1896: msyslog(LOG_ERR, "fcntl(FNDELAY) fails: %m");
1897: exit(1);
1898: /*NOTREACHED*/
1899: }
1900: #elif defined(O_NDELAY) /* generally the same as FNDELAY */
1901: if (fcntl(fd, F_SETFL, O_NDELAY) < 0)
1902: {
1903: msyslog(LOG_ERR, "fcntl(O_NDELAY) fails: %m");
1904: exit(1);
1905: /*NOTREACHED*/
1906: }
1907: #elif defined(FIONBIO)
1908: if (
1909: # if defined(VMS)
1910: (ioctl(fd,FIONBIO,&1) < 0)
1911: # elif defined(SYS_WINNT)
1912: (ioctlsocket(fd,FIONBIO,(u_long *) &on) == SOCKET_ERROR)
1913: # else
1914: (ioctl(fd,FIONBIO,&on) < 0)
1915: # endif
1916: )
1917: {
1918: msyslog(LOG_ERR, "ioctl(FIONBIO) fails: %m");
1919: exit(1);
1920: /*NOTREACHED*/
1921: }
1922: #elif defined(FIOSNBIO)
1923: if (ioctl(fd,FIOSNBIO,&on) < 0)
1924: {
1925: msyslog(LOG_ERR, "ioctl(FIOSNBIO) fails: %m");
1926: exit(1);
1927: /*NOTREACHED*/
1928: }
1929: #else
1930: # include "Bletch: Need non-blocking I/O!"
1931: #endif
1932:
1933: #ifdef HAVE_SIGNALED_IO
1934: init_socket_sig(fd);
1935: #endif /* not HAVE_SIGNALED_IO */
1936:
1937: UNBLOCKIO();
1938: }
1939:
1940:
1941: /*
1942: * sendpkt - send a packet to the specified destination
1943: */
1944: static int
1945: sendpkt(
1946: struct sockaddr_in *dest,
1947: struct pkt *pkt,
1948: int len
1949: )
1950: {
1951: int cc;
1952: static int horriblecnt = 0;
1953: #ifdef SYS_WINNT
1954: DWORD err;
1955: #endif /* SYS_WINNT */
1956:
1957: total_xmit++; /* count it */
1958:
1959: if (horrible) {
1960: if (++horriblecnt > HORRIBLEOK) {
1961: if (debug > 3)
1962: printf("dropping send (%s)\n", ntoa(dest));
1963: if (horriblecnt >= HORRIBLEOK+horrible)
1964: horriblecnt = 0;
1965: return 0;
1966: }
1967: }
1968:
1969:
1970: cc = sendto(fd, (char *)pkt, (size_t)len, 0, (struct sockaddr *)dest,
1971: sizeof(struct sockaddr_in));
1972: #ifndef SYS_WINNT
1973: if (cc == -1) {
1974: if (errno != EWOULDBLOCK && errno != ENOBUFS)
1975: #else
1976: if (cc == SOCKET_ERROR) {
1977: err = WSAGetLastError();
1978: if (err != WSAEWOULDBLOCK && err != WSAENOBUFS)
1979: #endif /* SYS_WINNT */
1980: msyslog(LOG_ERR, "sendto(%s): %m", ntoa(dest));
1981: return -1;
1982: }
1983: return 0;
1984: }
1985:
1986:
1987: /*
1988: * input_handler - receive packets asynchronously
1989: */
1990: void
1991: input_handler(l_fp *xts)
1992: {
1993: register int n;
1994: register struct recvbuf *rb;
1995: struct timeval tvzero;
1996: int fromlen;
1997: fd_set fds;
1998: l_fp ts;
1999: ts = *xts; /* we ignore xts, but make the compiler happy */
2000:
2001: /*
2002: * Do a poll to see if we have data
2003: */
2004: for (;;) {
2005: fds = fdmask;
2006: tvzero.tv_sec = tvzero.tv_usec = 0;
2007: n = select(fd+1, &fds, (fd_set *)0, (fd_set *)0, &tvzero);
2008:
2009: /*
2010: * If nothing to do, just return. If an error occurred,
2011: * complain and return. If we've got some, freeze a
2012: * timestamp.
2013: */
2014: if (n == 0)
2015: return;
2016: else if (n == -1) {
2017: if (errno != EINTR) {
2018: msyslog(LOG_ERR, "select() error: %m");
2019: }
2020: return;
2021: }
2022: get_systime(&ts);
2023:
2024: /*
2025: * Get a buffer and read the frame. If we
2026: * haven't got a buffer, or this is received
2027: * on the wild card socket, just dump the packet.
2028: */
2029: if (initializing || free_recvbuffs == 0) {
2030: char buf[100];
2031:
2032: #ifndef SYS_WINNT
2033: (void) read(fd, buf, sizeof buf);
2034: #else
2035: /* NT's _read does not operate on nonblocking sockets
2036: * either recvfrom or ReadFile() has to be used here.
2037: * ReadFile is used in [ntpd]ntp_intres() and ntpdc,
2038: * just to be different use recvfrom() here
2039: */
2040: recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)0, NULL);
2041: #endif /* SYS_WINNT */
2042: continue;
2043: }
2044:
2045: rb = get_free_recv_buffer();
2046:
2047: fromlen = sizeof(struct sockaddr_in);
2048: rb->recv_length = recvfrom(fd, (char *)&rb->recv_pkt,
2049: sizeof(rb->recv_pkt), 0,
2050: (struct sockaddr *)&rb->srcadr, &fromlen);
2051: if (rb->recv_length == -1) {
2052: freerecvbuf(rb);
2053: continue;
2054: }
2055:
2056: /*
2057: * Got one. Mark how and when it got here,
2058: * put it on the full list.
2059: */
2060: rb->recv_time = ts;
2061: add_full_recv_buffer(rb);
2062: total_recv++; /* count it */
2063: }
2064: }
2065:
2066:
2067: /* XXX ELIMINATE printserver similar in ntptrace.c, ntpdate.c */
2068: /*
2069: * printserver - print detail information for a server
2070: */
2071: static void
2072: printserver(
2073: register struct server *pp,
2074: FILE *fp
2075: )
2076: {
2077: register int i;
2078: char junk[5];
2079: char *str;
2080:
2081: if (!debug) {
2082: (void) fprintf(fp,
2083: "%-15s %d/%d %03o v%d s%d offset %9s delay %s disp %s\n",
2084: ntoa(&pp->srcadr),
2085: pp->xmtcnt,pp->rcvcnt,pp->reach,
2086: pp->version,pp->stratum,
2087: lfptoa(&pp->offset, 6), ufptoa(pp->delay, 5),
2088: ufptoa(pp->dispersion, 4));
2089: return;
2090: }
2091:
2092: (void) fprintf(fp, "server %s, port %d\n",
2093: ntoa(&pp->srcadr), ntohs(pp->srcadr.sin_port));
2094:
2095: (void) fprintf(fp, "stratum %d, precision %d, leap %c%c, trust %03o\n",
2096: pp->stratum, pp->precision,
2097: pp->leap & 0x2 ? '1' : '0',
2098: pp->leap & 0x1 ? '1' : '0',
2099: pp->trust);
2100:
2101: if (pp->stratum == 1) {
2102: junk[4] = 0;
2103: memmove(junk, (char *)&pp->refid, 4);
2104: str = junk;
2105: } else {
2106: str = numtoa(pp->refid);
2107: }
2108: (void) fprintf(fp,
2109: "refid [%s], delay %s, dispersion %s\n",
2110: str, fptoa((s_fp)pp->delay, 5),
2111: ufptoa(pp->dispersion, 5));
2112:
2113: (void) fprintf(fp, "transmitted %d, received %d, reachable %03o\n",
2114: pp->xmtcnt, pp->rcvcnt, pp->reach);
2115:
2116: (void) fprintf(fp, "reference time: %s\n",
2117: prettydate(&pp->reftime));
2118: (void) fprintf(fp, "originate timestamp: %s\n",
2119: prettydate(&pp->org));
2120: (void) fprintf(fp, "transmit timestamp: %s\n",
2121: prettydate(&pp->xmt));
2122:
2123: (void) fprintf(fp, "filter delay: ");
2124: for (i = 0; i < NTP_SHIFT; i++) {
2125: (void) fprintf(fp, " %-8.8s", fptoa(pp->filter_delay[i], 5));
2126: if (i == (NTP_SHIFT>>1)-1)
2127: (void) fprintf(fp, "\n ");
2128: }
2129: (void) fprintf(fp, "\n");
2130:
2131: (void) fprintf(fp, "filter offset:");
2132: for (i = 0; i < PEER_SHIFT; i++) {
2133: (void) fprintf(fp, " %-8.8s", lfptoa(&pp->filter_offset[i], 6));
2134: if (i == (PEER_SHIFT>>1)-1)
2135: (void) fprintf(fp, "\n ");
2136: }
2137: (void) fprintf(fp, "\n");
2138:
2139: (void) fprintf(fp, "delay %s, dispersion %s\n",
2140: fptoa((s_fp)pp->delay, 5), ufptoa(pp->dispersion, 5));
2141:
2142: (void) fprintf(fp, "offset %s\n\n",
2143: lfptoa(&pp->offset, 6));
2144: }
2145:
2146: #if !defined(HAVE_VSPRINTF)
2147: int
2148: vsprintf(
2149: char *str,
2150: const char *fmt,
2151: va_list ap
2152: )
2153: {
2154: FILE f;
2155: int len;
2156:
2157: f._flag = _IOWRT+_IOSTRG;
2158: f._ptr = str;
2159: f._cnt = 32767;
2160: len = _doprnt(fmt, ap, &f);
2161: *f._ptr = 0;
2162: return (len);
2163: }
2164: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>