1 /* $NetBSD: ntptimeset.c,v 1.4 2003/12/04 16:23:38 drochner Exp $ */
4 * ntptimeset - get/set the time via ntp
7 * The goal of ntptime is to set the current time on system startup
8 * to the best possible time using the network very wisely. It is assumed
9 * that after a resonable time has been sett then ntp daemon will
13 * We have three sets of issues related to acheiving the goal. The first
14 * issue is using the network when normal traffic is happening or when
15 * the entire network world is recovering from a campus wide power failure
16 * and is restarting. The second issue is the class of machine whether it
17 * is a user's office workstation being handled by an uneducated user or
18 * a server computer being handled by a trained operations staff. The third
19 * issue is whether the ratio of people to computers and whether the
20 * environment is stable and viable or not.
23 * The first issue of using the network wisely is a question of whether
24 * the network load and time server load and state are normal. If things
25 * are normal ntptime can do what ntpdate does of sending out 4 packets
26 * quickly to each server (new transmit done with each ack). However
27 * if network or time load is high then this scheme will simply contribute
28 * to problems. Given we have minimal state, we simply weight lost packets
29 * significantly and make sure we throttle output as much as possible
30 * without performance lost for quick startups.
32 * TRAINING AND KNOWLEDGE:
33 * The second issue of uneducated user of a office workstation versus a
34 * trained operation staff of a server machine translates into simply an
35 * issue of untrained and trained users.
37 * The training issue implies that for the sake of the users involved in the
38 * handling of their office workstation, problems and options should be
39 * communicated simply and effectively and not in terse expert related
40 * descriptions without possible options to be taken. The operator's training
41 * and education enables them to deal with either type of communication and
44 * AUTOMATION AND MANUAL CONTROL:
45 * The last issue boils down to a design problem. If the design tends to go
46 * into a manual mode when the environment is non-viable then one person
47 * handling many computers all at the same time will be heavily impacted. On
48 * the other hand, if the design tends to be automatic and does not indicate
49 * a way for the user to take over control then the computer will be
50 * unavailable for the user until the proble is resolved by someone else or
53 * NOTE: Please do not have this program print out every minute some line,
54 * of output. If this happens and the environment is in trouble then
55 * many pages of paper on many different machines will be filled up.
56 * Save some tress in your lifetime.
59 * The behavior of the program derived from these three issues should be
60 * that during normal situations it quickly sets the time and allow the
63 * However during abnormal conditions as detected by unresponsive servers,
64 * out-of-sync or bad responses and other detections, it should print out
65 * a simple but clear message and continue in a mellow way to get the best
66 * possible time. It may never get the time and if so should also indicate
72 ****************************************************************
74 * Much of the above is confusing or no longer relevant. For example,
75 * it is rare these days for a machine's console to be a printing terminal,
76 * so the comment about saving trees doesn't mean much. Nonetheless,
77 * the basic principles still stand:
79 * - Work automatically, without human control or intervention. To
80 * this end, we use the same configuration file as ntpd itself, so
81 * you don't have to specify servers or other information on the
82 * command line. We also recognize that sometimes we won't be able
83 * to contact any servers, and give up in that event instead of
86 * - Behave in a sane way, both internally and externally, even in the
87 * face of insane conditions. That means we back off quickly when
88 * we don't hear a response, to avoid network congestion. Like
89 * ntpd, we verify responses from several servers before accepting
92 * However, we don't assume that the local clock is right, or even
93 * close, because it might not be at boot time, and we want to catch
94 * and correct that situation. This behaviour has saved us in several
95 * instances. On HP-UX 9.0x, there used to be a bug in adjtimed which
96 * would cause the time to be set to some wild value, making the machine
97 * essentially unusable (we use Kerberos authentication pervasively,
98 * and it requires workstations and servers to have a time within five
99 * minutes of the Kerberos server). We also have problems on PC's
100 * running both Linux and some Microsoft OS -- they tend to disagree
101 * on what the BIOS clock should say, and who should update it, and
102 * when. On those systems, we not only run ntptimeset at boot, we
103 * also reset the BIOS clock based on the result, so the correct
104 * time will be retained across reboots.
106 * For these reasons, and others, we have continued to use this tool
107 * rather than ntpdate. It is run automatically at boot time on every
108 * workstation and server in our facility.
110 * In the past, we called this program 'ntptime'. Unfortunately, the
111 * ntp v4 distribution also includes a program with that name. In
112 * order to avoid confusion, we have renamed our program 'ntptimeset',
113 * which more accurately describes what it does.
115 * Jeffrey T. Hutzelman (N3NHS) <jhutz+@cmu.edu>
116 * School of Computer Science - Research Computing Facility
117 * Carnegie Mellon University - Pittsburgh, PA
126 #include "ntp_machine.h"
130 #include "iosignal.h"
131 #include "ntp_unixtime.h"
133 #include "ntp_string.h"
134 #include "ntp_syslog.h"
135 #include "ntp_select.h"
136 #include "ntp_stdlib.h"
146 # ifdef HAVE_SYS_SIGNAL_H
147 # include <sys/signal.h>
151 # include <sys/ioctl.h>
152 #endif /* SYS_WINNT */
154 #ifdef HAVE_SYS_RESOURCE_H
155 # include <sys/resource.h>
156 #endif /* HAVE_SYS_RESOURCE_H */
160 # include "sockLib.h"
164 #include "recvbuff.h"
167 # define TARGET_RESOLUTION 1 /* Try for 1-millisecond accuracy
168 on Windows NT timers. */
169 #pragma comment(lib, "winmm")
170 #endif /* SYS_WINNT */
173 * Scheduling priority we run at
176 # define NTPDATE_PRIO (-12)
178 # define NTPDATE_PRIO (100)
181 #if defined(HAVE_TIMER_SETTIME) || defined (HAVE_TIMER_CREATE)
182 /* POSIX TIMERS - vxWorks doesn't have itimer - casey */
183 static timer_t ntpdate_timerid
;
187 * Compatibility stuff for Version 2
189 #define NTP_MAXSKW 0x28f /* 0.01 sec in fp format */
190 #define NTP_MINDIST 0x51f /* 0.02 sec in fp format */
191 #define NTP_INFIN 15 /* max stratum, infinity a la Bellman-Ford */
192 #define NTP_MAXWGT (8*FP_SECOND) /* maximum select weight 8 seconds */
193 #define NTP_MAXLIST 5 /* maximum select list size */
194 #define PEER_SHIFT 8 /* 8 suitable for crystal time base */
199 volatile int debug
= 0;
202 * File descriptor masks etc. for call to select
208 * Initializing flag. All async routines watch this and only do their
209 * thing when it is clear.
211 int initializing
= 1;
214 * Alarm flag. Set when an alarm occurs
216 volatile int alarm_flag
= 0;
219 * Set the time if valid time determined
224 * transmission rate control
226 #define MINTRANSMITS (3) /* minimum total packets per server */
227 #define MAXXMITCOUNT (2) /* maximum packets per time interrupt */
230 * time setting constraints
232 #define DESIREDDISP (4*FP_SECOND) /* desired dispersion, (fp 4) */
233 int max_period
= DEFMAXPERIOD
;
234 int min_servers
= DEFMINSERVERS
;
235 int min_valid
= DEFMINVALID
;
238 * counters related to time setting constraints
240 int contacted
= 0; /* # of servers we have sent to */
241 int responding
= 0; /* servers responding */
242 int validcount
= 0; /* servers with valid time */
243 int valid_n_low
= 0; /* valid time servers with low dispersion */
246 * Unpriviledged port flag.
256 * Systemwide parameters and flags
258 struct server
**sys_servers
; /* the server list */
259 int sys_numservers
= 0; /* number of servers to poll */
260 int sys_authenticate
= 0; /* true when authenticating */
261 u_int32 sys_authkey
= 0; /* set to authentication key in use */
262 u_long sys_authdelay
= 0; /* authentication delay */
265 * The current internal time
267 u_long current_time
= 0;
270 * File of encryption keys
275 #define KEYFILE "/etc/ntp.keys"
277 #define KEYFILE "%windir%\\ntp.keys"
278 # endif /* SYS_WINNT */
282 const char *key_file
= KEYFILE
;
284 char key_file_storage
[MAX_PATH
+1], *key_file
;
285 #endif /* SYS_WINNT */
288 * total packet counts
290 u_long total_xmit
= 0;
291 u_long total_recv
= 0;
294 * Miscellaneous flags
297 #define HORRIBLEOK 3 /* how many packets to let out */
298 int horrible
= 0; /* how many packets we drop for testing */
299 int secondhalf
= 0; /* second half of timeout period */
300 int printmsg
= 0; /* print time response analysis */
303 * The half time and finish time in internal time
305 u_long half_time
= 0;
306 u_long finish_time
= 0;
309 int ntptimesetmain
P((int argc
, char *argv
[]));
310 static void analysis
P((int final
));
311 static int have_enough
P((void));
312 static void transmit
P((register struct server
*server
));
313 static void receive
P((struct recvbuf
*rbufp
));
314 static void clock_filter
P((register struct server
*server
, s_fp d
, l_fp
*c
));
315 static void clock_count
P((void));
316 static struct server
*clock_select
P((void));
317 static void set_local_clock
P((void));
318 static struct server
*findserver
P((struct sockaddr_in
*addr
));
319 static void timer
P((void));
321 static RETSIGTYPE alarming
P((int sig
));
322 #endif /* SYS_WINNT */
323 static void init_alarm
P((void));
324 static void init_io
P((void));
325 static int sendpkt
P((struct sockaddr_in
*dest
, struct pkt
*pkt
, int len
));
326 void input_handler
P((l_fp
*xts
));
327 static void printserver
P((register struct server
*pp
, FILE *fp
));
328 #if !defined(HAVE_VSPRINTF)
329 int vsprintf
P((char *str
, const char *fmt
, va_list ap
));
332 #ifdef HAVE_SIGNALED_IO
333 extern void wait_for_signal
P((void));
334 extern void unblock_io_and_alarm
P((void));
335 extern void block_io_and_alarm
P((void));
339 #ifdef NO_MAIN_ALLOWED
340 CALL(ntptimeset
,"ntptimeset",ntptimesetmain
);
352 * Initializing flag. All async routines watch this and only do their
353 * thing when it is clear.
358 * Alarm flag. Set when an alarm occurs
363 * Unpriviledged port flag.
368 * Systemwide parameters and flags
370 sys_numservers
= 0; /* number of servers to poll */
371 sys_authenticate
= 0; /* true when authenticating */
372 sys_authkey
= 0; /* set to authentication key in use */
373 sys_authdelay
= 0; /* authentication delay */
376 * The current internal time
382 #endif /* NO_MAIN_ALLOWED */
385 * Main program. Initialize us and loop waiting for I/O and/or
388 #ifndef NO_MAIN_ALLOWED
395 return ntptimesetmain(argc
, argv
);
397 #endif /* NO_MAIN_ALLOWED */
408 struct recvbuf
*rbuf
;
412 extern char *ntp_optarg
;
413 extern int ntp_optind
;
418 HANDLE process_handle
;
420 wVersionRequested
= MAKEWORD(1,1);
421 if (WSAStartup(wVersionRequested
, &wsaData
)) {
422 msyslog(LOG_ERR
, "No useable winsock.dll: %m");
425 #endif /* SYS_WINNT */
427 #ifdef NO_MAIN_ALLOWED
437 * Decode argument list
439 while ((c
= ntp_getopt(argc
, argv
, "a:c:de:slt:uvHS:V:")) != EOF
)
443 c
= atoi(ntp_optarg
);
444 sys_authenticate
= 1;
448 cfgpath
= ntp_optarg
;
454 if (!atolfp(ntp_optarg
, &tmp
)
456 (void) fprintf(stderr
,
457 "%s: encryption delay %s is unlikely\n",
458 progname
, ntp_optarg
);
461 sys_authdelay
= tmp
.l_uf
;
471 ltmp
= atoi(ntp_optarg
);
473 (void) fprintf(stderr
,
474 "%s: maximum time period (%d) is invalid\n",
491 ltmp
= atoi(ntp_optarg
);
493 (void) fprintf(stderr
,
494 "%s: minimum responding (%d) is invalid\n",
502 ltmp
= atoi(ntp_optarg
);
504 (void) fprintf(stderr
,
505 "%s: minimum valid (%d) is invalid\n",
520 if (errflg
|| ntp_optind
< argc
) {
521 fprintf(stderr
,"usage: %s [switches...]\n",progname
);
522 fprintf(stderr
," -v (verbose)\n");
523 fprintf(stderr
," -c path (set config file path)\n");
524 fprintf(stderr
," -a key (authenticate using key)\n");
525 fprintf(stderr
," -e delay (authentication delay)\n");
526 fprintf(stderr
," -S num (# of servers that must respond)\n");
527 fprintf(stderr
," -V num (# of servers that must valid)\n");
528 fprintf(stderr
," -s (set the time based if okay)\n");
529 fprintf(stderr
," -t secs (time period before ending)\n");
530 fprintf(stderr
," -l (use syslog facility)\n");
531 fprintf(stderr
," -u (use unprivileged port)\n");
532 fprintf(stderr
," -H (drop packets for debugging)\n");
533 fprintf(stderr
," -d (debug output)\n");
538 * Logging. Open the syslog if we have to
541 #if !defined (SYS_WINNT) && !defined (SYS_VXWORKS) && !defined SYS_CYGWIN32
543 openlog("ntptimeset", LOG_PID
);
547 # define LOG_NTP LOG_DAEMON
549 openlog("ntptimeset", LOG_PID
| LOG_NDELAY
, LOG_NTP
);
551 setlogmask(LOG_UPTO(LOG_DEBUG
));
553 setlogmask(LOG_UPTO(LOG_INFO
));
554 # endif /* LOG_DAEMON */
555 #endif /* SYS_WINNT */
558 if (debug
|| verbose
)
559 msyslog(LOG_INFO
, "%s", Version
);
562 msyslog(LOG_INFO
, "Dropping %d out of %d packets",
563 horrible
,horrible
+HORRIBLEOK
);
565 * Add servers we are going to be polling
567 loadservers(cfgpath
);
569 if (sys_numservers
< min_servers
) {
570 msyslog(LOG_ERR
, "Found %d servers, require %d servers",
571 sys_numservers
,min_servers
);
576 * determine when we will end at least
578 finish_time
= max_period
* TIMER_HZ
;
579 half_time
= finish_time
>> 1;
582 * Initialize the time of day routines and the I/O subsystem
584 if (sys_authenticate
) {
587 if (!key_file
) key_file
= KEYFILE
;
588 if (!ExpandEnvironmentStrings(key_file
, key_file_storage
, MAX_PATH
))
590 msyslog(LOG_ERR
, "ExpandEnvironmentStrings(%s) failed: %m\n",
593 key_file
= key_file_storage
;
595 #endif /* SYS_WINNT */
597 if (!authreadkeys(key_file
)) {
598 msyslog(LOG_ERR
, "no key file, exiting");
601 if (!authistrusted(sys_authkey
)) {
604 (void) sprintf(buf
, "%lu", (unsigned long)sys_authkey
);
605 msyslog(LOG_ERR
, "authentication key %s unknown", buf
);
616 taskPrioritySet( taskIdSelf(), NTPDATE_PRIO
);
618 #if defined(HAVE_ATT_NICE)
621 #if defined(HAVE_BSD_NICE)
622 (void) setpriority(PRIO_PROCESS
, 0, NTPDATE_PRIO
);
625 process_handle
= GetCurrentProcess();
626 if (!SetPriorityClass(process_handle
, (DWORD
) REALTIME_PRIORITY_CLASS
)) {
627 msyslog(LOG_ERR
, "SetPriorityClass failed: %m");
629 #endif /* SYS_WINNT */
634 * Use select() on all on all input fd's for unlimited
635 * time. select() will terminate on SIGALARM or on the
636 * reception of input. Using select() means we can't do
637 * robust signal handling and we get a potential race
638 * between checking for alarms and doing the select().
639 * Mostly harmless, I think.
640 * Keep going until we have enough information, or time is up.
642 /* On VMS, I suspect that select() can't be interrupted
643 * by a "signal" either, so I take the easy way out and
644 * have select() time out after one second.
645 * System clock updates really aren't time-critical,
646 * and - lacking a hardware reference clock - I have
647 * yet to learn about anything else that is.
650 while (finish_time
> current_time
) {
651 #if !defined(HAVE_SIGNALED_IO)
654 #elif defined(HAVE_SIGNALED_IO)
655 block_io_and_alarm();
658 tot_recvbufs
= full_recvbuffs(); /* get received buffers */
663 if (alarm_flag
) { /* alarmed? */
668 if (!was_alarmed
&& tot_recvbufs
> 0) {
670 * Nothing to do. Wait for something.
672 #ifndef HAVE_SIGNALED_IO
674 # if defined(VMS) || defined(SYS_VXWORKS)
675 /* make select() wake up after one second */
679 t1
.tv_sec
= 1; t1
.tv_usec
= 0;
680 nfound
= select(fd
+1, &rdfdes
, (fd_set
*)0,
684 nfound
= select(fd
+1, &rdfdes
, (fd_set
*)0,
685 (fd_set
*)0, (struct timeval
*)0);
690 (void)input_handler(&ts
);
692 else if (nfound
== -1 && errno
!= EINTR
)
693 msyslog(LOG_ERR
, "select() error: %m");
695 # if !defined SYS_VXWORKS && !defined SYS_CYGWIN32 /* to unclutter log */
696 msyslog(LOG_DEBUG
, "select(): nfound=%d, error: %m", nfound
);
699 #else /* HAVE_SIGNALED_IO */
702 #endif /* HAVE_SIGNALED_IO */
703 if (alarm_flag
) /* alarmed? */
708 tot_recvbufs
= full_recvbuffs(); /* get received buffers */
710 #ifdef HAVE_SIGNALED_IO
711 unblock_io_and_alarm();
712 #endif /* HAVE_SIGNALED_IO */
715 * Out here, signals are unblocked. Call timer routine
725 * Call the data procedure to handle each received
728 rbuf
= get_full_recv_buffer();
733 rbuf
= get_full_recv_buffer();
737 * Do we have enough information to stop now?
740 break; /* time to end */
748 * adjust the clock and exit accordingly
753 * if we get here then we are in trouble
760 * analysis - print a message indicating what is happening with time service
761 * must mimic have_enough() procedure.
768 if (contacted
< sys_numservers
) {
769 printf("%d servers of %d have been probed with %d packets\n",
770 contacted
,sys_numservers
,MINTRANSMITS
);
774 printf("No response from any of %d servers, network problem?\n",
778 else if (responding
< min_servers
) {
779 printf("%d servers out of %d responding, need at least %d.\n",
780 responding
, sys_numservers
, min_servers
);
784 printf("%d servers responding but none have valid time\n",
788 else if (validcount
< min_valid
) {
789 printf("%d servers responding, %d are valid, need %d valid\n",
790 responding
,validcount
,min_valid
);
793 if (!final
&& valid_n_low
!= validcount
) {
794 printf("%d valid servers but only %d have low dispersion\n",
795 validcount
,valid_n_low
);
801 /* have_enough - see if we have enough information to terminate probing
806 /* have we contacted all servers yet? */
807 if (contacted
< sys_numservers
)
808 return 0; /* no...try some more */
810 /* have we got at least minimum servers responding? */
811 if (responding
< min_servers
)
812 return 0; /* no...try some more */
814 /* count the clocks */
815 (void) clock_count();
817 /* have we got at least minimum valid clocks? */
818 if (validcount
<= 0 || validcount
< min_valid
)
819 return 0; /* no...try some more */
821 /* do we have all valid servers with low dispersion */
822 if (!secondhalf
&& valid_n_low
!= validcount
)
825 /* if we get into the secondhalf then we ignore dispersion */
827 /* all conditions have been met...end */
833 * transmit - transmit a packet to the given server, or mark it completed.
834 * This is called by the timeout routine and by the receive
839 register struct server
*server
846 printf("transmit(%s)\n", ntoa(&server
->srcadr
));
848 if ((server
->reach
& 01) == 0) {
851 * Last message to this server timed out. Shift
852 * zeros into the filter.
855 clock_filter(server
, 0, &ts
);
859 * shift reachable register over
864 * If we're here, send another message to the server. Fill in
865 * the packet and let 'er rip.
867 xpkt
.li_vn_mode
= PKT_LI_VN_MODE(LEAP_NOTINSYNC
,
868 server
->version
, MODE_CLIENT
);
869 xpkt
.stratum
= STRATUM_TO_PKT(STRATUM_UNSPEC
);
870 xpkt
.ppoll
= NTP_MINPOLL
;
871 xpkt
.precision
= NTPDATE_PRECISION
;
872 xpkt
.rootdelay
= htonl(NTPDATE_DISTANCE
);
873 xpkt
.rootdispersion
= htonl(NTPDATE_DISP
);
874 xpkt
.refid
= htonl(NTPDATE_REFID
);
875 L_CLR(&xpkt
.reftime
);
880 * Determine whether to authenticate or not. If so,
881 * fill in the extended part of the packet and do it.
882 * If not, just timestamp it and send it away.
884 if (sys_authenticate
) {
887 xpkt
.exten
[0] = htonl(sys_authkey
);
888 get_systime(&server
->xmt
);
889 L_ADDUF(&server
->xmt
, sys_authdelay
);
890 HTONL_FP(&server
->xmt
, &xpkt
.xmt
);
891 len
= authencrypt(sys_authkey
, (u_int32
*)&xpkt
, LEN_PKT_NOMAC
);
892 if (sendpkt(&(server
->srcadr
), &xpkt
, (int)(LEN_PKT_NOMAC
+ len
))) {
894 printf("failed transmit auth to %s\n",
895 ntoa(&(server
->srcadr
)));
900 printf("transmit auth to %s\n",
901 ntoa(&(server
->srcadr
)));
903 get_systime(&(server
->xmt
));
904 HTONL_FP(&server
->xmt
, &xpkt
.xmt
);
905 if (sendpkt(&(server
->srcadr
), &xpkt
, LEN_PKT_NOMAC
)) {
907 printf("failed transmit to %s\n",
908 ntoa(&(server
->srcadr
)));
913 printf("transmit to %s\n", ntoa(&(server
->srcadr
)));
917 * count transmits, record contacted count and set transmit time
919 if (++server
->xmtcnt
== MINTRANSMITS
)
921 server
->last_xmit
= current_time
;
924 * determine timeout for this packet. The more packets we send
925 * to the host, the slower we get. If the host indicates that
926 * it is not "sane" then we expect even less.
928 if (server
->xmtcnt
< MINTRANSMITS
) {
929 /* we have not sent enough */
930 timeout
= TIMER_HZ
; /* 1 second probe */
932 else if (server
->rcvcnt
<= 0) {
933 /* we have heard nothing */
935 timeout
= TIMER_HZ
<<4; /* 16 second probe */
937 timeout
= TIMER_HZ
<<3; /* 8 second probe */
940 /* if we have low dispersion then probe infrequently */
941 if (server
->dispersion
<= DESIREDDISP
)
942 timeout
= TIMER_HZ
<<4; /* 16 second probe */
943 /* if the server is not in sync then let it alone */
944 else if (server
->leap
== LEAP_NOTINSYNC
)
945 timeout
= TIMER_HZ
<<4; /* 16 second probe */
946 /* if the server looks broken ignore it */
947 else if (server
->org
.l_ui
< server
->reftime
.l_ui
)
948 timeout
= TIMER_HZ
<<5; /* 32 second probe */
950 timeout
= TIMER_HZ
<<2; /* 4 second probe */
952 timeout
= TIMER_HZ
<<1; /* 2 second probe */
956 * set next transmit time based on timeout
958 server
->event_time
= current_time
+ timeout
;
963 * receive - receive and process an incoming frame
967 struct recvbuf
*rbufp
970 register struct pkt
*rpkt
;
971 register struct server
*server
;
981 printf("receive(%s)\n", ntoa(&rbufp
->srcadr
));
983 * Check to see if the packet basically looks like something
986 if (rbufp
->recv_length
== LEN_PKT_NOMAC
)
988 else if (rbufp
->recv_length
>= LEN_PKT_NOMAC
)
992 printf("receive: packet length %d\n",
994 return; /* funny length packet */
997 rpkt
= &(rbufp
->recv_pkt
);
998 if (PKT_VERSION(rpkt
->li_vn_mode
) < NTP_OLDVERSION
||
999 PKT_VERSION(rpkt
->li_vn_mode
) > NTP_VERSION
) {
1001 printf("receive: bad version %d\n",
1002 PKT_VERSION(rpkt
->li_vn_mode
));
1006 if ((PKT_MODE(rpkt
->li_vn_mode
) != MODE_SERVER
1007 && PKT_MODE(rpkt
->li_vn_mode
) != MODE_PASSIVE
)
1008 || rpkt
->stratum
>=STRATUM_UNSPEC
) {
1010 printf("receive: mode %d stratum %d\n",
1011 PKT_MODE(rpkt
->li_vn_mode
), rpkt
->stratum
);
1016 * So far, so good. See if this is from a server we know.
1018 server
= findserver(&(rbufp
->srcadr
));
1019 if (server
== NULL
) {
1021 printf("receive: server not found\n");
1026 * Decode the org timestamp and make sure we're getting a response
1027 * to our last request.
1029 NTOHL_FP(&rpkt
->org
, &org
);
1030 if (!L_ISEQU(&org
, &server
->xmt
)) {
1032 printf("receive: pkt.org and peer.xmt differ\n");
1037 * Check out the authenticity if we're doing that.
1039 if (!sys_authenticate
)
1045 printf("receive: rpkt keyid=%ld sys_authkey=%ld decrypt=%ld\n",
1046 (long int)ntohl(rpkt
->exten
[0]), (long int)sys_authkey
,
1047 (long int)authdecrypt(sys_authkey
, (u_int32
*)rpkt
,
1048 LEN_PKT_NOMAC
, (int)(rbufp
->recv_length
- LEN_PKT_NOMAC
)));
1050 if (has_mac
&& ntohl(rpkt
->exten
[0]) == sys_authkey
&&
1051 authdecrypt(sys_authkey
, (u_int32
*)rpkt
, LEN_PKT_NOMAC
,
1052 (int)(rbufp
->recv_length
- LEN_PKT_NOMAC
)))
1055 printf("receive: authentication %s\n",
1056 is_authentic
? "passed" : "failed");
1058 server
->trust
<<= 1;
1063 * Looks good. Record info from the packet.
1065 server
->leap
= PKT_LEAP(rpkt
->li_vn_mode
);
1066 server
->stratum
= PKT_TO_STRATUM(rpkt
->stratum
);
1067 server
->precision
= rpkt
->precision
;
1068 server
->rootdelay
= ntohl(rpkt
->rootdelay
);
1069 server
->rootdispersion
= ntohl(rpkt
->rootdispersion
);
1070 server
->refid
= rpkt
->refid
;
1071 NTOHL_FP(&rpkt
->reftime
, &server
->reftime
);
1072 NTOHL_FP(&rpkt
->rec
, &rec
);
1073 NTOHL_FP(&rpkt
->xmt
, &server
->org
);
1076 * count this guy as responding
1079 if (server
->rcvcnt
++ == 0)
1083 * Make sure the server is at least somewhat sane. If not, ignore
1086 if (L_ISZERO(&rec
) || !L_ISHIS(&server
->org
, &rec
)) {
1088 printf("receive: pkt insane\n");
1093 * Calculate the round trip delay (di) and the clock offset (ci).
1094 * We use the equations (reordered from those in the spec):
1096 * d = (t2 - t3) - (t1 - t0)
1097 * c = ((t2 - t3) + (t1 - t0)) / 2
1099 t10
= server
->org
; /* pkt.xmt == t1 */
1100 L_SUB(&t10
, &rbufp
->recv_time
); /* recv_time == t0*/
1102 t23
= rec
; /* pkt.rec == t2 */
1103 L_SUB(&t23
, &org
); /* pkt->org == t3 */
1105 /* now have (t2 - t3) and (t0 - t1). Calculate (ci) and (di) */
1111 * Calculate di in t23 in full precision, then truncate
1118 printf("offset: %s, delay %s\n", lfptoa(&ci
, 6), fptoa(di
, 5));
1120 di
+= (FP_SECOND
>> (-(int)NTPDATE_PRECISION
))
1121 + (FP_SECOND
>> (-(int)server
->precision
)) + NTP_MAXSKW
;
1123 if (di
<= 0) { /* value still too raunchy to use? */
1127 di
= max(di
, NTP_MINDIST
);
1132 * This one is valid. Give it to clock_filter(),
1134 clock_filter(server
, di
, &ci
);
1136 printf("receive from %s\n", ntoa(&rbufp
->srcadr
));
1139 * See if we should goes the transmission. If not return now
1140 * otherwise have the next event time be shortened
1142 if (server
->stratum
<= NTP_INFIN
)
1143 return; /* server does not have a stratum */
1144 if (server
->leap
== LEAP_NOTINSYNC
)
1145 return; /* just booted server or out of sync */
1146 if (!L_ISHIS(&server
->org
, &server
->reftime
))
1147 return; /* broken host */
1148 if (server
->trust
!= 0)
1149 return; /* can not trust it */
1151 if (server
->dispersion
< DESIREDDISP
)
1152 return; /* we have the desired dispersion */
1154 server
->event_time
-= (TIMER_HZ
+1);
1159 * clock_filter - add clock sample, determine a server's delay, dispersion
1164 register struct server
*server
,
1173 * Insert sample and increment nextpt
1176 i
= server
->filter_nextpt
;
1177 server
->filter_delay
[i
] = di
;
1178 server
->filter_offset
[i
] = *c
;
1179 server
->filter_soffset
[i
] = LFPTOFP(c
);
1180 server
->filter_nextpt
++;
1181 if (server
->filter_nextpt
>= NTP_SHIFT
)
1182 server
->filter_nextpt
= 0;
1185 * Sort indices into increasing delay order
1187 for (i
= 0; i
< NTP_SHIFT
; i
++)
1190 for (i
= 0; i
< (NTP_SHIFT
-1); i
++) {
1191 for (j
= i
+1; j
< NTP_SHIFT
; j
++) {
1192 if (server
->filter_delay
[ord
[j
]] == 0)
1194 if (server
->filter_delay
[ord
[i
]] == 0
1195 || (server
->filter_delay
[ord
[i
]]
1196 > server
->filter_delay
[ord
[j
]])) {
1207 * Now compute the dispersion, and assign values to delay and
1208 * offset. If there are no samples in the register, delay and
1209 * offset go to zero and dispersion is set to the maximum.
1211 if (server
->filter_delay
[ord
[0]] == 0) {
1213 L_CLR(&server
->offset
);
1214 server
->soffset
= 0;
1215 server
->dispersion
= PEER_MAXDISP
;
1219 server
->delay
= server
->filter_delay
[ord
[0]];
1220 server
->offset
= server
->filter_offset
[ord
[0]];
1221 server
->soffset
= LFPTOFP(&server
->offset
);
1222 server
->dispersion
= 0;
1223 for (i
= 1; i
< NTP_SHIFT
; i
++) {
1224 if (server
->filter_delay
[ord
[i
]] == 0)
1227 d
= server
->filter_soffset
[ord
[i
]]
1228 - server
->filter_soffset
[ord
[0]];
1231 if (d
> PEER_MAXDISP
)
1235 * XXX This *knows* PEER_FILTER is 1/2
1237 server
->dispersion
+= (u_fp
)(d
) >> i
;
1246 /* clock_count - count the clock sources we have
1251 register struct server
*server
;
1255 validcount
= valid_n_low
= 0;
1257 /* go through the list of servers and count the clocks we believe
1258 * and that have low dispersion
1260 for (n
= 0; n
< sys_numservers
; n
++) {
1261 server
= sys_servers
[n
];
1262 if (server
->delay
== 0) {
1263 continue; /* no data */
1265 if (server
->stratum
> NTP_INFIN
) {
1266 continue; /* stratum no good */
1268 if (server
->delay
> NTP_MAXWGT
) {
1269 continue; /* too far away */
1271 if (server
->leap
== LEAP_NOTINSYNC
)
1272 continue; /* he's in trouble */
1273 if (!L_ISHIS(&server
->org
, &server
->reftime
)) {
1274 continue; /* very broken host */
1276 if ((server
->org
.l_ui
- server
->reftime
.l_ui
) >= NTP_MAXAGE
) {
1277 continue; /* too long without sync */
1279 if (server
->trust
!= 0) {
1284 * This one is a valid time source..
1289 * See if this one has a okay low dispersion
1291 if (server
->dispersion
<= DESIREDDISP
)
1296 printf("have %d, valid %d, low %d\n",
1297 responding
, validcount
, valid_n_low
);
1302 * clock_select - select the pick-of-the-litter clock from the samples
1305 static struct server
*
1308 register struct server
*server
;
1314 s_fp local_threshold
;
1315 struct server
*server_list
[NTP_MAXCLOCK
];
1316 u_fp server_badness
[NTP_MAXCLOCK
];
1317 struct server
*sys_server
;
1320 * This first chunk of code is supposed to go through all
1321 * servers we know about to find the NTP_MAXLIST servers which
1322 * are most likely to succeed. We run through the list
1323 * doing the sanity checks and trying to insert anyone who
1324 * looks okay. We are at all times aware that we should
1325 * only keep samples from the top two strata and we only need
1326 * NTP_MAXLIST of them.
1328 nlist
= 0; /* none yet */
1329 for (n
= 0; n
< sys_numservers
; n
++) {
1330 server
= sys_servers
[n
];
1331 if (server
->delay
== 0)
1332 continue; /* no data */
1333 if (server
->stratum
> NTP_INFIN
)
1334 continue; /* stratum no good */
1335 if (server
->delay
> NTP_MAXWGT
) {
1336 continue; /* too far away */
1338 if (server
->leap
== LEAP_NOTINSYNC
)
1339 continue; /* he's in trouble */
1340 if (!L_ISHIS(&server
->org
, &server
->reftime
)) {
1341 continue; /* very broken host */
1343 if ((server
->org
.l_ui
- server
->reftime
.l_ui
)
1345 continue; /* too long without sync */
1347 if (server
->trust
!= 0) {
1352 * This one seems sane. Find where he belongs
1355 d
= server
->dispersion
+ server
->dispersion
;
1356 for (i
= 0; i
< nlist
; i
++)
1357 if (server
->stratum
<= server_list
[i
]->stratum
)
1359 for ( ; i
< nlist
; i
++) {
1360 if (server
->stratum
< server_list
[i
]->stratum
)
1362 if (d
< (s_fp
) server_badness
[i
])
1367 * If i points past the end of the list, this
1368 * guy is a loser, else stick him in.
1370 if (i
>= NTP_MAXLIST
)
1372 for (j
= nlist
; j
> i
; j
--)
1373 if (j
< NTP_MAXLIST
) {
1374 server_list
[j
] = server_list
[j
-1];
1376 = server_badness
[j
-1];
1379 server_list
[i
] = server
;
1380 server_badness
[i
] = d
;
1381 if (nlist
< NTP_MAXLIST
)
1386 * Got the five-or-less best. Cut the list where the number of
1387 * strata exceeds two.
1390 for (i
= 1; i
< nlist
; i
++)
1391 if (server_list
[i
]->stratum
> server_list
[i
-1]->stratum
)
1398 * Whew! What we should have by now is 0 to 5 candidates for
1399 * the job of syncing us. If we have none, we're out of luck.
1400 * If we have one, he's a winner. If we have more, do falseticker
1406 else if (nlist
== 1) {
1407 sys_server
= server_list
[0];
1410 * Re-sort by stratum, bdelay estimate quality and
1413 for (i
= 0; i
< nlist
-1; i
++)
1414 for (j
= i
+1; j
< nlist
; j
++) {
1415 if (server_list
[i
]->stratum
1416 < server_list
[j
]->stratum
)
1417 break; /* already sorted by stratum */
1418 if (server_list
[i
]->delay
1419 < server_list
[j
]->delay
)
1421 server
= server_list
[i
];
1422 server_list
[i
] = server_list
[j
];
1423 server_list
[j
] = server
;
1427 * Calculate the fixed part of the dispersion limit
1429 local_threshold
= (FP_SECOND
>> (-(int)NTPDATE_PRECISION
))
1433 * Now drop samples until we're down to one.
1436 for (n
= 0; n
< nlist
; n
++) {
1437 server_badness
[n
] = 0;
1438 for (j
= 0; j
< nlist
; j
++) {
1439 if (j
== n
) /* with self? */
1441 d
= server_list
[j
]->soffset
1442 - server_list
[n
]->soffset
;
1443 if (d
< 0) /* absolute value */
1446 * XXX This code *knows* that
1449 for (i
= 0; i
< j
; i
++)
1450 d
= (d
>>1) + (d
>>2);
1451 server_badness
[n
] += d
;
1456 * We now have an array of nlist badness
1457 * coefficients. Find the badest. Find
1458 * the minimum precision while we're at
1462 n
= server_list
[0]->precision
;;
1463 for (j
= 1; j
< nlist
; j
++) {
1464 if (server_badness
[j
] >= server_badness
[i
])
1466 if (n
> server_list
[j
]->precision
)
1467 n
= server_list
[j
]->precision
;
1471 * i is the index of the server with the worst
1472 * dispersion. If his dispersion is less than
1473 * the threshold, stop now, else delete him and
1474 * continue around again.
1476 if (server_badness
[i
] < (local_threshold
1477 + (FP_SECOND
>> (-n
))))
1479 for (j
= i
+ 1; j
< nlist
; j
++)
1480 server_list
[j
-1] = server_list
[j
];
1485 * What remains is a list of less than 5 servers. Take
1488 sys_server
= server_list
[0];
1492 * That's it. Return our server.
1499 * set_local_clock -- handle setting the local clock or displaying info.
1502 set_local_clock(void)
1505 register struct server
*server
;
1510 * if setting time then print final analysis
1518 server
= clock_select();
1521 * do some display of information
1523 if (debug
|| verbose
) {
1524 for (i
= 0; i
< sys_numservers
; i
++)
1525 printserver(sys_servers
[i
], stdout
);
1527 printf("packets sent %ld, received %ld\n",
1528 total_xmit
, total_recv
);
1532 * see if we have a server to set the time with
1535 if (!set_time
|| verbose
)
1536 fprintf(stdout
,"No servers available to sync time with\n");
1541 * we have a valid and selected time to use!!!!!
1545 * if we are not setting the time then display offset and exit
1549 "Your clock is off by %s seconds. (%s) [%ld/%ld]\n",
1550 lfptoa(&server
->offset
, 7),
1551 ntoa(&server
->srcadr
),
1552 total_xmit
, total_recv
);
1558 * XXX: Examine the more flexible approach used by ntpdate.
1559 * Note that a design consideration here is that we sometimes
1560 * _want_ to step the clock by a _huge_ amount in either
1561 * direction, because the local clock is completely bogus.
1562 * This condition must be recognized and dealt with, so
1563 * that we always get a good time when this completes.
1564 * -- jhutz+@cmu.edu, 16-Aug-1999
1566 LFPTOD(&server
->offset
, dtemp
);
1567 step_systime(dtemp
);
1569 fprintf(stdout
,"Time set to %.20s [%s %s %ld/%ld]\n",
1571 ntoa(&server
->srcadr
),
1572 lfptoa(&server
->offset
, 7),
1573 total_xmit
, total_recv
);
1579 * findserver - find a server in the list given its address
1581 static struct server
*
1583 struct sockaddr_in
*addr
1587 register u_int32 netnum
;
1589 if (htons(addr
->sin_port
) != NTP_PORT
)
1591 netnum
= addr
->sin_addr
.s_addr
;
1593 for (i
= 0; i
< sys_numservers
; i
++) {
1594 if (netnum
== sys_servers
[i
]->srcadr
.sin_addr
.s_addr
)
1595 return sys_servers
[i
];
1602 * timer - process a timer interrupt
1610 * Bump the current idea of the time
1615 * see if we have reached half time
1617 if (current_time
>= half_time
&& !secondhalf
) {
1620 printf("\nSecond Half of Timeout!\n");
1625 * We only want to send a few packets per transmit interrupt
1626 * to throttle things
1628 for(k
= 0;k
< MAXXMITCOUNT
;k
++) {
1629 register int i
, oldi
;
1630 register u_long oldxtime
;
1633 * We want to send a packet out for a server that has an
1634 * expired event time. However to be mellow about this, we only
1635 * use one expired event timer and to avoid starvation we use
1636 * the one with the oldest last transmit time.
1640 for (i
= 0; i
< sys_numservers
; i
++) {
1641 if (sys_servers
[i
]->event_time
<= current_time
) {
1642 if (oldi
< 0 || oldxtime
> sys_servers
[i
]->last_xmit
) {
1643 oldxtime
= sys_servers
[i
]->last_xmit
;
1649 transmit(sys_servers
[oldi
]);
1651 break; /* no expired event */
1652 } /* end of transmit loop */
1658 * alarming - record the occurance of an alarm interrupt
1666 alarming(UINT uTimerID
, UINT uMsg
, DWORD dwUser
, DWORD dw1
, DWORD dw2
)
1667 #endif /* SYS_WINNT */
1674 * init_alarm - set up the timer interrupt
1680 # ifndef HAVE_TIMER_SETTIME
1681 struct itimerval itimer
;
1683 struct itimerspec ntpdate_itimer
;
1687 UINT wTimerRes
, wTimerID
;
1688 # endif /* SYS_WINNT */
1689 #if defined SYS_CYGWIN32 || defined SYS_WINNT
1691 TOKEN_PRIVILEGES tkp
;
1693 #endif /* SYS_WINNT */
1698 # if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME)
1700 /* this code was put in as setitimer() is non existant this us the
1701 * POSIX "equivalents" setup - casey
1703 /* ntpdate_timerid is global - so we can kill timer later */
1704 if (timer_create (CLOCK_REALTIME
, NULL
, &ntpdate_timerid
) ==
1712 fprintf (stderr
, "init_alarm(): timer_create (...) FAILED\n");
1717 * Set up the alarm interrupt. The first comes 1/(2*TIMER_HZ)
1718 * seconds from now and they continue on every 1/TIMER_HZ seconds.
1720 (void) signal_no_reset(SIGALRM
, alarming
);
1721 ntpdate_itimer
.it_interval
.tv_sec
= ntpdate_itimer
.it_value
.tv_sec
= 0;
1722 ntpdate_itimer
.it_interval
.tv_nsec
= 1000000000/TIMER_HZ
;
1723 ntpdate_itimer
.it_value
.tv_nsec
= 1000000000/(TIMER_HZ
<<1);
1724 timer_settime(ntpdate_timerid
, 0 /* !TIMER_ABSTIME */, &ntpdate_itimer
, NULL
);
1727 * Set up the alarm interrupt. The first comes 1/(2*TIMER_HZ)
1728 * seconds from now and they continue on every 1/TIMER_HZ seconds.
1730 (void) signal_no_reset(SIGALRM
, alarming
);
1731 itimer
.it_interval
.tv_sec
= itimer
.it_value
.tv_sec
= 0;
1732 itimer
.it_interval
.tv_usec
= 1000000/TIMER_HZ
;
1733 itimer
.it_value
.tv_usec
= 1000000/(TIMER_HZ
<<1);
1734 setitimer(ITIMER_REAL
, &itimer
, (struct itimerval
*)0);
1736 #if defined SYS_CYGWIN32
1738 * Get previleges needed for fiddling with the clock
1741 /* get the current process token handle */
1742 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
, &hToken
)) {
1743 msyslog(LOG_ERR
, "OpenProcessToken failed: %m");
1746 /* get the LUID for system-time privilege. */
1747 LookupPrivilegeValue(NULL
, SE_SYSTEMTIME_NAME
, &tkp
.Privileges
[0].Luid
);
1748 tkp
.PrivilegeCount
= 1; /* one privilege to set */
1749 tkp
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
1750 /* get set-time privilege for this process. */
1751 AdjustTokenPrivileges(hToken
, FALSE
, &tkp
, 0,(PTOKEN_PRIVILEGES
) NULL
, 0);
1752 /* cannot test return value of AdjustTokenPrivileges. */
1753 if (GetLastError() != ERROR_SUCCESS
)
1754 msyslog(LOG_ERR
, "AdjustTokenPrivileges failed: %m");
1756 #else /* SYS_WINNT */
1760 * Get previleges needed for fiddling with the clock
1763 /* get the current process token handle */
1764 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
, &hToken
)) {
1765 msyslog(LOG_ERR
, "OpenProcessToken failed: %m");
1768 /* get the LUID for system-time privilege. */
1769 LookupPrivilegeValue(NULL
, SE_SYSTEMTIME_NAME
, &tkp
.Privileges
[0].Luid
);
1770 tkp
.PrivilegeCount
= 1; /* one privilege to set */
1771 tkp
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
1772 /* get set-time privilege for this process. */
1773 AdjustTokenPrivileges(hToken
, FALSE
, &tkp
, 0,(PTOKEN_PRIVILEGES
) NULL
, 0);
1774 /* cannot test return value of AdjustTokenPrivileges. */
1775 if (GetLastError() != ERROR_SUCCESS
)
1776 msyslog(LOG_ERR
, "AdjustTokenPrivileges failed: %m");
1779 * Set up timer interrupts for every 2**EVENT_TIMEOUT seconds
1780 * Under Win/NT, expiry of timer interval leads to invocation
1781 * of a callback function (on a different thread) rather than
1782 * generating an alarm signal
1785 /* determine max and min resolution supported */
1786 if(timeGetDevCaps(&tc
, sizeof(TIMECAPS
)) != TIMERR_NOERROR
) {
1787 msyslog(LOG_ERR
, "timeGetDevCaps failed: %m");
1790 wTimerRes
= min(max(tc
.wPeriodMin
, TARGET_RESOLUTION
), tc
.wPeriodMax
);
1791 /* establish the minimum timer resolution that we'll use */
1792 timeBeginPeriod(wTimerRes
);
1794 /* start the timer event */
1795 wTimerID
= timeSetEvent(
1796 (UINT
) (1000/TIMER_HZ
), /* Delay */
1797 wTimerRes
, /* Resolution */
1798 (LPTIMECALLBACK
) alarming
, /* Callback function */
1799 (DWORD
) dwUser
, /* User data */
1800 TIME_PERIODIC
); /* Event type (periodic) */
1801 if (wTimerID
== 0) {
1802 msyslog(LOG_ERR
, "timeSetEvent failed: %m");
1805 #endif /* SYS_WINNT */
1810 * init_io - initialize I/O data and open socket
1816 WORD wVersionRequested
;
1818 init_transmitbuff();
1819 #endif /* SYS_WINNT */
1822 * Init buffer free list and stat counters
1824 init_recvbuff(sys_numservers
+ 2);
1826 #if defined(HAVE_SIGNALED_IO)
1831 wVersionRequested
= MAKEWORD(1,1);
1832 if (WSAStartup(wVersionRequested
, &wsaData
))
1834 msyslog(LOG_ERR
, "No useable winsock.dll: %m");
1837 #endif /* SYS_WINNT */
1841 /* create a datagram (UDP) socket */
1842 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
1843 msyslog(LOG_ERR
, "socket() failed: %m");
1849 * bind the socket to the NTP port
1851 if (!debug
&& set_time
&& !unpriv_port
) {
1852 struct sockaddr_in addr
;
1854 memset((char *)&addr
, 0, sizeof addr
);
1855 addr
.sin_family
= AF_INET
;
1856 addr
.sin_port
= htons(NTP_PORT
);
1857 addr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
1858 if (bind(fd
, (struct sockaddr
*)&addr
, sizeof(addr
)) < 0) {
1860 if (errno
== EADDRINUSE
)
1862 if (WSAGetLastError() == WSAEADDRINUSE
)
1865 "the NTP socket is in use, exiting");
1867 msyslog(LOG_ERR
, "bind() fails: %m");
1873 FD_SET(fd
, &fdmask
);
1880 /* in vxWorks we use FIONBIO, but the others are defined for old systems, so
1881 * all hell breaks loose if we leave them defined
1888 #if defined(O_NONBLOCK) /* POSIX */
1889 if (fcntl(fd
, F_SETFL
, O_NONBLOCK
) < 0)
1891 msyslog(LOG_ERR
, "fcntl(O_NONBLOCK) fails: %m");
1895 #elif defined(FNDELAY)
1896 if (fcntl(fd
, F_SETFL
, FNDELAY
) < 0)
1898 msyslog(LOG_ERR
, "fcntl(FNDELAY) fails: %m");
1902 #elif defined(O_NDELAY) /* generally the same as FNDELAY */
1903 if (fcntl(fd
, F_SETFL
, O_NDELAY
) < 0)
1905 msyslog(LOG_ERR
, "fcntl(O_NDELAY) fails: %m");
1909 #elif defined(FIONBIO)
1912 (ioctl(fd
,FIONBIO
,&1) < 0)
1913 # elif defined(SYS_WINNT)
1914 (ioctlsocket(fd
,FIONBIO
,(u_long
*) &on
) == SOCKET_ERROR
)
1916 (ioctl(fd
,FIONBIO
,&on
) < 0)
1920 msyslog(LOG_ERR
, "ioctl(FIONBIO) fails: %m");
1924 #elif defined(FIOSNBIO)
1925 if (ioctl(fd
,FIOSNBIO
,&on
) < 0)
1927 msyslog(LOG_ERR
, "ioctl(FIOSNBIO) fails: %m");
1932 # include "Bletch: Need non-blocking I/O!"
1935 #ifdef HAVE_SIGNALED_IO
1936 init_socket_sig(fd
);
1937 #endif /* not HAVE_SIGNALED_IO */
1944 * sendpkt - send a packet to the specified destination
1948 struct sockaddr_in
*dest
,
1954 static int horriblecnt
= 0;
1957 #endif /* SYS_WINNT */
1959 total_xmit
++; /* count it */
1962 if (++horriblecnt
> HORRIBLEOK
) {
1964 printf("dropping send (%s)\n", ntoa(dest
));
1965 if (horriblecnt
>= HORRIBLEOK
+horrible
)
1972 cc
= sendto(fd
, (char *)pkt
, (size_t)len
, 0, (struct sockaddr
*)dest
,
1973 sizeof(struct sockaddr_in
));
1976 if (errno
!= EWOULDBLOCK
&& errno
!= ENOBUFS
)
1978 if (cc
== SOCKET_ERROR
) {
1979 err
= WSAGetLastError();
1980 if (err
!= WSAEWOULDBLOCK
&& err
!= WSAENOBUFS
)
1981 #endif /* SYS_WINNT */
1982 msyslog(LOG_ERR
, "sendto(%s): %m", ntoa(dest
));
1990 * input_handler - receive packets asynchronously
1993 input_handler(l_fp
*xts
)
1996 register struct recvbuf
*rb
;
1997 struct timeval tvzero
;
2001 ts
= *xts
; /* we ignore xts, but make the compiler happy */
2004 * Do a poll to see if we have data
2008 tvzero
.tv_sec
= tvzero
.tv_usec
= 0;
2009 n
= select(fd
+1, &fds
, (fd_set
*)0, (fd_set
*)0, &tvzero
);
2012 * If nothing to do, just return. If an error occurred,
2013 * complain and return. If we've got some, freeze a
2019 if (errno
!= EINTR
) {
2020 msyslog(LOG_ERR
, "select() error: %m");
2027 * Get a buffer and read the frame. If we
2028 * haven't got a buffer, or this is received
2029 * on the wild card socket, just dump the packet.
2031 if (initializing
|| free_recvbuffs
== 0) {
2035 (void) read(fd
, buf
, sizeof buf
);
2037 /* NT's _read does not operate on nonblocking sockets
2038 * either recvfrom or ReadFile() has to be used here.
2039 * ReadFile is used in [ntpd]ntp_intres() and ntpdc,
2040 * just to be different use recvfrom() here
2042 recvfrom(fd
, buf
, sizeof(buf
), 0, (struct sockaddr
*)0, NULL
);
2043 #endif /* SYS_WINNT */
2047 rb
= get_free_recv_buffer();
2049 fromlen
= sizeof(struct sockaddr_in
);
2050 rb
->recv_length
= recvfrom(fd
, (char *)&rb
->recv_pkt
,
2051 sizeof(rb
->recv_pkt
), 0,
2052 (struct sockaddr
*)&rb
->srcadr
, &fromlen
);
2053 if (rb
->recv_length
== -1) {
2059 * Got one. Mark how and when it got here,
2060 * put it on the full list.
2063 add_full_recv_buffer(rb
);
2064 total_recv
++; /* count it */
2069 /* XXX ELIMINATE printserver similar in ntptrace.c, ntpdate.c */
2071 * printserver - print detail information for a server
2075 register struct server
*pp
,
2085 "%-15s %d/%d %03o v%d s%d offset %9s delay %s disp %s\n",
2087 pp
->xmtcnt
,pp
->rcvcnt
,pp
->reach
,
2088 pp
->version
,pp
->stratum
,
2089 lfptoa(&pp
->offset
, 6), ufptoa(pp
->delay
, 5),
2090 ufptoa(pp
->dispersion
, 4));
2094 (void) fprintf(fp
, "server %s, port %d\n",
2095 ntoa(&pp
->srcadr
), ntohs(pp
->srcadr
.sin_port
));
2097 (void) fprintf(fp
, "stratum %d, precision %d, leap %c%c, trust %03o\n",
2098 pp
->stratum
, pp
->precision
,
2099 pp
->leap
& 0x2 ? '1' : '0',
2100 pp
->leap
& 0x1 ? '1' : '0',
2103 if (pp
->stratum
== 1) {
2105 memmove(junk
, (char *)&pp
->refid
, 4);
2108 str
= numtoa(pp
->refid
);
2111 "refid [%s], delay %s, dispersion %s\n",
2112 str
, fptoa((s_fp
)pp
->delay
, 5),
2113 ufptoa(pp
->dispersion
, 5));
2115 (void) fprintf(fp
, "transmitted %d, received %d, reachable %03o\n",
2116 pp
->xmtcnt
, pp
->rcvcnt
, pp
->reach
);
2118 (void) fprintf(fp
, "reference time: %s\n",
2119 prettydate(&pp
->reftime
));
2120 (void) fprintf(fp
, "originate timestamp: %s\n",
2121 prettydate(&pp
->org
));
2122 (void) fprintf(fp
, "transmit timestamp: %s\n",
2123 prettydate(&pp
->xmt
));
2125 (void) fprintf(fp
, "filter delay: ");
2126 for (i
= 0; i
< NTP_SHIFT
; i
++) {
2127 (void) fprintf(fp
, " %-8.8s", fptoa(pp
->filter_delay
[i
], 5));
2128 if (i
== (NTP_SHIFT
>>1)-1)
2129 (void) fprintf(fp
, "\n ");
2131 (void) fprintf(fp
, "\n");
2133 (void) fprintf(fp
, "filter offset:");
2134 for (i
= 0; i
< PEER_SHIFT
; i
++) {
2135 (void) fprintf(fp
, " %-8.8s", lfptoa(&pp
->filter_offset
[i
], 6));
2136 if (i
== (PEER_SHIFT
>>1)-1)
2137 (void) fprintf(fp
, "\n ");
2139 (void) fprintf(fp
, "\n");
2141 (void) fprintf(fp
, "delay %s, dispersion %s\n",
2142 fptoa((s_fp
)pp
->delay
, 5), ufptoa(pp
->dispersion
, 5));
2144 (void) fprintf(fp
, "offset %s\n\n",
2145 lfptoa(&pp
->offset
, 6));
2148 #if !defined(HAVE_VSPRINTF)
2159 f
._flag
= _IOWRT
+_IOSTRG
;
2162 len
= _doprnt(fmt
, ap
, &f
);