2 * ntptimeset - get/set the time via ntp
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
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.
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.
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.
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
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
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.
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
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
70 ****************************************************************
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:
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
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
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.
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.
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.
113 * Jeffrey T. Hutzelman (N3NHS) <jhutz+@cmu.edu>
114 * School of Computer Science - Research Computing Facility
115 * Carnegie Mellon University - Pittsburgh, PA
124 #include "ntp_machine.h"
128 #include "iosignal.h"
129 #include "ntp_unixtime.h"
131 #include "ntp_string.h"
132 #include "ntp_syslog.h"
133 #include "ntp_select.h"
134 #include "ntp_stdlib.h"
144 # ifdef HAVE_SYS_SIGNAL_H
145 # include <sys/signal.h>
149 # include <sys/ioctl.h>
150 #endif /* SYS_WINNT */
152 #ifdef HAVE_SYS_RESOURCE_H
153 # include <sys/resource.h>
154 #endif /* HAVE_SYS_RESOURCE_H */
158 # include "sockLib.h"
162 #include "recvbuff.h"
165 # define TARGET_RESOLUTION 1 /* Try for 1-millisecond accuracy
166 on Windows NT timers. */
167 #pragma comment(lib, "winmm")
168 #endif /* SYS_WINNT */
171 * Scheduling priority we run at
174 # define NTPDATE_PRIO (-12)
176 # define NTPDATE_PRIO (100)
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;
185 * Compatibility stuff for Version 2
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 */
197 volatile int debug = 0;
200 * File descriptor masks etc. for call to select
206 * Initializing flag. All async routines watch this and only do their
207 * thing when it is clear.
209 int initializing = 1;
212 * Alarm flag. Set when an alarm occurs
214 volatile int alarm_flag = 0;
217 * Set the time if valid time determined
222 * transmission rate control
224 #define MINTRANSMITS (3) /* minimum total packets per server */
225 #define MAXXMITCOUNT (2) /* maximum packets per time interrupt */
228 * time setting constraints
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;
236 * counters related to time setting constraints
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 */
244 * Unpriviledged port flag.
254 * Systemwide parameters and flags
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 */
263 * The current internal time
265 u_long current_time = 0;
268 * File of encryption keys
273 #define KEYFILE "/etc/ntp.keys"
275 #define KEYFILE "%windir%\\ntp.keys"
276 # endif /* SYS_WINNT */
280 const char *key_file = KEYFILE;
282 char key_file_storage[MAX_PATH+1], *key_file ;
283 #endif /* SYS_WINNT */
286 * total packet counts
288 u_long total_xmit = 0;
289 u_long total_recv = 0;
292 * Miscellaneous flags
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 */
301 * The half time and finish time in internal time
303 u_long half_time = 0;
304 u_long finish_time = 0;
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));
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));
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));
337 #ifdef NO_MAIN_ALLOWED
338 CALL(ntptimeset,"ntptimeset",ntptimesetmain);
350 * Initializing flag. All async routines watch this and only do their
351 * thing when it is clear.
356 * Alarm flag. Set when an alarm occurs
361 * Unpriviledged port flag.
366 * Systemwide parameters and flags
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 */
374 * The current internal time
380 #endif /* NO_MAIN_ALLOWED */
383 * Main program. Initialize us and loop waiting for I/O and/or
386 #ifndef NO_MAIN_ALLOWED
393 return ntptimesetmain(argc, argv);
395 #endif /* NO_MAIN_ALLOWED */
406 struct recvbuf *rbuf;
410 extern char *ntp_optarg;
411 extern int ntp_optind;
416 HANDLE process_handle;
418 wVersionRequested = MAKEWORD(1,1);
419 if (WSAStartup(wVersionRequested, &wsaData)) {
420 msyslog(LOG_ERR, "No useable winsock.dll: %m");
423 #endif /* SYS_WINNT */
425 #ifdef NO_MAIN_ALLOWED
435 * Decode argument list
437 while ((c = ntp_getopt(argc, argv, "a:c:de:slt:uvHS:V:")) != EOF)
441 c = atoi(ntp_optarg);
442 sys_authenticate = 1;
446 cfgpath = ntp_optarg;
452 if (!atolfp(ntp_optarg, &tmp)
454 (void) fprintf(stderr,
455 "%s: encryption delay %s is unlikely\n",
456 progname, ntp_optarg);
459 sys_authdelay = tmp.l_uf;
469 ltmp = atoi(ntp_optarg);
471 (void) fprintf(stderr,
472 "%s: maximum time period (%d) is invalid\n",
489 ltmp = atoi(ntp_optarg);
491 (void) fprintf(stderr,
492 "%s: minimum responding (%d) is invalid\n",
500 ltmp = atoi(ntp_optarg);
502 (void) fprintf(stderr,
503 "%s: minimum valid (%d) is invalid\n",
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");
536 * Logging. Open the syslog if we have to
539 #if !defined (SYS_WINNT) && !defined (SYS_VXWORKS) && !defined SYS_CYGWIN32
541 openlog("ntptimeset", LOG_PID);
545 # define LOG_NTP LOG_DAEMON
547 openlog("ntptimeset", LOG_PID | LOG_NDELAY, LOG_NTP);
549 setlogmask(LOG_UPTO(LOG_DEBUG));
551 setlogmask(LOG_UPTO(LOG_INFO));
552 # endif /* LOG_DAEMON */
553 #endif /* SYS_WINNT */
556 if (debug || verbose)
557 msyslog(LOG_INFO, "%s", Version);
560 msyslog(LOG_INFO, "Dropping %d out of %d packets",
561 horrible,horrible+HORRIBLEOK);
563 * Add servers we are going to be polling
565 loadservers(cfgpath);
567 if (sys_numservers < min_servers) {
568 msyslog(LOG_ERR, "Found %d servers, require %d servers",
569 sys_numservers,min_servers);
574 * determine when we will end at least
576 finish_time = max_period * TIMER_HZ;
577 half_time = finish_time >> 1;
580 * Initialize the time of day routines and the I/O subsystem
582 if (sys_authenticate) {
585 if (!key_file) key_file = KEYFILE;
586 if (!ExpandEnvironmentStrings(key_file, key_file_storage, MAX_PATH))
588 msyslog(LOG_ERR, "ExpandEnvironmentStrings(%s) failed: %m\n",
591 key_file = key_file_storage;
593 #endif /* SYS_WINNT */
595 if (!authreadkeys(key_file)) {
596 msyslog(LOG_ERR, "no key file, exiting");
599 if (!authistrusted(sys_authkey)) {
602 (void) sprintf(buf, "%lu", (unsigned long)sys_authkey);
603 msyslog(LOG_ERR, "authentication key %s unknown", buf);
614 taskPrioritySet( taskIdSelf(), NTPDATE_PRIO);
616 #if defined(HAVE_ATT_NICE)
619 #if defined(HAVE_BSD_NICE)
620 (void) setpriority(PRIO_PROCESS, 0, NTPDATE_PRIO);
623 process_handle = GetCurrentProcess();
624 if (!SetPriorityClass(process_handle, (DWORD) REALTIME_PRIORITY_CLASS)) {
625 msyslog(LOG_ERR, "SetPriorityClass failed: %m");
627 #endif /* SYS_WINNT */
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.
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.
648 while (finish_time > current_time) {
649 #if !defined(HAVE_SIGNALED_IO)
652 #elif defined(HAVE_SIGNALED_IO)
653 block_io_and_alarm();
656 tot_recvbufs = full_recvbuffs(); /* get received buffers */
661 if (alarm_flag) { /* alarmed? */
666 if (!was_alarmed && tot_recvbufs > 0) {
668 * Nothing to do. Wait for something.
670 #ifndef HAVE_SIGNALED_IO
672 # if defined(VMS) || defined(SYS_VXWORKS)
673 /* make select() wake up after one second */
677 t1.tv_sec = 1; t1.tv_usec = 0;
678 nfound = select(fd+1, &rdfdes, (fd_set *)0,
682 nfound = select(fd+1, &rdfdes, (fd_set *)0,
683 (fd_set *)0, (struct timeval *)0);
688 (void)input_handler(&ts);
690 else if (nfound == -1 && errno != EINTR)
691 msyslog(LOG_ERR, "select() error: %m");
693 # if !defined SYS_VXWORKS && !defined SYS_CYGWIN32 /* to unclutter log */
694 msyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound);
697 #else /* HAVE_SIGNALED_IO */
700 #endif /* HAVE_SIGNALED_IO */
701 if (alarm_flag) /* alarmed? */
706 tot_recvbufs = full_recvbuffs(); /* get received buffers */
708 #ifdef HAVE_SIGNALED_IO
709 unblock_io_and_alarm();
710 #endif /* HAVE_SIGNALED_IO */
713 * Out here, signals are unblocked. Call timer routine
723 * Call the data procedure to handle each received
726 rbuf = get_full_recv_buffer();
731 rbuf = get_full_recv_buffer();
735 * Do we have enough information to stop now?
738 break; /* time to end */
746 * adjust the clock and exit accordingly
751 * if we get here then we are in trouble
758 * analysis - print a message indicating what is happening with time service
759 * must mimic have_enough() procedure.
766 if (contacted < sys_numservers) {
767 printf("%d servers of %d have been probed with %d packets\n",
768 contacted,sys_numservers,MINTRANSMITS);
772 printf("No response from any of %d servers, network problem?\n",
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);
782 printf("%d servers responding but none have valid time\n",
786 else if (validcount < min_valid) {
787 printf("%d servers responding, %d are valid, need %d valid\n",
788 responding,validcount,min_valid);
791 if (!final && valid_n_low != validcount) {
792 printf("%d valid servers but only %d have low dispersion\n",
793 validcount,valid_n_low);
799 /* have_enough - see if we have enough information to terminate probing
804 /* have we contacted all servers yet? */
805 if (contacted < sys_numservers)
806 return 0; /* no...try some more */
808 /* have we got at least minimum servers responding? */
809 if (responding < min_servers)
810 return 0; /* no...try some more */
812 /* count the clocks */
813 (void) clock_count();
815 /* have we got at least minimum valid clocks? */
816 if (validcount <= 0 || validcount < min_valid)
817 return 0; /* no...try some more */
819 /* do we have all valid servers with low dispersion */
820 if (!secondhalf && valid_n_low != validcount)
823 /* if we get into the secondhalf then we ignore dispersion */
825 /* all conditions have been met...end */
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
837 register struct server *server
844 printf("transmit(%s)\n", ntoa(&server->srcadr));
846 if ((server->reach & 01) == 0) {
849 * Last message to this server timed out. Shift
850 * zeros into the filter.
853 clock_filter(server, 0, &ts);
857 * shift reachable register over
862 * If we're here, send another message to the server. Fill in
863 * the packet and let 'er rip.
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);
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.
882 if (sys_authenticate) {
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))) {
892 printf("failed transmit auth to %s\n",
893 ntoa(&(server->srcadr)));
898 printf("transmit auth to %s\n",
899 ntoa(&(server->srcadr)));
901 get_systime(&(server->xmt));
902 HTONL_FP(&server->xmt, &xpkt.xmt);
903 if (sendpkt(&(server->srcadr), &xpkt, LEN_PKT_NOMAC)) {
905 printf("failed transmit to %s\n",
906 ntoa(&(server->srcadr)));
911 printf("transmit to %s\n", ntoa(&(server->srcadr)));
915 * count transmits, record contacted count and set transmit time
917 if (++server->xmtcnt == MINTRANSMITS)
919 server->last_xmit = current_time;
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.
926 if (server->xmtcnt < MINTRANSMITS) {
927 /* we have not sent enough */
928 timeout = TIMER_HZ; /* 1 second probe */
930 else if (server->rcvcnt <= 0) {
931 /* we have heard nothing */
933 timeout = TIMER_HZ<<4; /* 16 second probe */
935 timeout = TIMER_HZ<<3; /* 8 second probe */
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 */
948 timeout = TIMER_HZ<<2; /* 4 second probe */
950 timeout = TIMER_HZ<<1; /* 2 second probe */
954 * set next transmit time based on timeout
956 server->event_time = current_time + timeout;
961 * receive - receive and process an incoming frame
965 struct recvbuf *rbufp
968 register struct pkt *rpkt;
969 register struct server *server;
979 printf("receive(%s)\n", ntoa(&rbufp->srcadr));
981 * Check to see if the packet basically looks like something
984 if (rbufp->recv_length == LEN_PKT_NOMAC)
986 else if (rbufp->recv_length >= LEN_PKT_NOMAC)
990 printf("receive: packet length %d\n",
992 return; /* funny length packet */
995 rpkt = &(rbufp->recv_pkt);
996 if (PKT_VERSION(rpkt->li_vn_mode) < NTP_OLDVERSION ||
997 PKT_VERSION(rpkt->li_vn_mode) > NTP_VERSION) {
999 printf("receive: bad version %d\n",
1000 PKT_VERSION(rpkt->li_vn_mode));
1004 if ((PKT_MODE(rpkt->li_vn_mode) != MODE_SERVER
1005 && PKT_MODE(rpkt->li_vn_mode) != MODE_PASSIVE)
1006 || rpkt->stratum >=STRATUM_UNSPEC) {
1008 printf("receive: mode %d stratum %d\n",
1009 PKT_MODE(rpkt->li_vn_mode), rpkt->stratum);
1014 * So far, so good. See if this is from a server we know.
1016 server = findserver(&(rbufp->srcadr));
1017 if (server == NULL) {
1019 printf("receive: server not found\n");
1024 * Decode the org timestamp and make sure we're getting a response
1025 * to our last request.
1027 NTOHL_FP(&rpkt->org, &org);
1028 if (!L_ISEQU(&org, &server->xmt)) {
1030 printf("receive: pkt.org and peer.xmt differ\n");
1035 * Check out the authenticity if we're doing that.
1037 if (!sys_authenticate)
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)));
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)))
1053 printf("receive: authentication %s\n",
1054 is_authentic ? "passed" : "failed");
1056 server->trust <<= 1;
1061 * Looks good. Record info from the packet.
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);
1074 * count this guy as responding
1077 if (server->rcvcnt++ == 0)
1081 * Make sure the server is at least somewhat sane. If not, ignore
1084 if (L_ISZERO(&rec) || !L_ISHIS(&server->org, &rec)) {
1086 printf("receive: pkt insane\n");
1091 * Calculate the round trip delay (di) and the clock offset (ci).
1092 * We use the equations (reordered from those in the spec):
1094 * d = (t2 - t3) - (t1 - t0)
1095 * c = ((t2 - t3) + (t1 - t0)) / 2
1097 t10 = server->org; /* pkt.xmt == t1 */
1098 L_SUB(&t10, &rbufp->recv_time); /* recv_time == t0*/
1100 t23 = rec; /* pkt.rec == t2 */
1101 L_SUB(&t23, &org); /* pkt->org == t3 */
1103 /* now have (t2 - t3) and (t0 - t1). Calculate (ci) and (di) */
1109 * Calculate di in t23 in full precision, then truncate
1116 printf("offset: %s, delay %s\n", lfptoa(&ci, 6), fptoa(di, 5));
1118 di += (FP_SECOND >> (-(int)NTPDATE_PRECISION))
1119 + (FP_SECOND >> (-(int)server->precision)) + NTP_MAXSKW;
1121 if (di <= 0) { /* value still too raunchy to use? */
1125 di = max(di, NTP_MINDIST);
1130 * This one is valid. Give it to clock_filter(),
1132 clock_filter(server, di, &ci);
1134 printf("receive from %s\n", ntoa(&rbufp->srcadr));
1137 * See if we should goes the transmission. If not return now
1138 * otherwise have the next event time be shortened
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 */
1149 if (server->dispersion < DESIREDDISP)
1150 return; /* we have the desired dispersion */
1152 server->event_time -= (TIMER_HZ+1);
1157 * clock_filter - add clock sample, determine a server's delay, dispersion
1162 register struct server *server,
1171 * Insert sample and increment nextpt
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;
1183 * Sort indices into increasing delay order
1185 for (i = 0; i < NTP_SHIFT; i++)
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)
1192 if (server->filter_delay[ord[i]] == 0
1193 || (server->filter_delay[ord[i]]
1194 > server->filter_delay[ord[j]])) {
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.
1209 if (server->filter_delay[ord[0]] == 0) {
1211 L_CLR(&server->offset);
1212 server->soffset = 0;
1213 server->dispersion = PEER_MAXDISP;
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)
1225 d = server->filter_soffset[ord[i]]
1226 - server->filter_soffset[ord[0]];
1229 if (d > PEER_MAXDISP)
1233 * XXX This *knows* PEER_FILTER is 1/2
1235 server->dispersion += (u_fp)(d) >> i;
1244 /* clock_count - count the clock sources we have
1249 register struct server *server;
1253 validcount = valid_n_low = 0;
1255 /* go through the list of servers and count the clocks we believe
1256 * and that have low dispersion
1258 for (n = 0; n < sys_numservers; n++) {
1259 server = sys_servers[n];
1260 if (server->delay == 0) {
1261 continue; /* no data */
1263 if (server->stratum > NTP_INFIN) {
1264 continue; /* stratum no good */
1266 if (server->delay > NTP_MAXWGT) {
1267 continue; /* too far away */
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 */
1274 if ((server->org.l_ui - server->reftime.l_ui) >= NTP_MAXAGE) {
1275 continue; /* too long without sync */
1277 if (server->trust != 0) {
1282 * This one is a valid time source..
1287 * See if this one has a okay low dispersion
1289 if (server->dispersion <= DESIREDDISP)
1294 printf("have %d, valid %d, low %d\n",
1295 responding, validcount, valid_n_low);
1300 * clock_select - select the pick-of-the-litter clock from the samples
1303 static struct server *
1306 register struct server *server;
1312 s_fp local_threshold;
1313 struct server *server_list[NTP_MAXCLOCK];
1314 u_fp server_badness[NTP_MAXCLOCK];
1315 struct server *sys_server;
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.
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 */
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 */
1341 if ((server->org.l_ui - server->reftime.l_ui)
1343 continue; /* too long without sync */
1345 if (server->trust != 0) {
1350 * This one seems sane. Find where he belongs
1353 d = server->dispersion + server->dispersion;
1354 for (i = 0; i < nlist; i++)
1355 if (server->stratum <= server_list[i]->stratum)
1357 for ( ; i < nlist; i++) {
1358 if (server->stratum < server_list[i]->stratum)
1360 if (d < (s_fp) server_badness[i])
1365 * If i points past the end of the list, this
1366 * guy is a loser, else stick him in.
1368 if (i >= NTP_MAXLIST)
1370 for (j = nlist; j > i; j--)
1371 if (j < NTP_MAXLIST) {
1372 server_list[j] = server_list[j-1];
1374 = server_badness[j-1];
1377 server_list[i] = server;
1378 server_badness[i] = d;
1379 if (nlist < NTP_MAXLIST)
1384 * Got the five-or-less best. Cut the list where the number of
1385 * strata exceeds two.
1388 for (i = 1; i < nlist; i++)
1389 if (server_list[i]->stratum > server_list[i-1]->stratum)
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
1404 else if (nlist == 1) {
1405 sys_server = server_list[0];
1408 * Re-sort by stratum, bdelay estimate quality and
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)
1419 server = server_list[i];
1420 server_list[i] = server_list[j];
1421 server_list[j] = server;
1425 * Calculate the fixed part of the dispersion limit
1427 local_threshold = (FP_SECOND >> (-(int)NTPDATE_PRECISION))
1431 * Now drop samples until we're down to one.
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? */
1439 d = server_list[j]->soffset
1440 - server_list[n]->soffset;
1441 if (d < 0) /* absolute value */
1444 * XXX This code *knows* that
1447 for (i = 0; i < j; i++)
1448 d = (d>>1) + (d>>2);
1449 server_badness[n] += d;
1454 * We now have an array of nlist badness
1455 * coefficients. Find the badest. Find
1456 * the minimum precision while we're at
1460 n = server_list[0]->precision;;
1461 for (j = 1; j < nlist; j++) {
1462 if (server_badness[j] >= server_badness[i])
1464 if (n > server_list[j]->precision)
1465 n = server_list[j]->precision;
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.
1474 if (server_badness[i] < (local_threshold
1475 + (FP_SECOND >> (-n))))
1477 for (j = i + 1; j < nlist; j++)
1478 server_list[j-1] = server_list[j];
1483 * What remains is a list of less than 5 servers. Take
1486 sys_server = server_list[0];
1490 * That's it. Return our server.
1497 * set_local_clock -- handle setting the local clock or displaying info.
1500 set_local_clock(void)
1503 register struct server *server;
1508 * if setting time then print final analysis
1516 server = clock_select();
1519 * do some display of information
1521 if (debug || verbose) {
1522 for (i = 0; i < sys_numservers; i++)
1523 printserver(sys_servers[i], stdout);
1525 printf("packets sent %ld, received %ld\n",
1526 total_xmit, total_recv);
1530 * see if we have a server to set the time with
1533 if (!set_time || verbose)
1534 fprintf(stdout,"No servers available to sync time with\n");
1539 * we have a valid and selected time to use!!!!!
1543 * if we are not setting the time then display offset and exit
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);
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
1564 LFPTOD(&server->offset, dtemp);
1565 step_systime(dtemp);
1567 fprintf(stdout,"Time set to %.20s [%s %s %ld/%ld]\n",
1569 ntoa(&server->srcadr),
1570 lfptoa(&server->offset, 7),
1571 total_xmit, total_recv);
1577 * findserver - find a server in the list given its address
1579 static struct server *
1581 struct sockaddr_in *addr
1585 register u_int32 netnum;
1587 if (htons(addr->sin_port) != NTP_PORT)
1589 netnum = addr->sin_addr.s_addr;
1591 for (i = 0; i < sys_numservers; i++) {
1592 if (netnum == sys_servers[i]->srcadr.sin_addr.s_addr)
1593 return sys_servers[i];
1600 * timer - process a timer interrupt
1608 * Bump the current idea of the time
1613 * see if we have reached half time
1615 if (current_time >= half_time && !secondhalf) {
1618 printf("\nSecond Half of Timeout!\n");
1623 * We only want to send a few packets per transmit interrupt
1624 * to throttle things
1626 for(k = 0;k < MAXXMITCOUNT;k++) {
1627 register int i, oldi;
1628 register u_long oldxtime;
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.
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;
1647 transmit(sys_servers[oldi]);
1649 break; /* no expired event */
1650 } /* end of transmit loop */
1656 * alarming - record the occurance of an alarm interrupt
1664 alarming(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
1665 #endif /* SYS_WINNT */
1672 * init_alarm - set up the timer interrupt
1678 # ifndef HAVE_TIMER_SETTIME
1679 struct itimerval itimer;
1681 struct itimerspec ntpdate_itimer;
1685 UINT wTimerRes, wTimerID;
1686 # endif /* SYS_WINNT */
1687 #if defined SYS_CYGWIN32 || defined SYS_WINNT
1689 TOKEN_PRIVILEGES tkp;
1691 #endif /* SYS_WINNT */
1696 # if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME)
1698 /* this code was put in as setitimer() is non existant this us the
1699 * POSIX "equivalents" setup - casey
1701 /* ntpdate_timerid is global - so we can kill timer later */
1702 if (timer_create (CLOCK_REALTIME, NULL, &ntpdate_timerid) ==
1710 fprintf (stderr, "init_alarm(): timer_create (...) FAILED\n");
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.
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);
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.
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);
1734 #if defined SYS_CYGWIN32
1736 * Get previleges needed for fiddling with the clock
1739 /* get the current process token handle */
1740 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
1741 msyslog(LOG_ERR, "OpenProcessToken failed: %m");
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");
1754 #else /* SYS_WINNT */
1758 * Get previleges needed for fiddling with the clock
1761 /* get the current process token handle */
1762 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
1763 msyslog(LOG_ERR, "OpenProcessToken failed: %m");
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");
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
1783 /* determine max and min resolution supported */
1784 if(timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
1785 msyslog(LOG_ERR, "timeGetDevCaps failed: %m");
1788 wTimerRes = min(max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax);
1789 /* establish the minimum timer resolution that we'll use */
1790 timeBeginPeriod(wTimerRes);
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");
1803 #endif /* SYS_WINNT */
1808 * init_io - initialize I/O data and open socket
1814 WORD wVersionRequested;
1816 init_transmitbuff();
1817 #endif /* SYS_WINNT */
1820 * Init buffer free list and stat counters
1822 init_recvbuff(sys_numservers + 2);
1824 #if defined(HAVE_SIGNALED_IO)
1829 wVersionRequested = MAKEWORD(1,1);
1830 if (WSAStartup(wVersionRequested, &wsaData))
1832 msyslog(LOG_ERR, "No useable winsock.dll: %m");
1835 #endif /* SYS_WINNT */
1839 /* create a datagram (UDP) socket */
1840 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1841 msyslog(LOG_ERR, "socket() failed: %m");
1847 * bind the socket to the NTP port
1849 if (!debug && set_time && !unpriv_port) {
1850 struct sockaddr_in addr;
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) {
1858 if (errno == EADDRINUSE)
1860 if (WSAGetLastError() == WSAEADDRINUSE)
1863 "the NTP socket is in use, exiting");
1865 msyslog(LOG_ERR, "bind() fails: %m");
1871 FD_SET(fd, &fdmask);
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
1886 #if defined(O_NONBLOCK) /* POSIX */
1887 if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
1889 msyslog(LOG_ERR, "fcntl(O_NONBLOCK) fails: %m");
1893 #elif defined(FNDELAY)
1894 if (fcntl(fd, F_SETFL, FNDELAY) < 0)
1896 msyslog(LOG_ERR, "fcntl(FNDELAY) fails: %m");
1900 #elif defined(O_NDELAY) /* generally the same as FNDELAY */
1901 if (fcntl(fd, F_SETFL, O_NDELAY) < 0)
1903 msyslog(LOG_ERR, "fcntl(O_NDELAY) fails: %m");
1907 #elif defined(FIONBIO)
1910 (ioctl(fd,FIONBIO,&1) < 0)
1911 # elif defined(SYS_WINNT)
1912 (ioctlsocket(fd,FIONBIO,(u_long *) &on) == SOCKET_ERROR)
1914 (ioctl(fd,FIONBIO,&on) < 0)
1918 msyslog(LOG_ERR, "ioctl(FIONBIO) fails: %m");
1922 #elif defined(FIOSNBIO)
1923 if (ioctl(fd,FIOSNBIO,&on) < 0)
1925 msyslog(LOG_ERR, "ioctl(FIOSNBIO) fails: %m");
1930 # include "Bletch: Need non-blocking I/O!"
1933 #ifdef HAVE_SIGNALED_IO
1934 init_socket_sig(fd);
1935 #endif /* not HAVE_SIGNALED_IO */
1942 * sendpkt - send a packet to the specified destination
1946 struct sockaddr_in *dest,
1952 static int horriblecnt = 0;
1955 #endif /* SYS_WINNT */
1957 total_xmit++; /* count it */
1960 if (++horriblecnt > HORRIBLEOK) {
1962 printf("dropping send (%s)\n", ntoa(dest));
1963 if (horriblecnt >= HORRIBLEOK+horrible)
1970 cc = sendto(fd, (char *)pkt, (size_t)len, 0, (struct sockaddr *)dest,
1971 sizeof(struct sockaddr_in));
1974 if (errno != EWOULDBLOCK && errno != ENOBUFS)
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));
1988 * input_handler - receive packets asynchronously
1991 input_handler(l_fp *xts)
1994 register struct recvbuf *rb;
1995 struct timeval tvzero;
1999 ts = *xts; /* we ignore xts, but make the compiler happy */
2002 * Do a poll to see if we have data
2006 tvzero.tv_sec = tvzero.tv_usec = 0;
2007 n = select(fd+1, &fds, (fd_set *)0, (fd_set *)0, &tvzero);
2010 * If nothing to do, just return. If an error occurred,
2011 * complain and return. If we've got some, freeze a
2017 if (errno != EINTR) {
2018 msyslog(LOG_ERR, "select() error: %m");
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.
2029 if (initializing || free_recvbuffs == 0) {
2033 (void) read(fd, buf, sizeof buf);
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
2040 recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)0, NULL);
2041 #endif /* SYS_WINNT */
2045 rb = get_free_recv_buffer();
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) {
2057 * Got one. Mark how and when it got here,
2058 * put it on the full list.
2061 add_full_recv_buffer(rb);
2062 total_recv++; /* count it */
2067 /* XXX ELIMINATE printserver similar in ntptrace.c, ntpdate.c */
2069 * printserver - print detail information for a server
2073 register struct server *pp,
2083 "%-15s %d/%d %03o v%d s%d offset %9s delay %s disp %s\n",
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));
2092 (void) fprintf(fp, "server %s, port %d\n",
2093 ntoa(&pp->srcadr), ntohs(pp->srcadr.sin_port));
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',
2101 if (pp->stratum == 1) {
2103 memmove(junk, (char *)&pp->refid, 4);
2106 str = numtoa(pp->refid);
2109 "refid [%s], delay %s, dispersion %s\n",
2110 str, fptoa((s_fp)pp->delay, 5),
2111 ufptoa(pp->dispersion, 5));
2113 (void) fprintf(fp, "transmitted %d, received %d, reachable %03o\n",
2114 pp->xmtcnt, pp->rcvcnt, pp->reach);
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));
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 ");
2129 (void) fprintf(fp, "\n");
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 ");
2137 (void) fprintf(fp, "\n");
2139 (void) fprintf(fp, "delay %s, dispersion %s\n",
2140 fptoa((s_fp)pp->delay, 5), ufptoa(pp->dispersion, 5));
2142 (void) fprintf(fp, "offset %s\n\n",
2143 lfptoa(&pp->offset, 6));
2146 #if !defined(HAVE_VSPRINTF)
2157 f._flag = _IOWRT+_IOSTRG;
2160 len = _doprnt(fmt, ap, &f);