xref: /freebsd/contrib/ntp/ntpdate/ntpdate.c (revision c0b746e5)
1c0b746e5SOllivier Robert /*
2c0b746e5SOllivier Robert  * ntpdate - set the time of day by polling one or more NTP servers
3c0b746e5SOllivier Robert  */
4c0b746e5SOllivier Robert 
5c0b746e5SOllivier Robert #ifdef HAVE_CONFIG_H
6c0b746e5SOllivier Robert # include <config.h>
7c0b746e5SOllivier Robert #endif
8c0b746e5SOllivier Robert 
9c0b746e5SOllivier Robert #ifdef HAVE_SYS_TYPES_H
10c0b746e5SOllivier Robert # include <sys/types.h>
11c0b746e5SOllivier Robert #endif
12c0b746e5SOllivier Robert #ifdef HAVE_UNISTD_H
13c0b746e5SOllivier Robert # include <unistd.h>
14c0b746e5SOllivier Robert #endif
15c0b746e5SOllivier Robert 
16c0b746e5SOllivier Robert #include <stdio.h>
17c0b746e5SOllivier Robert #include <signal.h>
18c0b746e5SOllivier Robert #include <ctype.h>
19c0b746e5SOllivier Robert #ifdef HAVE_POLL_H
20c0b746e5SOllivier Robert #include <poll.h>
21c0b746e5SOllivier Robert #endif
22c0b746e5SOllivier Robert #ifndef SYS_WINNT
23c0b746e5SOllivier Robert # include <netdb.h>
24c0b746e5SOllivier Robert # include <sys/signal.h>
25c0b746e5SOllivier Robert # include <sys/ioctl.h>
26c0b746e5SOllivier Robert #endif /* SYS_WINNT */
27c0b746e5SOllivier Robert #include <sys/time.h>
28c0b746e5SOllivier Robert #ifdef HAVE_SYS_RESOURCE_H
29c0b746e5SOllivier Robert # include <sys/resource.h>
30c0b746e5SOllivier Robert #endif /* HAVE_SYS_RESOURCE_H */
31c0b746e5SOllivier Robert 
32c0b746e5SOllivier Robert #ifdef SYS_VXWORKS
33c0b746e5SOllivier Robert # include "ioLib.h"
34c0b746e5SOllivier Robert # include "sockLib.h"
35c0b746e5SOllivier Robert # include "timers.h"
36c0b746e5SOllivier Robert 
37c0b746e5SOllivier Robert /* select wants a zero structure ... */
38c0b746e5SOllivier Robert struct timeval timeout = {0,0};
39c0b746e5SOllivier Robert #else
40c0b746e5SOllivier Robert struct timeval timeout = {60,0};
41c0b746e5SOllivier Robert #endif
42c0b746e5SOllivier Robert 
43c0b746e5SOllivier Robert 
44c0b746e5SOllivier Robert #if defined(SYS_HPUX)
45c0b746e5SOllivier Robert # include <utmp.h>
46c0b746e5SOllivier Robert #endif
47c0b746e5SOllivier Robert 
48c0b746e5SOllivier Robert #ifdef HAVE_NETINFO
49c0b746e5SOllivier Robert #include <netinfo/ni.h>
50c0b746e5SOllivier Robert #endif
51c0b746e5SOllivier Robert 
52c0b746e5SOllivier Robert #include "ntp_fp.h"
53c0b746e5SOllivier Robert #include "ntp.h"
54c0b746e5SOllivier Robert #include "ntp_io.h"
55c0b746e5SOllivier Robert #include "ntp_unixtime.h"
56c0b746e5SOllivier Robert #include "ntpdate.h"
57c0b746e5SOllivier Robert #include "ntp_string.h"
58c0b746e5SOllivier Robert #include "ntp_syslog.h"
59c0b746e5SOllivier Robert #include "ntp_select.h"
60c0b746e5SOllivier Robert #include "ntp_stdlib.h"
61c0b746e5SOllivier Robert #include "recvbuff.h"
62c0b746e5SOllivier Robert 
63c0b746e5SOllivier Robert #ifdef SYS_WINNT
64c0b746e5SOllivier Robert # define TARGET_RESOLUTION 1  /* Try for 1-millisecond accuracy
65c0b746e5SOllivier Robert 				on Windows NT timers. */
66c0b746e5SOllivier Robert #pragma comment(lib, "winmm")
67c0b746e5SOllivier Robert #endif /* SYS_WINNT */
68c0b746e5SOllivier Robert 
69c0b746e5SOllivier Robert /*
70c0b746e5SOllivier Robert  * Scheduling priority we run at
71c0b746e5SOllivier Robert  */
72c0b746e5SOllivier Robert #ifndef SYS_VXWORKS
73c0b746e5SOllivier Robert # define	NTPDATE_PRIO	(-12)
74c0b746e5SOllivier Robert #else
75c0b746e5SOllivier Robert # define	NTPDATE_PRIO	(100)
76c0b746e5SOllivier Robert #endif
77c0b746e5SOllivier Robert 
78c0b746e5SOllivier Robert #if defined(HAVE_TIMER_SETTIME) || defined (HAVE_TIMER_CREATE)
79c0b746e5SOllivier Robert /* POSIX TIMERS - vxWorks doesn't have itimer - casey */
80c0b746e5SOllivier Robert static timer_t ntpdate_timerid;
81c0b746e5SOllivier Robert #endif
82c0b746e5SOllivier Robert 
83c0b746e5SOllivier Robert /*
84c0b746e5SOllivier Robert  * Compatibility stuff for Version 2
85c0b746e5SOllivier Robert  */
86c0b746e5SOllivier Robert #define NTP_MAXSKW	0x28f	/* 0.01 sec in fp format */
87c0b746e5SOllivier Robert #define NTP_MINDIST 0x51f	/* 0.02 sec in fp format */
88c0b746e5SOllivier Robert #define PEER_MAXDISP	(64*FP_SECOND)	/* maximum dispersion (fp 64) */
89c0b746e5SOllivier Robert #define NTP_INFIN	15	/* max stratum, infinity a la Bellman-Ford */
90c0b746e5SOllivier Robert #define NTP_MAXWGT	(8*FP_SECOND)	/* maximum select weight 8 seconds */
91c0b746e5SOllivier Robert #define NTP_MAXLIST 5	/* maximum select list size */
92c0b746e5SOllivier Robert #define PEER_SHIFT	8	/* 8 suitable for crystal time base */
93c0b746e5SOllivier Robert 
94c0b746e5SOllivier Robert /*
95c0b746e5SOllivier Robert  * Debugging flag
96c0b746e5SOllivier Robert  */
97c0b746e5SOllivier Robert volatile int debug = 0;
98c0b746e5SOllivier Robert 
99c0b746e5SOllivier Robert /*
100c0b746e5SOllivier Robert  * File descriptor masks etc. for call to select
101c0b746e5SOllivier Robert  */
102c0b746e5SOllivier Robert int fd;
103c0b746e5SOllivier Robert #ifdef HAVE_POLL_H
104c0b746e5SOllivier Robert struct pollfd fdmask;
105c0b746e5SOllivier Robert #else
106c0b746e5SOllivier Robert fd_set fdmask;
107c0b746e5SOllivier Robert #endif
108c0b746e5SOllivier Robert 
109c0b746e5SOllivier Robert /*
110c0b746e5SOllivier Robert  * Initializing flag.  All async routines watch this and only do their
111c0b746e5SOllivier Robert  * thing when it is clear.
112c0b746e5SOllivier Robert  */
113c0b746e5SOllivier Robert int initializing = 1;
114c0b746e5SOllivier Robert 
115c0b746e5SOllivier Robert /*
116c0b746e5SOllivier Robert  * Alarm flag.	Set when an alarm occurs
117c0b746e5SOllivier Robert  */
118c0b746e5SOllivier Robert volatile int alarm_flag = 0;
119c0b746e5SOllivier Robert 
120c0b746e5SOllivier Robert /*
121c0b746e5SOllivier Robert  * Simple query flag.
122c0b746e5SOllivier Robert  */
123c0b746e5SOllivier Robert int simple_query = 0;
124c0b746e5SOllivier Robert 
125c0b746e5SOllivier Robert /*
126c0b746e5SOllivier Robert  * Unpriviledged port flag.
127c0b746e5SOllivier Robert  */
128c0b746e5SOllivier Robert int unpriv_port = 0;
129c0b746e5SOllivier Robert 
130c0b746e5SOllivier Robert /*
131c0b746e5SOllivier Robert  * Time to spend measuring drift rate
132c0b746e5SOllivier Robert  */
133c0b746e5SOllivier Robert int rate = 0;
134c0b746e5SOllivier Robert 
135c0b746e5SOllivier Robert /*
136c0b746e5SOllivier Robert  * Program name.
137c0b746e5SOllivier Robert  */
138c0b746e5SOllivier Robert char *progname;
139c0b746e5SOllivier Robert 
140c0b746e5SOllivier Robert /*
141c0b746e5SOllivier Robert  * Systemwide parameters and flags
142c0b746e5SOllivier Robert  */
143c0b746e5SOllivier Robert int sys_samples = DEFSAMPLES;	/* number of samples/server */
144c0b746e5SOllivier Robert u_long sys_timeout = DEFTIMEOUT; /* timeout time, in TIMER_HZ units */
145c0b746e5SOllivier Robert struct server **sys_servers;	/* the server list */
146c0b746e5SOllivier Robert int sys_numservers = 0; 	/* number of servers to poll */
147c0b746e5SOllivier Robert int sys_maxservers = 0; 	/* max number of servers to deal with */
148c0b746e5SOllivier Robert int sys_authenticate = 0;	/* true when authenticating */
149c0b746e5SOllivier Robert u_int32 sys_authkey = 0;	/* set to authentication key in use */
150c0b746e5SOllivier Robert u_long sys_authdelay = 0;	/* authentication delay */
151c0b746e5SOllivier Robert int sys_version = NTP_VERSION;	/* version to poll with */
152c0b746e5SOllivier Robert 
153c0b746e5SOllivier Robert /*
154c0b746e5SOllivier Robert  * The current internal time
155c0b746e5SOllivier Robert  */
156c0b746e5SOllivier Robert u_long current_time = 0;
157c0b746e5SOllivier Robert 
158c0b746e5SOllivier Robert /*
159c0b746e5SOllivier Robert  * Counter for keeping track of completed servers
160c0b746e5SOllivier Robert  */
161c0b746e5SOllivier Robert int complete_servers = 0;
162c0b746e5SOllivier Robert 
163c0b746e5SOllivier Robert /*
164c0b746e5SOllivier Robert  * File of encryption keys
165c0b746e5SOllivier Robert  */
166c0b746e5SOllivier Robert 
167c0b746e5SOllivier Robert #ifndef KEYFILE
168c0b746e5SOllivier Robert # ifndef SYS_WINNT
169c0b746e5SOllivier Robert #define KEYFILE 	"/etc/ntp.keys"
170c0b746e5SOllivier Robert # else
171c0b746e5SOllivier Robert #define KEYFILE 	"%windir%\\ntp.keys"
172c0b746e5SOllivier Robert # endif /* SYS_WINNT */
173c0b746e5SOllivier Robert #endif /* KEYFILE */
174c0b746e5SOllivier Robert 
175c0b746e5SOllivier Robert #ifndef SYS_WINNT
176c0b746e5SOllivier Robert const char *key_file = KEYFILE;
177c0b746e5SOllivier Robert #else
178c0b746e5SOllivier Robert char key_file_storage[MAX_PATH+1], *key_file ;
179c0b746e5SOllivier Robert #endif	 /* SYS_WINNT */
180c0b746e5SOllivier Robert 
181c0b746e5SOllivier Robert /*
182c0b746e5SOllivier Robert  * Miscellaneous flags
183c0b746e5SOllivier Robert  */
184c0b746e5SOllivier Robert int verbose = 0;
185c0b746e5SOllivier Robert int always_step = 0;
186c0b746e5SOllivier Robert int never_step = 0;
187c0b746e5SOllivier Robert 
188c0b746e5SOllivier Robert int 	ntpdatemain P((int, char **));
189c0b746e5SOllivier Robert static	void	transmit	P((struct server *));
190c0b746e5SOllivier Robert static	void	receive 	P((struct recvbuf *));
191c0b746e5SOllivier Robert static	void	server_data P((struct server *, s_fp, l_fp *, u_fp));
192c0b746e5SOllivier Robert static	void	clock_filter	P((struct server *));
193c0b746e5SOllivier Robert static	struct server *clock_select P((void));
194c0b746e5SOllivier Robert static	int clock_adjust	P((void));
195c0b746e5SOllivier Robert static	void	addserver	P((char *));
196c0b746e5SOllivier Robert static	struct server *findserver P((struct sockaddr_in *));
197c0b746e5SOllivier Robert 		void	timer		P((void));
198c0b746e5SOllivier Robert static	void	init_alarm	P((void));
199c0b746e5SOllivier Robert #ifndef SYS_WINNT
200c0b746e5SOllivier Robert static	RETSIGTYPE alarming P((int));
201c0b746e5SOllivier Robert #endif /* SYS_WINNT */
202c0b746e5SOllivier Robert static	void	init_io 	P((void));
203c0b746e5SOllivier Robert static	void	sendpkt 	P((struct sockaddr_in *, struct pkt *, int));
204c0b746e5SOllivier Robert void	input_handler	P((void));
205c0b746e5SOllivier Robert 
206c0b746e5SOllivier Robert static	int l_adj_systime	P((l_fp *));
207c0b746e5SOllivier Robert static	int l_step_systime	P((l_fp *));
208c0b746e5SOllivier Robert 
209c0b746e5SOllivier Robert static	int getnetnum	P((const char *, u_int32 *));
210c0b746e5SOllivier Robert static	void	printserver P((struct server *, FILE *));
211c0b746e5SOllivier Robert 
212c0b746e5SOllivier Robert #ifdef SYS_WINNT
213c0b746e5SOllivier Robert int 	on = 1;
214c0b746e5SOllivier Robert WORD	wVersionRequested;
215c0b746e5SOllivier Robert WSADATA wsaData;
216c0b746e5SOllivier Robert HANDLE	TimerThreadHandle = NULL;
217c0b746e5SOllivier Robert #endif /* SYS_WINNT */
218c0b746e5SOllivier Robert 
219c0b746e5SOllivier Robert #ifdef NO_MAIN_ALLOWED
220c0b746e5SOllivier Robert CALL(ntpdate,"ntpdate",ntpdatemain);
221c0b746e5SOllivier Robert 
222c0b746e5SOllivier Robert void clear_globals()
223c0b746e5SOllivier Robert {
224c0b746e5SOllivier Robert   /*
225c0b746e5SOllivier Robert    * Debugging flag
226c0b746e5SOllivier Robert    */
227c0b746e5SOllivier Robert   debug = 0;
228c0b746e5SOllivier Robert 
229c0b746e5SOllivier Robert   ntp_optind = 0;
230c0b746e5SOllivier Robert   /*
231c0b746e5SOllivier Robert    * Initializing flag.  All async routines watch this and only do their
232c0b746e5SOllivier Robert    * thing when it is clear.
233c0b746e5SOllivier Robert    */
234c0b746e5SOllivier Robert   initializing = 1;
235c0b746e5SOllivier Robert 
236c0b746e5SOllivier Robert   /*
237c0b746e5SOllivier Robert    * Alarm flag.  Set when an alarm occurs
238c0b746e5SOllivier Robert    */
239c0b746e5SOllivier Robert   alarm_flag = 0;
240c0b746e5SOllivier Robert 
241c0b746e5SOllivier Robert   /*
242c0b746e5SOllivier Robert    * Simple query flag.
243c0b746e5SOllivier Robert    */
244c0b746e5SOllivier Robert   simple_query = 0;
245c0b746e5SOllivier Robert 
246c0b746e5SOllivier Robert   /*
247c0b746e5SOllivier Robert    * Unpriviledged port flag.
248c0b746e5SOllivier Robert    */
249c0b746e5SOllivier Robert   unpriv_port = 0;
250c0b746e5SOllivier Robert 
251c0b746e5SOllivier Robert   /*
252c0b746e5SOllivier Robert    * Time to spend measuring drift rate
253c0b746e5SOllivier Robert    */
254c0b746e5SOllivier Robert   rate = 0;
255c0b746e5SOllivier Robert   /*
256c0b746e5SOllivier Robert    * Systemwide parameters and flags
257c0b746e5SOllivier Robert    */
258c0b746e5SOllivier Robert   sys_numservers = 0;	  /* number of servers to poll */
259c0b746e5SOllivier Robert   sys_maxservers = 0;	  /* max number of servers to deal with */
260c0b746e5SOllivier Robert   sys_authenticate = 0;   /* true when authenticating */
261c0b746e5SOllivier Robert   sys_authkey = 0;	   /* set to authentication key in use */
262c0b746e5SOllivier Robert   sys_authdelay = 0;   /* authentication delay */
263c0b746e5SOllivier Robert   sys_version = NTP_VERSION;  /* version to poll with */
264c0b746e5SOllivier Robert 
265c0b746e5SOllivier Robert   /*
266c0b746e5SOllivier Robert    * The current internal time
267c0b746e5SOllivier Robert    */
268c0b746e5SOllivier Robert   current_time = 0;
269c0b746e5SOllivier Robert 
270c0b746e5SOllivier Robert   /*
271c0b746e5SOllivier Robert    * Counter for keeping track of completed servers
272c0b746e5SOllivier Robert    */
273c0b746e5SOllivier Robert   complete_servers = 0;
274c0b746e5SOllivier Robert   verbose = 0;
275c0b746e5SOllivier Robert   always_step = 0;
276c0b746e5SOllivier Robert   never_step = 0;
277c0b746e5SOllivier Robert }
278c0b746e5SOllivier Robert #endif
279c0b746e5SOllivier Robert 
280c0b746e5SOllivier Robert #ifdef HAVE_NETINFO
281c0b746e5SOllivier Robert static ni_namelist *getnetinfoservers P((void));
282c0b746e5SOllivier Robert #endif
283c0b746e5SOllivier Robert 
284c0b746e5SOllivier Robert /*
285c0b746e5SOllivier Robert  * Main program.  Initialize us and loop waiting for I/O and/or
286c0b746e5SOllivier Robert  * timer expiries.
287c0b746e5SOllivier Robert  */
288c0b746e5SOllivier Robert #ifndef NO_MAIN_ALLOWED
289c0b746e5SOllivier Robert int
290c0b746e5SOllivier Robert main(
291c0b746e5SOllivier Robert 	int argc,
292c0b746e5SOllivier Robert 	char *argv[]
293c0b746e5SOllivier Robert 	)
294c0b746e5SOllivier Robert {
295c0b746e5SOllivier Robert 	return ntpdatemain (argc, argv);
296c0b746e5SOllivier Robert }
297c0b746e5SOllivier Robert #endif /* NO_MAIN_ALLOWED */
298c0b746e5SOllivier Robert 
299c0b746e5SOllivier Robert int
300c0b746e5SOllivier Robert ntpdatemain (
301c0b746e5SOllivier Robert 	int argc,
302c0b746e5SOllivier Robert 	char *argv[]
303c0b746e5SOllivier Robert 	)
304c0b746e5SOllivier Robert {
305c0b746e5SOllivier Robert 	int was_alarmed;
306c0b746e5SOllivier Robert 	struct recvbuf *rbuflist;
307c0b746e5SOllivier Robert 	struct recvbuf *rbuf;
308c0b746e5SOllivier Robert 	l_fp tmp;
309c0b746e5SOllivier Robert 	int errflg;
310c0b746e5SOllivier Robert 	int c;
311c0b746e5SOllivier Robert #ifdef HAVE_NETINFO
312c0b746e5SOllivier Robert 	ni_namelist *netinfoservers;
313c0b746e5SOllivier Robert #endif
314c0b746e5SOllivier Robert #ifdef SYS_WINNT
315c0b746e5SOllivier Robert 	HANDLE process_handle;
316c0b746e5SOllivier Robert 
317c0b746e5SOllivier Robert 	wVersionRequested = MAKEWORD(1,1);
318c0b746e5SOllivier Robert 	if (WSAStartup(wVersionRequested, &wsaData)) {
319c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "No useable winsock.dll: %m");
320c0b746e5SOllivier Robert 		exit(1);
321c0b746e5SOllivier Robert 	}
322c0b746e5SOllivier Robert 
323c0b746e5SOllivier Robert 	key_file = key_file_storage;
324c0b746e5SOllivier Robert 
325c0b746e5SOllivier Robert 	if (!ExpandEnvironmentStrings(KEYFILE, key_file, MAX_PATH))
326c0b746e5SOllivier Robert 	{
327c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "ExpandEnvironmentStrings(KEYFILE) failed: %m\n");
328c0b746e5SOllivier Robert 	}
329c0b746e5SOllivier Robert #endif /* SYS_WINNT */
330c0b746e5SOllivier Robert 
331c0b746e5SOllivier Robert #ifdef NO_MAIN_ALLOWED
332c0b746e5SOllivier Robert 	clear_globals();
333c0b746e5SOllivier Robert #endif
334c0b746e5SOllivier Robert 
335c0b746e5SOllivier Robert 	errflg = 0;
336c0b746e5SOllivier Robert 	progname = argv[0];
337c0b746e5SOllivier Robert 	syslogit = 0;
338c0b746e5SOllivier Robert 
339c0b746e5SOllivier Robert 	/*
340c0b746e5SOllivier Robert 	 * Decode argument list
341c0b746e5SOllivier Robert 	 */
342c0b746e5SOllivier Robert 	while ((c = ntp_getopt(argc, argv, "a:bBde:k:o:p:qr:st:uv")) != EOF)
343c0b746e5SOllivier Robert 		switch (c)
344c0b746e5SOllivier Robert 		{
345c0b746e5SOllivier Robert 		case 'a':
346c0b746e5SOllivier Robert 			c = atoi(ntp_optarg);
347c0b746e5SOllivier Robert 			sys_authenticate = 1;
348c0b746e5SOllivier Robert 			sys_authkey = c;
349c0b746e5SOllivier Robert 			break;
350c0b746e5SOllivier Robert 		case 'b':
351c0b746e5SOllivier Robert 			always_step++;
352c0b746e5SOllivier Robert 			never_step = 0;
353c0b746e5SOllivier Robert 			break;
354c0b746e5SOllivier Robert 		case 'B':
355c0b746e5SOllivier Robert 			never_step++;
356c0b746e5SOllivier Robert 			always_step = 0;
357c0b746e5SOllivier Robert 			break;
358c0b746e5SOllivier Robert 		case 'd':
359c0b746e5SOllivier Robert 			++debug;
360c0b746e5SOllivier Robert 			break;
361c0b746e5SOllivier Robert 		case 'e':
362c0b746e5SOllivier Robert 			if (!atolfp(ntp_optarg, &tmp)
363c0b746e5SOllivier Robert 			|| tmp.l_ui != 0) {
364c0b746e5SOllivier Robert 				(void) fprintf(stderr,
365c0b746e5SOllivier Robert 					   "%s: encryption delay %s is unlikely\n",
366c0b746e5SOllivier Robert 					   progname, ntp_optarg);
367c0b746e5SOllivier Robert 				errflg++;
368c0b746e5SOllivier Robert 			} else {
369c0b746e5SOllivier Robert 				sys_authdelay = tmp.l_uf;
370c0b746e5SOllivier Robert 			}
371c0b746e5SOllivier Robert 			break;
372c0b746e5SOllivier Robert 		case 'k':
373c0b746e5SOllivier Robert 			key_file = ntp_optarg;
374c0b746e5SOllivier Robert 			break;
375c0b746e5SOllivier Robert 		case 'o':
376c0b746e5SOllivier Robert 			sys_version = atoi(ntp_optarg);
377c0b746e5SOllivier Robert 			break;
378c0b746e5SOllivier Robert 		case 'p':
379c0b746e5SOllivier Robert 			c = atoi(ntp_optarg);
380c0b746e5SOllivier Robert 			if (c <= 0 || c > NTP_SHIFT) {
381c0b746e5SOllivier Robert 				(void) fprintf(stderr,
382c0b746e5SOllivier Robert 					   "%s: number of samples (%d) is invalid\n",
383c0b746e5SOllivier Robert 					   progname, c);
384c0b746e5SOllivier Robert 				errflg++;
385c0b746e5SOllivier Robert 			} else {
386c0b746e5SOllivier Robert 				sys_samples = c;
387c0b746e5SOllivier Robert 			}
388c0b746e5SOllivier Robert 			break;
389c0b746e5SOllivier Robert 		case 'q':
390c0b746e5SOllivier Robert 			simple_query = 1;
391c0b746e5SOllivier Robert 			break;
392c0b746e5SOllivier Robert 		case 'r':
393c0b746e5SOllivier Robert 			c = atoi(ntp_optarg);
394c0b746e5SOllivier Robert 			if (c <= 0 || c > (60 * 60)) {
395c0b746e5SOllivier Robert 				(void) fprintf(stderr,
396c0b746e5SOllivier Robert 					   "%s: rate (%d) is invalid: 0 - %d\n",
397c0b746e5SOllivier Robert 					   progname, c, (60 * 60));
398c0b746e5SOllivier Robert 				errflg++;
399c0b746e5SOllivier Robert 			} else {
400c0b746e5SOllivier Robert 				rate = c;
401c0b746e5SOllivier Robert 			}
402c0b746e5SOllivier Robert 			break;
403c0b746e5SOllivier Robert 		case 's':
404c0b746e5SOllivier Robert 			syslogit = 1;
405c0b746e5SOllivier Robert 			break;
406c0b746e5SOllivier Robert 		case 't':
407c0b746e5SOllivier Robert 			if (!atolfp(ntp_optarg, &tmp)) {
408c0b746e5SOllivier Robert 				(void) fprintf(stderr,
409c0b746e5SOllivier Robert 					   "%s: timeout %s is undecodeable\n",
410c0b746e5SOllivier Robert 					   progname, ntp_optarg);
411c0b746e5SOllivier Robert 				errflg++;
412c0b746e5SOllivier Robert 			} else {
413c0b746e5SOllivier Robert 				sys_timeout = ((LFPTOFP(&tmp) * TIMER_HZ)
414c0b746e5SOllivier Robert 					   + 0x8000) >> 16;
415c0b746e5SOllivier Robert 				if (sys_timeout == 0)
416c0b746e5SOllivier Robert 				sys_timeout = 1;
417c0b746e5SOllivier Robert 			}
418c0b746e5SOllivier Robert 			break;
419c0b746e5SOllivier Robert 		case 'v':
420c0b746e5SOllivier Robert 			verbose = 1;
421c0b746e5SOllivier Robert 			break;
422c0b746e5SOllivier Robert 		case 'u':
423c0b746e5SOllivier Robert 			unpriv_port = 1;
424c0b746e5SOllivier Robert 			break;
425c0b746e5SOllivier Robert 		case '?':
426c0b746e5SOllivier Robert 			++errflg;
427c0b746e5SOllivier Robert 			break;
428c0b746e5SOllivier Robert 		default:
429c0b746e5SOllivier Robert 			break;
430c0b746e5SOllivier Robert 	    }
431c0b746e5SOllivier Robert 
432c0b746e5SOllivier Robert 	if (errflg) {
433c0b746e5SOllivier Robert 		(void) fprintf(stderr,
434c0b746e5SOllivier Robert 				   "usage: %s [-bBdqsv] [-a key#] [-e delay] [-k file] [-p samples] [-o version#] [-r rate] [-t timeo] server ...\n",
435c0b746e5SOllivier Robert 				   progname);
436c0b746e5SOllivier Robert 		exit(2);
437c0b746e5SOllivier Robert 	}
438c0b746e5SOllivier Robert 
439c0b746e5SOllivier Robert 	if (debug || simple_query) {
440c0b746e5SOllivier Robert #ifdef HAVE_SETVBUF
441c0b746e5SOllivier Robert 		static char buf[BUFSIZ];
442c0b746e5SOllivier Robert 		setvbuf(stdout, buf, _IOLBF, BUFSIZ);
443c0b746e5SOllivier Robert #else
444c0b746e5SOllivier Robert 		setlinebuf(stdout);
445c0b746e5SOllivier Robert #endif
446c0b746e5SOllivier Robert 	}
447c0b746e5SOllivier Robert 
448c0b746e5SOllivier Robert 	/*
449c0b746e5SOllivier Robert 	 * Logging.  Open the syslog if we have to
450c0b746e5SOllivier Robert 	 */
451c0b746e5SOllivier Robert 	if (syslogit) {
452c0b746e5SOllivier Robert #if !defined (SYS_WINNT) && !defined (SYS_VXWORKS) && !defined SYS_CYGWIN32
453c0b746e5SOllivier Robert # ifndef	LOG_DAEMON
454c0b746e5SOllivier Robert 		openlog("ntpdate", LOG_PID);
455c0b746e5SOllivier Robert # else
456c0b746e5SOllivier Robert 
457c0b746e5SOllivier Robert #  ifndef	LOG_NTP
458c0b746e5SOllivier Robert #	define	LOG_NTP LOG_DAEMON
459c0b746e5SOllivier Robert #  endif
460c0b746e5SOllivier Robert 		openlog("ntpdate", LOG_PID | LOG_NDELAY, LOG_NTP);
461c0b746e5SOllivier Robert 		if (debug)
462c0b746e5SOllivier Robert 			setlogmask(LOG_UPTO(LOG_DEBUG));
463c0b746e5SOllivier Robert 		else
464c0b746e5SOllivier Robert 			setlogmask(LOG_UPTO(LOG_INFO));
465c0b746e5SOllivier Robert # endif /* LOG_DAEMON */
466c0b746e5SOllivier Robert #endif	/* SYS_WINNT */
467c0b746e5SOllivier Robert 	}
468c0b746e5SOllivier Robert 
469c0b746e5SOllivier Robert 	if (debug || verbose)
470c0b746e5SOllivier Robert 		msyslog(LOG_NOTICE, "%s", Version);
471c0b746e5SOllivier Robert 
472c0b746e5SOllivier Robert 	/*
473c0b746e5SOllivier Robert 	 * Add servers we are going to be polling
474c0b746e5SOllivier Robert 	 */
475c0b746e5SOllivier Robert 	sys_maxservers = argc - ntp_optind;
476c0b746e5SOllivier Robert #ifdef HAVE_NETINFO
477c0b746e5SOllivier Robert 	if ((netinfoservers = getnetinfoservers()))
478c0b746e5SOllivier Robert 		sys_maxservers += netinfoservers->ni_namelist_len;
479c0b746e5SOllivier Robert #endif
480c0b746e5SOllivier Robert 	sys_servers = (struct server **)
481c0b746e5SOllivier Robert 		emalloc(sys_maxservers * sizeof(struct server *));
482c0b746e5SOllivier Robert 
483c0b746e5SOllivier Robert 	for ( ; ntp_optind < argc; ntp_optind++)
484c0b746e5SOllivier Robert 		addserver(argv[ntp_optind]);
485c0b746e5SOllivier Robert 
486c0b746e5SOllivier Robert #ifdef HAVE_NETINFO
487c0b746e5SOllivier Robert 	if (netinfoservers) {
488c0b746e5SOllivier Robert 		if ( netinfoservers->ni_namelist_len &&
489c0b746e5SOllivier Robert 		    *netinfoservers->ni_namelist_val ) {
490c0b746e5SOllivier Robert 			u_int servercount = 0;
491c0b746e5SOllivier Robert 			while (servercount < netinfoservers->ni_namelist_len) {
492c0b746e5SOllivier Robert 				if (debug) msyslog(LOG_DEBUG,
493c0b746e5SOllivier Robert 						   "Adding time server %s from NetInfo configuration.",
494c0b746e5SOllivier Robert 						   netinfoservers->ni_namelist_val[servercount]);
495c0b746e5SOllivier Robert 				addserver(netinfoservers->ni_namelist_val[servercount++]);
496c0b746e5SOllivier Robert 			}
497c0b746e5SOllivier Robert 		}
498c0b746e5SOllivier Robert 		ni_namelist_free(netinfoservers);
499c0b746e5SOllivier Robert 		free(netinfoservers);
500c0b746e5SOllivier Robert 	}
501c0b746e5SOllivier Robert #endif
502c0b746e5SOllivier Robert 
503c0b746e5SOllivier Robert 	if (sys_numservers == 0) {
504c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "no servers can be used, exiting");
505c0b746e5SOllivier Robert 		exit(1);
506c0b746e5SOllivier Robert 	}
507c0b746e5SOllivier Robert 
508c0b746e5SOllivier Robert 	/*
509c0b746e5SOllivier Robert 	 * Initialize the time of day routines and the I/O subsystem
510c0b746e5SOllivier Robert 	 */
511c0b746e5SOllivier Robert 	if (sys_authenticate) {
512c0b746e5SOllivier Robert 		init_auth();
513c0b746e5SOllivier Robert 		if (!authreadkeys(key_file)) {
514c0b746e5SOllivier Robert 			msyslog(LOG_ERR, "no key file, exitting");
515c0b746e5SOllivier Robert 			exit(1);
516c0b746e5SOllivier Robert 		}
517c0b746e5SOllivier Robert 		if (!authistrusted(sys_authkey)) {
518c0b746e5SOllivier Robert 			char buf[10];
519c0b746e5SOllivier Robert 
520c0b746e5SOllivier Robert 			(void) sprintf(buf, "%lu", (unsigned long)sys_authkey);
521c0b746e5SOllivier Robert 			msyslog(LOG_ERR, "authentication key %s unknown", buf);
522c0b746e5SOllivier Robert 			exit(1);
523c0b746e5SOllivier Robert 		}
524c0b746e5SOllivier Robert 	}
525c0b746e5SOllivier Robert 	init_io();
526c0b746e5SOllivier Robert 	init_alarm();
527c0b746e5SOllivier Robert 
528c0b746e5SOllivier Robert 	/*
529c0b746e5SOllivier Robert 	 * Set the priority.
530c0b746e5SOllivier Robert 	 */
531c0b746e5SOllivier Robert #ifdef SYS_VXWORKS
532c0b746e5SOllivier Robert 	taskPrioritySet( taskIdSelf(), NTPDATE_PRIO);
533c0b746e5SOllivier Robert #endif
534c0b746e5SOllivier Robert #if defined(HAVE_ATT_NICE)
535c0b746e5SOllivier Robert 	nice (NTPDATE_PRIO);
536c0b746e5SOllivier Robert #endif
537c0b746e5SOllivier Robert #if defined(HAVE_BSD_NICE)
538c0b746e5SOllivier Robert 	(void) setpriority(PRIO_PROCESS, 0, NTPDATE_PRIO);
539c0b746e5SOllivier Robert #endif
540c0b746e5SOllivier Robert #ifdef SYS_WINNT
541c0b746e5SOllivier Robert 	process_handle = GetCurrentProcess();
542c0b746e5SOllivier Robert 	if (!SetPriorityClass(process_handle, (DWORD) REALTIME_PRIORITY_CLASS)) {
543c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "SetPriorityClass failed: %m");
544c0b746e5SOllivier Robert 	}
545c0b746e5SOllivier Robert #endif /* SYS_WINNT */
546c0b746e5SOllivier Robert 
547c0b746e5SOllivier Robert 	initializing = 0;
548c0b746e5SOllivier Robert 
549c0b746e5SOllivier Robert 	was_alarmed = 0;
550c0b746e5SOllivier Robert 	rbuflist = (struct recvbuf *)0;
551c0b746e5SOllivier Robert 	while (complete_servers < sys_numservers) {
552c0b746e5SOllivier Robert #ifdef HAVE_POLL_H
553c0b746e5SOllivier Robert 		struct pollfd rdfdes;
554c0b746e5SOllivier Robert #else
555c0b746e5SOllivier Robert 		fd_set rdfdes;
556c0b746e5SOllivier Robert #endif
557c0b746e5SOllivier Robert 		int nfound;
558c0b746e5SOllivier Robert 
559c0b746e5SOllivier Robert 		if (alarm_flag) {		/* alarmed? */
560c0b746e5SOllivier Robert 			was_alarmed = 1;
561c0b746e5SOllivier Robert 			alarm_flag = 0;
562c0b746e5SOllivier Robert 		}
563c0b746e5SOllivier Robert 		rbuflist = getrecvbufs();	/* get received buffers */
564c0b746e5SOllivier Robert 
565c0b746e5SOllivier Robert 		if (!was_alarmed && rbuflist == (struct recvbuf *)0) {
566c0b746e5SOllivier Robert 			/*
567c0b746e5SOllivier Robert 			 * Nothing to do.	 Wait for something.
568c0b746e5SOllivier Robert 			 */
569c0b746e5SOllivier Robert 			rdfdes = fdmask;
570c0b746e5SOllivier Robert #ifdef HAVE_POLL_H
571c0b746e5SOllivier Robert 			nfound = poll(&rdfdes, 1, timeout.tv_sec * 1000);
572c0b746e5SOllivier Robert #else
573c0b746e5SOllivier Robert 			nfound = select(fd+1, &rdfdes, (fd_set *)0,
574c0b746e5SOllivier Robert 					(fd_set *)0, &timeout);
575c0b746e5SOllivier Robert #endif
576c0b746e5SOllivier Robert 			if (nfound > 0)
577c0b746e5SOllivier Robert 				input_handler();
578c0b746e5SOllivier Robert 			else if (
579c0b746e5SOllivier Robert #ifndef SYS_WINNT
580c0b746e5SOllivier Robert 				nfound == -1
581c0b746e5SOllivier Robert #else
582c0b746e5SOllivier Robert 				nfound == SOCKET_ERROR
583c0b746e5SOllivier Robert #endif /* SYS_WINNT */
584c0b746e5SOllivier Robert 				) {
585c0b746e5SOllivier Robert #ifndef SYS_WINNT
586c0b746e5SOllivier Robert 				if (errno != EINTR)
587c0b746e5SOllivier Robert #endif
588c0b746e5SOllivier Robert 					msyslog(LOG_ERR,
589c0b746e5SOllivier Robert #ifdef HAVE_POLL_H
590c0b746e5SOllivier Robert 						"poll() error: %m"
591c0b746e5SOllivier Robert #else
592c0b746e5SOllivier Robert 						"select() error: %m"
593c0b746e5SOllivier Robert #endif
594c0b746e5SOllivier Robert 						);
595c0b746e5SOllivier Robert 			} else {
596c0b746e5SOllivier Robert #ifndef SYS_VXWORKS
597c0b746e5SOllivier Robert 				msyslog(LOG_DEBUG,
598c0b746e5SOllivier Robert #ifdef HAVE_POLL_H
599c0b746e5SOllivier Robert 					"poll(): nfound = %d, error: %m",
600c0b746e5SOllivier Robert #else
601c0b746e5SOllivier Robert 					"select(): nfound = %d, error: %m",
602c0b746e5SOllivier Robert #endif
603c0b746e5SOllivier Robert 					nfound);
604c0b746e5SOllivier Robert #endif
605c0b746e5SOllivier Robert 			}
606c0b746e5SOllivier Robert 			if (alarm_flag) {		/* alarmed? */
607c0b746e5SOllivier Robert 				was_alarmed = 1;
608c0b746e5SOllivier Robert 				alarm_flag = 0;
609c0b746e5SOllivier Robert 			}
610c0b746e5SOllivier Robert 			rbuflist = getrecvbufs();	/* get received buffers */
611c0b746e5SOllivier Robert 		}
612c0b746e5SOllivier Robert 
613c0b746e5SOllivier Robert 		/*
614c0b746e5SOllivier Robert 		 * Out here, signals are unblocked.  Call receive
615c0b746e5SOllivier Robert 		 * procedure for each incoming packet.
616c0b746e5SOllivier Robert 		 */
617c0b746e5SOllivier Robert 		while (rbuflist != (struct recvbuf *)0) {
618c0b746e5SOllivier Robert 			rbuf = rbuflist;
619c0b746e5SOllivier Robert 			rbuflist = rbuf->next;
620c0b746e5SOllivier Robert 			receive(rbuf);
621c0b746e5SOllivier Robert 			freerecvbuf(rbuf);
622c0b746e5SOllivier Robert 		}
623c0b746e5SOllivier Robert 
624c0b746e5SOllivier Robert 		/*
625c0b746e5SOllivier Robert 		 * Call timer to process any timeouts
626c0b746e5SOllivier Robert 		 */
627c0b746e5SOllivier Robert 		if (was_alarmed) {
628c0b746e5SOllivier Robert 			timer();
629c0b746e5SOllivier Robert 			was_alarmed = 0;
630c0b746e5SOllivier Robert 		}
631c0b746e5SOllivier Robert 
632c0b746e5SOllivier Robert 		/*
633c0b746e5SOllivier Robert 		 * Go around again
634c0b746e5SOllivier Robert 		 */
635c0b746e5SOllivier Robert 	}
636c0b746e5SOllivier Robert 
637c0b746e5SOllivier Robert 	/*
638c0b746e5SOllivier Robert 	 * When we get here we've completed the polling of all servers.
639c0b746e5SOllivier Robert 	 * Adjust the clock, then exit.
640c0b746e5SOllivier Robert 	 */
641c0b746e5SOllivier Robert #ifdef SYS_WINNT
642c0b746e5SOllivier Robert 	WSACleanup();
643c0b746e5SOllivier Robert #endif
644c0b746e5SOllivier Robert #ifdef SYS_VXWORKS
645c0b746e5SOllivier Robert 	close (fd);
646c0b746e5SOllivier Robert 	timer_delete(ntpdate_timerid);
647c0b746e5SOllivier Robert #endif
648c0b746e5SOllivier Robert 	return clock_adjust();
649c0b746e5SOllivier Robert }
650c0b746e5SOllivier Robert 
651c0b746e5SOllivier Robert 
652c0b746e5SOllivier Robert /*
653c0b746e5SOllivier Robert  * transmit - transmit a packet to the given server, or mark it completed.
654c0b746e5SOllivier Robert  *		  This is called by the timeout routine and by the receive
655c0b746e5SOllivier Robert  *		  procedure.
656c0b746e5SOllivier Robert  */
657c0b746e5SOllivier Robert static void
658c0b746e5SOllivier Robert transmit(
659c0b746e5SOllivier Robert 	register struct server *server
660c0b746e5SOllivier Robert 	)
661c0b746e5SOllivier Robert {
662c0b746e5SOllivier Robert 	struct pkt xpkt;
663c0b746e5SOllivier Robert 
664c0b746e5SOllivier Robert 	if (debug)
665c0b746e5SOllivier Robert 		printf("transmit(%s)\n", ntoa(&server->srcadr));
666c0b746e5SOllivier Robert 
667c0b746e5SOllivier Robert 	if (server->filter_nextpt < server->xmtcnt) {
668c0b746e5SOllivier Robert 		l_fp ts;
669c0b746e5SOllivier Robert 		/*
670c0b746e5SOllivier Robert 		 * Last message to this server timed out.  Shift
671c0b746e5SOllivier Robert 		 * zeros into the filter.
672c0b746e5SOllivier Robert 		 */
673c0b746e5SOllivier Robert 		L_CLR(&ts);
674c0b746e5SOllivier Robert 		server_data(server, 0, &ts, 0);
675c0b746e5SOllivier Robert 	}
676c0b746e5SOllivier Robert 
677c0b746e5SOllivier Robert 	if ((int)server->filter_nextpt >= sys_samples) {
678c0b746e5SOllivier Robert 		/*
679c0b746e5SOllivier Robert 		 * Got all the data we need.  Mark this guy
680c0b746e5SOllivier Robert 		 * completed and return.
681c0b746e5SOllivier Robert 		 */
682c0b746e5SOllivier Robert 		server->event_time = 0;
683c0b746e5SOllivier Robert 		complete_servers++;
684c0b746e5SOllivier Robert 		return;
685c0b746e5SOllivier Robert 	}
686c0b746e5SOllivier Robert 
687c0b746e5SOllivier Robert 	/*
688c0b746e5SOllivier Robert 	 * If we're here, send another message to the server.    Fill in
689c0b746e5SOllivier Robert 	 * the packet and let 'er rip.
690c0b746e5SOllivier Robert 	 */
691c0b746e5SOllivier Robert 	xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOTINSYNC,
692c0b746e5SOllivier Robert 					 sys_version, MODE_CLIENT);
693c0b746e5SOllivier Robert 	xpkt.stratum = STRATUM_TO_PKT(STRATUM_UNSPEC);
694c0b746e5SOllivier Robert 	xpkt.ppoll = NTP_MINPOLL;
695c0b746e5SOllivier Robert 	xpkt.precision = NTPDATE_PRECISION;
696c0b746e5SOllivier Robert 	xpkt.rootdelay = htonl(NTPDATE_DISTANCE);
697c0b746e5SOllivier Robert 	xpkt.rootdispersion = htonl(NTPDATE_DISP);
698c0b746e5SOllivier Robert 	xpkt.refid = htonl(NTPDATE_REFID);
699c0b746e5SOllivier Robert 	L_CLR(&xpkt.reftime);
700c0b746e5SOllivier Robert 	L_CLR(&xpkt.org);
701c0b746e5SOllivier Robert 	L_CLR(&xpkt.rec);
702c0b746e5SOllivier Robert 
703c0b746e5SOllivier Robert 	/*
704c0b746e5SOllivier Robert 	 * Determine whether to authenticate or not.	If so,
705c0b746e5SOllivier Robert 	 * fill in the extended part of the packet and do it.
706c0b746e5SOllivier Robert 	 * If not, just timestamp it and send it away.
707c0b746e5SOllivier Robert 	 */
708c0b746e5SOllivier Robert 	if (sys_authenticate) {
709c0b746e5SOllivier Robert 		int len;
710c0b746e5SOllivier Robert 
711c0b746e5SOllivier Robert 		xpkt.keyid1 = htonl(sys_authkey);
712c0b746e5SOllivier Robert 		get_systime(&server->xmt);
713c0b746e5SOllivier Robert 		L_ADDUF(&server->xmt, sys_authdelay);
714c0b746e5SOllivier Robert 		HTONL_FP(&server->xmt, &xpkt.xmt);
715c0b746e5SOllivier Robert 		len = authencrypt(sys_authkey, (u_int32 *)&xpkt, LEN_PKT_NOMAC);
716c0b746e5SOllivier Robert 		sendpkt(&(server->srcadr), &xpkt, (int)(LEN_PKT_NOMAC + len));
717c0b746e5SOllivier Robert 
718c0b746e5SOllivier Robert 		if (debug > 1)
719c0b746e5SOllivier Robert 			printf("transmit auth to %s\n",
720c0b746e5SOllivier Robert 			   ntoa(&(server->srcadr)));
721c0b746e5SOllivier Robert 	} else {
722c0b746e5SOllivier Robert 		get_systime(&(server->xmt));
723c0b746e5SOllivier Robert 		HTONL_FP(&server->xmt, &xpkt.xmt);
724c0b746e5SOllivier Robert 		sendpkt(&(server->srcadr), &xpkt, LEN_PKT_NOMAC);
725c0b746e5SOllivier Robert 
726c0b746e5SOllivier Robert 		if (debug > 1)
727c0b746e5SOllivier Robert 			printf("transmit to %s\n", ntoa(&(server->srcadr)));
728c0b746e5SOllivier Robert 	}
729c0b746e5SOllivier Robert 
730c0b746e5SOllivier Robert 	/*
731c0b746e5SOllivier Robert 	 * Update the server timeout and transmit count
732c0b746e5SOllivier Robert 	 */
733c0b746e5SOllivier Robert 	server->event_time = current_time + sys_timeout;
734c0b746e5SOllivier Robert 	server->xmtcnt++;
735c0b746e5SOllivier Robert }
736c0b746e5SOllivier Robert 
737c0b746e5SOllivier Robert 
738c0b746e5SOllivier Robert /*
739c0b746e5SOllivier Robert  * receive - receive and process an incoming frame
740c0b746e5SOllivier Robert  */
741c0b746e5SOllivier Robert static void
742c0b746e5SOllivier Robert receive(
743c0b746e5SOllivier Robert 	struct recvbuf *rbufp
744c0b746e5SOllivier Robert 	)
745c0b746e5SOllivier Robert {
746c0b746e5SOllivier Robert 	register struct pkt *rpkt;
747c0b746e5SOllivier Robert 	register struct server *server;
748c0b746e5SOllivier Robert 	register s_fp di;
749c0b746e5SOllivier Robert 	l_fp t10, t23;
750c0b746e5SOllivier Robert 	l_fp org;
751c0b746e5SOllivier Robert 	l_fp rec;
752c0b746e5SOllivier Robert 	l_fp ci;
753c0b746e5SOllivier Robert 	int has_mac;
754c0b746e5SOllivier Robert 	int is_authentic;
755c0b746e5SOllivier Robert 
756c0b746e5SOllivier Robert 	if (debug)
757c0b746e5SOllivier Robert 		printf("receive(%s)\n", ntoa(&rbufp->recv_srcadr));
758c0b746e5SOllivier Robert 	/*
759c0b746e5SOllivier Robert 	 * Check to see if the packet basically looks like something
760c0b746e5SOllivier Robert 	 * intended for us.
761c0b746e5SOllivier Robert 	 */
762c0b746e5SOllivier Robert 	if (rbufp->recv_length == LEN_PKT_NOMAC)
763c0b746e5SOllivier Robert 		has_mac = 0;
764c0b746e5SOllivier Robert 	else if (rbufp->recv_length >= LEN_PKT_NOMAC)
765c0b746e5SOllivier Robert 		has_mac = 1;
766c0b746e5SOllivier Robert 	else {
767c0b746e5SOllivier Robert 		if (debug)
768c0b746e5SOllivier Robert 			printf("receive: packet length %d\n",
769c0b746e5SOllivier Robert 			   rbufp->recv_length);
770c0b746e5SOllivier Robert 		return; 		/* funny length packet */
771c0b746e5SOllivier Robert 	}
772c0b746e5SOllivier Robert 
773c0b746e5SOllivier Robert 	rpkt = &(rbufp->recv_pkt);
774c0b746e5SOllivier Robert 	if (PKT_VERSION(rpkt->li_vn_mode) < NTP_OLDVERSION ||
775c0b746e5SOllivier Robert 		PKT_VERSION(rpkt->li_vn_mode) > NTP_VERSION) {
776c0b746e5SOllivier Robert 		return;
777c0b746e5SOllivier Robert 	}
778c0b746e5SOllivier Robert 
779c0b746e5SOllivier Robert 	if ((PKT_MODE(rpkt->li_vn_mode) != MODE_SERVER
780c0b746e5SOllivier Robert 		 && PKT_MODE(rpkt->li_vn_mode) != MODE_PASSIVE)
781c0b746e5SOllivier Robert 		|| rpkt->stratum > NTP_MAXSTRATUM) {
782c0b746e5SOllivier Robert 		if (debug)
783c0b746e5SOllivier Robert 			printf("receive: mode %d stratum %d\n",
784c0b746e5SOllivier Robert 			   PKT_MODE(rpkt->li_vn_mode), rpkt->stratum);
785c0b746e5SOllivier Robert 		return;
786c0b746e5SOllivier Robert 	}
787c0b746e5SOllivier Robert 
788c0b746e5SOllivier Robert 	/*
789c0b746e5SOllivier Robert 	 * So far, so good.  See if this is from a server we know.
790c0b746e5SOllivier Robert 	 */
791c0b746e5SOllivier Robert 	server = findserver(&(rbufp->recv_srcadr));
792c0b746e5SOllivier Robert 	if (server == NULL) {
793c0b746e5SOllivier Robert 		if (debug)
794c0b746e5SOllivier Robert 			printf("receive: server not found\n");
795c0b746e5SOllivier Robert 		return;
796c0b746e5SOllivier Robert 	}
797c0b746e5SOllivier Robert 
798c0b746e5SOllivier Robert 	/*
799c0b746e5SOllivier Robert 	 * Decode the org timestamp and make sure we're getting a response
800c0b746e5SOllivier Robert 	 * to our last request.
801c0b746e5SOllivier Robert 	 */
802c0b746e5SOllivier Robert 	NTOHL_FP(&rpkt->org, &org);
803c0b746e5SOllivier Robert 	if (!L_ISEQU(&org, &server->xmt)) {
804c0b746e5SOllivier Robert 		if (debug)
805c0b746e5SOllivier Robert 			printf("receive: pkt.org and peer.xmt differ\n");
806c0b746e5SOllivier Robert 		return;
807c0b746e5SOllivier Robert 	}
808c0b746e5SOllivier Robert 
809c0b746e5SOllivier Robert 	/*
810c0b746e5SOllivier Robert 	 * Check out the authenticity if we're doing that.
811c0b746e5SOllivier Robert 	 */
812c0b746e5SOllivier Robert 	if (!sys_authenticate)
813c0b746e5SOllivier Robert 		is_authentic = 1;
814c0b746e5SOllivier Robert 	else {
815c0b746e5SOllivier Robert 		is_authentic = 0;
816c0b746e5SOllivier Robert 
817c0b746e5SOllivier Robert 		if (debug > 3)
818c0b746e5SOllivier Robert 			printf("receive: rpkt keyid=%ld sys_authkey=%ld decrypt=%ld\n",
819c0b746e5SOllivier Robert 			   (long int)ntohl(rpkt->keyid1), (long int)sys_authkey,
820c0b746e5SOllivier Robert 			   (long int)authdecrypt(sys_authkey, (u_int32 *)rpkt,
821c0b746e5SOllivier Robert 				LEN_PKT_NOMAC, (int)(rbufp->recv_length - LEN_PKT_NOMAC)));
822c0b746e5SOllivier Robert 
823c0b746e5SOllivier Robert 		if (has_mac && ntohl(rpkt->keyid1) == sys_authkey &&
824c0b746e5SOllivier Robert 			authdecrypt(sys_authkey, (u_int32 *)rpkt, LEN_PKT_NOMAC,
825c0b746e5SOllivier Robert 			(int)(rbufp->recv_length - LEN_PKT_NOMAC)))
826c0b746e5SOllivier Robert 			is_authentic = 1;
827c0b746e5SOllivier Robert 		if (debug)
828c0b746e5SOllivier Robert 			printf("receive: authentication %s\n",
829c0b746e5SOllivier Robert 			   is_authentic ? "passed" : "failed");
830c0b746e5SOllivier Robert 	}
831c0b746e5SOllivier Robert 	server->trust <<= 1;
832c0b746e5SOllivier Robert 	if (!is_authentic)
833c0b746e5SOllivier Robert 		server->trust |= 1;
834c0b746e5SOllivier Robert 
835c0b746e5SOllivier Robert 	/*
836c0b746e5SOllivier Robert 	 * Looks good.	Record info from the packet.
837c0b746e5SOllivier Robert 	 */
838c0b746e5SOllivier Robert 	server->leap = PKT_LEAP(rpkt->li_vn_mode);
839c0b746e5SOllivier Robert 	server->stratum = PKT_TO_STRATUM(rpkt->stratum);
840c0b746e5SOllivier Robert 	server->precision = rpkt->precision;
841c0b746e5SOllivier Robert 	server->rootdelay = ntohl(rpkt->rootdelay);
842c0b746e5SOllivier Robert 	server->rootdispersion = ntohl(rpkt->rootdispersion);
843c0b746e5SOllivier Robert 	server->refid = rpkt->refid;
844c0b746e5SOllivier Robert 	NTOHL_FP(&rpkt->reftime, &server->reftime);
845c0b746e5SOllivier Robert 	NTOHL_FP(&rpkt->rec, &rec);
846c0b746e5SOllivier Robert 	NTOHL_FP(&rpkt->xmt, &server->org);
847c0b746e5SOllivier Robert 
848c0b746e5SOllivier Robert 	/*
849c0b746e5SOllivier Robert 	 * Make sure the server is at least somewhat sane.	If not, try
850c0b746e5SOllivier Robert 	 * again.
851c0b746e5SOllivier Robert 	 */
852c0b746e5SOllivier Robert 	if (L_ISZERO(&rec) || !L_ISHIS(&server->org, &rec)) {
853c0b746e5SOllivier Robert 		transmit(server);
854c0b746e5SOllivier Robert 		return;
855c0b746e5SOllivier Robert 	}
856c0b746e5SOllivier Robert 
857c0b746e5SOllivier Robert 	/*
858c0b746e5SOllivier Robert 	 * Calculate the round trip delay (di) and the clock offset (ci).
859c0b746e5SOllivier Robert 	 * We use the equations (reordered from those in the spec):
860c0b746e5SOllivier Robert 	 *
861c0b746e5SOllivier Robert 	 * d = (t2 - t3) - (t1 - t0)
862c0b746e5SOllivier Robert 	 * c = ((t2 - t3) + (t1 - t0)) / 2
863c0b746e5SOllivier Robert 	 */
864c0b746e5SOllivier Robert 	t10 = server->org;		/* pkt.xmt == t1 */
865c0b746e5SOllivier Robert 	L_SUB(&t10, &rbufp->recv_time); /* recv_time == t0*/
866c0b746e5SOllivier Robert 
867c0b746e5SOllivier Robert 	t23 = rec;			/* pkt.rec == t2 */
868c0b746e5SOllivier Robert 	L_SUB(&t23, &org);		/* pkt->org == t3 */
869c0b746e5SOllivier Robert 
870c0b746e5SOllivier Robert 	/* now have (t2 - t3) and (t0 - t1).	Calculate (ci) and (di) */
871c0b746e5SOllivier Robert 	ci = t10;
872c0b746e5SOllivier Robert 	L_ADD(&ci, &t23);
873c0b746e5SOllivier Robert 	L_RSHIFT(&ci);
874c0b746e5SOllivier Robert 
875c0b746e5SOllivier Robert 	/*
876c0b746e5SOllivier Robert 	 * Calculate di in t23 in full precision, then truncate
877c0b746e5SOllivier Robert 	 * to an s_fp.
878c0b746e5SOllivier Robert 	 */
879c0b746e5SOllivier Robert 	L_SUB(&t23, &t10);
880c0b746e5SOllivier Robert 	di = LFPTOFP(&t23);
881c0b746e5SOllivier Robert 
882c0b746e5SOllivier Robert 	if (debug > 3)
883c0b746e5SOllivier Robert 		printf("offset: %s, delay %s\n", lfptoa(&ci, 6), fptoa(di, 5));
884c0b746e5SOllivier Robert 
885c0b746e5SOllivier Robert 	di += (FP_SECOND >> (-(int)NTPDATE_PRECISION))
886c0b746e5SOllivier Robert 		+ (FP_SECOND >> (-(int)server->precision)) + NTP_MAXSKW;
887c0b746e5SOllivier Robert 
888c0b746e5SOllivier Robert 	if (di <= 0) {		/* value still too raunchy to use? */
889c0b746e5SOllivier Robert 		L_CLR(&ci);
890c0b746e5SOllivier Robert 		di = 0;
891c0b746e5SOllivier Robert 	} else {
892c0b746e5SOllivier Robert 		di = max(di, NTP_MINDIST);
893c0b746e5SOllivier Robert 	}
894c0b746e5SOllivier Robert 
895c0b746e5SOllivier Robert 	/*
896c0b746e5SOllivier Robert 	 * Shift this data in, then transmit again.
897c0b746e5SOllivier Robert 	 */
898c0b746e5SOllivier Robert 	server_data(server, (s_fp) di, &ci, 0);
899c0b746e5SOllivier Robert 	transmit(server);
900c0b746e5SOllivier Robert }
901c0b746e5SOllivier Robert 
902c0b746e5SOllivier Robert 
903c0b746e5SOllivier Robert /*
904c0b746e5SOllivier Robert  * server_data - add a sample to the server's filter registers
905c0b746e5SOllivier Robert  */
906c0b746e5SOllivier Robert static void
907c0b746e5SOllivier Robert server_data(
908c0b746e5SOllivier Robert 	register struct server *server,
909c0b746e5SOllivier Robert 	s_fp d,
910c0b746e5SOllivier Robert 	l_fp *c,
911c0b746e5SOllivier Robert 	u_fp e
912c0b746e5SOllivier Robert 	)
913c0b746e5SOllivier Robert {
914c0b746e5SOllivier Robert 	register int i;
915c0b746e5SOllivier Robert 
916c0b746e5SOllivier Robert 	i = server->filter_nextpt;
917c0b746e5SOllivier Robert 	if (i < NTP_SHIFT) {
918c0b746e5SOllivier Robert 		server->filter_delay[i] = d;
919c0b746e5SOllivier Robert 		server->filter_offset[i] = *c;
920c0b746e5SOllivier Robert 		server->filter_soffset[i] = LFPTOFP(c);
921c0b746e5SOllivier Robert 		server->filter_error[i] = e;
922c0b746e5SOllivier Robert 		server->filter_nextpt = i + 1;
923c0b746e5SOllivier Robert 	}
924c0b746e5SOllivier Robert }
925c0b746e5SOllivier Robert 
926c0b746e5SOllivier Robert 
927c0b746e5SOllivier Robert /*
928c0b746e5SOllivier Robert  * clock_filter - determine a server's delay, dispersion and offset
929c0b746e5SOllivier Robert  */
930c0b746e5SOllivier Robert static void
931c0b746e5SOllivier Robert clock_filter(
932c0b746e5SOllivier Robert 	register struct server *server
933c0b746e5SOllivier Robert 	)
934c0b746e5SOllivier Robert {
935c0b746e5SOllivier Robert 	register int i, j;
936c0b746e5SOllivier Robert 	int ord[NTP_SHIFT];
937c0b746e5SOllivier Robert 
938c0b746e5SOllivier Robert 	/*
939c0b746e5SOllivier Robert 	 * Sort indices into increasing delay order
940c0b746e5SOllivier Robert 	 */
941c0b746e5SOllivier Robert 	for (i = 0; i < sys_samples; i++)
942c0b746e5SOllivier Robert 		ord[i] = i;
943c0b746e5SOllivier Robert 
944c0b746e5SOllivier Robert 	for (i = 0; i < (sys_samples-1); i++) {
945c0b746e5SOllivier Robert 		for (j = i+1; j < sys_samples; j++) {
946c0b746e5SOllivier Robert 			if (server->filter_delay[ord[j]] == 0)
947c0b746e5SOllivier Robert 				continue;
948c0b746e5SOllivier Robert 			if (server->filter_delay[ord[i]] == 0
949c0b746e5SOllivier Robert 				|| (server->filter_delay[ord[i]]
950c0b746e5SOllivier Robert 				> server->filter_delay[ord[j]])) {
951c0b746e5SOllivier Robert 				register int tmp;
952c0b746e5SOllivier Robert 
953c0b746e5SOllivier Robert 				tmp = ord[i];
954c0b746e5SOllivier Robert 				ord[i] = ord[j];
955c0b746e5SOllivier Robert 				ord[j] = tmp;
956c0b746e5SOllivier Robert 			}
957c0b746e5SOllivier Robert 		}
958c0b746e5SOllivier Robert 	}
959c0b746e5SOllivier Robert 
960c0b746e5SOllivier Robert 	/*
961c0b746e5SOllivier Robert 	 * Now compute the dispersion, and assign values to delay and
962c0b746e5SOllivier Robert 	 * offset.	If there are no samples in the register, delay and
963c0b746e5SOllivier Robert 	 * offset go to zero and dispersion is set to the maximum.
964c0b746e5SOllivier Robert 	 */
965c0b746e5SOllivier Robert 	if (server->filter_delay[ord[0]] == 0) {
966c0b746e5SOllivier Robert 		server->delay = 0;
967c0b746e5SOllivier Robert 		L_CLR(&server->offset);
968c0b746e5SOllivier Robert 		server->soffset = 0;
969c0b746e5SOllivier Robert 		server->dispersion = PEER_MAXDISP;
970c0b746e5SOllivier Robert 	} else {
971c0b746e5SOllivier Robert 		register s_fp d;
972c0b746e5SOllivier Robert 
973c0b746e5SOllivier Robert 		server->delay = server->filter_delay[ord[0]];
974c0b746e5SOllivier Robert 		server->offset = server->filter_offset[ord[0]];
975c0b746e5SOllivier Robert 		server->soffset = LFPTOFP(&server->offset);
976c0b746e5SOllivier Robert 		server->dispersion = 0;
977c0b746e5SOllivier Robert 		for (i = 1; i < sys_samples; i++) {
978c0b746e5SOllivier Robert 			if (server->filter_delay[ord[i]] == 0)
979c0b746e5SOllivier Robert 				d = PEER_MAXDISP;
980c0b746e5SOllivier Robert 			else {
981c0b746e5SOllivier Robert 				d = server->filter_soffset[ord[i]]
982c0b746e5SOllivier Robert 					- server->filter_soffset[ord[0]];
983c0b746e5SOllivier Robert 				if (d < 0)
984c0b746e5SOllivier Robert 					d = -d;
985c0b746e5SOllivier Robert 				if (d > PEER_MAXDISP)
986c0b746e5SOllivier Robert 					d = PEER_MAXDISP;
987c0b746e5SOllivier Robert 			}
988c0b746e5SOllivier Robert 			/*
989c0b746e5SOllivier Robert 			 * XXX This *knows* PEER_FILTER is 1/2
990c0b746e5SOllivier Robert 			 */
991c0b746e5SOllivier Robert 			server->dispersion += (u_fp)(d) >> i;
992c0b746e5SOllivier Robert 		}
993c0b746e5SOllivier Robert 	}
994c0b746e5SOllivier Robert 	/*
995c0b746e5SOllivier Robert 	 * We're done
996c0b746e5SOllivier Robert 	 */
997c0b746e5SOllivier Robert }
998c0b746e5SOllivier Robert 
999c0b746e5SOllivier Robert 
1000c0b746e5SOllivier Robert /*
1001c0b746e5SOllivier Robert  * clock_select - select the pick-of-the-litter clock from the samples
1002c0b746e5SOllivier Robert  *		  we've got.
1003c0b746e5SOllivier Robert  */
1004c0b746e5SOllivier Robert static struct server *
1005c0b746e5SOllivier Robert clock_select(void)
1006c0b746e5SOllivier Robert {
1007c0b746e5SOllivier Robert 	register struct server *server;
1008c0b746e5SOllivier Robert 	register int i;
1009c0b746e5SOllivier Robert 	register int nlist;
1010c0b746e5SOllivier Robert 	register s_fp d;
1011c0b746e5SOllivier Robert 	register int j;
1012c0b746e5SOllivier Robert 	register int n;
1013c0b746e5SOllivier Robert 	s_fp local_threshold;
1014c0b746e5SOllivier Robert 	struct server *server_list[NTP_MAXCLOCK];
1015c0b746e5SOllivier Robert 	u_fp server_badness[NTP_MAXCLOCK];
1016c0b746e5SOllivier Robert 	struct server *sys_server;
1017c0b746e5SOllivier Robert 
1018c0b746e5SOllivier Robert 	/*
1019c0b746e5SOllivier Robert 	 * This first chunk of code is supposed to go through all
1020c0b746e5SOllivier Robert 	 * servers we know about to find the NTP_MAXLIST servers which
1021c0b746e5SOllivier Robert 	 * are most likely to succeed.	We run through the list
1022c0b746e5SOllivier Robert 	 * doing the sanity checks and trying to insert anyone who
1023c0b746e5SOllivier Robert 	 * looks okay.	We are at all times aware that we should
1024c0b746e5SOllivier Robert 	 * only keep samples from the top two strata and we only need
1025c0b746e5SOllivier Robert 	 * NTP_MAXLIST of them.
1026c0b746e5SOllivier Robert 	 */
1027c0b746e5SOllivier Robert 	nlist = 0;	/* none yet */
1028c0b746e5SOllivier Robert 	for (n = 0; n < sys_numservers; n++) {
1029c0b746e5SOllivier Robert 		server = sys_servers[n];
1030c0b746e5SOllivier Robert 		if (server->delay == 0)
1031c0b746e5SOllivier Robert 			continue;	/* no data */
1032c0b746e5SOllivier Robert 		if (server->stratum > NTP_INFIN)
1033c0b746e5SOllivier Robert 			continue;	/* stratum no good */
1034c0b746e5SOllivier Robert 		if (server->delay > NTP_MAXWGT) {
1035c0b746e5SOllivier Robert 			continue;	/* too far away */
1036c0b746e5SOllivier Robert 		}
1037c0b746e5SOllivier Robert 		if (server->leap == LEAP_NOTINSYNC)
1038c0b746e5SOllivier Robert 			continue;	/* he's in trouble */
1039c0b746e5SOllivier Robert 		if (!L_ISHIS(&server->org, &server->reftime)) {
1040c0b746e5SOllivier Robert 			continue;	/* very broken host */
1041c0b746e5SOllivier Robert 		}
1042c0b746e5SOllivier Robert 		if ((server->org.l_ui - server->reftime.l_ui)
1043c0b746e5SOllivier Robert 			>= NTP_MAXAGE) {
1044c0b746e5SOllivier Robert 			continue;	/* too long without sync */
1045c0b746e5SOllivier Robert 		}
1046c0b746e5SOllivier Robert 		if (server->trust != 0) {
1047c0b746e5SOllivier Robert 			continue;
1048c0b746e5SOllivier Robert 		}
1049c0b746e5SOllivier Robert 
1050c0b746e5SOllivier Robert 		/*
1051c0b746e5SOllivier Robert 		 * This one seems sane.  Find where he belongs
1052c0b746e5SOllivier Robert 		 * on the list.
1053c0b746e5SOllivier Robert 		 */
1054c0b746e5SOllivier Robert 		d = server->dispersion + server->dispersion;
1055c0b746e5SOllivier Robert 		for (i = 0; i < nlist; i++)
1056c0b746e5SOllivier Robert 			if (server->stratum <= server_list[i]->stratum)
1057c0b746e5SOllivier Robert 			break;
1058c0b746e5SOllivier Robert 		for ( ; i < nlist; i++) {
1059c0b746e5SOllivier Robert 			if (server->stratum < server_list[i]->stratum)
1060c0b746e5SOllivier Robert 				break;
1061c0b746e5SOllivier Robert 			if (d < (s_fp) server_badness[i])
1062c0b746e5SOllivier Robert 				break;
1063c0b746e5SOllivier Robert 		}
1064c0b746e5SOllivier Robert 
1065c0b746e5SOllivier Robert 		/*
1066c0b746e5SOllivier Robert 		 * If i points past the end of the list, this
1067c0b746e5SOllivier Robert 		 * guy is a loser, else stick him in.
1068c0b746e5SOllivier Robert 		 */
1069c0b746e5SOllivier Robert 		if (i >= NTP_MAXLIST)
1070c0b746e5SOllivier Robert 			continue;
1071c0b746e5SOllivier Robert 		for (j = nlist; j > i; j--)
1072c0b746e5SOllivier Robert 			if (j < NTP_MAXLIST) {
1073c0b746e5SOllivier Robert 				server_list[j] = server_list[j-1];
1074c0b746e5SOllivier Robert 				server_badness[j]
1075c0b746e5SOllivier Robert 					= server_badness[j-1];
1076c0b746e5SOllivier Robert 			}
1077c0b746e5SOllivier Robert 
1078c0b746e5SOllivier Robert 		server_list[i] = server;
1079c0b746e5SOllivier Robert 		server_badness[i] = d;
1080c0b746e5SOllivier Robert 		if (nlist < NTP_MAXLIST)
1081c0b746e5SOllivier Robert 			nlist++;
1082c0b746e5SOllivier Robert 	}
1083c0b746e5SOllivier Robert 
1084c0b746e5SOllivier Robert 	/*
1085c0b746e5SOllivier Robert 	 * Got the five-or-less best.	 Cut the list where the number of
1086c0b746e5SOllivier Robert 	 * strata exceeds two.
1087c0b746e5SOllivier Robert 	 */
1088c0b746e5SOllivier Robert 	j = 0;
1089c0b746e5SOllivier Robert 	for (i = 1; i < nlist; i++)
1090c0b746e5SOllivier Robert 		if (server_list[i]->stratum > server_list[i-1]->stratum)
1091c0b746e5SOllivier Robert 		if (++j == 2) {
1092c0b746e5SOllivier Robert 			nlist = i;
1093c0b746e5SOllivier Robert 			break;
1094c0b746e5SOllivier Robert 		}
1095c0b746e5SOllivier Robert 
1096c0b746e5SOllivier Robert 	/*
1097c0b746e5SOllivier Robert 	 * Whew!  What we should have by now is 0 to 5 candidates for
1098c0b746e5SOllivier Robert 	 * the job of syncing us.  If we have none, we're out of luck.
1099c0b746e5SOllivier Robert 	 * If we have one, he's a winner.  If we have more, do falseticker
1100c0b746e5SOllivier Robert 	 * detection.
1101c0b746e5SOllivier Robert 	 */
1102c0b746e5SOllivier Robert 
1103c0b746e5SOllivier Robert 	if (nlist == 0)
1104c0b746e5SOllivier Robert 		sys_server = 0;
1105c0b746e5SOllivier Robert 	else if (nlist == 1) {
1106c0b746e5SOllivier Robert 		sys_server = server_list[0];
1107c0b746e5SOllivier Robert 	} else {
1108c0b746e5SOllivier Robert 		/*
1109c0b746e5SOllivier Robert 		 * Re-sort by stratum, bdelay estimate quality and
1110c0b746e5SOllivier Robert 		 * server.delay.
1111c0b746e5SOllivier Robert 		 */
1112c0b746e5SOllivier Robert 		for (i = 0; i < nlist-1; i++)
1113c0b746e5SOllivier Robert 			for (j = i+1; j < nlist; j++) {
1114c0b746e5SOllivier Robert 				if (server_list[i]->stratum
1115c0b746e5SOllivier Robert 				< server_list[j]->stratum)
1116c0b746e5SOllivier Robert 				break;	/* already sorted by stratum */
1117c0b746e5SOllivier Robert 				if (server_list[i]->delay
1118c0b746e5SOllivier Robert 				< server_list[j]->delay)
1119c0b746e5SOllivier Robert 				continue;
1120c0b746e5SOllivier Robert 				server = server_list[i];
1121c0b746e5SOllivier Robert 				server_list[i] = server_list[j];
1122c0b746e5SOllivier Robert 				server_list[j] = server;
1123c0b746e5SOllivier Robert 			}
1124c0b746e5SOllivier Robert 
1125c0b746e5SOllivier Robert 		/*
1126c0b746e5SOllivier Robert 		 * Calculate the fixed part of the dispersion limit
1127c0b746e5SOllivier Robert 		 */
1128c0b746e5SOllivier Robert 		local_threshold = (FP_SECOND >> (-(int)NTPDATE_PRECISION))
1129c0b746e5SOllivier Robert 			+ NTP_MAXSKW;
1130c0b746e5SOllivier Robert 
1131c0b746e5SOllivier Robert 		/*
1132c0b746e5SOllivier Robert 		 * Now drop samples until we're down to one.
1133c0b746e5SOllivier Robert 		 */
1134c0b746e5SOllivier Robert 		while (nlist > 1) {
1135c0b746e5SOllivier Robert 			for (n = 0; n < nlist; n++) {
1136c0b746e5SOllivier Robert 				server_badness[n] = 0;
1137c0b746e5SOllivier Robert 				for (j = 0; j < nlist; j++) {
1138c0b746e5SOllivier Robert 					if (j == n) /* with self? */
1139c0b746e5SOllivier Robert 						continue;
1140c0b746e5SOllivier Robert 					d = server_list[j]->soffset
1141c0b746e5SOllivier Robert 						- server_list[n]->soffset;
1142c0b746e5SOllivier Robert 					if (d < 0)	/* absolute value */
1143c0b746e5SOllivier Robert 						d = -d;
1144c0b746e5SOllivier Robert 					/*
1145c0b746e5SOllivier Robert 					 * XXX This code *knows* that
1146c0b746e5SOllivier Robert 					 * NTP_SELECT is 3/4
1147c0b746e5SOllivier Robert 					 */
1148c0b746e5SOllivier Robert 					for (i = 0; i < j; i++)
1149c0b746e5SOllivier Robert 						d = (d>>1) + (d>>2);
1150c0b746e5SOllivier Robert 					server_badness[n] += d;
1151c0b746e5SOllivier Robert 				}
1152c0b746e5SOllivier Robert 			}
1153c0b746e5SOllivier Robert 
1154c0b746e5SOllivier Robert 			/*
1155c0b746e5SOllivier Robert 			 * We now have an array of nlist badness
1156c0b746e5SOllivier Robert 			 * coefficients.	Find the badest.  Find
1157c0b746e5SOllivier Robert 			 * the minimum precision while we're at
1158c0b746e5SOllivier Robert 			 * it.
1159c0b746e5SOllivier Robert 			 */
1160c0b746e5SOllivier Robert 			i = 0;
1161c0b746e5SOllivier Robert 			n = server_list[0]->precision;;
1162c0b746e5SOllivier Robert 			for (j = 1; j < nlist; j++) {
1163c0b746e5SOllivier Robert 				if (server_badness[j] >= server_badness[i])
1164c0b746e5SOllivier Robert 					i = j;
1165c0b746e5SOllivier Robert 				if (n > server_list[j]->precision)
1166c0b746e5SOllivier Robert 					n = server_list[j]->precision;
1167c0b746e5SOllivier Robert 			}
1168c0b746e5SOllivier Robert 
1169c0b746e5SOllivier Robert 			/*
1170c0b746e5SOllivier Robert 			 * i is the index of the server with the worst
1171c0b746e5SOllivier Robert 			 * dispersion.	If his dispersion is less than
1172c0b746e5SOllivier Robert 			 * the threshold, stop now, else delete him and
1173c0b746e5SOllivier Robert 			 * continue around again.
1174c0b746e5SOllivier Robert 			 */
1175c0b746e5SOllivier Robert 			if ( (s_fp) server_badness[i] < (local_threshold
1176c0b746e5SOllivier Robert 							 + (FP_SECOND >> (-n))))
1177c0b746e5SOllivier Robert 				break;
1178c0b746e5SOllivier Robert 			for (j = i + 1; j < nlist; j++)
1179c0b746e5SOllivier Robert 				server_list[j-1] = server_list[j];
1180c0b746e5SOllivier Robert 			nlist--;
1181c0b746e5SOllivier Robert 		}
1182c0b746e5SOllivier Robert 
1183c0b746e5SOllivier Robert 		/*
1184c0b746e5SOllivier Robert 		 * What remains is a list of less than 5 servers.  Take
1185c0b746e5SOllivier Robert 		 * the best.
1186c0b746e5SOllivier Robert 		 */
1187c0b746e5SOllivier Robert 		sys_server = server_list[0];
1188c0b746e5SOllivier Robert 	}
1189c0b746e5SOllivier Robert 
1190c0b746e5SOllivier Robert 	/*
1191c0b746e5SOllivier Robert 	 * That's it.    Return our server.
1192c0b746e5SOllivier Robert 	 */
1193c0b746e5SOllivier Robert 	return sys_server;
1194c0b746e5SOllivier Robert }
1195c0b746e5SOllivier Robert 
1196c0b746e5SOllivier Robert 
1197c0b746e5SOllivier Robert /*
1198c0b746e5SOllivier Robert  * clock_adjust - process what we've received, and adjust the time
1199c0b746e5SOllivier Robert  *		 if we got anything decent.
1200c0b746e5SOllivier Robert  */
1201c0b746e5SOllivier Robert static int
1202c0b746e5SOllivier Robert clock_adjust(void)
1203c0b746e5SOllivier Robert {
1204c0b746e5SOllivier Robert 	register int i;
1205c0b746e5SOllivier Robert 	register struct server *server;
1206c0b746e5SOllivier Robert 	s_fp absoffset;
1207c0b746e5SOllivier Robert 	int dostep;
1208c0b746e5SOllivier Robert 
1209c0b746e5SOllivier Robert 	for (i = 0; i < sys_numservers; i++)
1210c0b746e5SOllivier Robert 		clock_filter(sys_servers[i]);
1211c0b746e5SOllivier Robert 	server = clock_select();
1212c0b746e5SOllivier Robert 
1213c0b746e5SOllivier Robert 	if (debug || simple_query) {
1214c0b746e5SOllivier Robert 		for (i = 0; i < sys_numservers; i++)
1215c0b746e5SOllivier Robert 			printserver(sys_servers[i], stdout);
1216c0b746e5SOllivier Robert 	}
1217c0b746e5SOllivier Robert 
1218c0b746e5SOllivier Robert 	if (server == 0) {
1219c0b746e5SOllivier Robert 		msyslog(LOG_ERR,
1220c0b746e5SOllivier Robert 			"no server suitable for synchronization found");
1221c0b746e5SOllivier Robert 		return(1);
1222c0b746e5SOllivier Robert 	}
1223c0b746e5SOllivier Robert 
1224c0b746e5SOllivier Robert 	if (always_step) {
1225c0b746e5SOllivier Robert 		dostep = 1;
1226c0b746e5SOllivier Robert 	} else if (never_step) {
1227c0b746e5SOllivier Robert 		dostep = 0;
1228c0b746e5SOllivier Robert 	} else {
1229c0b746e5SOllivier Robert 		absoffset = server->soffset;
1230c0b746e5SOllivier Robert 		if (absoffset < 0)
1231c0b746e5SOllivier Robert 			absoffset = -absoffset;
1232c0b746e5SOllivier Robert 		dostep = (absoffset >= NTPDATE_THRESHOLD);
1233c0b746e5SOllivier Robert 	}
1234c0b746e5SOllivier Robert 
1235c0b746e5SOllivier Robert 	if (dostep) {
1236c0b746e5SOllivier Robert 		if (simple_query || l_step_systime(&server->offset)) {
1237c0b746e5SOllivier Robert 			msyslog(LOG_NOTICE, "step time server %s offset %s sec",
1238c0b746e5SOllivier Robert 				ntoa(&server->srcadr),
1239c0b746e5SOllivier Robert 				lfptoa(&server->offset, 6));
1240c0b746e5SOllivier Robert 		}
1241c0b746e5SOllivier Robert 	} else {
1242c0b746e5SOllivier Robert #if !defined SYS_WINNT && !defined SYS_CYGWIN32
1243c0b746e5SOllivier Robert 		if (simple_query || l_adj_systime(&server->offset)) {
1244c0b746e5SOllivier Robert 			msyslog(LOG_NOTICE, "adjust time server %s offset %s sec",
1245c0b746e5SOllivier Robert 				ntoa(&server->srcadr),
1246c0b746e5SOllivier Robert 				lfptoa(&server->offset, 6));
1247c0b746e5SOllivier Robert 		}
1248c0b746e5SOllivier Robert #else
1249c0b746e5SOllivier Robert 		/* The NT SetSystemTimeAdjustment() call achieves slewing by
1250c0b746e5SOllivier Robert 		 * changing the clock frequency. This means that we cannot specify
1251c0b746e5SOllivier Robert 		 * it to slew the clock by a definite amount and then stop like
1252c0b746e5SOllivier Robert 		 * the Unix adjtime() routine. We can technically adjust the clock
1253c0b746e5SOllivier Robert 		 * frequency, have ntpdate sleep for a while, and then wake
1254c0b746e5SOllivier Robert 		 * up and reset the clock frequency, but this might cause some
1255c0b746e5SOllivier Robert 		 * grief if the user attempts to run ntpd immediately after
1256c0b746e5SOllivier Robert 		 * ntpdate and the socket is in use.
1257c0b746e5SOllivier Robert 		 */
1258c0b746e5SOllivier Robert 		printf("\nThe -b option is required by ntpdate on Windows NT platforms\n");
1259c0b746e5SOllivier Robert 		exit(1);
1260c0b746e5SOllivier Robert #endif /* SYS_WINNT */
1261c0b746e5SOllivier Robert 	}
1262c0b746e5SOllivier Robert 	return(0);
1263c0b746e5SOllivier Robert }
1264c0b746e5SOllivier Robert 
1265c0b746e5SOllivier Robert 
1266c0b746e5SOllivier Robert /* XXX ELIMINATE: merge BIG slew into adj_systime in lib/systime.c */
1267c0b746e5SOllivier Robert /*
1268c0b746e5SOllivier Robert  * addserver - determine a server's address and allocate a new structure
1269c0b746e5SOllivier Robert  *		   for it.
1270c0b746e5SOllivier Robert  */
1271c0b746e5SOllivier Robert static void
1272c0b746e5SOllivier Robert addserver(
1273c0b746e5SOllivier Robert 	char *serv
1274c0b746e5SOllivier Robert 	)
1275c0b746e5SOllivier Robert {
1276c0b746e5SOllivier Robert 	register struct server *server;
1277c0b746e5SOllivier Robert 	u_int32 netnum;
1278c0b746e5SOllivier Robert 	static int toomany = 0;
1279c0b746e5SOllivier Robert 
1280c0b746e5SOllivier Robert 	if (sys_numservers >= sys_maxservers) {
1281c0b746e5SOllivier Robert 		if (!toomany) {
1282c0b746e5SOllivier Robert 			/*
1283c0b746e5SOllivier Robert 			 * This is actually a `can't happen' now.    Leave
1284c0b746e5SOllivier Robert 			 * the error message in anyway, though
1285c0b746e5SOllivier Robert 			 */
1286c0b746e5SOllivier Robert 			toomany = 1;
1287c0b746e5SOllivier Robert 			msyslog(LOG_ERR,
1288c0b746e5SOllivier Robert 				"too many servers (> %d) specified, remainder not used",
1289c0b746e5SOllivier Robert 				sys_maxservers);
1290c0b746e5SOllivier Robert 		}
1291c0b746e5SOllivier Robert 		return;
1292c0b746e5SOllivier Robert 	}
1293c0b746e5SOllivier Robert 
1294c0b746e5SOllivier Robert 	if (!getnetnum(serv, &netnum)) {
1295c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "can't find host %s\n", serv);
1296c0b746e5SOllivier Robert 		return;
1297c0b746e5SOllivier Robert 	}
1298c0b746e5SOllivier Robert 
1299c0b746e5SOllivier Robert 	server = (struct server *)emalloc(sizeof(struct server));
1300c0b746e5SOllivier Robert 	memset((char *)server, 0, sizeof(struct server));
1301c0b746e5SOllivier Robert 
1302c0b746e5SOllivier Robert 	server->srcadr.sin_family = AF_INET;
1303c0b746e5SOllivier Robert 	server->srcadr.sin_addr.s_addr = netnum;
1304c0b746e5SOllivier Robert 	server->srcadr.sin_port = htons(NTP_PORT);
1305c0b746e5SOllivier Robert 
1306c0b746e5SOllivier Robert 	sys_servers[sys_numservers++] = server;
1307c0b746e5SOllivier Robert 	server->event_time = sys_numservers;
1308c0b746e5SOllivier Robert }
1309c0b746e5SOllivier Robert 
1310c0b746e5SOllivier Robert 
1311c0b746e5SOllivier Robert /*
1312c0b746e5SOllivier Robert  * findserver - find a server in the list given its address
1313c0b746e5SOllivier Robert  */
1314c0b746e5SOllivier Robert static struct server *
1315c0b746e5SOllivier Robert findserver(
1316c0b746e5SOllivier Robert 	struct sockaddr_in *addr
1317c0b746e5SOllivier Robert 	)
1318c0b746e5SOllivier Robert {
1319c0b746e5SOllivier Robert 	register int i;
1320c0b746e5SOllivier Robert 	register u_int32 netnum;
1321c0b746e5SOllivier Robert 
1322c0b746e5SOllivier Robert 	if (htons(addr->sin_port) != NTP_PORT)
1323c0b746e5SOllivier Robert 		return 0;
1324c0b746e5SOllivier Robert 	netnum = addr->sin_addr.s_addr;
1325c0b746e5SOllivier Robert 
1326c0b746e5SOllivier Robert 	for (i = 0; i < sys_numservers; i++) {
1327c0b746e5SOllivier Robert 		if (netnum == sys_servers[i]->srcadr.sin_addr.s_addr)
1328c0b746e5SOllivier Robert 			return sys_servers[i];
1329c0b746e5SOllivier Robert 	}
1330c0b746e5SOllivier Robert 	return 0;
1331c0b746e5SOllivier Robert }
1332c0b746e5SOllivier Robert 
1333c0b746e5SOllivier Robert 
1334c0b746e5SOllivier Robert /*
1335c0b746e5SOllivier Robert  * timer - process a timer interrupt
1336c0b746e5SOllivier Robert  */
1337c0b746e5SOllivier Robert void
1338c0b746e5SOllivier Robert timer(void)
1339c0b746e5SOllivier Robert {
1340c0b746e5SOllivier Robert 	register int i;
1341c0b746e5SOllivier Robert 
1342c0b746e5SOllivier Robert 	/*
1343c0b746e5SOllivier Robert 	 * Bump the current idea of the time
1344c0b746e5SOllivier Robert 	 */
1345c0b746e5SOllivier Robert 	current_time++;
1346c0b746e5SOllivier Robert 
1347c0b746e5SOllivier Robert 	/*
1348c0b746e5SOllivier Robert 	 * Search through the server list looking for guys
1349c0b746e5SOllivier Robert 	 * who's event timers have expired.  Give these to
1350c0b746e5SOllivier Robert 	 * the transmit routine.
1351c0b746e5SOllivier Robert 	 */
1352c0b746e5SOllivier Robert 	for (i = 0; i < sys_numservers; i++) {
1353c0b746e5SOllivier Robert 		if (sys_servers[i]->event_time != 0
1354c0b746e5SOllivier Robert 			&& sys_servers[i]->event_time <= current_time)
1355c0b746e5SOllivier Robert 			transmit(sys_servers[i]);
1356c0b746e5SOllivier Robert 	}
1357c0b746e5SOllivier Robert }
1358c0b746e5SOllivier Robert 
1359c0b746e5SOllivier Robert 
1360c0b746e5SOllivier Robert #ifndef SYS_WINNT
1361c0b746e5SOllivier Robert /*
1362c0b746e5SOllivier Robert  * alarming - record the occurance of an alarm interrupt
1363c0b746e5SOllivier Robert  */
1364c0b746e5SOllivier Robert static RETSIGTYPE
1365c0b746e5SOllivier Robert alarming(
1366c0b746e5SOllivier Robert 	int sig
1367c0b746e5SOllivier Robert 	)
1368c0b746e5SOllivier Robert #else
1369c0b746e5SOllivier Robert void CALLBACK
1370c0b746e5SOllivier Robert alarming(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
1371c0b746e5SOllivier Robert #endif /* SYS_WINNT */
1372c0b746e5SOllivier Robert {
1373c0b746e5SOllivier Robert 	alarm_flag++;
1374c0b746e5SOllivier Robert }
1375c0b746e5SOllivier Robert 
1376c0b746e5SOllivier Robert 
1377c0b746e5SOllivier Robert /*
1378c0b746e5SOllivier Robert  * init_alarm - set up the timer interrupt
1379c0b746e5SOllivier Robert  */
1380c0b746e5SOllivier Robert static void
1381c0b746e5SOllivier Robert init_alarm(void)
1382c0b746e5SOllivier Robert {
1383c0b746e5SOllivier Robert #ifndef SYS_WINNT
1384c0b746e5SOllivier Robert # ifndef HAVE_TIMER_SETTIME
1385c0b746e5SOllivier Robert 	struct itimerval itimer;
1386c0b746e5SOllivier Robert # else
1387c0b746e5SOllivier Robert 	struct itimerspec ntpdate_itimer;
1388c0b746e5SOllivier Robert # endif
1389c0b746e5SOllivier Robert #else
1390c0b746e5SOllivier Robert 	TIMECAPS tc;
1391c0b746e5SOllivier Robert 	UINT wTimerRes, wTimerID;
1392c0b746e5SOllivier Robert # endif /* SYS_WINNT */
1393c0b746e5SOllivier Robert #if defined SYS_CYGWIN32 || defined SYS_WINNT
1394c0b746e5SOllivier Robert 	HANDLE hToken;
1395c0b746e5SOllivier Robert 	TOKEN_PRIVILEGES tkp;
1396c0b746e5SOllivier Robert 	DWORD dwUser = 0;
1397c0b746e5SOllivier Robert #endif /* SYS_WINNT */
1398c0b746e5SOllivier Robert 
1399c0b746e5SOllivier Robert 	alarm_flag = 0;
1400c0b746e5SOllivier Robert 
1401c0b746e5SOllivier Robert #ifndef SYS_WINNT
1402c0b746e5SOllivier Robert # if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME)
1403c0b746e5SOllivier Robert 	alarm_flag = 0;
1404c0b746e5SOllivier Robert 	/* this code was put in as setitimer() is non existant this us the
1405c0b746e5SOllivier Robert 	 * POSIX "equivalents" setup - casey
1406c0b746e5SOllivier Robert 	 */
1407c0b746e5SOllivier Robert 	/* ntpdate_timerid is global - so we can kill timer later */
1408c0b746e5SOllivier Robert 	if (timer_create (CLOCK_REALTIME, NULL, &ntpdate_timerid) ==
1409c0b746e5SOllivier Robert #  ifdef SYS_VXWORKS
1410c0b746e5SOllivier Robert 		ERROR
1411c0b746e5SOllivier Robert #  else
1412c0b746e5SOllivier Robert 		-1
1413c0b746e5SOllivier Robert #  endif
1414c0b746e5SOllivier Robert 		)
1415c0b746e5SOllivier Robert 	{
1416c0b746e5SOllivier Robert 		fprintf (stderr, "init_alarm(): timer_create (...) FAILED\n");
1417c0b746e5SOllivier Robert 		return;
1418c0b746e5SOllivier Robert 	}
1419c0b746e5SOllivier Robert 
1420c0b746e5SOllivier Robert 	/*	TIMER_HZ = (5)
1421c0b746e5SOllivier Robert 	 * Set up the alarm interrupt.	The first comes 1/(2*TIMER_HZ)
1422c0b746e5SOllivier Robert 	 * seconds from now and they continue on every 1/TIMER_HZ seconds.
1423c0b746e5SOllivier Robert 	 */
1424c0b746e5SOllivier Robert 	(void) signal_no_reset(SIGALRM, alarming);
1425c0b746e5SOllivier Robert 	ntpdate_itimer.it_interval.tv_sec = ntpdate_itimer.it_value.tv_sec = 0;
1426c0b746e5SOllivier Robert 	ntpdate_itimer.it_interval.tv_nsec = 1000000000/TIMER_HZ;
1427c0b746e5SOllivier Robert 	ntpdate_itimer.it_value.tv_nsec = 1000000000/(TIMER_HZ<<1);
1428c0b746e5SOllivier Robert 	timer_settime(ntpdate_timerid, 0 /* !TIMER_ABSTIME */, &ntpdate_itimer, NULL);
1429c0b746e5SOllivier Robert # else
1430c0b746e5SOllivier Robert 	/*
1431c0b746e5SOllivier Robert 	 * Set up the alarm interrupt.	The first comes 1/(2*TIMER_HZ)
1432c0b746e5SOllivier Robert 	 * seconds from now and they continue on every 1/TIMER_HZ seconds.
1433c0b746e5SOllivier Robert 	 */
1434c0b746e5SOllivier Robert 	(void) signal_no_reset(SIGALRM, alarming);
1435c0b746e5SOllivier Robert 	itimer.it_interval.tv_sec = itimer.it_value.tv_sec = 0;
1436c0b746e5SOllivier Robert 	itimer.it_interval.tv_usec = 1000000/TIMER_HZ;
1437c0b746e5SOllivier Robert 	itimer.it_value.tv_usec = 1000000/(TIMER_HZ<<1);
1438c0b746e5SOllivier Robert 	setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
1439c0b746e5SOllivier Robert # endif
1440c0b746e5SOllivier Robert #if defined SYS_CYGWIN32
1441c0b746e5SOllivier Robert 	/*
1442c0b746e5SOllivier Robert 	 * Get previleges needed for fiddling with the clock
1443c0b746e5SOllivier Robert 	 */
1444c0b746e5SOllivier Robert 
1445c0b746e5SOllivier Robert 	/* get the current process token handle */
1446c0b746e5SOllivier Robert 	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
1447c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "OpenProcessToken failed: %m");
1448c0b746e5SOllivier Robert 		exit(1);
1449c0b746e5SOllivier Robert 	}
1450c0b746e5SOllivier Robert 	/* get the LUID for system-time privilege. */
1451c0b746e5SOllivier Robert 	LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid);
1452c0b746e5SOllivier Robert 	tkp.PrivilegeCount = 1;  /* one privilege to set */
1453c0b746e5SOllivier Robert 	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
1454c0b746e5SOllivier Robert 	/* get set-time privilege for this process. */
1455c0b746e5SOllivier Robert 	AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES) NULL, 0);
1456c0b746e5SOllivier Robert 	/* cannot test return value of AdjustTokenPrivileges. */
1457c0b746e5SOllivier Robert 	if (GetLastError() != ERROR_SUCCESS)
1458c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m");
1459c0b746e5SOllivier Robert #endif
1460c0b746e5SOllivier Robert #else	/* SYS_WINNT */
1461c0b746e5SOllivier Robert 	_tzset();
1462c0b746e5SOllivier Robert 
1463c0b746e5SOllivier Robert 	/*
1464c0b746e5SOllivier Robert 	 * Get previleges needed for fiddling with the clock
1465c0b746e5SOllivier Robert 	 */
1466c0b746e5SOllivier Robert 
1467c0b746e5SOllivier Robert 	/* get the current process token handle */
1468c0b746e5SOllivier Robert 	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
1469c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "OpenProcessToken failed: %m");
1470c0b746e5SOllivier Robert 		exit(1);
1471c0b746e5SOllivier Robert 	}
1472c0b746e5SOllivier Robert 	/* get the LUID for system-time privilege. */
1473c0b746e5SOllivier Robert 	LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid);
1474c0b746e5SOllivier Robert 	tkp.PrivilegeCount = 1;  /* one privilege to set */
1475c0b746e5SOllivier Robert 	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
1476c0b746e5SOllivier Robert 	/* get set-time privilege for this process. */
1477c0b746e5SOllivier Robert 	AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES) NULL, 0);
1478c0b746e5SOllivier Robert 	/* cannot test return value of AdjustTokenPrivileges. */
1479c0b746e5SOllivier Robert 	if (GetLastError() != ERROR_SUCCESS)
1480c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m");
1481c0b746e5SOllivier Robert 
1482c0b746e5SOllivier Robert 	/*
1483c0b746e5SOllivier Robert 	 * Set up timer interrupts for every 2**EVENT_TIMEOUT seconds
1484c0b746e5SOllivier Robert 	 * Under Win/NT, expiry of timer interval leads to invocation
1485c0b746e5SOllivier Robert 	 * of a callback function (on a different thread) rather than
1486c0b746e5SOllivier Robert 	 * generating an alarm signal
1487c0b746e5SOllivier Robert 	 */
1488c0b746e5SOllivier Robert 
1489c0b746e5SOllivier Robert 	/* determine max and min resolution supported */
1490c0b746e5SOllivier Robert 	if(timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
1491c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "timeGetDevCaps failed: %m");
1492c0b746e5SOllivier Robert 		exit(1);
1493c0b746e5SOllivier Robert 	}
1494c0b746e5SOllivier Robert 	wTimerRes = min(max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax);
1495c0b746e5SOllivier Robert 	/* establish the minimum timer resolution that we'll use */
1496c0b746e5SOllivier Robert 	timeBeginPeriod(wTimerRes);
1497c0b746e5SOllivier Robert 
1498c0b746e5SOllivier Robert 	/* start the timer event */
1499c0b746e5SOllivier Robert 	wTimerID = timeSetEvent(
1500c0b746e5SOllivier Robert 		(UINT) (1000/TIMER_HZ),    /* Delay */
1501c0b746e5SOllivier Robert 		wTimerRes,			 /* Resolution */
1502c0b746e5SOllivier Robert 		(LPTIMECALLBACK) alarming, /* Callback function */
1503c0b746e5SOllivier Robert 		(DWORD) dwUser, 	 /* User data */
1504c0b746e5SOllivier Robert 		TIME_PERIODIC); 	 /* Event type (periodic) */
1505c0b746e5SOllivier Robert 	if (wTimerID == 0) {
1506c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "timeSetEvent failed: %m");
1507c0b746e5SOllivier Robert 		exit(1);
1508c0b746e5SOllivier Robert 	}
1509c0b746e5SOllivier Robert #endif /* SYS_WINNT */
1510c0b746e5SOllivier Robert }
1511c0b746e5SOllivier Robert 
1512c0b746e5SOllivier Robert 
1513c0b746e5SOllivier Robert 
1514c0b746e5SOllivier Robert 
1515c0b746e5SOllivier Robert /*
1516c0b746e5SOllivier Robert  * We do asynchronous input using the SIGIO facility.  A number of
1517c0b746e5SOllivier Robert  * recvbuf buffers are preallocated for input.	In the signal
1518c0b746e5SOllivier Robert  * handler we poll to see if the socket is ready and read the
1519c0b746e5SOllivier Robert  * packets from it into the recvbuf's along with a time stamp and
1520c0b746e5SOllivier Robert  * an indication of the source host and the interface it was received
1521c0b746e5SOllivier Robert  * through.  This allows us to get as accurate receive time stamps
1522c0b746e5SOllivier Robert  * as possible independent of other processing going on.
1523c0b746e5SOllivier Robert  *
1524c0b746e5SOllivier Robert  * We allocate a number of recvbufs equal to the number of servers
1525c0b746e5SOllivier Robert  * plus 2.	This should be plenty.
1526c0b746e5SOllivier Robert  */
1527c0b746e5SOllivier Robert 
1528c0b746e5SOllivier Robert 
1529c0b746e5SOllivier Robert /*
1530c0b746e5SOllivier Robert  * init_io - initialize I/O data and open socket
1531c0b746e5SOllivier Robert  */
1532c0b746e5SOllivier Robert static void
1533c0b746e5SOllivier Robert init_io(void)
1534c0b746e5SOllivier Robert {
1535c0b746e5SOllivier Robert 	/*
1536c0b746e5SOllivier Robert 	 * Init buffer free list and stat counters
1537c0b746e5SOllivier Robert 	 */
1538c0b746e5SOllivier Robert 	init_recvbuff(sys_numservers + 2);
1539c0b746e5SOllivier Robert 	/*
1540c0b746e5SOllivier Robert 	 * Open the socket
1541c0b746e5SOllivier Robert 	 */
1542c0b746e5SOllivier Robert 
1543c0b746e5SOllivier Robert 	/* create a datagram (UDP) socket */
1544c0b746e5SOllivier Robert 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1545c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "socket() failed: %m");
1546c0b746e5SOllivier Robert 		exit(1);
1547c0b746e5SOllivier Robert 		/*NOTREACHED*/
1548c0b746e5SOllivier Robert 	}
1549c0b746e5SOllivier Robert 
1550c0b746e5SOllivier Robert 	/*
1551c0b746e5SOllivier Robert 	 * bind the socket to the NTP port
1552c0b746e5SOllivier Robert 	 */
1553c0b746e5SOllivier Robert 	if (!debug && !simple_query && !unpriv_port) {
1554c0b746e5SOllivier Robert 		struct sockaddr_in addr;
1555c0b746e5SOllivier Robert 
1556c0b746e5SOllivier Robert 		memset((char *)&addr, 0, sizeof addr);
1557c0b746e5SOllivier Robert 		addr.sin_family = AF_INET;
1558c0b746e5SOllivier Robert 		addr.sin_port = htons(NTP_PORT);
1559c0b746e5SOllivier Robert 		addr.sin_addr.s_addr = htonl(INADDR_ANY);
1560c0b746e5SOllivier Robert 		if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
1561c0b746e5SOllivier Robert #ifndef SYS_WINNT
1562c0b746e5SOllivier Robert 			if (errno == EADDRINUSE)
1563c0b746e5SOllivier Robert #else
1564c0b746e5SOllivier Robert 				if (WSAGetLastError() == WSAEADDRINUSE)
1565c0b746e5SOllivier Robert #endif /* SYS_WINNT */
1566c0b746e5SOllivier Robert 				msyslog(LOG_ERR,
1567c0b746e5SOllivier Robert 					"the NTP socket is in use, exiting");
1568c0b746e5SOllivier Robert 				else
1569c0b746e5SOllivier Robert 				msyslog(LOG_ERR, "bind() fails: %m");
1570c0b746e5SOllivier Robert 			exit(1);
1571c0b746e5SOllivier Robert 		}
1572c0b746e5SOllivier Robert 	}
1573c0b746e5SOllivier Robert 
1574c0b746e5SOllivier Robert #ifdef HAVE_POLL_H
1575c0b746e5SOllivier Robert 	fdmask.fd = fd;
1576c0b746e5SOllivier Robert 	fdmask.events = POLLIN;
1577c0b746e5SOllivier Robert #else
1578c0b746e5SOllivier Robert 	FD_ZERO(&fdmask);
1579c0b746e5SOllivier Robert 	FD_SET(fd, &fdmask);
1580c0b746e5SOllivier Robert #endif
1581c0b746e5SOllivier Robert 
1582c0b746e5SOllivier Robert 	/*
1583c0b746e5SOllivier Robert 	 * set non-blocking,
1584c0b746e5SOllivier Robert 	 */
1585c0b746e5SOllivier Robert #ifndef SYS_WINNT
1586c0b746e5SOllivier Robert # ifdef SYS_VXWORKS
1587c0b746e5SOllivier Robert   {
1588c0b746e5SOllivier Robert 	int on = TRUE;
1589c0b746e5SOllivier Robert 
1590c0b746e5SOllivier Robert 	if (ioctl(fd,FIONBIO, &on) == ERROR) {
1591c0b746e5SOllivier Robert 	  msyslog(LOG_ERR, "ioctl(FIONBIO) fails: %m");
1592c0b746e5SOllivier Robert 	  exit(1);
1593c0b746e5SOllivier Robert 	}
1594c0b746e5SOllivier Robert   }
1595c0b746e5SOllivier Robert # else /* not SYS_VXWORKS */
1596c0b746e5SOllivier Robert #  if defined(O_NONBLOCK)
1597c0b746e5SOllivier Robert 	if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
1598c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails: %m");
1599c0b746e5SOllivier Robert 		exit(1);
1600c0b746e5SOllivier Robert 		/*NOTREACHED*/
1601c0b746e5SOllivier Robert 	}
1602c0b746e5SOllivier Robert #  else /* not O_NONBLOCK */
1603c0b746e5SOllivier Robert #	if defined(FNDELAY)
1604c0b746e5SOllivier Robert 	if (fcntl(fd, F_SETFL, FNDELAY) < 0) {
1605c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails: %m");
1606c0b746e5SOllivier Robert 		exit(1);
1607c0b746e5SOllivier Robert 		/*NOTREACHED*/
1608c0b746e5SOllivier Robert 	}
1609c0b746e5SOllivier Robert #	else /* FNDELAY */
1610c0b746e5SOllivier Robert #	 include "Bletch: Need non blocking I/O"
1611c0b746e5SOllivier Robert #	endif /* FNDELAY */
1612c0b746e5SOllivier Robert #  endif /* not O_NONBLOCK */
1613c0b746e5SOllivier Robert # endif /* SYS_VXWORKS */
1614c0b746e5SOllivier Robert #else /* SYS_WINNT */
1615c0b746e5SOllivier Robert 	if (ioctlsocket(fd, FIONBIO, (u_long *) &on) == SOCKET_ERROR) {
1616c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "ioctlsocket(FIONBIO) fails: %m");
1617c0b746e5SOllivier Robert 		exit(1);
1618c0b746e5SOllivier Robert 	}
1619c0b746e5SOllivier Robert #endif /* SYS_WINNT */
1620c0b746e5SOllivier Robert }
1621c0b746e5SOllivier Robert 
1622c0b746e5SOllivier Robert 
1623c0b746e5SOllivier Robert /*
1624c0b746e5SOllivier Robert  * sendpkt - send a packet to the specified destination
1625c0b746e5SOllivier Robert  */
1626c0b746e5SOllivier Robert static void
1627c0b746e5SOllivier Robert sendpkt(
1628c0b746e5SOllivier Robert 	struct sockaddr_in *dest,
1629c0b746e5SOllivier Robert 	struct pkt *pkt,
1630c0b746e5SOllivier Robert 	int len
1631c0b746e5SOllivier Robert 	)
1632c0b746e5SOllivier Robert {
1633c0b746e5SOllivier Robert 	int cc;
1634c0b746e5SOllivier Robert 
1635c0b746e5SOllivier Robert #ifdef SYS_WINNT
1636c0b746e5SOllivier Robert 	DWORD err;
1637c0b746e5SOllivier Robert #endif /* SYS_WINNT */
1638c0b746e5SOllivier Robert 
1639c0b746e5SOllivier Robert 	cc = sendto(fd, (char *)pkt, len, 0, (struct sockaddr *)dest,
1640c0b746e5SOllivier Robert 			sizeof(struct sockaddr_in));
1641c0b746e5SOllivier Robert #ifndef SYS_WINNT
1642c0b746e5SOllivier Robert 	if (cc == -1) {
1643c0b746e5SOllivier Robert 		if (errno != EWOULDBLOCK && errno != ENOBUFS)
1644c0b746e5SOllivier Robert #else
1645c0b746e5SOllivier Robert 	if (cc == SOCKET_ERROR) {
1646c0b746e5SOllivier Robert 		err = WSAGetLastError();
1647c0b746e5SOllivier Robert 		if (err != WSAEWOULDBLOCK && err != WSAENOBUFS)
1648c0b746e5SOllivier Robert #endif /* SYS_WINNT */
1649c0b746e5SOllivier Robert 			msyslog(LOG_ERR, "sendto(%s): %m", ntoa(dest));
1650c0b746e5SOllivier Robert 	}
1651c0b746e5SOllivier Robert }
1652c0b746e5SOllivier Robert 
1653c0b746e5SOllivier Robert 
1654c0b746e5SOllivier Robert /*
1655c0b746e5SOllivier Robert  * input_handler - receive packets asynchronously
1656c0b746e5SOllivier Robert  */
1657c0b746e5SOllivier Robert void
1658c0b746e5SOllivier Robert input_handler(void)
1659c0b746e5SOllivier Robert {
1660c0b746e5SOllivier Robert 	register int n;
1661c0b746e5SOllivier Robert 	register struct recvbuf *rb;
1662c0b746e5SOllivier Robert 	struct timeval tvzero;
1663c0b746e5SOllivier Robert 	int fromlen;
1664c0b746e5SOllivier Robert 	l_fp ts;
1665c0b746e5SOllivier Robert #ifdef HAVE_POLL_H
1666c0b746e5SOllivier Robert 	struct pollfd fds;
1667c0b746e5SOllivier Robert #else
1668c0b746e5SOllivier Robert 	fd_set fds;
1669c0b746e5SOllivier Robert #endif
1670c0b746e5SOllivier Robert 
1671c0b746e5SOllivier Robert 	/*
1672c0b746e5SOllivier Robert 	 * Do a poll to see if we have data
1673c0b746e5SOllivier Robert 	 */
1674c0b746e5SOllivier Robert 	for (;;) {
1675c0b746e5SOllivier Robert 		fds = fdmask;
1676c0b746e5SOllivier Robert 		tvzero.tv_sec = tvzero.tv_usec = 0;
1677c0b746e5SOllivier Robert #ifdef HAVE_POLL_H
1678c0b746e5SOllivier Robert 		n = poll(&fds, 1, tvzero.tv_sec * 1000);
1679c0b746e5SOllivier Robert #else
1680c0b746e5SOllivier Robert 		n = select(fd+1, &fds, (fd_set *)0, (fd_set *)0, &tvzero);
1681c0b746e5SOllivier Robert #endif
1682c0b746e5SOllivier Robert 
1683c0b746e5SOllivier Robert 		/*
1684c0b746e5SOllivier Robert 		 * If nothing to do, just return.  If an error occurred,
1685c0b746e5SOllivier Robert 		 * complain and return.  If we've got some, freeze a
1686c0b746e5SOllivier Robert 		 * timestamp.
1687c0b746e5SOllivier Robert 		 */
1688c0b746e5SOllivier Robert 		if (n == 0)
1689c0b746e5SOllivier Robert 			return;
1690c0b746e5SOllivier Robert 		else if (n == -1) {
1691c0b746e5SOllivier Robert 			if (errno != EINTR)
1692c0b746e5SOllivier Robert 				msyslog(LOG_ERR,
1693c0b746e5SOllivier Robert #ifdef HAVE_POLL_H
1694c0b746e5SOllivier Robert 					"poll() error: %m"
1695c0b746e5SOllivier Robert #else
1696c0b746e5SOllivier Robert 					"select() error: %m"
1697c0b746e5SOllivier Robert #endif
1698c0b746e5SOllivier Robert 					);
1699c0b746e5SOllivier Robert 			return;
1700c0b746e5SOllivier Robert 		}
1701c0b746e5SOllivier Robert 		get_systime(&ts);
1702c0b746e5SOllivier Robert 
1703c0b746e5SOllivier Robert 		/*
1704c0b746e5SOllivier Robert 		 * Get a buffer and read the frame.  If we
1705c0b746e5SOllivier Robert 		 * haven't got a buffer, or this is received
1706c0b746e5SOllivier Robert 		 * on the wild card socket, just dump the packet.
1707c0b746e5SOllivier Robert 		 */
1708c0b746e5SOllivier Robert 		if (initializing || free_recvbuffs() == 0) {
1709c0b746e5SOllivier Robert 			char buf[100];
1710c0b746e5SOllivier Robert 
1711c0b746e5SOllivier Robert #ifndef SYS_WINNT
1712c0b746e5SOllivier Robert 			(void) read(fd, buf, sizeof buf);
1713c0b746e5SOllivier Robert #else
1714c0b746e5SOllivier Robert 			/* NT's _read does not operate on nonblocking sockets
1715c0b746e5SOllivier Robert 			 * either recvfrom or ReadFile() has to be used here.
1716c0b746e5SOllivier Robert 			 * ReadFile is used in [ntpd]ntp_intres() and ntpdc,
1717c0b746e5SOllivier Robert 			 * just to be different use recvfrom() here
1718c0b746e5SOllivier Robert 			 */
1719c0b746e5SOllivier Robert 			recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)0, NULL);
1720c0b746e5SOllivier Robert #endif /* SYS_WINNT */
1721c0b746e5SOllivier Robert 			continue;
1722c0b746e5SOllivier Robert 		}
1723c0b746e5SOllivier Robert 
1724c0b746e5SOllivier Robert 		rb = get_free_recv_buffer();
1725c0b746e5SOllivier Robert 
1726c0b746e5SOllivier Robert 		fromlen = sizeof(struct sockaddr_in);
1727c0b746e5SOllivier Robert 		rb->recv_length = recvfrom(fd, (char *)&rb->recv_pkt,
1728c0b746e5SOllivier Robert 		   sizeof(rb->recv_pkt), 0,
1729c0b746e5SOllivier Robert 		   (struct sockaddr *)&rb->recv_srcadr, &fromlen);
1730c0b746e5SOllivier Robert 		if (rb->recv_length == -1) {
1731c0b746e5SOllivier Robert 			freerecvbuf(rb);
1732c0b746e5SOllivier Robert 			continue;
1733c0b746e5SOllivier Robert 		}
1734c0b746e5SOllivier Robert 
1735c0b746e5SOllivier Robert 		/*
1736c0b746e5SOllivier Robert 		 * Got one.  Mark how and when it got here,
1737c0b746e5SOllivier Robert 		 * put it on the full list.
1738c0b746e5SOllivier Robert 		 */
1739c0b746e5SOllivier Robert 		rb->recv_time = ts;
1740c0b746e5SOllivier Robert 		add_full_recv_buffer(rb);
1741c0b746e5SOllivier Robert 	}
1742c0b746e5SOllivier Robert }
1743c0b746e5SOllivier Robert 
1744c0b746e5SOllivier Robert 
1745c0b746e5SOllivier Robert #if !defined SYS_WINNT && !defined SYS_CYGWIN32
1746c0b746e5SOllivier Robert /*
1747c0b746e5SOllivier Robert  * adj_systime - do a big long slew of the system time
1748c0b746e5SOllivier Robert  */
1749c0b746e5SOllivier Robert static int
1750c0b746e5SOllivier Robert l_adj_systime(
1751c0b746e5SOllivier Robert 	l_fp *ts
1752c0b746e5SOllivier Robert 	)
1753c0b746e5SOllivier Robert {
1754c0b746e5SOllivier Robert 	struct timeval adjtv, oadjtv;
1755c0b746e5SOllivier Robert 	int isneg = 0;
1756c0b746e5SOllivier Robert 	l_fp offset;
1757c0b746e5SOllivier Robert #ifndef STEP_SLEW
1758c0b746e5SOllivier Robert 	l_fp overshoot;
1759c0b746e5SOllivier Robert #endif
1760c0b746e5SOllivier Robert 
1761c0b746e5SOllivier Robert 	/*
1762c0b746e5SOllivier Robert 	 * Take the absolute value of the offset
1763c0b746e5SOllivier Robert 	 */
1764c0b746e5SOllivier Robert 	offset = *ts;
1765c0b746e5SOllivier Robert 	if (L_ISNEG(&offset)) {
1766c0b746e5SOllivier Robert 		isneg = 1;
1767c0b746e5SOllivier Robert 		L_NEG(&offset);
1768c0b746e5SOllivier Robert 	}
1769c0b746e5SOllivier Robert 
1770c0b746e5SOllivier Robert #ifndef STEP_SLEW
1771c0b746e5SOllivier Robert 	/*
1772c0b746e5SOllivier Robert 	 * Calculate the overshoot.  XXX N.B. This code *knows*
1773c0b746e5SOllivier Robert 	 * ADJ_OVERSHOOT is 1/2.
1774c0b746e5SOllivier Robert 	 */
1775c0b746e5SOllivier Robert 	overshoot = offset;
1776c0b746e5SOllivier Robert 	L_RSHIFTU(&overshoot);
1777c0b746e5SOllivier Robert 	if (overshoot.l_ui != 0 || (overshoot.l_uf > ADJ_MAXOVERSHOOT)) {
1778c0b746e5SOllivier Robert 		overshoot.l_ui = 0;
1779c0b746e5SOllivier Robert 		overshoot.l_uf = ADJ_MAXOVERSHOOT;
1780c0b746e5SOllivier Robert 	}
1781c0b746e5SOllivier Robert 	L_ADD(&offset, &overshoot);
1782c0b746e5SOllivier Robert #endif
1783c0b746e5SOllivier Robert 	TSTOTV(&offset, &adjtv);
1784c0b746e5SOllivier Robert 
1785c0b746e5SOllivier Robert 	if (isneg) {
1786c0b746e5SOllivier Robert 		adjtv.tv_sec = -adjtv.tv_sec;
1787c0b746e5SOllivier Robert 		adjtv.tv_usec = -adjtv.tv_usec;
1788c0b746e5SOllivier Robert 	}
1789c0b746e5SOllivier Robert 
1790c0b746e5SOllivier Robert 	if (adjtv.tv_usec != 0 && !debug) {
1791c0b746e5SOllivier Robert 		if (adjtime(&adjtv, &oadjtv) < 0) {
1792c0b746e5SOllivier Robert 			msyslog(LOG_ERR, "Can't adjust the time of day: %m");
1793c0b746e5SOllivier Robert 			return 0;
1794c0b746e5SOllivier Robert 		}
1795c0b746e5SOllivier Robert 	}
1796c0b746e5SOllivier Robert 	return 1;
1797c0b746e5SOllivier Robert }
1798c0b746e5SOllivier Robert #endif /* SYS_WINNT */
1799c0b746e5SOllivier Robert 
1800c0b746e5SOllivier Robert 
1801c0b746e5SOllivier Robert /*
1802c0b746e5SOllivier Robert  * This fuction is not the same as lib/systime step_systime!!!
1803c0b746e5SOllivier Robert  */
1804c0b746e5SOllivier Robert static int
1805c0b746e5SOllivier Robert l_step_systime(
1806c0b746e5SOllivier Robert 	l_fp *ts
1807c0b746e5SOllivier Robert 	)
1808c0b746e5SOllivier Robert {
1809c0b746e5SOllivier Robert 	double dtemp;
1810c0b746e5SOllivier Robert 
1811c0b746e5SOllivier Robert #ifdef SLEWALWAYS
1812c0b746e5SOllivier Robert #ifdef STEP_SLEW
1813c0b746e5SOllivier Robert 	l_fp ftmp;
1814c0b746e5SOllivier Robert 	int isneg;
1815c0b746e5SOllivier Robert 	int n;
1816c0b746e5SOllivier Robert 
1817c0b746e5SOllivier Robert 	if (debug) return 1;
1818c0b746e5SOllivier Robert 	/*
1819c0b746e5SOllivier Robert 	 * Take the absolute value of the offset
1820c0b746e5SOllivier Robert 	 */
1821c0b746e5SOllivier Robert 	ftmp = *ts;
1822c0b746e5SOllivier Robert 	if (L_ISNEG(&ftmp)) {
1823c0b746e5SOllivier Robert 		L_NEG(&ftmp);
1824c0b746e5SOllivier Robert 		isneg = 1;
1825c0b746e5SOllivier Robert 	} else
1826c0b746e5SOllivier Robert 		isneg = 0;
1827c0b746e5SOllivier Robert 
1828c0b746e5SOllivier Robert 	if (ftmp.l_ui >= 3) {		/* Step it and slew - we might win */
1829c0b746e5SOllivier Robert 		n = step_systime(ts);
1830c0b746e5SOllivier Robert 		if (!n)
1831c0b746e5SOllivier Robert 			return n;
1832c0b746e5SOllivier Robert 		if (isneg)
1833c0b746e5SOllivier Robert 			ts->l_ui = ~0;
1834c0b746e5SOllivier Robert 		else
1835c0b746e5SOllivier Robert 			ts->l_ui = ~0;
1836c0b746e5SOllivier Robert 	}
1837c0b746e5SOllivier Robert 	/*
1838c0b746e5SOllivier Robert 	 * Just add adjustment into the current offset.  The update
1839c0b746e5SOllivier Robert 	 * routine will take care of bringing the system clock into
1840c0b746e5SOllivier Robert 	 * line.
1841c0b746e5SOllivier Robert 	 */
1842c0b746e5SOllivier Robert #endif
1843c0b746e5SOllivier Robert 	if (debug)
1844c0b746e5SOllivier Robert 		return 1;
1845c0b746e5SOllivier Robert #ifdef FORCE_NTPDATE_STEP
1846c0b746e5SOllivier Robert 	LFPTOD(ts, dtemp);
1847c0b746e5SOllivier Robert 	return step_systime(dtemp);
1848c0b746e5SOllivier Robert #else
1849c0b746e5SOllivier Robert 	l_adj_systime(ts);
1850c0b746e5SOllivier Robert 	return 1;
1851c0b746e5SOllivier Robert #endif
1852c0b746e5SOllivier Robert #else /* SLEWALWAYS  */
1853c0b746e5SOllivier Robert 	if (debug)
1854c0b746e5SOllivier Robert 		return 1;
1855c0b746e5SOllivier Robert 	LFPTOD(ts, dtemp);
1856c0b746e5SOllivier Robert 	return step_systime(dtemp);
1857c0b746e5SOllivier Robert #endif	/* SLEWALWAYS */
1858c0b746e5SOllivier Robert }
1859c0b746e5SOllivier Robert 
1860c0b746e5SOllivier Robert /*
1861c0b746e5SOllivier Robert  * getnetnum - given a host name, return its net number
1862c0b746e5SOllivier Robert  */
1863c0b746e5SOllivier Robert static int
1864c0b746e5SOllivier Robert getnetnum(
1865c0b746e5SOllivier Robert 	const char *host,
1866c0b746e5SOllivier Robert 	u_int32 *num
1867c0b746e5SOllivier Robert 	)
1868c0b746e5SOllivier Robert {
1869c0b746e5SOllivier Robert 	struct hostent *hp;
1870c0b746e5SOllivier Robert 
1871c0b746e5SOllivier Robert 	if (decodenetnum(host, num)) {
1872c0b746e5SOllivier Robert 		return 1;
1873c0b746e5SOllivier Robert 	} else if ((hp = gethostbyname(host)) != 0) {
1874c0b746e5SOllivier Robert 		memmove((char *)num, hp->h_addr, sizeof(u_int32));
1875c0b746e5SOllivier Robert 		return (1);
1876c0b746e5SOllivier Robert 	}
1877c0b746e5SOllivier Robert 	return (0);
1878c0b746e5SOllivier Robert }
1879c0b746e5SOllivier Robert 
1880c0b746e5SOllivier Robert /* XXX ELIMINATE printserver similar in ntptrace.c, ntpdate.c */
1881c0b746e5SOllivier Robert /*
1882c0b746e5SOllivier Robert  * printserver - print detail information for a server
1883c0b746e5SOllivier Robert  */
1884c0b746e5SOllivier Robert static void
1885c0b746e5SOllivier Robert printserver(
1886c0b746e5SOllivier Robert 	register struct server *pp,
1887c0b746e5SOllivier Robert 	FILE *fp
1888c0b746e5SOllivier Robert 	)
1889c0b746e5SOllivier Robert {
1890c0b746e5SOllivier Robert 	register int i;
1891c0b746e5SOllivier Robert 	char junk[5];
1892c0b746e5SOllivier Robert 	char *str;
1893c0b746e5SOllivier Robert 
1894c0b746e5SOllivier Robert 	if (!debug) {
1895c0b746e5SOllivier Robert 		(void) fprintf(fp, "server %s, stratum %d, offset %s, delay %s\n",
1896c0b746e5SOllivier Robert 				   ntoa(&pp->srcadr), pp->stratum,
1897c0b746e5SOllivier Robert 				   lfptoa(&pp->offset, 6), fptoa((s_fp)pp->delay, 5));
1898c0b746e5SOllivier Robert 		return;
1899c0b746e5SOllivier Robert 	}
1900c0b746e5SOllivier Robert 
1901c0b746e5SOllivier Robert 	(void) fprintf(fp, "server %s, port %d\n",
1902c0b746e5SOllivier Robert 			   ntoa(&pp->srcadr), ntohs(pp->srcadr.sin_port));
1903c0b746e5SOllivier Robert 
1904c0b746e5SOllivier Robert 	(void) fprintf(fp, "stratum %d, precision %d, leap %c%c, trust %03o\n",
1905c0b746e5SOllivier Robert 			   pp->stratum, pp->precision,
1906c0b746e5SOllivier Robert 			   pp->leap & 0x2 ? '1' : '0',
1907c0b746e5SOllivier Robert 			   pp->leap & 0x1 ? '1' : '0',
1908c0b746e5SOllivier Robert 			   pp->trust);
1909c0b746e5SOllivier Robert 
1910c0b746e5SOllivier Robert 	if (pp->stratum == 1) {
1911c0b746e5SOllivier Robert 		junk[4] = 0;
1912c0b746e5SOllivier Robert 		memmove(junk, (char *)&pp->refid, 4);
1913c0b746e5SOllivier Robert 		str = junk;
1914c0b746e5SOllivier Robert 	} else {
1915c0b746e5SOllivier Robert 		str = numtoa(pp->refid);
1916c0b746e5SOllivier Robert 	}
1917c0b746e5SOllivier Robert 	(void) fprintf(fp,
1918c0b746e5SOllivier Robert 			   "refid [%s], delay %s, dispersion %s\n",
1919c0b746e5SOllivier Robert 			   str, fptoa((s_fp)pp->delay, 5),
1920c0b746e5SOllivier Robert 			   ufptoa(pp->dispersion, 5));
1921c0b746e5SOllivier Robert 
1922c0b746e5SOllivier Robert 	(void) fprintf(fp, "transmitted %d, in filter %d\n",
1923c0b746e5SOllivier Robert 			   pp->xmtcnt, pp->filter_nextpt);
1924c0b746e5SOllivier Robert 
1925c0b746e5SOllivier Robert 	(void) fprintf(fp, "reference time:    %s\n",
1926c0b746e5SOllivier Robert 			   prettydate(&pp->reftime));
1927c0b746e5SOllivier Robert 	(void) fprintf(fp, "originate timestamp: %s\n",
1928c0b746e5SOllivier Robert 			   prettydate(&pp->org));
1929c0b746e5SOllivier Robert 	(void) fprintf(fp, "transmit timestamp:  %s\n",
1930c0b746e5SOllivier Robert 			   prettydate(&pp->xmt));
1931c0b746e5SOllivier Robert 
1932c0b746e5SOllivier Robert 	(void) fprintf(fp, "filter delay: ");
1933c0b746e5SOllivier Robert 	for (i = 0; i < NTP_SHIFT; i++) {
1934c0b746e5SOllivier Robert 		(void) fprintf(fp, " %-8.8s", fptoa(pp->filter_delay[i], 5));
1935c0b746e5SOllivier Robert 		if (i == (NTP_SHIFT>>1)-1)
1936c0b746e5SOllivier Robert 			(void) fprintf(fp, "\n        ");
1937c0b746e5SOllivier Robert 	}
1938c0b746e5SOllivier Robert 	(void) fprintf(fp, "\n");
1939c0b746e5SOllivier Robert 
1940c0b746e5SOllivier Robert 	(void) fprintf(fp, "filter offset:");
1941c0b746e5SOllivier Robert 	for (i = 0; i < PEER_SHIFT; i++) {
1942c0b746e5SOllivier Robert 		(void) fprintf(fp, " %-8.8s", lfptoa(&pp->filter_offset[i], 6));
1943c0b746e5SOllivier Robert 		if (i == (PEER_SHIFT>>1)-1)
1944c0b746e5SOllivier Robert 			(void) fprintf(fp, "\n        ");
1945c0b746e5SOllivier Robert 	}
1946c0b746e5SOllivier Robert 	(void) fprintf(fp, "\n");
1947c0b746e5SOllivier Robert 
1948c0b746e5SOllivier Robert 	(void) fprintf(fp, "delay %s, dispersion %s\n",
1949c0b746e5SOllivier Robert 			   fptoa((s_fp)pp->delay, 5), ufptoa(pp->dispersion, 5));
1950c0b746e5SOllivier Robert 
1951c0b746e5SOllivier Robert 	(void) fprintf(fp, "offset %s\n\n",
1952c0b746e5SOllivier Robert 			   lfptoa(&pp->offset, 6));
1953c0b746e5SOllivier Robert }
1954c0b746e5SOllivier Robert 
1955c0b746e5SOllivier Robert #if !defined(HAVE_VSPRINTF)
1956c0b746e5SOllivier Robert int
1957c0b746e5SOllivier Robert vsprintf(
1958c0b746e5SOllivier Robert 	char *str,
1959c0b746e5SOllivier Robert 	const char *fmt,
1960c0b746e5SOllivier Robert 	va_list ap
1961c0b746e5SOllivier Robert 	)
1962c0b746e5SOllivier Robert {
1963c0b746e5SOllivier Robert 	FILE f;
1964c0b746e5SOllivier Robert 	int len;
1965c0b746e5SOllivier Robert 
1966c0b746e5SOllivier Robert 	f._flag = _IOWRT+_IOSTRG;
1967c0b746e5SOllivier Robert 	f._ptr = str;
1968c0b746e5SOllivier Robert 	f._cnt = 32767;
1969c0b746e5SOllivier Robert 	len = _doprnt(fmt, ap, &f);
1970c0b746e5SOllivier Robert 	*f._ptr = 0;
1971c0b746e5SOllivier Robert 	return (len);
1972c0b746e5SOllivier Robert }
1973c0b746e5SOllivier Robert #endif
1974c0b746e5SOllivier Robert 
1975c0b746e5SOllivier Robert #if 0
1976c0b746e5SOllivier Robert /* override function in library since SA_RESTART makes ALL syscalls restart */
1977c0b746e5SOllivier Robert #ifdef SA_RESTART
1978c0b746e5SOllivier Robert void
1979c0b746e5SOllivier Robert signal_no_reset(
1980c0b746e5SOllivier Robert 	int sig,
1981c0b746e5SOllivier Robert 	void (*func)()
1982c0b746e5SOllivier Robert 	)
1983c0b746e5SOllivier Robert {
1984c0b746e5SOllivier Robert 	int n;
1985c0b746e5SOllivier Robert 	struct sigaction vec;
1986c0b746e5SOllivier Robert 
1987c0b746e5SOllivier Robert 	vec.sa_handler = func;
1988c0b746e5SOllivier Robert 	sigemptyset(&vec.sa_mask);
1989c0b746e5SOllivier Robert 	vec.sa_flags = 0;
1990c0b746e5SOllivier Robert 
1991c0b746e5SOllivier Robert 	while (1)
1992c0b746e5SOllivier Robert 	{
1993c0b746e5SOllivier Robert 		n = sigaction(sig, &vec, NULL);
1994c0b746e5SOllivier Robert 		if (n == -1 && errno == EINTR)
1995c0b746e5SOllivier Robert 			continue;
1996c0b746e5SOllivier Robert 		break;
1997c0b746e5SOllivier Robert 	}
1998c0b746e5SOllivier Robert 	if (n == -1)
1999c0b746e5SOllivier Robert 	{
2000c0b746e5SOllivier Robert 		perror("sigaction");
2001c0b746e5SOllivier Robert 		exit(1);
2002c0b746e5SOllivier Robert 	}
2003c0b746e5SOllivier Robert }
2004c0b746e5SOllivier Robert #endif
2005c0b746e5SOllivier Robert #endif
2006c0b746e5SOllivier Robert 
2007c0b746e5SOllivier Robert #ifdef HAVE_NETINFO
2008c0b746e5SOllivier Robert static ni_namelist *
2009c0b746e5SOllivier Robert getnetinfoservers(void)
2010c0b746e5SOllivier Robert {
2011c0b746e5SOllivier Robert 	ni_status status;
2012c0b746e5SOllivier Robert 	void *domain;
2013c0b746e5SOllivier Robert 	ni_id confdir;
2014c0b746e5SOllivier Robert 	ni_namelist *namelist = (ni_namelist*)malloc(sizeof(ni_namelist));
2015c0b746e5SOllivier Robert 
2016c0b746e5SOllivier Robert 	/* Find a time server in NetInfo */
2017c0b746e5SOllivier Robert 	if ((status = ni_open(NULL, ".", &domain)) != NI_OK) return NULL;
2018c0b746e5SOllivier Robert 
2019c0b746e5SOllivier Robert 	while (status = ni_pathsearch(domain, &confdir, NETINFO_CONFIG_DIR) == NI_NODIR) {
2020c0b746e5SOllivier Robert 		void *next_domain;
2021c0b746e5SOllivier Robert 		if (ni_open(domain, "..", &next_domain) != NI_OK) break;
2022c0b746e5SOllivier Robert 		ni_free(domain);
2023c0b746e5SOllivier Robert 		domain = next_domain;
2024c0b746e5SOllivier Robert 	}
2025c0b746e5SOllivier Robert 	if (status != NI_OK) return NULL;
2026c0b746e5SOllivier Robert 
2027c0b746e5SOllivier Robert 	NI_INIT(namelist);
2028c0b746e5SOllivier Robert 	if (ni_lookupprop(domain, &confdir, "server", namelist) != NI_OK) {
2029c0b746e5SOllivier Robert 		ni_namelist_free(namelist);
2030c0b746e5SOllivier Robert 		free(namelist);
2031c0b746e5SOllivier Robert 		return NULL;
2032c0b746e5SOllivier Robert 	}
2033c0b746e5SOllivier Robert 
2034c0b746e5SOllivier Robert 	return(namelist);
2035c0b746e5SOllivier Robert }
2036c0b746e5SOllivier Robert #endif
2037