xref: /freebsd/contrib/ntp/ntpdate/ntpdate.c (revision b9bb0f5d)
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 
9224ba2bdSOllivier Robert #ifdef HAVE_NETINFO
10224ba2bdSOllivier Robert #include <netinfo/ni.h>
11c0b746e5SOllivier Robert #endif
12224ba2bdSOllivier Robert 
13ce265a54SOllivier Robert #include "ntp_machine.h"
14224ba2bdSOllivier Robert #include "ntp_fp.h"
15224ba2bdSOllivier Robert #include "ntp.h"
16224ba2bdSOllivier Robert #include "ntp_io.h"
17224ba2bdSOllivier Robert #include "timevalops.h"
18224ba2bdSOllivier Robert #include "ntpdate.h"
19224ba2bdSOllivier Robert #include "ntp_string.h"
20224ba2bdSOllivier Robert #include "ntp_syslog.h"
21224ba2bdSOllivier Robert #include "ntp_select.h"
22224ba2bdSOllivier Robert #include "ntp_stdlib.h"
23224ba2bdSOllivier Robert #include <ssl_applink.c>
24c0b746e5SOllivier Robert 
25c0b746e5SOllivier Robert #include "isc/net.h"
26c0b746e5SOllivier Robert #include "isc/result.h"
27c0b746e5SOllivier Robert #include "isc/sockaddr.h"
28c0b746e5SOllivier Robert 
29c0b746e5SOllivier Robert #ifdef HAVE_UNISTD_H
30c0b746e5SOllivier Robert # include <unistd.h>
31c0b746e5SOllivier Robert #endif
32c0b746e5SOllivier Robert 
33c0b746e5SOllivier Robert #include <stdio.h>
34c0b746e5SOllivier Robert #include <signal.h>
35c0b746e5SOllivier Robert #include <ctype.h>
36ce265a54SOllivier Robert #ifdef HAVE_POLL_H
37c0b746e5SOllivier Robert # include <poll.h>
38ce265a54SOllivier Robert #endif
39ce265a54SOllivier Robert #ifdef HAVE_SYS_SIGNAL_H
40ce265a54SOllivier Robert # include <sys/signal.h>
41224ba2bdSOllivier Robert #endif
42c0b746e5SOllivier Robert #ifdef HAVE_SYS_IOCTL_H
43224ba2bdSOllivier Robert # include <sys/ioctl.h>
44c0b746e5SOllivier Robert #endif
45c0b746e5SOllivier Robert #ifdef HAVE_SYS_RESOURCE_H
46c0b746e5SOllivier Robert # include <sys/resource.h>
47c0b746e5SOllivier Robert #endif
48c0b746e5SOllivier Robert 
499c2daa00SOllivier Robert #include <arpa/inet.h>
509c2daa00SOllivier Robert 
519c2daa00SOllivier Robert #ifdef SYS_VXWORKS
529c2daa00SOllivier Robert # include "ioLib.h"
539c2daa00SOllivier Robert # include "sockLib.h"
549c2daa00SOllivier Robert # include "timers.h"
55c0b746e5SOllivier Robert 
56c0b746e5SOllivier Robert /* select wants a zero structure ... */
57c0b746e5SOllivier Robert struct timeval timeout = {0,0};
58c0b746e5SOllivier Robert #elif defined(SYS_WINNT)
59c0b746e5SOllivier Robert /*
60c0b746e5SOllivier Robert  * Windows does not abort a select select call if SIGALRM goes off
61c0b746e5SOllivier Robert  * so a 200 ms timeout is needed (TIMER_HZ is 5).
62c0b746e5SOllivier Robert  */
63c0b746e5SOllivier Robert struct sock_timeval timeout = {0,1000000/TIMER_HZ};
64c0b746e5SOllivier Robert #else
65c0b746e5SOllivier Robert struct timeval timeout = {60,0};
669c2daa00SOllivier Robert #endif
679c2daa00SOllivier Robert 
689c2daa00SOllivier Robert #ifdef HAVE_NETINFO
699c2daa00SOllivier Robert #include <netinfo/ni.h>
70c0b746e5SOllivier Robert #endif
71c0b746e5SOllivier Robert 
72c0b746e5SOllivier Robert #include "recvbuff.h"
739c2daa00SOllivier Robert 
749c2daa00SOllivier Robert #ifdef SYS_WINNT
759c2daa00SOllivier Robert #define TARGET_RESOLUTION 1  /* Try for 1-millisecond accuracy
76c0b746e5SOllivier Robert 				on Windows NT timers. */
77c0b746e5SOllivier Robert #pragma comment(lib, "winmm")
78c0b746e5SOllivier Robert isc_boolean_t ntp_port_inuse(int af, u_short port);
79c0b746e5SOllivier Robert UINT wTimerRes;
80c0b746e5SOllivier Robert #endif /* SYS_WINNT */
81c0b746e5SOllivier Robert 
82c0b746e5SOllivier Robert /*
83c0b746e5SOllivier Robert  * Scheduling priority we run at
84c0b746e5SOllivier Robert  */
85c0b746e5SOllivier Robert #ifndef SYS_VXWORKS
86c0b746e5SOllivier Robert # define	NTPDATE_PRIO	(-12)
87c0b746e5SOllivier Robert #else
88c0b746e5SOllivier Robert # define	NTPDATE_PRIO	(100)
89c0b746e5SOllivier Robert #endif
90c0b746e5SOllivier Robert 
91c0b746e5SOllivier Robert #ifdef HAVE_TIMER_CREATE
92c0b746e5SOllivier Robert /* POSIX TIMERS - vxWorks doesn't have itimer - casey */
93c0b746e5SOllivier Robert static timer_t ntpdate_timerid;
94c0b746e5SOllivier Robert #endif
95c0b746e5SOllivier Robert 
96c0b746e5SOllivier Robert /*
97c0b746e5SOllivier Robert  * Compatibility stuff for Version 2
98c0b746e5SOllivier Robert  */
99c0b746e5SOllivier Robert #define NTP_MAXSKW	0x28f	/* 0.01 sec in fp format */
100c0b746e5SOllivier Robert #define NTP_MINDIST	0x51f	/* 0.02 sec in fp format */
101c0b746e5SOllivier Robert #define PEER_MAXDISP	(64*FP_SECOND)	/* maximum dispersion (fp 64) */
102c0b746e5SOllivier Robert #define NTP_INFIN	15	/* max stratum, infinity a la Bellman-Ford */
103c0b746e5SOllivier Robert #define NTP_MAXWGT	(8*FP_SECOND)	/* maximum select weight 8 seconds */
104c0b746e5SOllivier Robert #define NTP_MAXLIST	5	/* maximum select list size */
105c0b746e5SOllivier Robert #define PEER_SHIFT	8	/* 8 suitable for crystal time base */
106c0b746e5SOllivier Robert 
107c0b746e5SOllivier Robert /*
108c0b746e5SOllivier Robert  * for get_systime()
109c0b746e5SOllivier Robert  */
110c0b746e5SOllivier Robert s_char	sys_precision;		/* local clock precision (log2 s) */
111c0b746e5SOllivier Robert 
112c0b746e5SOllivier Robert /*
113c0b746e5SOllivier Robert  * File descriptor masks etc. for call to select
1149c2daa00SOllivier Robert  */
1159c2daa00SOllivier Robert 
1169c2daa00SOllivier Robert int ai_fam_templ;
1179c2daa00SOllivier Robert int nbsock;			/* the number of sockets used */
1189c2daa00SOllivier Robert SOCKET fd[MAX_AF];
119c0b746e5SOllivier Robert int fd_family[MAX_AF];		/* to remember the socket family */
1209c2daa00SOllivier Robert #ifdef HAVE_POLL_H
121c0b746e5SOllivier Robert struct pollfd fdmask[MAX_AF];
122c0b746e5SOllivier Robert #else
1239c2daa00SOllivier Robert fd_set fdmask;
124c0b746e5SOllivier Robert SOCKET maxfd;
1259c2daa00SOllivier Robert #endif
126c0b746e5SOllivier Robert int polltest = 0;
127c0b746e5SOllivier Robert 
128c0b746e5SOllivier Robert /*
129c0b746e5SOllivier Robert  * Initializing flag.  All async routines watch this and only do their
130c0b746e5SOllivier Robert  * thing when it is clear.
131c0b746e5SOllivier Robert  */
132c0b746e5SOllivier Robert int initializing = 1;
133c0b746e5SOllivier Robert 
134c0b746e5SOllivier Robert /*
135c0b746e5SOllivier Robert  * Alarm flag.	Set when an alarm occurs
136c0b746e5SOllivier Robert  */
137c0b746e5SOllivier Robert volatile int alarm_flag = 0;
138c0b746e5SOllivier Robert 
139c0b746e5SOllivier Robert /*
140c0b746e5SOllivier Robert  * Simple query flag.
141c0b746e5SOllivier Robert  */
142c0b746e5SOllivier Robert int simple_query = 0;
143c0b746e5SOllivier Robert 
144c0b746e5SOllivier Robert /*
145c0b746e5SOllivier Robert  * Unprivileged port flag.
146c0b746e5SOllivier Robert  */
147c0b746e5SOllivier Robert int unpriv_port = 0;
148c0b746e5SOllivier Robert 
149c0b746e5SOllivier Robert /*
150c0b746e5SOllivier Robert  * Program name.
151c0b746e5SOllivier Robert  */
152c0b746e5SOllivier Robert char const *progname;
153c0b746e5SOllivier Robert 
154c0b746e5SOllivier Robert /*
155c0b746e5SOllivier Robert  * Systemwide parameters and flags
156c0b746e5SOllivier Robert  */
157c0b746e5SOllivier Robert int sys_samples = 0;		/* number of samples/server, will be modified later */
158c0b746e5SOllivier Robert u_long sys_timeout = DEFTIMEOUT; /* timeout time, in TIMER_HZ units */
159c0b746e5SOllivier Robert struct server *sys_servers;	/* the server list */
160c0b746e5SOllivier Robert int sys_numservers = 0; 	/* number of servers to poll */
161c0b746e5SOllivier Robert int sys_authenticate = 0;	/* true when authenticating */
162c0b746e5SOllivier Robert u_int32 sys_authkey = 0;	/* set to authentication key in use */
163a151a66cSOllivier Robert u_long sys_authdelay = 0;	/* authentication delay */
164c0b746e5SOllivier Robert int sys_version = NTP_VERSION;	/* version to poll with */
165c0b746e5SOllivier Robert 
166c0b746e5SOllivier Robert /*
167c0b746e5SOllivier Robert  * The current internal time
168c0b746e5SOllivier Robert  */
169c0b746e5SOllivier Robert u_long current_time = 0;
170c0b746e5SOllivier Robert 
171c0b746e5SOllivier Robert /*
172c0b746e5SOllivier Robert  * Counter for keeping track of completed servers
173c0b746e5SOllivier Robert  */
174c0b746e5SOllivier Robert int complete_servers = 0;
175c0b746e5SOllivier Robert 
176c0b746e5SOllivier Robert /*
177c0b746e5SOllivier Robert  * File of encryption keys
178c0b746e5SOllivier Robert  */
179c0b746e5SOllivier Robert 
180c0b746e5SOllivier Robert #ifndef KEYFILE
181c0b746e5SOllivier Robert # ifndef SYS_WINNT
182c0b746e5SOllivier Robert #define KEYFILE 	"/etc/ntp.keys"
183c0b746e5SOllivier Robert # else
184c0b746e5SOllivier Robert #define KEYFILE 	"%windir%\\ntp.keys"
185c0b746e5SOllivier Robert # endif /* SYS_WINNT */
186c0b746e5SOllivier Robert #endif /* KEYFILE */
187c0b746e5SOllivier Robert 
188c0b746e5SOllivier Robert #ifndef SYS_WINNT
189c0b746e5SOllivier Robert const char *key_file = KEYFILE;
190c0b746e5SOllivier Robert #else
191c0b746e5SOllivier Robert char key_file_storage[MAX_PATH+1], *key_file ;
192c0b746e5SOllivier Robert #endif	 /* SYS_WINNT */
193c0b746e5SOllivier Robert 
194c0b746e5SOllivier Robert /*
195c0b746e5SOllivier Robert  * Miscellaneous flags
196c0b746e5SOllivier Robert  */
197c0b746e5SOllivier Robert int verbose = 0;
198c0b746e5SOllivier Robert int always_step = 0;
199c0b746e5SOllivier Robert int never_step = 0;
200c0b746e5SOllivier Robert 
201c0b746e5SOllivier Robert int 	ntpdatemain (int, char **);
202c0b746e5SOllivier Robert 
203c0b746e5SOllivier Robert static	void	transmit	(struct server *);
204c0b746e5SOllivier Robert static	void	receive 	(struct recvbuf *);
205c0b746e5SOllivier Robert static	void	server_data (struct server *, s_fp, l_fp *, u_fp);
2069c2daa00SOllivier Robert static	void	clock_filter	(struct server *);
207c0b746e5SOllivier Robert static	struct server *clock_select (void);
208c0b746e5SOllivier Robert static	int clock_adjust	(void);
209c0b746e5SOllivier Robert static	void	addserver	(char *);
210c0b746e5SOllivier Robert static	struct server *findserver (sockaddr_u *);
211c0b746e5SOllivier Robert 		void	timer		(void);
212c0b746e5SOllivier Robert static	void	init_alarm	(void);
213c0b746e5SOllivier Robert #ifndef SYS_WINNT
2149c2daa00SOllivier Robert static	RETSIGTYPE alarming (int);
215c0b746e5SOllivier Robert #endif /* SYS_WINNT */
216c0b746e5SOllivier Robert static	void	init_io 	(void);
217c0b746e5SOllivier Robert static	void	sendpkt 	(sockaddr_u *, struct pkt *, int);
218c0b746e5SOllivier Robert void	input_handler	(void);
219c0b746e5SOllivier Robert 
220c0b746e5SOllivier Robert static	int l_adj_systime	(l_fp *);
2219c2daa00SOllivier Robert static	int l_step_systime	(l_fp *);
222c0b746e5SOllivier Robert 
223c0b746e5SOllivier Robert static	void	print_server (struct server *, FILE *);
224c0b746e5SOllivier Robert 
225c0b746e5SOllivier Robert #ifdef SYS_WINNT
226c0b746e5SOllivier Robert int 	on = 1;
227c0b746e5SOllivier Robert WORD	wVersionRequested;
228c0b746e5SOllivier Robert WSADATA	wsaData;
229c0b746e5SOllivier Robert #endif /* SYS_WINNT */
230c0b746e5SOllivier Robert 
231c0b746e5SOllivier Robert #ifdef NO_MAIN_ALLOWED
232c0b746e5SOllivier Robert CALL(ntpdate,"ntpdate",ntpdatemain);
233c0b746e5SOllivier Robert 
clear_globals()234c0b746e5SOllivier Robert void clear_globals()
235c0b746e5SOllivier Robert {
236c0b746e5SOllivier Robert   /*
237c0b746e5SOllivier Robert    * Debugging flag
238c0b746e5SOllivier Robert    */
239c0b746e5SOllivier Robert   debug = 0;
240c0b746e5SOllivier Robert 
241c0b746e5SOllivier Robert   ntp_optind = 0;
242c0b746e5SOllivier Robert   /*
243c0b746e5SOllivier Robert    * Initializing flag.  All async routines watch this and only do their
244c0b746e5SOllivier Robert    * thing when it is clear.
245c0b746e5SOllivier Robert    */
246c0b746e5SOllivier Robert   initializing = 1;
247c0b746e5SOllivier Robert 
248c0b746e5SOllivier Robert   /*
249c0b746e5SOllivier Robert    * Alarm flag.  Set when an alarm occurs
250c0b746e5SOllivier Robert    */
251c0b746e5SOllivier Robert   alarm_flag = 0;
252c0b746e5SOllivier Robert 
253c0b746e5SOllivier Robert   /*
254c0b746e5SOllivier Robert    * Simple query flag.
255c0b746e5SOllivier Robert    */
256c0b746e5SOllivier Robert   simple_query = 0;
257c0b746e5SOllivier Robert 
258c0b746e5SOllivier Robert   /*
259c0b746e5SOllivier Robert    * Unprivileged port flag.
260c0b746e5SOllivier Robert    */
261c0b746e5SOllivier Robert   unpriv_port = 0;
262c0b746e5SOllivier Robert 
263c0b746e5SOllivier Robert   /*
264c0b746e5SOllivier Robert    * Systemwide parameters and flags
265c0b746e5SOllivier Robert    */
266c0b746e5SOllivier Robert   sys_numservers = 0;	  /* number of servers to poll */
267c0b746e5SOllivier Robert   sys_authenticate = 0;   /* true when authenticating */
268c0b746e5SOllivier Robert   sys_authkey = 0;	   /* set to authentication key in use */
269c0b746e5SOllivier Robert   sys_authdelay = 0;   /* authentication delay */
270c0b746e5SOllivier Robert   sys_version = NTP_VERSION;  /* version to poll with */
271c0b746e5SOllivier Robert 
272c0b746e5SOllivier Robert   /*
273c0b746e5SOllivier Robert    * The current internal time
274c0b746e5SOllivier Robert    */
275c0b746e5SOllivier Robert   current_time = 0;
276c0b746e5SOllivier Robert 
277c0b746e5SOllivier Robert   /*
278c0b746e5SOllivier Robert    * Counter for keeping track of completed servers
279c0b746e5SOllivier Robert    */
280c0b746e5SOllivier Robert   complete_servers = 0;
281c0b746e5SOllivier Robert   verbose = 0;
282c0b746e5SOllivier Robert   always_step = 0;
283c0b746e5SOllivier Robert   never_step = 0;
284c0b746e5SOllivier Robert }
285c0b746e5SOllivier Robert #endif
286c0b746e5SOllivier Robert 
287c0b746e5SOllivier Robert #ifdef HAVE_NETINFO
288c0b746e5SOllivier Robert static ni_namelist *getnetinfoservers (void);
289c0b746e5SOllivier Robert #endif
290c0b746e5SOllivier Robert 
291c0b746e5SOllivier Robert /*
292c0b746e5SOllivier Robert  * Main program.  Initialize us and loop waiting for I/O and/or
293c0b746e5SOllivier Robert  * timer expiries.
294c0b746e5SOllivier Robert  */
295c0b746e5SOllivier Robert #ifndef NO_MAIN_ALLOWED
296c0b746e5SOllivier Robert int
main(int argc,char * argv[])297c0b746e5SOllivier Robert main(
298c0b746e5SOllivier Robert 	int argc,
299c0b746e5SOllivier Robert 	char *argv[]
300c0b746e5SOllivier Robert 	)
301c0b746e5SOllivier Robert {
302c0b746e5SOllivier Robert 	return ntpdatemain (argc, argv);
303c0b746e5SOllivier Robert }
304c0b746e5SOllivier Robert #endif /* NO_MAIN_ALLOWED */
305c0b746e5SOllivier Robert 
306c0b746e5SOllivier Robert int
ntpdatemain(int argc,char * argv[])307c0b746e5SOllivier Robert ntpdatemain (
308c0b746e5SOllivier Robert 	int argc,
309c0b746e5SOllivier Robert 	char *argv[]
310c0b746e5SOllivier Robert 	)
311c0b746e5SOllivier Robert {
312c0b746e5SOllivier Robert 	int was_alarmed;
313c0b746e5SOllivier Robert 	int tot_recvbufs;
314c0b746e5SOllivier Robert 	struct recvbuf *rbuf;
315c0b746e5SOllivier Robert 	l_fp tmp;
316c0b746e5SOllivier Robert 	int errflg;
317c0b746e5SOllivier Robert 	int c;
318c0b746e5SOllivier Robert 	int nfound;
319c0b746e5SOllivier Robert 
320c0b746e5SOllivier Robert #ifdef HAVE_NETINFO
321c0b746e5SOllivier Robert 	ni_namelist *netinfoservers;
322c0b746e5SOllivier Robert #endif
323c0b746e5SOllivier Robert #ifdef SYS_WINNT
324c0b746e5SOllivier Robert 	key_file = key_file_storage;
325c0b746e5SOllivier Robert 
326c0b746e5SOllivier Robert 	if (!ExpandEnvironmentStrings(KEYFILE, key_file, MAX_PATH))
3279c2daa00SOllivier Robert 		msyslog(LOG_ERR, "ExpandEnvironmentStrings(KEYFILE) failed: %m");
3289c2daa00SOllivier Robert 
329c0b746e5SOllivier Robert 	ssl_applink();
330c0b746e5SOllivier Robert #endif /* SYS_WINNT */
331c0b746e5SOllivier Robert 
332c0b746e5SOllivier Robert #ifdef NO_MAIN_ALLOWED
333c0b746e5SOllivier Robert 	clear_globals();
334c0b746e5SOllivier Robert #endif
335c0b746e5SOllivier Robert 
336c0b746e5SOllivier Robert 	init_lib();	/* sets up ipv4_works, ipv6_works */
3379c2daa00SOllivier Robert 
338c0b746e5SOllivier Robert 	/* Check to see if we have IPv6. Otherwise default to IPv4 */
339c0b746e5SOllivier Robert 	if (!ipv6_works)
340c0b746e5SOllivier Robert 		ai_fam_templ = AF_INET;
341c0b746e5SOllivier Robert 
342c0b746e5SOllivier Robert #ifdef HAVE_NETINFO
343c0b746e5SOllivier Robert 	errflg = 0;		/* servers can come from netinfo */
344c0b746e5SOllivier Robert #else
345c0b746e5SOllivier Robert 	errflg = (argc < 2);	/* need at least server on cmdline */
346c0b746e5SOllivier Robert #endif
347c0b746e5SOllivier Robert 	progname = argv[0];
348c0b746e5SOllivier Robert 	syslogit = 0;
349c0b746e5SOllivier Robert 
350c0b746e5SOllivier Robert 	/*
351c0b746e5SOllivier Robert 	 * Decode argument list
352c0b746e5SOllivier Robert 	 */
353c0b746e5SOllivier Robert 	while ((c = ntp_getopt(argc, argv, "46a:bBde:k:o:p:qst:uv")) != EOF)
354c0b746e5SOllivier Robert 		switch (c)
355c0b746e5SOllivier Robert 		{
356c0b746e5SOllivier Robert 		case '4':
357c0b746e5SOllivier Robert 			ai_fam_templ = AF_INET;
358c0b746e5SOllivier Robert 			break;
359c0b746e5SOllivier Robert 		case '6':
3609c2daa00SOllivier Robert 			ai_fam_templ = AF_INET6;
361c0b746e5SOllivier Robert 			break;
362c0b746e5SOllivier Robert 		case 'a':
3639c2daa00SOllivier Robert 			c = atoi(ntp_optarg);
3649c2daa00SOllivier Robert 			sys_authenticate = 1;
3659c2daa00SOllivier Robert 			sys_authkey = c;
3669c2daa00SOllivier Robert 			break;
3679c2daa00SOllivier Robert 		case 'b':
3689c2daa00SOllivier Robert 			always_step++;
369c0b746e5SOllivier Robert 			never_step = 0;
370c0b746e5SOllivier Robert 			break;
371c0b746e5SOllivier Robert 		case 'B':
372c0b746e5SOllivier Robert 			never_step++;
373c0b746e5SOllivier Robert 			always_step = 0;
374c0b746e5SOllivier Robert 			break;
375c0b746e5SOllivier Robert 		case 'd':
376c0b746e5SOllivier Robert 			++debug;
377c0b746e5SOllivier Robert 			break;
378c0b746e5SOllivier Robert 		case 'e':
379c0b746e5SOllivier Robert 			if (!atolfp(ntp_optarg, &tmp)
380c0b746e5SOllivier Robert 			|| tmp.l_ui != 0) {
381c0b746e5SOllivier Robert 				(void) fprintf(stderr,
382c0b746e5SOllivier Robert 					   "%s: encryption delay %s is unlikely\n",
383c0b746e5SOllivier Robert 					   progname, ntp_optarg);
384c0b746e5SOllivier Robert 				errflg++;
385c0b746e5SOllivier Robert 			} else {
386c0b746e5SOllivier Robert 				sys_authdelay = tmp.l_uf;
387c0b746e5SOllivier Robert 			}
388c0b746e5SOllivier Robert 			break;
389c0b746e5SOllivier Robert 		case 'k':
390c0b746e5SOllivier Robert 			key_file = ntp_optarg;
391c0b746e5SOllivier Robert 			break;
392c0b746e5SOllivier Robert 		case 'o':
393c0b746e5SOllivier Robert 			sys_version = atoi(ntp_optarg);
394c0b746e5SOllivier Robert 			break;
395c0b746e5SOllivier Robert 		case 'p':
396c0b746e5SOllivier Robert 			c = atoi(ntp_optarg);
397c0b746e5SOllivier Robert 			if (c <= 0 || c > NTP_SHIFT) {
398c0b746e5SOllivier Robert 				(void) fprintf(stderr,
399c0b746e5SOllivier Robert 					   "%s: number of samples (%d) is invalid\n",
400c0b746e5SOllivier Robert 					   progname, c);
401c0b746e5SOllivier Robert 				errflg++;
402c0b746e5SOllivier Robert 			} else {
403c0b746e5SOllivier Robert 				sys_samples = c;
404c0b746e5SOllivier Robert 			}
405c0b746e5SOllivier Robert 			break;
406c0b746e5SOllivier Robert 		case 'q':
407c0b746e5SOllivier Robert 			simple_query = 1;
408c0b746e5SOllivier Robert 			break;
409c0b746e5SOllivier Robert 		case 's':
410c0b746e5SOllivier Robert 			syslogit = 1;
411c0b746e5SOllivier Robert 			break;
412c0b746e5SOllivier Robert 		case 't':
413c0b746e5SOllivier Robert 			if (!atolfp(ntp_optarg, &tmp)) {
414c0b746e5SOllivier Robert 				(void) fprintf(stderr,
415c0b746e5SOllivier Robert 					   "%s: timeout %s is undecodeable\n",
416c0b746e5SOllivier Robert 					   progname, ntp_optarg);
417c0b746e5SOllivier Robert 				errflg++;
418c0b746e5SOllivier Robert 			} else {
419c0b746e5SOllivier Robert 				sys_timeout = ((LFPTOFP(&tmp) * TIMER_HZ)
420c0b746e5SOllivier Robert 					   + 0x8000) >> 16;
421c0b746e5SOllivier Robert 				sys_timeout = max(sys_timeout, MINTIMEOUT);
422c0b746e5SOllivier Robert 			}
423c0b746e5SOllivier Robert 			break;
424c0b746e5SOllivier Robert 		case 'v':
425c0b746e5SOllivier Robert 			verbose = 1;
426c0b746e5SOllivier Robert 			break;
427c0b746e5SOllivier Robert 		case 'u':
428c0b746e5SOllivier Robert 			unpriv_port = 1;
429c0b746e5SOllivier Robert 			break;
430c0b746e5SOllivier Robert 		case '?':
431c0b746e5SOllivier Robert 			++errflg;
432c0b746e5SOllivier Robert 			break;
433c0b746e5SOllivier Robert 		default:
434c0b746e5SOllivier Robert 			break;
435c0b746e5SOllivier Robert 	    }
436c0b746e5SOllivier Robert 
437c0b746e5SOllivier Robert 	if (errflg) {
438c0b746e5SOllivier Robert 		(void) fprintf(stderr,
439c0b746e5SOllivier Robert 		    "usage: %s [-46bBdqsuv] [-a key#] [-e delay] [-k file] [-p samples] [-o version#] [-t timeo] server ...\n",
440c0b746e5SOllivier Robert 		    progname);
441c0b746e5SOllivier Robert 		exit(2);
442c0b746e5SOllivier Robert 	}
443c0b746e5SOllivier Robert 
444c0b746e5SOllivier Robert 	/*
445c0b746e5SOllivier Robert 	 * If number of Samples (-p) not specified by user:
446c0b746e5SOllivier Robert 	 * - if a simple_query (-q) just ONE will do
447c0b746e5SOllivier Robert 	 * - otherwise the normal is DEFSAMPLES
448c0b746e5SOllivier Robert 	 */
449c0b746e5SOllivier Robert 	if (sys_samples == 0)
450c0b746e5SOllivier Robert 		 sys_samples = (simple_query ? 1 : DEFSAMPLES);
451c0b746e5SOllivier Robert 
452c0b746e5SOllivier Robert 	if (debug || simple_query) {
453c0b746e5SOllivier Robert #ifdef HAVE_SETVBUF
454c0b746e5SOllivier Robert 		static char buf[BUFSIZ];
455c0b746e5SOllivier Robert 		setvbuf(stdout, buf, _IOLBF, BUFSIZ);
456c0b746e5SOllivier Robert #else
457c0b746e5SOllivier Robert 		setlinebuf(stdout);
4589c2daa00SOllivier Robert #endif
459c0b746e5SOllivier Robert 	}
460c0b746e5SOllivier Robert 
461c0b746e5SOllivier Robert 	/*
462c0b746e5SOllivier Robert 	 * Logging.  Open the syslog if we have to
463c0b746e5SOllivier Robert 	 */
464c0b746e5SOllivier Robert 	if (syslogit) {
465c0b746e5SOllivier Robert #if !defined (SYS_WINNT) && !defined (SYS_VXWORKS) && !defined SYS_CYGWIN32
466c0b746e5SOllivier Robert # ifndef	LOG_DAEMON
467c0b746e5SOllivier Robert 		openlog("ntpdate", LOG_PID);
468c0b746e5SOllivier Robert # else
469c0b746e5SOllivier Robert 
470c0b746e5SOllivier Robert #  ifndef	LOG_NTP
471c0b746e5SOllivier Robert #	define	LOG_NTP LOG_DAEMON
472c0b746e5SOllivier Robert #  endif
473c0b746e5SOllivier Robert 		openlog("ntpdate", LOG_PID | LOG_NDELAY, LOG_NTP);
474c0b746e5SOllivier Robert 		if (debug)
475c0b746e5SOllivier Robert 			setlogmask(LOG_UPTO(LOG_DEBUG));
476c0b746e5SOllivier Robert 		else
477c0b746e5SOllivier Robert 			setlogmask(LOG_UPTO(LOG_INFO));
478c0b746e5SOllivier Robert # endif /* LOG_DAEMON */
479c0b746e5SOllivier Robert #endif	/* SYS_WINNT */
480c0b746e5SOllivier Robert 	}
481c0b746e5SOllivier Robert 
482c0b746e5SOllivier Robert 	if (debug || verbose)
483c0b746e5SOllivier Robert 		msyslog(LOG_NOTICE, "%s", Version);
484c0b746e5SOllivier Robert 
485c0b746e5SOllivier Robert 	/*
486c0b746e5SOllivier Robert 	 * Add servers we are going to be polling
487c0b746e5SOllivier Robert 	 */
488c0b746e5SOllivier Robert #ifdef HAVE_NETINFO
489c0b746e5SOllivier Robert 	netinfoservers = getnetinfoservers();
490c0b746e5SOllivier Robert #endif
491c0b746e5SOllivier Robert 
492c0b746e5SOllivier Robert 	for ( ; ntp_optind < argc; ntp_optind++)
493c0b746e5SOllivier Robert 		addserver(argv[ntp_optind]);
494c0b746e5SOllivier Robert 
495c0b746e5SOllivier Robert #ifdef HAVE_NETINFO
496c0b746e5SOllivier Robert 	if (netinfoservers) {
497c0b746e5SOllivier Robert 		if ( netinfoservers->ni_namelist_len &&
498c0b746e5SOllivier Robert 		    *netinfoservers->ni_namelist_val ) {
499c0b746e5SOllivier Robert 			u_int servercount = 0;
500224ba2bdSOllivier Robert 			while (servercount < netinfoservers->ni_namelist_len) {
501c0b746e5SOllivier Robert 				if (debug) msyslog(LOG_DEBUG,
502c0b746e5SOllivier Robert 						   "Adding time server %s from NetInfo configuration.",
503c0b746e5SOllivier Robert 						   netinfoservers->ni_namelist_val[servercount]);
504c0b746e5SOllivier Robert 				addserver(netinfoservers->ni_namelist_val[servercount++]);
505c0b746e5SOllivier Robert 			}
506c0b746e5SOllivier Robert 		}
507c0b746e5SOllivier Robert 		ni_namelist_free(netinfoservers);
508c0b746e5SOllivier Robert 		free(netinfoservers);
509c0b746e5SOllivier Robert 	}
510c0b746e5SOllivier Robert #endif
511c0b746e5SOllivier Robert 
512c0b746e5SOllivier Robert 	if (sys_numservers == 0) {
513c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "no servers can be used, exiting");
514c0b746e5SOllivier Robert 		exit(1);
515c0b746e5SOllivier Robert 	}
516c0b746e5SOllivier Robert 
517c0b746e5SOllivier Robert 	/*
518c0b746e5SOllivier Robert 	 * Initialize the time of day routines and the I/O subsystem
519c0b746e5SOllivier Robert 	 */
520c0b746e5SOllivier Robert 	if (sys_authenticate) {
521c0b746e5SOllivier Robert 		init_auth();
522c0b746e5SOllivier Robert 		if (!authreadkeys(key_file)) {
523c0b746e5SOllivier Robert 			msyslog(LOG_ERR, "no key file <%s>, exiting", key_file);
524c0b746e5SOllivier Robert 			exit(1);
525c0b746e5SOllivier Robert 		}
526c0b746e5SOllivier Robert 		authtrust(sys_authkey, 1);
527c0b746e5SOllivier Robert 		if (!authistrusted(sys_authkey)) {
528c0b746e5SOllivier Robert 			msyslog(LOG_ERR, "authentication key %lu unknown",
529c0b746e5SOllivier Robert 				(unsigned long) sys_authkey);
530c0b746e5SOllivier Robert 			exit(1);
531c0b746e5SOllivier Robert 		}
532c0b746e5SOllivier Robert 	}
533c0b746e5SOllivier Robert 	init_io();
534224ba2bdSOllivier Robert 	init_alarm();
535c0b746e5SOllivier Robert 
536c0b746e5SOllivier Robert 	/*
537224ba2bdSOllivier Robert 	 * Set the priority.
538c0b746e5SOllivier Robert 	 */
539c0b746e5SOllivier Robert #ifdef SYS_VXWORKS
540c0b746e5SOllivier Robert 	taskPrioritySet( taskIdSelf(), NTPDATE_PRIO);
541c0b746e5SOllivier Robert #endif
542c0b746e5SOllivier Robert #if defined(HAVE_ATT_NICE)
543c0b746e5SOllivier Robert 	nice (NTPDATE_PRIO);
544c0b746e5SOllivier Robert #endif
545c0b746e5SOllivier Robert #if defined(HAVE_BSD_NICE)
546c0b746e5SOllivier Robert 	(void) setpriority(PRIO_PROCESS, 0, NTPDATE_PRIO);
547c0b746e5SOllivier Robert #endif
548c0b746e5SOllivier Robert 
549c0b746e5SOllivier Robert 
550c0b746e5SOllivier Robert 	initializing = 0;
551c0b746e5SOllivier Robert 	was_alarmed = 0;
552c0b746e5SOllivier Robert 
553c0b746e5SOllivier Robert 	while (complete_servers < sys_numservers) {
554c0b746e5SOllivier Robert #ifdef HAVE_POLL_H
555c0b746e5SOllivier Robert 		struct pollfd* rdfdes;
556c0b746e5SOllivier Robert 		rdfdes = fdmask;
557c0b746e5SOllivier Robert #else
558c0b746e5SOllivier Robert 		fd_set rdfdes;
559c0b746e5SOllivier Robert 		rdfdes = fdmask;
560c0b746e5SOllivier Robert #endif
561c0b746e5SOllivier Robert 
562c0b746e5SOllivier Robert 		if (alarm_flag) {		/* alarmed? */
563c0b746e5SOllivier Robert 			was_alarmed = 1;
564c0b746e5SOllivier Robert 			alarm_flag = 0;
565c0b746e5SOllivier Robert 		}
566c0b746e5SOllivier Robert 		tot_recvbufs = full_recvbuffs();	/* get received buffers */
567c0b746e5SOllivier Robert 
568c0b746e5SOllivier Robert 		if (!was_alarmed && tot_recvbufs == 0) {
5699c2daa00SOllivier Robert 			/*
5709c2daa00SOllivier Robert 			 * Nothing to do.	 Wait for something.
571c0b746e5SOllivier Robert 			 */
572c0b746e5SOllivier Robert #ifdef HAVE_POLL_H
5739c2daa00SOllivier Robert 			nfound = poll(rdfdes, (unsigned int)nbsock, timeout.tv_sec * 1000);
574c0b746e5SOllivier Robert 
575c0b746e5SOllivier Robert #else
5769c2daa00SOllivier Robert 			nfound = select(maxfd, &rdfdes, NULL, NULL,
5779c2daa00SOllivier Robert 					&timeout);
578c0b746e5SOllivier Robert #endif
579c0b746e5SOllivier Robert 			if (nfound > 0)
5809c2daa00SOllivier Robert 				input_handler();
581c0b746e5SOllivier Robert 			else if (nfound == SOCKET_ERROR)
582c0b746e5SOllivier Robert 			{
583c0b746e5SOllivier Robert #ifndef SYS_WINNT
584c0b746e5SOllivier Robert 				if (errno != EINTR)
585c0b746e5SOllivier Robert #else
586c0b746e5SOllivier Robert 				if (WSAGetLastError() != WSAEINTR)
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
5949c2daa00SOllivier Robert 						);
5959c2daa00SOllivier Robert 			} else if (errno != 0) {
596c0b746e5SOllivier Robert #ifndef SYS_VXWORKS
5979c2daa00SOllivier 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 			tot_recvbufs = full_recvbuffs();	/* get received buffers */
611c0b746e5SOllivier Robert 		}
6129c2daa00SOllivier Robert 
613c0b746e5SOllivier Robert 		/*
614c0b746e5SOllivier Robert 		 * Out here, signals are unblocked.  Call receive
615c0b746e5SOllivier Robert 		 * procedure for each incoming packet.
616c0b746e5SOllivier Robert 		 */
617c0b746e5SOllivier Robert 		rbuf = get_full_recv_buffer();
618c0b746e5SOllivier Robert 		while (rbuf != NULL)
619c0b746e5SOllivier Robert 		{
620c0b746e5SOllivier Robert 			receive(rbuf);
6219c2daa00SOllivier Robert 			freerecvbuf(rbuf);
622c0b746e5SOllivier Robert 			rbuf = get_full_recv_buffer();
623c0b746e5SOllivier Robert 		}
624c0b746e5SOllivier Robert 
625c0b746e5SOllivier Robert 		/*
626c0b746e5SOllivier Robert 		 * Call timer to process any timeouts
627c0b746e5SOllivier Robert 		 */
628c0b746e5SOllivier Robert 		if (was_alarmed) {
629c0b746e5SOllivier Robert 			timer();
630c0b746e5SOllivier Robert 			was_alarmed = 0;
631c0b746e5SOllivier Robert 		}
632c0b746e5SOllivier Robert 
633c0b746e5SOllivier Robert 		/*
634c0b746e5SOllivier Robert 		 * Go around again
635c0b746e5SOllivier Robert 		 */
636c0b746e5SOllivier Robert 	}
637c0b746e5SOllivier Robert 
638c0b746e5SOllivier Robert 	/*
639c0b746e5SOllivier Robert 	 * When we get here we've completed the polling of all servers.
640c0b746e5SOllivier Robert 	 * Adjust the clock, then exit.
641c0b746e5SOllivier Robert 	 */
642c0b746e5SOllivier Robert #ifdef SYS_WINNT
643c0b746e5SOllivier Robert 	WSACleanup();
644c0b746e5SOllivier Robert #endif
645c0b746e5SOllivier Robert #ifdef SYS_VXWORKS
646c0b746e5SOllivier Robert 	close (fd);
647c0b746e5SOllivier Robert 	timer_delete(ntpdate_timerid);
648c0b746e5SOllivier Robert #endif
649c0b746e5SOllivier Robert 
650c0b746e5SOllivier Robert 	return clock_adjust();
651c0b746e5SOllivier Robert }
652c0b746e5SOllivier Robert 
653c0b746e5SOllivier Robert 
654c0b746e5SOllivier Robert /*
655c0b746e5SOllivier Robert  * transmit - transmit a packet to the given server, or mark it completed.
656c0b746e5SOllivier Robert  *		This is called by the timeout routine and by the receive
657c0b746e5SOllivier Robert  *		procedure.
658c0b746e5SOllivier Robert  */
659c0b746e5SOllivier Robert static void
transmit(register struct server * server)660c0b746e5SOllivier Robert transmit(
661c0b746e5SOllivier Robert 	register struct server *server
662c0b746e5SOllivier Robert 	)
663c0b746e5SOllivier Robert {
664c0b746e5SOllivier Robert 	struct pkt xpkt;
665c0b746e5SOllivier Robert 
666c0b746e5SOllivier Robert 	if (server->filter_nextpt < server->xmtcnt) {
667c0b746e5SOllivier Robert 		l_fp ts;
668c0b746e5SOllivier Robert 		/*
669c0b746e5SOllivier Robert 		 * Last message to this server timed out.  Shift
670c0b746e5SOllivier Robert 		 * zeros into the filter.
671c0b746e5SOllivier Robert 		 */
6729c2daa00SOllivier Robert 		L_CLR(&ts);
673c0b746e5SOllivier Robert 		server_data(server, 0, &ts, 0);
674c0b746e5SOllivier Robert 	}
675c0b746e5SOllivier Robert 
676c0b746e5SOllivier Robert 	if ((int)server->filter_nextpt >= sys_samples) {
677c0b746e5SOllivier Robert 		/*
678c0b746e5SOllivier Robert 		 * Got all the data we need.  Mark this guy
679c0b746e5SOllivier Robert 		 * completed and return.
680c0b746e5SOllivier Robert 		 */
681c0b746e5SOllivier Robert 		server->event_time = 0;
682c0b746e5SOllivier Robert 		complete_servers++;
683c0b746e5SOllivier Robert 		return;
684c0b746e5SOllivier Robert 	}
685c0b746e5SOllivier Robert 
686c0b746e5SOllivier Robert 	if (debug)
687c0b746e5SOllivier Robert 		printf("transmit(%s)\n", stoa(&server->srcadr));
688c0b746e5SOllivier Robert 
689c0b746e5SOllivier Robert 	/*
6909c2daa00SOllivier Robert 	 * If we're here, send another message to the server.  Fill in
691c0b746e5SOllivier Robert 	 * the packet and let 'er rip.
692c0b746e5SOllivier Robert 	 */
693c0b746e5SOllivier Robert 	xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOTINSYNC,
694c0b746e5SOllivier Robert 					 sys_version, MODE_CLIENT);
695c0b746e5SOllivier Robert 	xpkt.stratum = STRATUM_TO_PKT(STRATUM_UNSPEC);
696c0b746e5SOllivier Robert 	xpkt.ppoll = NTP_MINPOLL;
697c0b746e5SOllivier Robert 	xpkt.precision = NTPDATE_PRECISION;
698c0b746e5SOllivier Robert 	xpkt.rootdelay = htonl(NTPDATE_DISTANCE);
699c0b746e5SOllivier Robert 	xpkt.rootdisp = htonl(NTPDATE_DISP);
700c0b746e5SOllivier Robert 	xpkt.refid = htonl(NTPDATE_REFID);
701c0b746e5SOllivier Robert 	L_CLR(&xpkt.reftime);
702c0b746e5SOllivier Robert 	L_CLR(&xpkt.org);
703c0b746e5SOllivier Robert 	L_CLR(&xpkt.rec);
704c0b746e5SOllivier Robert 
705c0b746e5SOllivier Robert 	/*
706c0b746e5SOllivier Robert 	 * Determine whether to authenticate or not.	If so,
707c0b746e5SOllivier Robert 	 * fill in the extended part of the packet and do it.
708c0b746e5SOllivier Robert 	 * If not, just timestamp it and send it away.
709c0b746e5SOllivier Robert 	 */
710c0b746e5SOllivier Robert 	if (sys_authenticate) {
711c0b746e5SOllivier Robert 		size_t len;
712c0b746e5SOllivier Robert 
713c0b746e5SOllivier Robert 		xpkt.exten[0] = htonl(sys_authkey);
714c0b746e5SOllivier Robert 		get_systime(&server->xmt);
715c0b746e5SOllivier Robert 		L_ADDUF(&server->xmt, sys_authdelay);
716c0b746e5SOllivier Robert 		HTONL_FP(&server->xmt, &xpkt.xmt);
717c0b746e5SOllivier Robert 		len = authencrypt(sys_authkey, (u_int32 *)&xpkt, LEN_PKT_NOMAC);
718c0b746e5SOllivier Robert 		sendpkt(&server->srcadr, &xpkt, (int)(LEN_PKT_NOMAC + len));
719c0b746e5SOllivier Robert 
720c0b746e5SOllivier Robert 		if (debug > 1)
721c0b746e5SOllivier Robert 			printf("transmit auth to %s\n",
722c0b746e5SOllivier Robert 			   stoa(&server->srcadr));
723c0b746e5SOllivier Robert 	} else {
724c0b746e5SOllivier Robert 		get_systime(&(server->xmt));
725c0b746e5SOllivier Robert 		HTONL_FP(&server->xmt, &xpkt.xmt);
726c0b746e5SOllivier Robert 		sendpkt(&server->srcadr, &xpkt, LEN_PKT_NOMAC);
727c0b746e5SOllivier Robert 
728c0b746e5SOllivier Robert 		if (debug > 1)
729c0b746e5SOllivier Robert 			printf("transmit to %s\n", stoa(&server->srcadr));
730c0b746e5SOllivier Robert 	}
731c0b746e5SOllivier Robert 
732c0b746e5SOllivier Robert 	/*
733c0b746e5SOllivier Robert 	 * Update the server timeout and transmit count
734c0b746e5SOllivier Robert 	 */
735c0b746e5SOllivier Robert 	server->event_time = current_time + sys_timeout;
736224ba2bdSOllivier Robert 	server->xmtcnt++;
737c0b746e5SOllivier Robert }
738c0b746e5SOllivier Robert 
739c0b746e5SOllivier Robert 
740c0b746e5SOllivier Robert /*
741c0b746e5SOllivier Robert  * receive - receive and process an incoming frame
742c0b746e5SOllivier Robert  */
743c0b746e5SOllivier Robert static void
receive(struct recvbuf * rbufp)744c0b746e5SOllivier Robert receive(
7459c2daa00SOllivier Robert 	struct recvbuf *rbufp
746c0b746e5SOllivier Robert 	)
747c0b746e5SOllivier Robert {
748c0b746e5SOllivier Robert 	register struct pkt *rpkt;
749c0b746e5SOllivier Robert 	register struct server *server;
750c0b746e5SOllivier Robert 	register s_fp di;
751c0b746e5SOllivier Robert 	l_fp t10, t23, tmp;
7529c2daa00SOllivier Robert 	l_fp org;
753c0b746e5SOllivier Robert 	l_fp rec;
754c0b746e5SOllivier Robert 	l_fp ci;
755c0b746e5SOllivier Robert 	int has_mac;
756c0b746e5SOllivier Robert 	int is_authentic;
757c0b746e5SOllivier Robert 
758c0b746e5SOllivier Robert 	if (debug)
759c0b746e5SOllivier Robert 		printf("receive(%s)\n", stoa(&rbufp->recv_srcadr));
760c0b746e5SOllivier Robert 	/*
761c0b746e5SOllivier Robert 	 * Check to see if the packet basically looks like something
762c0b746e5SOllivier Robert 	 * intended for us.
763c0b746e5SOllivier Robert 	 */
764c0b746e5SOllivier Robert 	if (rbufp->recv_length == LEN_PKT_NOMAC)
765c0b746e5SOllivier Robert 		has_mac = 0;
766c0b746e5SOllivier Robert 	else if (rbufp->recv_length >= (int)LEN_PKT_NOMAC)
767c0b746e5SOllivier Robert 		has_mac = 1;
768c0b746e5SOllivier Robert 	else {
769c0b746e5SOllivier Robert 		if (debug)
770c0b746e5SOllivier Robert 			printf("receive: packet length %d\n",
771c0b746e5SOllivier Robert 			   rbufp->recv_length);
772c0b746e5SOllivier Robert 		return; 		/* funny length packet */
773c0b746e5SOllivier Robert 	}
774ce265a54SOllivier Robert 
775c0b746e5SOllivier Robert 	rpkt = &(rbufp->recv_pkt);
776c0b746e5SOllivier Robert 	if (PKT_VERSION(rpkt->li_vn_mode) < NTP_OLDVERSION ||
777c0b746e5SOllivier Robert 		PKT_VERSION(rpkt->li_vn_mode) > NTP_VERSION) {
778c0b746e5SOllivier Robert 		return;
779c0b746e5SOllivier Robert 	}
780c0b746e5SOllivier Robert 
781c0b746e5SOllivier Robert 	if ((PKT_MODE(rpkt->li_vn_mode) != MODE_SERVER
7829c2daa00SOllivier Robert 		 && PKT_MODE(rpkt->li_vn_mode) != MODE_PASSIVE)
783c0b746e5SOllivier Robert 		|| rpkt->stratum >= STRATUM_UNSPEC) {
784c0b746e5SOllivier Robert 		if (debug)
785c0b746e5SOllivier Robert 			printf("receive: mode %d stratum %d\n",
786c0b746e5SOllivier Robert 			   PKT_MODE(rpkt->li_vn_mode), rpkt->stratum);
787c0b746e5SOllivier Robert 		return;
788c0b746e5SOllivier Robert 	}
789c0b746e5SOllivier Robert 
790c0b746e5SOllivier Robert 	/*
791c0b746e5SOllivier Robert 	 * So far, so good.  See if this is from a server we know.
792c0b746e5SOllivier Robert 	 */
793c0b746e5SOllivier Robert 	server = findserver(&(rbufp->recv_srcadr));
794c0b746e5SOllivier Robert 	if (server == NULL) {
795c0b746e5SOllivier Robert 		if (debug)
796c0b746e5SOllivier Robert 			printf("receive: server not found\n");
797c0b746e5SOllivier Robert 		return;
798c0b746e5SOllivier Robert 	}
799c0b746e5SOllivier Robert 
800c0b746e5SOllivier Robert 	/*
801c0b746e5SOllivier Robert 	 * Decode the org timestamp and make sure we're getting a response
802c0b746e5SOllivier Robert 	 * to our last request.
803c0b746e5SOllivier Robert 	 */
804c0b746e5SOllivier Robert 	NTOHL_FP(&rpkt->org, &org);
805c0b746e5SOllivier Robert 	if (!L_ISEQU(&org, &server->xmt)) {
806224ba2bdSOllivier Robert 		if (debug)
807c0b746e5SOllivier Robert 			printf("receive: pkt.org and peer.xmt differ\n");
808c0b746e5SOllivier Robert 		return;
809c0b746e5SOllivier Robert 	}
810c0b746e5SOllivier Robert 
811c0b746e5SOllivier Robert 	/*
812c0b746e5SOllivier Robert 	 * Check out the authenticity if we're doing that.
813c0b746e5SOllivier Robert 	 */
814c0b746e5SOllivier Robert 	if (!sys_authenticate)
815c0b746e5SOllivier Robert 		is_authentic = 1;
816c0b746e5SOllivier Robert 	else {
817c0b746e5SOllivier Robert 		is_authentic = 0;
818c0b746e5SOllivier Robert 
819c0b746e5SOllivier Robert 		if (debug > 3)
820c0b746e5SOllivier Robert 			printf("receive: rpkt keyid=%ld sys_authkey=%ld decrypt=%ld\n",
821c0b746e5SOllivier Robert 			   (long int)ntohl(rpkt->exten[0]), (long int)sys_authkey,
822c0b746e5SOllivier Robert 			   (long int)authdecrypt(sys_authkey, (u_int32 *)rpkt,
823c0b746e5SOllivier Robert 				LEN_PKT_NOMAC, (size_t)(rbufp->recv_length - LEN_PKT_NOMAC)));
824c0b746e5SOllivier Robert 
825c0b746e5SOllivier Robert 		if (has_mac && ntohl(rpkt->exten[0]) == sys_authkey &&
826c0b746e5SOllivier Robert 			authdecrypt(sys_authkey, (u_int32 *)rpkt, LEN_PKT_NOMAC,
827c0b746e5SOllivier Robert 			(size_t)(rbufp->recv_length - LEN_PKT_NOMAC)))
828c0b746e5SOllivier Robert 			is_authentic = 1;
829c0b746e5SOllivier Robert 		if (debug)
830c0b746e5SOllivier Robert 			printf("receive: authentication %s\n",
831c0b746e5SOllivier Robert 			   is_authentic ? "passed" : "failed");
832c0b746e5SOllivier Robert 	}
833c0b746e5SOllivier Robert 	server->trust <<= 1;
834c0b746e5SOllivier Robert 	if (!is_authentic)
835c0b746e5SOllivier Robert 		server->trust |= 1;
836c0b746e5SOllivier Robert 
837c0b746e5SOllivier Robert 	/*
838c0b746e5SOllivier Robert 	 * Check for a KoD (rate limiting) response, cease and decist.
839c0b746e5SOllivier Robert 	 */
840c0b746e5SOllivier Robert 	if (LEAP_NOTINSYNC == PKT_LEAP(rpkt->li_vn_mode) &&
841c0b746e5SOllivier Robert 	    STRATUM_PKT_UNSPEC == rpkt->stratum &&
842c0b746e5SOllivier Robert 	    !memcmp("RATE", &rpkt->refid, 4)) {
843c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "%s rate limit response from server.",
844224ba2bdSOllivier Robert 			stoa(&rbufp->recv_srcadr));
845c0b746e5SOllivier Robert 		server->event_time = 0;
846c0b746e5SOllivier Robert 		complete_servers++;
847c0b746e5SOllivier Robert 		return;
848224ba2bdSOllivier Robert 	}
849c0b746e5SOllivier Robert 
850c0b746e5SOllivier Robert 	/*
851c0b746e5SOllivier Robert 	 * Looks good.	Record info from the packet.
852c0b746e5SOllivier Robert 	 */
853c0b746e5SOllivier Robert 	server->leap = PKT_LEAP(rpkt->li_vn_mode);
854c0b746e5SOllivier Robert 	server->stratum = PKT_TO_STRATUM(rpkt->stratum);
855c0b746e5SOllivier Robert 	server->precision = rpkt->precision;
856c0b746e5SOllivier Robert 	server->rootdelay = ntohl(rpkt->rootdelay);
857c0b746e5SOllivier Robert 	server->rootdisp = ntohl(rpkt->rootdisp);
858c0b746e5SOllivier Robert 	server->refid = rpkt->refid;
859c0b746e5SOllivier Robert 	NTOHL_FP(&rpkt->reftime, &server->reftime);
860c0b746e5SOllivier Robert 	NTOHL_FP(&rpkt->rec, &rec);
861c0b746e5SOllivier Robert 	NTOHL_FP(&rpkt->xmt, &server->org);
862c0b746e5SOllivier Robert 
863c0b746e5SOllivier Robert 	/*
864c0b746e5SOllivier Robert 	 * Make sure the server is at least somewhat sane. If not, try
865c0b746e5SOllivier Robert 	 * again.
866c0b746e5SOllivier Robert 	 */
867c0b746e5SOllivier Robert 	if (L_ISZERO(&rec) || !L_ISHIS(&server->org, &rec)) {
868c0b746e5SOllivier Robert 		server->event_time = current_time + sys_timeout;
869c0b746e5SOllivier Robert 		return;
870c0b746e5SOllivier Robert 	}
871c0b746e5SOllivier Robert 
872c0b746e5SOllivier Robert 	/*
873c0b746e5SOllivier Robert 	 * Calculate the round trip delay (di) and the clock offset (ci).
874c0b746e5SOllivier Robert 	 * We use the equations (reordered from those in the spec):
875c0b746e5SOllivier Robert 	 *
876c0b746e5SOllivier Robert 	 * d = (t2 - t3) - (t1 - t0)
877c0b746e5SOllivier Robert 	 * c = ((t2 - t3) + (t1 - t0)) / 2
878c0b746e5SOllivier Robert 	 */
879c0b746e5SOllivier Robert 	t10 = server->org;		/* pkt.xmt == t1 */
880c0b746e5SOllivier Robert 	L_SUB(&t10, &rbufp->recv_time); /* recv_time == t0*/
881c0b746e5SOllivier Robert 
882c0b746e5SOllivier Robert 	t23 = rec;			/* pkt.rec == t2 */
883c0b746e5SOllivier Robert 	L_SUB(&t23, &org);		/* pkt->org == t3 */
884c0b746e5SOllivier Robert 
885c0b746e5SOllivier Robert 	/* now have (t2 - t3) and (t0 - t1).	Calculate (ci) and (di) */
886c0b746e5SOllivier Robert 	/*
887c0b746e5SOllivier Robert 	 * Calculate (ci) = ((t1 - t0) / 2) + ((t2 - t3) / 2)
888c0b746e5SOllivier Robert 	 * For large offsets this may prevent an overflow on '+'
889c0b746e5SOllivier Robert 	 */
890c0b746e5SOllivier Robert 	ci = t10;
891c0b746e5SOllivier Robert 	L_RSHIFT(&ci);
892c0b746e5SOllivier Robert 	tmp = t23;
893c0b746e5SOllivier Robert 	L_RSHIFT(&tmp);
894c0b746e5SOllivier Robert 	L_ADD(&ci, &tmp);
895c0b746e5SOllivier Robert 
896ce265a54SOllivier Robert 	/*
897ce265a54SOllivier Robert 	 * Calculate di in t23 in full precision, then truncate
898ce265a54SOllivier Robert 	 * to an s_fp.
899ce265a54SOllivier Robert 	 */
900c0b746e5SOllivier Robert 	L_SUB(&t23, &t10);
901c0b746e5SOllivier Robert 	di = LFPTOFP(&t23);
902ce265a54SOllivier Robert 
903ce265a54SOllivier Robert 	if (debug > 3)
904ce265a54SOllivier Robert 		printf("offset: %s, delay %s\n", lfptoa(&ci, 6), fptoa(di, 5));
905c0b746e5SOllivier Robert 
906c0b746e5SOllivier Robert 	di += (FP_SECOND >> (-(int)NTPDATE_PRECISION))
907c0b746e5SOllivier Robert 		+ (FP_SECOND >> (-(int)server->precision)) + NTP_MAXSKW;
908c0b746e5SOllivier Robert 
909c0b746e5SOllivier Robert 	if (di <= 0) {		/* value still too raunchy to use? */
910c0b746e5SOllivier Robert 		L_CLR(&ci);
911c0b746e5SOllivier Robert 		di = 0;
912c0b746e5SOllivier Robert 	} else {
913c0b746e5SOllivier Robert 		di = max(di, NTP_MINDIST);
914c0b746e5SOllivier Robert 	}
915c0b746e5SOllivier Robert 
916c0b746e5SOllivier Robert 	/*
917c0b746e5SOllivier Robert 	 * Shift this data in, then schedule another transmit.
918c0b746e5SOllivier Robert 	 */
919c0b746e5SOllivier Robert 	server_data(server, (s_fp) di, &ci, 0);
920c0b746e5SOllivier Robert 
921c0b746e5SOllivier Robert 	if ((int)server->filter_nextpt >= sys_samples) {
922c0b746e5SOllivier Robert 		/*
923c0b746e5SOllivier Robert 		 * Got all the data we need.  Mark this guy
924c0b746e5SOllivier Robert 		 * completed and return.
925c0b746e5SOllivier Robert 		 */
926c0b746e5SOllivier Robert 		server->event_time = 0;
927c0b746e5SOllivier Robert 		complete_servers++;
928c0b746e5SOllivier Robert 		return;
929c0b746e5SOllivier Robert 	}
930c0b746e5SOllivier Robert 
931c0b746e5SOllivier Robert 	server->event_time = current_time + sys_timeout;
932c0b746e5SOllivier Robert }
933c0b746e5SOllivier Robert 
934c0b746e5SOllivier Robert 
935c0b746e5SOllivier Robert /*
936c0b746e5SOllivier Robert  * server_data - add a sample to the server's filter registers
937c0b746e5SOllivier Robert  */
938c0b746e5SOllivier Robert static void
server_data(register struct server * server,s_fp d,l_fp * c,u_fp e)939c0b746e5SOllivier Robert server_data(
940c0b746e5SOllivier Robert 	register struct server *server,
941c0b746e5SOllivier Robert 	s_fp d,
942c0b746e5SOllivier Robert 	l_fp *c,
943c0b746e5SOllivier Robert 	u_fp e
944c0b746e5SOllivier Robert 	)
9459c2daa00SOllivier Robert {
946c0b746e5SOllivier Robert 	u_short i;
947c0b746e5SOllivier Robert 
948c0b746e5SOllivier Robert 	i = server->filter_nextpt;
949c0b746e5SOllivier Robert 	if (i < NTP_SHIFT) {
950c0b746e5SOllivier Robert 		server->filter_delay[i] = d;
951c0b746e5SOllivier Robert 		server->filter_offset[i] = *c;
952c0b746e5SOllivier Robert 		server->filter_soffset[i] = LFPTOFP(c);
9539c2daa00SOllivier Robert 		server->filter_error[i] = e;
954c0b746e5SOllivier Robert 		server->filter_nextpt = (u_short)(i + 1);
955c0b746e5SOllivier Robert 	}
956c0b746e5SOllivier Robert }
957c0b746e5SOllivier Robert 
958c0b746e5SOllivier Robert 
959c0b746e5SOllivier Robert /*
960c0b746e5SOllivier Robert  * clock_filter - determine a server's delay, dispersion and offset
961c0b746e5SOllivier Robert  */
962c0b746e5SOllivier Robert static void
clock_filter(register struct server * server)963c0b746e5SOllivier Robert clock_filter(
964c0b746e5SOllivier Robert 	register struct server *server
965c0b746e5SOllivier Robert 	)
966c0b746e5SOllivier Robert {
967c0b746e5SOllivier Robert 	register int i, j;
968c0b746e5SOllivier Robert 	int ord[NTP_SHIFT];
969c0b746e5SOllivier Robert 
970c0b746e5SOllivier Robert 	INSIST((0 < sys_samples) && (sys_samples <= NTP_SHIFT));
971c0b746e5SOllivier Robert 
972c0b746e5SOllivier Robert 	/*
973c0b746e5SOllivier Robert 	 * Sort indices into increasing delay order
974c0b746e5SOllivier Robert 	 */
975c0b746e5SOllivier Robert 	for (i = 0; i < sys_samples; i++)
976c0b746e5SOllivier Robert 		ord[i] = i;
977c0b746e5SOllivier Robert 
978c0b746e5SOllivier Robert 	for (i = 0; i < (sys_samples-1); i++) {
979c0b746e5SOllivier Robert 		for (j = i+1; j < sys_samples; j++) {
980c0b746e5SOllivier Robert 			if (server->filter_delay[ord[j]] == 0)
981c0b746e5SOllivier Robert 				continue;
982c0b746e5SOllivier Robert 			if (server->filter_delay[ord[i]] == 0
983c0b746e5SOllivier Robert 				|| (server->filter_delay[ord[i]]
984c0b746e5SOllivier Robert 				> server->filter_delay[ord[j]])) {
985c0b746e5SOllivier Robert 				register int tmp;
986c0b746e5SOllivier Robert 
987c0b746e5SOllivier Robert 				tmp = ord[i];
988c0b746e5SOllivier Robert 				ord[i] = ord[j];
989c0b746e5SOllivier Robert 				ord[j] = tmp;
990c0b746e5SOllivier Robert 			}
991c0b746e5SOllivier Robert 		}
992c0b746e5SOllivier Robert 	}
993c0b746e5SOllivier Robert 
994c0b746e5SOllivier Robert 	/*
995c0b746e5SOllivier Robert 	 * Now compute the dispersion, and assign values to delay and
996c0b746e5SOllivier Robert 	 * offset.	If there are no samples in the register, delay and
997c0b746e5SOllivier Robert 	 * offset go to zero and dispersion is set to the maximum.
998c0b746e5SOllivier Robert 	 */
999c0b746e5SOllivier Robert 	if (server->filter_delay[ord[0]] == 0) {
1000c0b746e5SOllivier Robert 		server->delay = 0;
1001c0b746e5SOllivier Robert 		L_CLR(&server->offset);
1002c0b746e5SOllivier Robert 		server->soffset = 0;
1003c0b746e5SOllivier Robert 		server->dispersion = PEER_MAXDISP;
1004c0b746e5SOllivier Robert 	} else {
1005c0b746e5SOllivier Robert 		register s_fp d;
1006c0b746e5SOllivier Robert 
1007c0b746e5SOllivier Robert 		server->delay = server->filter_delay[ord[0]];
1008c0b746e5SOllivier Robert 		server->offset = server->filter_offset[ord[0]];
1009c0b746e5SOllivier Robert 		server->soffset = LFPTOFP(&server->offset);
1010c0b746e5SOllivier Robert 		server->dispersion = 0;
1011c0b746e5SOllivier Robert 		for (i = 1; i < sys_samples; i++) {
1012c0b746e5SOllivier Robert 			if (server->filter_delay[ord[i]] == 0)
1013c0b746e5SOllivier Robert 				d = PEER_MAXDISP;
1014c0b746e5SOllivier Robert 			else {
1015c0b746e5SOllivier Robert 				d = server->filter_soffset[ord[i]]
1016c0b746e5SOllivier Robert 					- server->filter_soffset[ord[0]];
1017c0b746e5SOllivier Robert 				if (d < 0)
1018c0b746e5SOllivier Robert 					d = -d;
1019c0b746e5SOllivier Robert 				if (d > PEER_MAXDISP)
1020c0b746e5SOllivier Robert 					d = PEER_MAXDISP;
1021c0b746e5SOllivier Robert 			}
1022c0b746e5SOllivier Robert 			/*
1023c0b746e5SOllivier Robert 			 * XXX This *knows* PEER_FILTER is 1/2
1024c0b746e5SOllivier Robert 			 */
1025c0b746e5SOllivier Robert 			server->dispersion += (u_fp)(d) >> i;
1026c0b746e5SOllivier Robert 		}
1027c0b746e5SOllivier Robert 	}
1028c0b746e5SOllivier Robert 	/*
1029c0b746e5SOllivier Robert 	 * We're done
1030c0b746e5SOllivier Robert 	 */
1031c0b746e5SOllivier Robert }
1032c0b746e5SOllivier Robert 
1033c0b746e5SOllivier Robert 
1034c0b746e5SOllivier Robert /*
1035c0b746e5SOllivier Robert  * clock_select - select the pick-of-the-litter clock from the samples
1036c0b746e5SOllivier Robert  *		  we've got.
1037c0b746e5SOllivier Robert  */
1038c0b746e5SOllivier Robert static struct server *
clock_select(void)1039c0b746e5SOllivier Robert clock_select(void)
1040c0b746e5SOllivier Robert {
1041c0b746e5SOllivier Robert 	struct server *server;
1042c0b746e5SOllivier Robert 	u_int nlist;
1043c0b746e5SOllivier Robert 	s_fp d;
1044c0b746e5SOllivier Robert 	u_int count;
1045c0b746e5SOllivier Robert 	u_int i;
1046c0b746e5SOllivier Robert 	u_int j;
1047c0b746e5SOllivier Robert 	u_int k;
1048c0b746e5SOllivier Robert 	int n;
1049c0b746e5SOllivier Robert 	s_fp local_threshold;
1050c0b746e5SOllivier Robert 	struct server *server_list[NTP_MAXCLOCK];
1051c0b746e5SOllivier Robert 	u_fp server_badness[NTP_MAXCLOCK];
1052c0b746e5SOllivier Robert 	struct server *sys_server;
1053c0b746e5SOllivier Robert 
1054c0b746e5SOllivier Robert 	/*
1055c0b746e5SOllivier Robert 	 * This first chunk of code is supposed to go through all
1056c0b746e5SOllivier Robert 	 * servers we know about to find the NTP_MAXLIST servers which
1057c0b746e5SOllivier Robert 	 * are most likely to succeed. We run through the list
1058c0b746e5SOllivier Robert 	 * doing the sanity checks and trying to insert anyone who
1059a151a66cSOllivier Robert 	 * looks okay. We are at all times aware that we should
1060ce265a54SOllivier Robert 	 * only keep samples from the top two strata and we only need
1061ce265a54SOllivier Robert 	 * NTP_MAXLIST of them.
1062ce265a54SOllivier Robert 	 */
1063c0b746e5SOllivier Robert 	nlist = 0;	/* none yet */
1064ce265a54SOllivier Robert 	for (server = sys_servers; server != NULL; server = server->next_server) {
1065ce265a54SOllivier Robert 		if (server->stratum == 0) {
1066ce265a54SOllivier Robert 			if (debug)
1067ce265a54SOllivier Robert 				printf("%s: Server dropped: no data\n", ntoa(&server->srcadr));
1068c0b746e5SOllivier Robert 			continue;	/* no data */
1069ce265a54SOllivier Robert 		}
1070c0b746e5SOllivier Robert 		if (server->stratum > NTP_INFIN) {
1071ce265a54SOllivier Robert 			if (debug)
1072ce265a54SOllivier Robert 				printf("%s: Server dropped: strata too high\n", ntoa(&server->srcadr));
1073ce265a54SOllivier Robert 			continue;	/* stratum no good */
1074c0b746e5SOllivier Robert 		}
1075c0b746e5SOllivier Robert 		if (server->delay > NTP_MAXWGT) {
1076ce265a54SOllivier Robert 			if (debug)
1077ce265a54SOllivier Robert 				printf("%s: Server dropped: server too far away\n",
1078ce265a54SOllivier Robert 					ntoa(&server->srcadr));
1079c0b746e5SOllivier Robert 			continue;	/* too far away */
1080ce265a54SOllivier Robert 		}
1081c0b746e5SOllivier Robert 		if (server->leap == LEAP_NOTINSYNC) {
1082ce265a54SOllivier Robert 			if (debug)
1083ce265a54SOllivier Robert 				printf("%s: Server dropped: leap not in sync\n", ntoa(&server->srcadr));
1084ce265a54SOllivier Robert 			continue;	/* he's in trouble */
1085c0b746e5SOllivier Robert 		}
1086c0b746e5SOllivier Robert 		if (!L_ISHIS(&server->org, &server->reftime)) {
1087c0b746e5SOllivier Robert 			if (debug)
1088c0b746e5SOllivier Robert 				printf("%s: Server dropped: server is very broken\n",
1089ce265a54SOllivier Robert 				       ntoa(&server->srcadr));
1090ce265a54SOllivier Robert 			continue;	/* very broken host */
1091ce265a54SOllivier Robert 		}
1092c0b746e5SOllivier Robert 		if ((server->org.l_ui - server->reftime.l_ui)
1093c0b746e5SOllivier Robert 		    >= NTP_MAXAGE) {
1094c0b746e5SOllivier Robert 			if (debug)
1095ce265a54SOllivier Robert 				printf("%s: Server dropped: server has gone too long without sync\n",
1096ce265a54SOllivier Robert 				       ntoa(&server->srcadr));
1097ce265a54SOllivier Robert 			continue;	/* too long without sync */
1098c0b746e5SOllivier Robert 		}
1099c0b746e5SOllivier Robert 		if (server->trust != 0) {
1100c0b746e5SOllivier Robert 			if (debug)
1101c0b746e5SOllivier Robert 				printf("%s: Server dropped: Server is untrusted\n",
1102c0b746e5SOllivier Robert 				       ntoa(&server->srcadr));
1103c0b746e5SOllivier Robert 			continue;
1104c0b746e5SOllivier Robert 		}
1105c0b746e5SOllivier Robert 
1106c0b746e5SOllivier Robert 		/*
1107c0b746e5SOllivier Robert 		 * This one seems sane.  Find where he belongs
1108c0b746e5SOllivier Robert 		 * on the list.
1109c0b746e5SOllivier Robert 		 */
1110c0b746e5SOllivier Robert 		d = server->dispersion + server->dispersion;
1111c0b746e5SOllivier Robert 		for (i = 0; i < nlist; i++)
1112c0b746e5SOllivier Robert 			if (server->stratum <= server_list[i]->stratum)
1113c0b746e5SOllivier Robert 			break;
1114c0b746e5SOllivier Robert 		for ( ; i < nlist; i++) {
1115c0b746e5SOllivier Robert 			if (server->stratum < server_list[i]->stratum)
1116c0b746e5SOllivier Robert 				break;
1117c0b746e5SOllivier Robert 			if (d < (s_fp) server_badness[i])
1118c0b746e5SOllivier Robert 				break;
1119c0b746e5SOllivier Robert 		}
1120c0b746e5SOllivier Robert 
1121c0b746e5SOllivier Robert 		/*
1122c0b746e5SOllivier Robert 		 * If i points past the end of the list, this
1123c0b746e5SOllivier Robert 		 * guy is a loser, else stick him in.
1124c0b746e5SOllivier Robert 		 */
1125c0b746e5SOllivier Robert 		if (i >= NTP_MAXLIST)
1126c0b746e5SOllivier Robert 			continue;
1127c0b746e5SOllivier Robert 		for (j = nlist; j > i; j--)
1128c0b746e5SOllivier Robert 			if (j < NTP_MAXLIST) {
1129c0b746e5SOllivier Robert 				server_list[j] = server_list[j-1];
1130c0b746e5SOllivier Robert 				server_badness[j]
1131c0b746e5SOllivier Robert 					= server_badness[j-1];
1132c0b746e5SOllivier Robert 			}
1133c0b746e5SOllivier Robert 
1134c0b746e5SOllivier Robert 		server_list[i] = server;
1135c0b746e5SOllivier Robert 		server_badness[i] = d;
1136c0b746e5SOllivier Robert 		if (nlist < NTP_MAXLIST)
1137c0b746e5SOllivier Robert 			nlist++;
1138c0b746e5SOllivier Robert 	}
1139c0b746e5SOllivier Robert 
1140c0b746e5SOllivier Robert 	/*
1141c0b746e5SOllivier Robert 	 * Got the five-or-less best.	 Cut the list where the number of
1142c0b746e5SOllivier Robert 	 * strata exceeds two.
1143c0b746e5SOllivier Robert 	 */
1144c0b746e5SOllivier Robert 	count = 0;
1145c0b746e5SOllivier Robert 	for (i = 1; i < nlist; i++)
1146c0b746e5SOllivier Robert 		if (server_list[i]->stratum > server_list[i-1]->stratum) {
1147c0b746e5SOllivier Robert 			count++;
1148c0b746e5SOllivier Robert 			if (2 == count) {
1149c0b746e5SOllivier Robert 				nlist = i;
1150c0b746e5SOllivier Robert 				break;
1151c0b746e5SOllivier Robert 			}
1152c0b746e5SOllivier Robert 		}
1153c0b746e5SOllivier Robert 
1154c0b746e5SOllivier Robert 	/*
1155c0b746e5SOllivier Robert 	 * Whew!  What we should have by now is 0 to 5 candidates for
1156c0b746e5SOllivier Robert 	 * the job of syncing us.  If we have none, we're out of luck.
1157c0b746e5SOllivier Robert 	 * If we have one, he's a winner.  If we have more, do falseticker
1158c0b746e5SOllivier Robert 	 * detection.
1159c0b746e5SOllivier Robert 	 */
1160c0b746e5SOllivier Robert 
1161c0b746e5SOllivier Robert 	if (0 == nlist)
1162c0b746e5SOllivier Robert 		sys_server = NULL;
1163c0b746e5SOllivier Robert 	else if (1 == nlist) {
1164c0b746e5SOllivier Robert 		sys_server = server_list[0];
1165c0b746e5SOllivier Robert 	} else {
1166c0b746e5SOllivier Robert 		/*
1167c0b746e5SOllivier Robert 		 * Re-sort by stratum, bdelay estimate quality and
1168c0b746e5SOllivier Robert 		 * server.delay.
1169c0b746e5SOllivier Robert 		 */
1170c0b746e5SOllivier Robert 		for (i = 0; i < nlist-1; i++)
1171c0b746e5SOllivier Robert 			for (j = i+1; j < nlist; j++) {
1172c0b746e5SOllivier Robert 				if (server_list[i]->stratum <
1173c0b746e5SOllivier Robert 				    server_list[j]->stratum)
1174c0b746e5SOllivier Robert 					/* already sorted by stratum */
1175c0b746e5SOllivier Robert 					break;
1176c0b746e5SOllivier Robert 				if (server_list[i]->delay <
1177c0b746e5SOllivier Robert 				    server_list[j]->delay)
1178c0b746e5SOllivier Robert 					continue;
1179c0b746e5SOllivier Robert 				server = server_list[i];
1180c0b746e5SOllivier Robert 				server_list[i] = server_list[j];
1181c0b746e5SOllivier Robert 				server_list[j] = server;
1182c0b746e5SOllivier Robert 			}
1183c0b746e5SOllivier Robert 
1184c0b746e5SOllivier Robert 		/*
1185c0b746e5SOllivier Robert 		 * Calculate the fixed part of the dispersion limit
1186c0b746e5SOllivier Robert 		 */
1187c0b746e5SOllivier Robert 		local_threshold = (FP_SECOND >> (-(int)NTPDATE_PRECISION))
1188c0b746e5SOllivier Robert 			+ NTP_MAXSKW;
1189c0b746e5SOllivier Robert 
1190c0b746e5SOllivier Robert 		/*
1191c0b746e5SOllivier Robert 		 * Now drop samples until we're down to one.
1192c0b746e5SOllivier Robert 		 */
1193c0b746e5SOllivier Robert 		while (nlist > 1) {
1194c0b746e5SOllivier Robert 			for (k = 0; k < nlist; k++) {
1195c0b746e5SOllivier Robert 				server_badness[k] = 0;
1196c0b746e5SOllivier Robert 				for (j = 0; j < nlist; j++) {
1197c0b746e5SOllivier Robert 					if (j == k) /* with self? */
1198c0b746e5SOllivier Robert 						continue;
1199c0b746e5SOllivier Robert 					d = server_list[j]->soffset -
1200c0b746e5SOllivier Robert 					    server_list[k]->soffset;
1201c0b746e5SOllivier Robert 					if (d < 0)	/* abs value */
1202c0b746e5SOllivier Robert 						d = -d;
1203c0b746e5SOllivier Robert 					/*
1204c0b746e5SOllivier Robert 					 * XXX This code *knows* that
1205c0b746e5SOllivier Robert 					 * NTP_SELECT is 3/4
1206c0b746e5SOllivier Robert 					 */
1207c0b746e5SOllivier Robert 					for (i = 0; i < j; i++)
1208c0b746e5SOllivier Robert 						d = (d>>1) + (d>>2);
1209c0b746e5SOllivier Robert 					server_badness[k] += d;
1210c0b746e5SOllivier Robert 				}
1211c0b746e5SOllivier Robert 			}
1212c0b746e5SOllivier Robert 
1213c0b746e5SOllivier Robert 			/*
1214c0b746e5SOllivier Robert 			 * We now have an array of nlist badness
1215c0b746e5SOllivier Robert 			 * coefficients.	Find the badest.  Find
1216c0b746e5SOllivier Robert 			 * the minimum precision while we're at
1217c0b746e5SOllivier Robert 			 * it.
1218c0b746e5SOllivier Robert 			 */
1219c0b746e5SOllivier Robert 			i = 0;
1220c0b746e5SOllivier Robert 			n = server_list[0]->precision;;
1221c0b746e5SOllivier Robert 			for (j = 1; j < nlist; j++) {
1222c0b746e5SOllivier Robert 				if (server_badness[j] >= server_badness[i])
1223c0b746e5SOllivier Robert 					i = j;
1224c0b746e5SOllivier Robert 				if (n > server_list[j]->precision)
1225c0b746e5SOllivier Robert 					n = server_list[j]->precision;
1226c0b746e5SOllivier Robert 			}
1227c0b746e5SOllivier Robert 
1228c0b746e5SOllivier Robert 			/*
1229c0b746e5SOllivier Robert 			 * i is the index of the server with the worst
1230c0b746e5SOllivier Robert 			 * dispersion.	If his dispersion is less than
1231c0b746e5SOllivier Robert 			 * the threshold, stop now, else delete him and
1232c0b746e5SOllivier Robert 			 * continue around again.
1233c0b746e5SOllivier Robert 			 */
1234c0b746e5SOllivier Robert 			if ( (s_fp) server_badness[i] < (local_threshold
1235c0b746e5SOllivier Robert 							 + (FP_SECOND >> (-n))))
1236c0b746e5SOllivier Robert 				break;
1237c0b746e5SOllivier Robert 			for (j = i + 1; j < nlist; j++)
1238c0b746e5SOllivier Robert 				server_list[j-1] = server_list[j];
1239c0b746e5SOllivier Robert 			nlist--;
1240c0b746e5SOllivier Robert 		}
1241c0b746e5SOllivier Robert 
1242c0b746e5SOllivier Robert 		/*
1243c0b746e5SOllivier Robert 		 * What remains is a list of less than 5 servers.  Take
1244c0b746e5SOllivier Robert 		 * the best.
1245c0b746e5SOllivier Robert 		 */
1246c0b746e5SOllivier Robert 		sys_server = server_list[0];
1247c0b746e5SOllivier Robert 	}
1248c0b746e5SOllivier Robert 
1249c0b746e5SOllivier Robert 	/*
1250c0b746e5SOllivier Robert 	 * That's it.  Return our server.
1251c0b746e5SOllivier Robert 	 */
1252c0b746e5SOllivier Robert 	return sys_server;
1253c0b746e5SOllivier Robert }
1254c0b746e5SOllivier Robert 
1255a151a66cSOllivier Robert 
1256c0b746e5SOllivier Robert /*
1257c0b746e5SOllivier Robert  * clock_adjust - process what we've received, and adjust the time
1258c0b746e5SOllivier Robert  *		 if we got anything decent.
1259a151a66cSOllivier Robert  */
1260a151a66cSOllivier Robert static int
clock_adjust(void)1261c0b746e5SOllivier Robert clock_adjust(void)
1262c0b746e5SOllivier Robert {
1263c0b746e5SOllivier Robert 	register struct server *sp, *server;
1264a151a66cSOllivier Robert 	int dostep;
1265a151a66cSOllivier Robert 
1266c0b746e5SOllivier Robert 	for (sp = sys_servers; sp != NULL; sp = sp->next_server)
1267c0b746e5SOllivier Robert 		clock_filter(sp);
1268c0b746e5SOllivier Robert 	server = clock_select();
1269c0b746e5SOllivier Robert 
1270c0b746e5SOllivier Robert 	if (debug || simple_query) {
1271c0b746e5SOllivier Robert 		if (debug)
1272c0b746e5SOllivier Robert 			printf ("\n");
1273c0b746e5SOllivier Robert 		for (sp = sys_servers; sp != NULL; sp = sp->next_server)
1274c0b746e5SOllivier Robert 			print_server(sp, stdout);
1275c0b746e5SOllivier Robert 	}
1276c0b746e5SOllivier Robert 
1277c0b746e5SOllivier Robert 	if (server == 0) {
1278c0b746e5SOllivier Robert 		msyslog(LOG_ERR,
1279c0b746e5SOllivier Robert 			"no server suitable for synchronization found");
1280c0b746e5SOllivier Robert 		return(1);
1281c0b746e5SOllivier Robert 	}
1282ba371819SOllivier Robert 
1283c0b746e5SOllivier Robert 	if (always_step) {
1284c0b746e5SOllivier Robert 		dostep = 1;
1285c0b746e5SOllivier Robert 	} else if (never_step) {
1286c0b746e5SOllivier Robert 		dostep = 0;
1287c0b746e5SOllivier Robert 	} else {
12889c2daa00SOllivier Robert 		/* [Bug 3023] get absolute difference, avoiding signed
1289c0b746e5SOllivier Robert 		 * integer overflow like hell.
1290c0b746e5SOllivier Robert 		 */
1291c0b746e5SOllivier Robert 		u_fp absoffset;
1292c0b746e5SOllivier Robert 		if (server->soffset < 0)
1293c0b746e5SOllivier Robert 			absoffset = 1u + (u_fp)(-(server->soffset + 1));
1294c0b746e5SOllivier Robert 		else
12959c2daa00SOllivier Robert 			absoffset = (u_fp)server->soffset;
1296c0b746e5SOllivier Robert 		dostep = (absoffset >= NTPDATE_THRESHOLD);
1297c0b746e5SOllivier Robert 	}
1298c0b746e5SOllivier Robert 
1299c0b746e5SOllivier Robert 	if (dostep) {
1300c0b746e5SOllivier Robert 		if (simple_query || l_step_systime(&server->offset)){
1301c0b746e5SOllivier Robert 			msyslog(LOG_NOTICE, "step time server %s offset %s sec",
1302c0b746e5SOllivier Robert 				stoa(&server->srcadr),
1303c0b746e5SOllivier Robert 				lfptoa(&server->offset, 6));
1304c0b746e5SOllivier Robert 		}
1305c0b746e5SOllivier Robert 	} else {
1306c0b746e5SOllivier Robert 		if (simple_query || l_adj_systime(&server->offset)) {
1307c0b746e5SOllivier Robert 			msyslog(LOG_NOTICE, "adjust time server %s offset %s sec",
1308c0b746e5SOllivier Robert 				stoa(&server->srcadr),
1309c0b746e5SOllivier Robert 				lfptoa(&server->offset, 6));
1310c0b746e5SOllivier Robert 		}
1311c0b746e5SOllivier Robert 	}
1312c0b746e5SOllivier Robert 	return(0);
1313c0b746e5SOllivier Robert }
1314c0b746e5SOllivier Robert 
1315c0b746e5SOllivier Robert 
1316c0b746e5SOllivier Robert /*
1317c0b746e5SOllivier Robert  * is_unreachable - check to see if we have a route to given destination
1318c0b746e5SOllivier Robert  *		    (non-blocking).
1319c0b746e5SOllivier Robert  */
1320c0b746e5SOllivier Robert static int
is_reachable(sockaddr_u * dst)1321c0b746e5SOllivier Robert is_reachable (sockaddr_u *dst)
1322c0b746e5SOllivier Robert {
1323c0b746e5SOllivier Robert 	SOCKET sockfd;
1324c0b746e5SOllivier Robert 
1325c0b746e5SOllivier Robert 	sockfd = socket(AF(dst), SOCK_DGRAM, 0);
1326c0b746e5SOllivier Robert 	if (sockfd == -1) {
13279c2daa00SOllivier Robert 		return 0;
13289c2daa00SOllivier Robert 	}
13299c2daa00SOllivier Robert 
13309c2daa00SOllivier Robert 	if (connect(sockfd, &dst->sa, SOCKLEN(dst))) {
13319c2daa00SOllivier Robert 		closesocket(sockfd);
13329c2daa00SOllivier Robert 		return 0;
13339c2daa00SOllivier Robert 	}
13349c2daa00SOllivier Robert 	closesocket(sockfd);
13359c2daa00SOllivier Robert 	return 1;
1336c0b746e5SOllivier Robert }
13379c2daa00SOllivier Robert 
13389c2daa00SOllivier Robert 
13399c2daa00SOllivier Robert 
13409c2daa00SOllivier Robert /* XXX ELIMINATE: merge BIG slew into adj_systime in lib/systime.c */
13419c2daa00SOllivier Robert /*
1342b9bb0f5dSOllivier Robert  * addserver - determine a server's address and allocate a new structure
1343b9bb0f5dSOllivier Robert  *		for it.
13449c2daa00SOllivier Robert  */
1345b9bb0f5dSOllivier Robert static void
addserver(char * serv)13469c2daa00SOllivier Robert addserver(
13479c2daa00SOllivier Robert 	char *serv
13489c2daa00SOllivier Robert 	)
13499c2daa00SOllivier Robert {
1350c0b746e5SOllivier Robert 	register struct server *server;
1351c0b746e5SOllivier Robert 	/* Address infos structure to store result of getaddrinfo */
1352c0b746e5SOllivier Robert 	struct addrinfo *addrResult, *ptr;
1353b9bb0f5dSOllivier Robert 	/* Address infos structure to store hints for getaddrinfo */
1354b9bb0f5dSOllivier Robert 	struct addrinfo hints;
13559c2daa00SOllivier Robert 	/* Error variable for getaddrinfo */
13569c2daa00SOllivier Robert 	int error;
1357b9bb0f5dSOllivier Robert 	/* Service name */
1358c0b746e5SOllivier Robert 	char service[5];
1359c0b746e5SOllivier Robert 	sockaddr_u addr;
1360c0b746e5SOllivier Robert 
1361c0b746e5SOllivier Robert 	strlcpy(service, "ntp", sizeof(service));
13629c2daa00SOllivier Robert 
13639c2daa00SOllivier Robert 	/* Get host address. Looking for UDP datagram connection. */
13649c2daa00SOllivier Robert 	ZERO(hints);
1365a151a66cSOllivier Robert 	hints.ai_family = ai_fam_templ;
1366a151a66cSOllivier Robert 	hints.ai_socktype = SOCK_DGRAM;
1367a151a66cSOllivier Robert 
1368a151a66cSOllivier Robert #ifdef DEBUG
1369a151a66cSOllivier Robert 	if (debug)
1370a151a66cSOllivier Robert 		printf("Looking for host %s and service %s\n", serv, service);
1371a151a66cSOllivier Robert #endif
1372a151a66cSOllivier Robert 
1373a151a66cSOllivier Robert 	error = getaddrinfo(serv, service, &hints, &addrResult);
1374a151a66cSOllivier Robert 	if (error == EAI_SERVICE) {
1375c0b746e5SOllivier Robert 		strlcpy(service, "123", sizeof(service));
1376c0b746e5SOllivier Robert 		error = getaddrinfo(serv, service, &hints, &addrResult);
1377c0b746e5SOllivier Robert 	}
1378c0b746e5SOllivier Robert 	if (error != 0) {
1379c0b746e5SOllivier Robert 		/* Conduct more refined error analysis */
13809c2daa00SOllivier Robert 		if (error == EAI_FAIL || error == EAI_AGAIN){
1381c0b746e5SOllivier Robert 			/* Name server is unusable. Exit after failing on the
1382c0b746e5SOllivier Robert 			   first server, in order to shorten the timeout caused
1383c0b746e5SOllivier Robert 			   by waiting for resolution of several servers */
13849c2daa00SOllivier Robert 			fprintf(stderr, "Exiting, name server cannot be used: %s (%d)",
1385c0b746e5SOllivier Robert 				gai_strerror(error), error);
1386c0b746e5SOllivier Robert 			msyslog(LOG_ERR, "name server cannot be used: %s (%d)",
1387a151a66cSOllivier Robert 				gai_strerror(error), error);
1388a151a66cSOllivier Robert 			exit(1);
1389c0b746e5SOllivier Robert 		}
1390a151a66cSOllivier Robert 		fprintf(stderr, "Error resolving %s: %s (%d)\n", serv,
13919c2daa00SOllivier Robert 			gai_strerror(error), error);
1392c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "Can't find host %s: %s (%d)", serv,
1393c0b746e5SOllivier Robert 			gai_strerror(error), error);
1394a151a66cSOllivier Robert 		return;
1395a151a66cSOllivier Robert 	}
1396a151a66cSOllivier Robert #ifdef DEBUG
13979c2daa00SOllivier Robert 	if (debug) {
1398a151a66cSOllivier Robert 		ZERO(addr);
13999c2daa00SOllivier Robert 		INSIST(addrResult->ai_addrlen <= sizeof(addr));
14009c2daa00SOllivier Robert 		memcpy(&addr, addrResult->ai_addr, addrResult->ai_addrlen);
14019c2daa00SOllivier Robert 		fprintf(stderr, "host found : %s\n", stohost(&addr));
1402a151a66cSOllivier Robert 	}
1403c0b746e5SOllivier Robert #endif
14049c2daa00SOllivier Robert 
14059c2daa00SOllivier Robert 	/* We must get all returned server in case the first one fails */
14069c2daa00SOllivier Robert 	for (ptr = addrResult; ptr != NULL; ptr = ptr->ai_next) {
14079c2daa00SOllivier Robert 		ZERO(addr);
14089c2daa00SOllivier Robert 		INSIST(ptr->ai_addrlen <= sizeof(addr));
14099c2daa00SOllivier Robert 		memcpy(&addr, ptr->ai_addr, ptr->ai_addrlen);
14109c2daa00SOllivier Robert 		if (is_reachable(&addr)) {
14119c2daa00SOllivier Robert 			server = emalloc_zero(sizeof(*server));
14129c2daa00SOllivier Robert 			memcpy(&server->srcadr, ptr->ai_addr, ptr->ai_addrlen);
1413a151a66cSOllivier Robert 			server->event_time = ++sys_numservers;
1414a151a66cSOllivier Robert 			if (sys_servers == NULL)
14159c2daa00SOllivier Robert 				sys_servers = server;
1416a151a66cSOllivier Robert 			else {
1417a151a66cSOllivier Robert 				struct server *sp;
1418a151a66cSOllivier Robert 
1419a151a66cSOllivier Robert 				for (sp = sys_servers; sp->next_server != NULL;
1420a151a66cSOllivier Robert 				     sp = sp->next_server)
1421a151a66cSOllivier Robert 					/* empty */;
14229c2daa00SOllivier Robert 				sp->next_server = server;
1423a151a66cSOllivier Robert 			}
1424a151a66cSOllivier Robert 		}
1425a151a66cSOllivier Robert 	}
14269c2daa00SOllivier Robert 
1427a151a66cSOllivier Robert 	freeaddrinfo(addrResult);
1428a151a66cSOllivier Robert }
14299c2daa00SOllivier Robert 
1430a151a66cSOllivier Robert 
1431a151a66cSOllivier Robert /*
1432a151a66cSOllivier Robert  * findserver - find a server in the list given its address
1433a151a66cSOllivier Robert  * ***(For now it isn't totally AF-Independant, to check later..)
1434a151a66cSOllivier Robert  */
1435a151a66cSOllivier Robert static struct server *
findserver(sockaddr_u * addr)1436c0b746e5SOllivier Robert findserver(
1437c0b746e5SOllivier Robert 	sockaddr_u *addr
1438c0b746e5SOllivier Robert 	)
1439c0b746e5SOllivier Robert {
1440c0b746e5SOllivier Robert 	struct server *server;
1441c0b746e5SOllivier Robert 	struct server *mc_server;
1442c0b746e5SOllivier Robert 
1443c0b746e5SOllivier Robert 	mc_server = NULL;
1444c0b746e5SOllivier Robert 	if (SRCPORT(addr) != NTP_PORT)
1445a151a66cSOllivier Robert 		return 0;
1446c0b746e5SOllivier Robert 
1447c0b746e5SOllivier Robert 	for (server = sys_servers; server != NULL;
1448c0b746e5SOllivier Robert 	     server = server->next_server) {
1449c0b746e5SOllivier Robert 		if (SOCK_EQ(addr, &server->srcadr))
1450c0b746e5SOllivier Robert 			return server;
1451c0b746e5SOllivier Robert 
1452c0b746e5SOllivier Robert 		if (AF(addr) == AF(&server->srcadr)) {
1453c0b746e5SOllivier Robert 			if (IS_MCAST(&server->srcadr))
1454c0b746e5SOllivier Robert 				mc_server = server;
1455c0b746e5SOllivier Robert 		}
1456c0b746e5SOllivier Robert 	}
1457a151a66cSOllivier Robert 
1458a151a66cSOllivier Robert 	if (mc_server != NULL) {
1459a151a66cSOllivier Robert 
1460a151a66cSOllivier Robert 		struct server *sp;
1461a151a66cSOllivier Robert 
1462c0b746e5SOllivier Robert 		if (mc_server->event_time != 0) {
1463c0b746e5SOllivier Robert 			mc_server->event_time = 0;
1464c0b746e5SOllivier Robert 			complete_servers++;
1465c0b746e5SOllivier Robert 		}
1466224ba2bdSOllivier Robert 
1467224ba2bdSOllivier Robert 		server = emalloc_zero(sizeof(*server));
1468224ba2bdSOllivier Robert 
1469224ba2bdSOllivier Robert 		server->srcadr = *addr;
1470224ba2bdSOllivier Robert 
1471c0b746e5SOllivier Robert 		server->event_time = ++sys_numservers;
1472c0b746e5SOllivier Robert 
1473c0b746e5SOllivier Robert 		for (sp = sys_servers; sp->next_server != NULL;
1474c0b746e5SOllivier Robert 		     sp = sp->next_server)
1475c0b746e5SOllivier Robert 			/* empty */;
1476c0b746e5SOllivier Robert 		sp->next_server = server;
1477c0b746e5SOllivier Robert 		transmit(server);
1478c0b746e5SOllivier Robert 	}
1479c0b746e5SOllivier Robert 	return NULL;
1480c0b746e5SOllivier Robert }
1481c0b746e5SOllivier Robert 
1482224ba2bdSOllivier Robert 
1483224ba2bdSOllivier Robert /*
1484224ba2bdSOllivier Robert  * timer - process a timer interrupt
1485224ba2bdSOllivier Robert  */
1486224ba2bdSOllivier Robert void
timer(void)1487224ba2bdSOllivier Robert timer(void)
1488224ba2bdSOllivier Robert {
1489c0b746e5SOllivier Robert 	struct server *server;
1490c0b746e5SOllivier Robert 
1491c0b746e5SOllivier Robert 	/*
1492c0b746e5SOllivier Robert 	 * Bump the current idea of the time
1493c0b746e5SOllivier Robert 	 */
1494c0b746e5SOllivier Robert 	current_time++;
1495c0b746e5SOllivier Robert 
1496c0b746e5SOllivier Robert 	/*
1497c0b746e5SOllivier Robert 	 * Search through the server list looking for guys
1498c0b746e5SOllivier Robert 	 * who's event timers have expired.  Give these to
1499c0b746e5SOllivier Robert 	 * the transmit routine.
1500c0b746e5SOllivier Robert 	 */
1501c0b746e5SOllivier Robert 	for (server = sys_servers; server != NULL;
1502c0b746e5SOllivier Robert 	     server = server->next_server) {
1503c0b746e5SOllivier Robert 		if (server->event_time != 0
1504c0b746e5SOllivier Robert 		    && server->event_time <= current_time)
1505c0b746e5SOllivier Robert 			transmit(server);
1506c0b746e5SOllivier Robert 	}
1507c0b746e5SOllivier Robert }
1508c0b746e5SOllivier Robert 
1509c0b746e5SOllivier Robert 
1510c0b746e5SOllivier Robert /*
1511c0b746e5SOllivier Robert  * The code duplication in the following subroutine sucks, but
1512c0b746e5SOllivier Robert  * we need to appease ansi2knr.
1513c0b746e5SOllivier Robert  */
1514c0b746e5SOllivier Robert 
1515c0b746e5SOllivier Robert #ifndef SYS_WINNT
1516c0b746e5SOllivier Robert /*
1517c0b746e5SOllivier Robert  * alarming - record the occurance of an alarm interrupt
1518c0b746e5SOllivier Robert  */
1519c0b746e5SOllivier Robert static RETSIGTYPE
alarming(int sig)1520c0b746e5SOllivier Robert alarming(
1521c0b746e5SOllivier Robert 	int sig
1522c0b746e5SOllivier Robert 	)
1523c0b746e5SOllivier Robert {
1524c0b746e5SOllivier Robert 	alarm_flag++;
1525c0b746e5SOllivier Robert }
1526c0b746e5SOllivier Robert #else	/* SYS_WINNT follows */
1527c0b746e5SOllivier Robert void CALLBACK
alarming(UINT uTimerID,UINT uMsg,DWORD dwUser,DWORD dw1,DWORD dw2)1528c0b746e5SOllivier Robert alarming(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
1529c0b746e5SOllivier Robert {
1530c0b746e5SOllivier Robert 	UNUSED_ARG(uTimerID); UNUSED_ARG(uMsg); UNUSED_ARG(dwUser);
1531c0b746e5SOllivier Robert 	UNUSED_ARG(dw1); UNUSED_ARG(dw2);
1532c0b746e5SOllivier Robert 
1533c0b746e5SOllivier Robert 	alarm_flag++;
1534c0b746e5SOllivier Robert }
1535c0b746e5SOllivier Robert 
1536c0b746e5SOllivier Robert static void
callTimeEndPeriod(void)1537c0b746e5SOllivier Robert callTimeEndPeriod(void)
1538c0b746e5SOllivier Robert {
1539c0b746e5SOllivier Robert 	timeEndPeriod( wTimerRes );
1540c0b746e5SOllivier Robert 	wTimerRes = 0;
1541c0b746e5SOllivier Robert }
1542c0b746e5SOllivier Robert #endif /* SYS_WINNT */
1543c0b746e5SOllivier Robert 
1544c0b746e5SOllivier Robert 
1545c0b746e5SOllivier Robert /*
1546c0b746e5SOllivier Robert  * init_alarm - set up the timer interrupt
1547c0b746e5SOllivier Robert  */
1548c0b746e5SOllivier Robert static void
init_alarm(void)1549c0b746e5SOllivier Robert init_alarm(void)
1550c0b746e5SOllivier Robert {
1551c0b746e5SOllivier Robert #ifndef SYS_WINNT
15529c2daa00SOllivier Robert # ifdef HAVE_TIMER_CREATE
1553c0b746e5SOllivier Robert 	struct itimerspec its;
1554c0b746e5SOllivier Robert # else
1555c0b746e5SOllivier Robert 	struct itimerval itv;
1556c0b746e5SOllivier Robert # endif
1557c0b746e5SOllivier Robert #else	/* SYS_WINNT follows */
1558c0b746e5SOllivier Robert 	TIMECAPS tc;
1559c0b746e5SOllivier Robert 	UINT wTimerID;
1560c0b746e5SOllivier Robert 	HANDLE hToken;
1561c0b746e5SOllivier Robert 	TOKEN_PRIVILEGES tkp;
1562c0b746e5SOllivier Robert 	DWORD dwUser = 0;
1563c0b746e5SOllivier Robert #endif /* SYS_WINNT */
1564c0b746e5SOllivier Robert 
1565c0b746e5SOllivier Robert 	alarm_flag = 0;
1566c0b746e5SOllivier Robert 
1567c0b746e5SOllivier Robert #ifndef SYS_WINNT
1568c0b746e5SOllivier Robert # ifdef HAVE_TIMER_CREATE
1569c0b746e5SOllivier Robert 	alarm_flag = 0;
1570c0b746e5SOllivier Robert 	/* this code was put in as setitimer() is non existant this us the
1571c0b746e5SOllivier Robert 	 * POSIX "equivalents" setup - casey
1572c0b746e5SOllivier Robert 	 */
1573c0b746e5SOllivier Robert 	/* ntpdate_timerid is global - so we can kill timer later */
1574c0b746e5SOllivier Robert 	if (timer_create (CLOCK_REALTIME, NULL, &ntpdate_timerid) ==
1575c0b746e5SOllivier Robert #  ifdef SYS_VXWORKS
1576c0b746e5SOllivier Robert 		ERROR
1577c0b746e5SOllivier Robert #  else
1578c0b746e5SOllivier Robert 		-1
1579c0b746e5SOllivier Robert #  endif
1580c0b746e5SOllivier Robert 		)
1581c0b746e5SOllivier Robert 	{
1582c0b746e5SOllivier Robert 		fprintf (stderr, "init_alarm(): timer_create (...) FAILED\n");
1583c0b746e5SOllivier Robert 		return;
1584c0b746e5SOllivier Robert 	}
1585c0b746e5SOllivier Robert 
1586c0b746e5SOllivier Robert 	/*	TIMER_HZ = (5)
1587c0b746e5SOllivier Robert 	 * Set up the alarm interrupt.	The first comes 1/(2*TIMER_HZ)
1588c0b746e5SOllivier Robert 	 * seconds from now and they continue on every 1/TIMER_HZ seconds.
1589c0b746e5SOllivier Robert 	 */
1590c0b746e5SOllivier Robert 	signal_no_reset(SIGALRM, alarming);
1591c0b746e5SOllivier Robert 	its.it_interval.tv_sec = 0;
1592c0b746e5SOllivier Robert 	its.it_value.tv_sec = 0;
1593c0b746e5SOllivier Robert 	its.it_interval.tv_nsec = 1000000000/TIMER_HZ;
1594c0b746e5SOllivier Robert 	its.it_value.tv_nsec = 1000000000/(TIMER_HZ<<1);
1595c0b746e5SOllivier Robert 	timer_settime(ntpdate_timerid, 0 /* !TIMER_ABSTIME */, &its, NULL);
1596c0b746e5SOllivier Robert # else	/* !HAVE_TIMER_CREATE follows */
1597c0b746e5SOllivier Robert 	/*
1598c0b746e5SOllivier Robert 	 * Set up the alarm interrupt.	The first comes 1/(2*TIMER_HZ)
1599c0b746e5SOllivier Robert 	 * seconds from now and they continue on every 1/TIMER_HZ seconds.
1600c0b746e5SOllivier Robert 	 */
1601c0b746e5SOllivier Robert 	signal_no_reset(SIGALRM, alarming);
1602c0b746e5SOllivier Robert 	itv.it_interval.tv_sec = 0;
1603c0b746e5SOllivier Robert 	itv.it_value.tv_sec = 0;
1604c0b746e5SOllivier Robert 	itv.it_interval.tv_usec = 1000000/TIMER_HZ;
1605c0b746e5SOllivier Robert 	itv.it_value.tv_usec = 1000000/(TIMER_HZ<<1);
1606c0b746e5SOllivier Robert 
1607c0b746e5SOllivier Robert 	setitimer(ITIMER_REAL, &itv, NULL);
1608c0b746e5SOllivier Robert # endif	/* !HAVE_TIMER_CREATE */
1609c0b746e5SOllivier Robert #else	/* SYS_WINNT follows */
1610c0b746e5SOllivier Robert 	_tzset();
1611c0b746e5SOllivier Robert 
1612c0b746e5SOllivier Robert 	if (!simple_query && !debug) {
1613c0b746e5SOllivier Robert 		/*
1614c0b746e5SOllivier Robert 		 * Get privileges needed for fiddling with the clock
1615c0b746e5SOllivier Robert 		 */
1616c0b746e5SOllivier Robert 
1617c0b746e5SOllivier Robert 		/* get the current process token handle */
1618c0b746e5SOllivier Robert 		if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
1619c0b746e5SOllivier Robert 			msyslog(LOG_ERR, "OpenProcessToken failed: %m");
1620c0b746e5SOllivier Robert 			exit(1);
1621c0b746e5SOllivier Robert 		}
1622c0b746e5SOllivier Robert 		/* get the LUID for system-time privilege. */
1623c0b746e5SOllivier Robert 		LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid);
1624c0b746e5SOllivier Robert 		tkp.PrivilegeCount = 1;		/* one privilege to set */
1625c0b746e5SOllivier Robert 		tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
1626c0b746e5SOllivier Robert 		/* get set-time privilege for this process. */
1627c0b746e5SOllivier Robert 		AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES) NULL, 0);
1628c0b746e5SOllivier Robert 		/* cannot test return value of AdjustTokenPrivileges. */
1629c0b746e5SOllivier Robert 		if (GetLastError() != ERROR_SUCCESS)
1630c0b746e5SOllivier Robert 			msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m");
1631c0b746e5SOllivier Robert 	}
1632c0b746e5SOllivier Robert 
1633c0b746e5SOllivier Robert 	/*
1634c0b746e5SOllivier Robert 	 * Set up timer interrupts for every 2**EVENT_TIMEOUT seconds
1635c0b746e5SOllivier Robert 	 * Under Win/NT, expiry of timer interval leads to invocation
1636c0b746e5SOllivier Robert 	 * of a callback function (on a different thread) rather than
1637c0b746e5SOllivier Robert 	 * generating an alarm signal
1638c0b746e5SOllivier Robert 	 */
1639c0b746e5SOllivier Robert 
1640c0b746e5SOllivier Robert 	/* determine max and min resolution supported */
1641c0b746e5SOllivier Robert 	if(timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
1642c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "timeGetDevCaps failed: %m");
1643c0b746e5SOllivier Robert 		exit(1);
1644c0b746e5SOllivier Robert 	}
1645c0b746e5SOllivier Robert 	wTimerRes = min(max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax);
1646c0b746e5SOllivier Robert 	/* establish the minimum timer resolution that we'll use */
1647c0b746e5SOllivier Robert 	timeBeginPeriod(wTimerRes);
1648c0b746e5SOllivier Robert 	atexit(callTimeEndPeriod);
1649c0b746e5SOllivier Robert 
16509c2daa00SOllivier Robert 	/* start the timer event */
16519c2daa00SOllivier Robert 	wTimerID = timeSetEvent(
16529c2daa00SOllivier Robert 		(UINT) (1000/TIMER_HZ),		/* Delay */
16539c2daa00SOllivier Robert 		wTimerRes,			/* Resolution */
16549c2daa00SOllivier Robert 		(LPTIMECALLBACK) alarming,	/* Callback function */
1655c0b746e5SOllivier Robert 		(DWORD) dwUser,			/* User data */
1656c0b746e5SOllivier Robert 		TIME_PERIODIC);			/* Event type (periodic) */
1657c0b746e5SOllivier Robert 	if (wTimerID == 0) {
1658c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "timeSetEvent failed: %m");
16599c2daa00SOllivier Robert 		exit(1);
1660c0b746e5SOllivier Robert 	}
1661c0b746e5SOllivier Robert #endif /* SYS_WINNT */
1662c0b746e5SOllivier Robert }
1663c0b746e5SOllivier Robert 
16649c2daa00SOllivier Robert 
16659c2daa00SOllivier Robert 
16669c2daa00SOllivier Robert 
16679c2daa00SOllivier Robert /*
16689c2daa00SOllivier Robert  * We do asynchronous input using the SIGIO facility.  A number of
16699c2daa00SOllivier Robert  * recvbuf buffers are preallocated for input.	In the signal
16709c2daa00SOllivier Robert  * handler we poll to see if the socket is ready and read the
16719c2daa00SOllivier Robert  * packets from it into the recvbuf's along with a time stamp and
16729c2daa00SOllivier Robert  * an indication of the source host and the interface it was received
16739c2daa00SOllivier Robert  * through.  This allows us to get as accurate receive time stamps
16749c2daa00SOllivier Robert  * as possible independent of other processing going on.
1675c0b746e5SOllivier Robert  *
1676c0b746e5SOllivier Robert  * We allocate a number of recvbufs equal to the number of servers
1677c0b746e5SOllivier Robert  * plus 2.	This should be plenty.
1678c0b746e5SOllivier Robert  */
16799c2daa00SOllivier Robert 
16809c2daa00SOllivier Robert 
16819c2daa00SOllivier Robert /*
16829c2daa00SOllivier Robert  * init_io - initialize I/O data and open socket
16839c2daa00SOllivier Robert  */
16849c2daa00SOllivier Robert static void
init_io(void)16859c2daa00SOllivier Robert init_io(void)
16869c2daa00SOllivier Robert {
16879c2daa00SOllivier Robert 	struct addrinfo *res, *ressave;
16889c2daa00SOllivier Robert 	struct addrinfo hints;
16899c2daa00SOllivier Robert 	sockaddr_u addr;
16909c2daa00SOllivier Robert 	char service[5];
16919c2daa00SOllivier Robert 	int rc;
16929c2daa00SOllivier Robert 	int optval = 1;
16939c2daa00SOllivier Robert 	int check_ntp_port_in_use = !debug && !simple_query && !unpriv_port;
16949c2daa00SOllivier Robert 
16959c2daa00SOllivier Robert 	/*
16969c2daa00SOllivier Robert 	 * Init buffer free list and stat counters
16979c2daa00SOllivier Robert 	 */
16989c2daa00SOllivier Robert 	init_recvbuff(sys_numservers + 2);
16999c2daa00SOllivier Robert 
17009c2daa00SOllivier Robert 	/*
17019c2daa00SOllivier Robert 	 * Open the socket
17029c2daa00SOllivier Robert 	 */
17039c2daa00SOllivier Robert 
17049c2daa00SOllivier Robert 	strlcpy(service, "ntp", sizeof(service));
17059c2daa00SOllivier Robert 
17069c2daa00SOllivier Robert 	/*
17079c2daa00SOllivier Robert 	 * Init hints addrinfo structure
17089c2daa00SOllivier Robert 	 */
17099c2daa00SOllivier Robert 	ZERO(hints);
17109c2daa00SOllivier Robert 	hints.ai_family = ai_fam_templ;
17119c2daa00SOllivier Robert 	hints.ai_flags = AI_PASSIVE;
17129c2daa00SOllivier Robert 	hints.ai_socktype = SOCK_DGRAM;
17139c2daa00SOllivier Robert 
1714c0b746e5SOllivier Robert 	rc = getaddrinfo(NULL, service, &hints, &res);
1715c0b746e5SOllivier Robert 	if (rc == EAI_SERVICE) {
1716c0b746e5SOllivier Robert 		strlcpy(service, "123", sizeof(service));
1717c0b746e5SOllivier Robert 		rc = getaddrinfo(NULL, service, &hints, &res);
17189c2daa00SOllivier Robert 	}
1719c0b746e5SOllivier Robert 	if (rc != 0) {
1720c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "getaddrinfo() failed: %m");
1721c0b746e5SOllivier Robert 		exit(1);
1722c0b746e5SOllivier Robert 		/*NOTREACHED*/
1723c0b746e5SOllivier Robert 	}
17249c2daa00SOllivier Robert 
1725c0b746e5SOllivier Robert #ifdef SYS_WINNT
1726c0b746e5SOllivier Robert 	if (check_ntp_port_in_use && ntp_port_inuse(AF_INET, NTP_PORT)){
17279c2daa00SOllivier Robert 		msyslog(LOG_ERR, "the NTP socket is in use, exiting: %m");
1728c0b746e5SOllivier Robert 		exit(1);
1729c0b746e5SOllivier Robert 	}
1730c0b746e5SOllivier Robert #endif
1731c0b746e5SOllivier Robert 
1732c0b746e5SOllivier Robert 	/* Remember the address of the addrinfo structure chain */
17339c2daa00SOllivier Robert 	ressave = res;
17349c2daa00SOllivier Robert 
1735c0b746e5SOllivier Robert 	/*
17369c2daa00SOllivier Robert 	 * For each structure returned, open and bind socket
17379c2daa00SOllivier Robert 	 */
17389c2daa00SOllivier Robert 	for(nbsock = 0; (nbsock < MAX_AF) && res ; res = res->ai_next) {
17399c2daa00SOllivier Robert 	/* create a datagram (UDP) socket */
1740c0b746e5SOllivier Robert 		fd[nbsock] = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
1741c0b746e5SOllivier Robert 		if (fd[nbsock] == SOCKET_ERROR) {
1742c0b746e5SOllivier Robert #ifndef SYS_WINNT
1743c0b746e5SOllivier Robert 		if (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT ||
1744c0b746e5SOllivier Robert 		    errno == EPFNOSUPPORT)
1745c0b746e5SOllivier Robert #else
1746c0b746e5SOllivier Robert 		int err = WSAGetLastError();
1747c0b746e5SOllivier Robert 		if (err == WSAEPROTONOSUPPORT || err == WSAEAFNOSUPPORT ||
1748c0b746e5SOllivier Robert 		    err == WSAEPFNOSUPPORT)
1749c0b746e5SOllivier Robert #endif
17509c2daa00SOllivier Robert 			continue;
17519c2daa00SOllivier Robert 		msyslog(LOG_ERR, "socket() failed: %m");
1752c0b746e5SOllivier Robert 		exit(1);
1753c0b746e5SOllivier Robert 		/*NOTREACHED*/
1754c0b746e5SOllivier Robert 		}
1755c0b746e5SOllivier Robert 		/* set socket to reuse address */
1756c0b746e5SOllivier Robert 		if (setsockopt(fd[nbsock], SOL_SOCKET, SO_REUSEADDR, (void*) &optval, sizeof(optval)) < 0) {
17579c2daa00SOllivier Robert 				msyslog(LOG_ERR, "setsockopt() SO_REUSEADDR failed: %m");
17589c2daa00SOllivier Robert 				exit(1);
1759c0b746e5SOllivier Robert 				/*NOTREACHED*/
1760c0b746e5SOllivier Robert 		}
1761c0b746e5SOllivier Robert #ifdef IPV6_V6ONLY
1762c0b746e5SOllivier Robert 		/* Restricts AF_INET6 socket to IPv6 communications (see RFC 2553bis-03) */
1763c0b746e5SOllivier Robert 		if (res->ai_family == AF_INET6)
17649c2daa00SOllivier Robert 			if (setsockopt(fd[nbsock], IPPROTO_IPV6, IPV6_V6ONLY, (void*) &optval, sizeof(optval)) < 0) {
17659c2daa00SOllivier Robert 				msyslog(LOG_ERR, "setsockopt() IPV6_V6ONLY failed: %m");
1766c0b746e5SOllivier Robert 		}
1767c0b746e5SOllivier Robert #endif
1768c0b746e5SOllivier Robert 
1769c0b746e5SOllivier Robert 		/* Remember the socket family in fd_family structure */
1770c0b746e5SOllivier Robert 		fd_family[nbsock] = res->ai_family;
1771c0b746e5SOllivier Robert 
1772c0b746e5SOllivier Robert 		/*
1773c0b746e5SOllivier Robert 		 * bind the socket to the NTP port
1774c0b746e5SOllivier Robert 		 */
17759c2daa00SOllivier Robert 		if (check_ntp_port_in_use) {
17769c2daa00SOllivier Robert 			ZERO(addr);
1777c0b746e5SOllivier Robert 			INSIST(res->ai_addrlen <= sizeof(addr));
1778c0b746e5SOllivier Robert 			memcpy(&addr, res->ai_addr, res->ai_addrlen);
1779c0b746e5SOllivier Robert 			rc = bind(fd[nbsock], &addr.sa, SOCKLEN(&addr));
17809c2daa00SOllivier Robert 			if (rc < 0) {
1781c0b746e5SOllivier Robert 				if (EADDRINUSE == socket_errno())
17829c2daa00SOllivier Robert 					msyslog(LOG_ERR, "the NTP socket is in use, exiting");
17839c2daa00SOllivier Robert 				else
1784c0b746e5SOllivier Robert 					msyslog(LOG_ERR, "bind() fails: %m");
1785c0b746e5SOllivier Robert 				exit(1);
1786c0b746e5SOllivier Robert 			}
1787c0b746e5SOllivier Robert 		}
1788c0b746e5SOllivier Robert 
1789c0b746e5SOllivier Robert #ifdef HAVE_POLL_H
17909c2daa00SOllivier Robert 		fdmask[nbsock].fd = fd[nbsock];
1791c0b746e5SOllivier Robert 		fdmask[nbsock].events = POLLIN;
1792c0b746e5SOllivier Robert #else
1793c0b746e5SOllivier Robert 		FD_SET(fd[nbsock], &fdmask);
1794c0b746e5SOllivier Robert 		if (maxfd < fd[nbsock]+1) {
17959c2daa00SOllivier Robert 			maxfd = fd[nbsock]+1;
1796c0b746e5SOllivier Robert 		}
17979c2daa00SOllivier Robert #endif
1798c0b746e5SOllivier Robert 
1799c0b746e5SOllivier Robert 		/*
1800c0b746e5SOllivier Robert 		 * set non-blocking,
1801c0b746e5SOllivier Robert 		 */
1802c0b746e5SOllivier Robert #ifndef SYS_WINNT
18039c2daa00SOllivier Robert # ifdef SYS_VXWORKS
18049c2daa00SOllivier Robert 		{
18059c2daa00SOllivier Robert 			int on = TRUE;
18069c2daa00SOllivier Robert 
18079c2daa00SOllivier Robert 			if (ioctl(fd[nbsock],FIONBIO, &on) == ERROR) {
18089c2daa00SOllivier Robert 				msyslog(LOG_ERR, "ioctl(FIONBIO) fails: %m");
18099c2daa00SOllivier Robert 				exit(1);
18109c2daa00SOllivier Robert 			}
18119c2daa00SOllivier Robert 		}
18129c2daa00SOllivier Robert # else /* not SYS_VXWORKS */
18139c2daa00SOllivier Robert #  if defined(O_NONBLOCK)
18149c2daa00SOllivier Robert 		if (fcntl(fd[nbsock], F_SETFL, O_NONBLOCK) < 0) {
18159c2daa00SOllivier Robert 			msyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails: %m");
18169c2daa00SOllivier Robert 			exit(1);
18179c2daa00SOllivier Robert 			/*NOTREACHED*/
18189c2daa00SOllivier Robert 		}
18199c2daa00SOllivier Robert #  else /* not O_NONBLOCK */
1820c0b746e5SOllivier Robert #	if defined(FNDELAY)
1821c0b746e5SOllivier Robert 		if (fcntl(fd[nbsock], F_SETFL, FNDELAY) < 0) {
1822c0b746e5SOllivier Robert 			msyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails: %m");
1823c0b746e5SOllivier Robert 			exit(1);
1824c0b746e5SOllivier Robert 			/*NOTREACHED*/
1825c0b746e5SOllivier Robert 		}
1826c0b746e5SOllivier Robert #	else /* FNDELAY */
1827c0b746e5SOllivier Robert #	 include "Bletch: Need non blocking I/O"
18289c2daa00SOllivier Robert #	endif /* FNDELAY */
1829c0b746e5SOllivier Robert #  endif /* not O_NONBLOCK */
1830c0b746e5SOllivier Robert # endif /* SYS_VXWORKS */
1831c0b746e5SOllivier Robert #else /* SYS_WINNT */
1832c0b746e5SOllivier Robert 		if (ioctlsocket(fd[nbsock], FIONBIO, (u_long *) &on) == SOCKET_ERROR) {
1833c0b746e5SOllivier Robert 			msyslog(LOG_ERR, "ioctlsocket(FIONBIO) fails: %m");
1834c0b746e5SOllivier Robert 			exit(1);
1835c0b746e5SOllivier Robert 		}
1836c0b746e5SOllivier Robert #endif /* SYS_WINNT */
1837c0b746e5SOllivier Robert 		nbsock++;
1838c0b746e5SOllivier Robert 	}
1839c0b746e5SOllivier Robert 	freeaddrinfo(ressave);
1840c0b746e5SOllivier Robert }
1841c0b746e5SOllivier Robert 
1842c0b746e5SOllivier Robert /*
1843c0b746e5SOllivier Robert  * sendpkt - send a packet to the specified destination
18449c2daa00SOllivier Robert  */
1845c0b746e5SOllivier Robert static void
sendpkt(sockaddr_u * dest,struct pkt * pkt,int len)18469c2daa00SOllivier Robert sendpkt(
1847c0b746e5SOllivier Robert 	sockaddr_u *dest,
1848c0b746e5SOllivier Robert 	struct pkt *pkt,
1849c0b746e5SOllivier Robert 	int len
18509c2daa00SOllivier Robert 	)
1851c0b746e5SOllivier Robert {
1852c0b746e5SOllivier Robert 	int i;
1853c0b746e5SOllivier Robert 	int cc;
1854c0b746e5SOllivier Robert 	SOCKET sock = INVALID_SOCKET;
1855c0b746e5SOllivier Robert 
1856c0b746e5SOllivier Robert #ifdef SYS_WINNT
1857c0b746e5SOllivier Robert 	DWORD err;
18589c2daa00SOllivier Robert #endif /* SYS_WINNT */
18599c2daa00SOllivier Robert 
18609c2daa00SOllivier Robert 	/* Find a local family compatible socket to send ntp packet to ntp server */
18619c2daa00SOllivier Robert 	for(i = 0; (i < MAX_AF); i++) {
18629c2daa00SOllivier Robert 		if(AF(dest) == fd_family[i]) {
18639c2daa00SOllivier Robert 			sock = fd[i];
18649c2daa00SOllivier Robert 		break;
18659c2daa00SOllivier Robert 		}
18669c2daa00SOllivier Robert 	}
18679c2daa00SOllivier Robert 
18689c2daa00SOllivier Robert 	if (INVALID_SOCKET == sock) {
18699c2daa00SOllivier Robert 		msyslog(LOG_ERR, "cannot find family compatible socket to send ntp packet");
18709c2daa00SOllivier Robert 		exit(1);
18719c2daa00SOllivier Robert 		/*NOTREACHED*/
1872c0b746e5SOllivier Robert 	}
18739c2daa00SOllivier Robert 
18749c2daa00SOllivier Robert 	cc = sendto(sock, (char *)pkt, len, 0, (struct sockaddr *)dest,
18759c2daa00SOllivier Robert 			SOCKLEN(dest));
18769c2daa00SOllivier Robert 
18779c2daa00SOllivier Robert 	if (SOCKET_ERROR == cc) {
18789c2daa00SOllivier Robert #ifndef SYS_WINNT
18799c2daa00SOllivier Robert 		if (errno != EWOULDBLOCK && errno != ENOBUFS)
18809c2daa00SOllivier Robert #else
18819c2daa00SOllivier Robert 		err = WSAGetLastError();
18829c2daa00SOllivier Robert 		if (err != WSAEWOULDBLOCK && err != WSAENOBUFS)
18839c2daa00SOllivier Robert #endif /* SYS_WINNT */
18849c2daa00SOllivier Robert 			msyslog(LOG_ERR, "sendto(%s): %m", stohost(dest));
18859c2daa00SOllivier Robert 	}
18869c2daa00SOllivier Robert }
1887c0b746e5SOllivier Robert 
1888c0b746e5SOllivier Robert 
1889c0b746e5SOllivier Robert /*
1890c0b746e5SOllivier Robert  * input_handler - receive packets asynchronously
1891c0b746e5SOllivier Robert  */
1892c0b746e5SOllivier Robert void
input_handler(void)1893c0b746e5SOllivier Robert input_handler(void)
1894c0b746e5SOllivier Robert {
1895c0b746e5SOllivier Robert 	register int n;
1896c0b746e5SOllivier Robert 	register struct recvbuf *rb;
1897c0b746e5SOllivier Robert 	struct sock_timeval tvzero;
18989c2daa00SOllivier Robert 	GETSOCKNAME_SOCKLEN_TYPE fromlen;
1899c0b746e5SOllivier Robert 	l_fp ts;
1900c0b746e5SOllivier Robert 	int i;
1901c0b746e5SOllivier Robert #ifdef HAVE_POLL_H
1902c0b746e5SOllivier Robert 	struct pollfd fds[MAX_AF];
1903c0b746e5SOllivier Robert #else
1904c0b746e5SOllivier Robert 	fd_set fds;
1905c0b746e5SOllivier Robert #endif
1906c0b746e5SOllivier Robert 	SOCKET fdc = 0;
1907c0b746e5SOllivier Robert 
1908c0b746e5SOllivier Robert 	/*
1909c0b746e5SOllivier Robert 	 * Do a poll to see if we have data
1910c0b746e5SOllivier Robert 	 */
1911c0b746e5SOllivier Robert 	for (;;) {
1912c0b746e5SOllivier Robert 		tvzero.tv_sec = tvzero.tv_usec = 0;
1913c0b746e5SOllivier Robert #ifdef HAVE_POLL_H
1914c0b746e5SOllivier Robert 		memcpy(fds, fdmask, sizeof(fdmask));
1915c0b746e5SOllivier Robert 		n = poll(fds, (unsigned int)nbsock, tvzero.tv_sec * 1000);
1916c0b746e5SOllivier Robert 
19179c2daa00SOllivier Robert 		/*
1918c0b746e5SOllivier Robert 		 * Determine which socket received data
19199c2daa00SOllivier Robert 		 */
1920c0b746e5SOllivier Robert 
1921c0b746e5SOllivier Robert 		for(i=0; i < nbsock; i++) {
1922c0b746e5SOllivier Robert 			if(fds[i].revents & POLLIN) {
1923c0b746e5SOllivier Robert 				fdc = fd[i];
1924c0b746e5SOllivier Robert 				break;
1925c0b746e5SOllivier Robert 			}
19269c2daa00SOllivier Robert 		}
1927c0b746e5SOllivier Robert 
1928c0b746e5SOllivier Robert #else
1929c0b746e5SOllivier Robert 		fds = fdmask;
1930c0b746e5SOllivier Robert 		n = select(maxfd, &fds, NULL, NULL, &tvzero);
1931c0b746e5SOllivier Robert 
1932c0b746e5SOllivier Robert 		/*
19339c2daa00SOllivier Robert 		 * Determine which socket received data
19349c2daa00SOllivier Robert 		 */
1935c0b746e5SOllivier Robert 
1936c0b746e5SOllivier Robert 		for(i=0; i < nbsock; i++) {
1937c0b746e5SOllivier Robert 			if(FD_ISSET(fd[i], &fds)) {
1938c0b746e5SOllivier Robert 				 fdc = fd[i];
1939c0b746e5SOllivier Robert 				 break;
1940c0b746e5SOllivier Robert 			}
1941c0b746e5SOllivier Robert 		}
1942c0b746e5SOllivier Robert 
1943c0b746e5SOllivier Robert #endif
1944c0b746e5SOllivier Robert 
1945c0b746e5SOllivier Robert 		/*
1946c0b746e5SOllivier Robert 		 * If nothing to do, just return.  If an error occurred,
1947c0b746e5SOllivier Robert 		 * complain and return.  If we've got some, freeze a
1948c0b746e5SOllivier Robert 		 * timestamp.
1949c0b746e5SOllivier Robert 		 */
1950c0b746e5SOllivier Robert 		if (n == 0)
1951c0b746e5SOllivier Robert 			return;
1952c0b746e5SOllivier Robert 		else if (n == -1) {
1953c0b746e5SOllivier Robert 			if (errno != EINTR)
1954c0b746e5SOllivier Robert 				msyslog(LOG_ERR,
1955c0b746e5SOllivier Robert #ifdef HAVE_POLL_H
1956c0b746e5SOllivier Robert 					"poll() error: %m"
1957c0b746e5SOllivier Robert #else
1958c0b746e5SOllivier Robert 					"select() error: %m"
1959c0b746e5SOllivier Robert #endif
1960c0b746e5SOllivier Robert 					);
1961c0b746e5SOllivier Robert 			return;
1962c0b746e5SOllivier Robert 		}
1963c0b746e5SOllivier Robert 		get_systime(&ts);
1964c0b746e5SOllivier Robert 
1965c0b746e5SOllivier Robert 		/*
1966c0b746e5SOllivier Robert 		 * Get a buffer and read the frame.  If we
1967c0b746e5SOllivier Robert 		 * haven't got a buffer, or this is received
1968c0b746e5SOllivier Robert 		 * on the wild card socket, just dump the packet.
1969c0b746e5SOllivier Robert 		 */
1970c0b746e5SOllivier Robert 		if (initializing || free_recvbuffs() == 0) {
1971c0b746e5SOllivier Robert 			char buf[100];
1972c0b746e5SOllivier Robert 
1973c0b746e5SOllivier Robert 
1974c0b746e5SOllivier Robert #ifndef SYS_WINNT
1975c0b746e5SOllivier Robert 			(void) read(fdc, buf, sizeof buf);
1976c0b746e5SOllivier Robert #else
1977c0b746e5SOllivier Robert 			/* NT's _read does not operate on nonblocking sockets
1978c0b746e5SOllivier Robert 			 * either recvfrom or ReadFile() has to be used here.
1979c0b746e5SOllivier Robert 			 * ReadFile is used in [ntpd]ntp_intres() and ntpdc,
1980c0b746e5SOllivier Robert 			 * just to be different use recvfrom() here
1981c0b746e5SOllivier Robert 			 */
1982c0b746e5SOllivier Robert 			recvfrom(fdc, buf, sizeof(buf), 0, (struct sockaddr *)0, NULL);
1983c0b746e5SOllivier Robert #endif /* SYS_WINNT */
1984c0b746e5SOllivier Robert 			continue;
1985c0b746e5SOllivier Robert 		}
1986c0b746e5SOllivier Robert 
1987c0b746e5SOllivier Robert 		rb = get_free_recv_buffer(TRUE);
1988c0b746e5SOllivier Robert 
1989c0b746e5SOllivier Robert 		fromlen = sizeof(rb->recv_srcadr);
1990c0b746e5SOllivier Robert 		rb->recv_length = recvfrom(fdc, (char *)&rb->recv_pkt,
1991c0b746e5SOllivier Robert 		   sizeof(rb->recv_pkt), 0,
1992c0b746e5SOllivier Robert 		   (struct sockaddr *)&rb->recv_srcadr, &fromlen);
1993c0b746e5SOllivier Robert 		if (rb->recv_length == -1) {
1994c0b746e5SOllivier Robert 			freerecvbuf(rb);
1995c0b746e5SOllivier Robert 			continue;
1996c0b746e5SOllivier Robert 		}
1997c0b746e5SOllivier Robert 
1998c0b746e5SOllivier Robert 		/*
1999c0b746e5SOllivier Robert 		 * Got one.  Mark how and when it got here,
2000c0b746e5SOllivier Robert 		 * put it on the full list.
2001c0b746e5SOllivier Robert 		 */
2002c0b746e5SOllivier Robert 		rb->recv_time = ts;
2003c0b746e5SOllivier Robert 		add_full_recv_buffer(rb);
2004c0b746e5SOllivier Robert 	}
2005c0b746e5SOllivier Robert }
2006c0b746e5SOllivier Robert 
2007c0b746e5SOllivier Robert 
2008c0b746e5SOllivier Robert /*
2009c0b746e5SOllivier Robert  * adj_systime - do a big long slew of the system time
2010c0b746e5SOllivier Robert  */
2011c0b746e5SOllivier Robert static int
l_adj_systime(l_fp * ts)2012c0b746e5SOllivier Robert l_adj_systime(
2013c0b746e5SOllivier Robert 	l_fp *ts
2014c0b746e5SOllivier Robert 	)
2015c0b746e5SOllivier Robert {
2016c0b746e5SOllivier Robert 	struct timeval adjtv;
2017c0b746e5SOllivier Robert 	int isneg = 0;
2018c0b746e5SOllivier Robert 	l_fp offset;
2019c0b746e5SOllivier Robert #ifndef STEP_SLEW
2020c0b746e5SOllivier Robert 	l_fp overshoot;
2021c0b746e5SOllivier Robert #endif
2022c0b746e5SOllivier Robert 
2023c0b746e5SOllivier Robert 	/*
2024c0b746e5SOllivier Robert 	 * Take the absolute value of the offset
2025c0b746e5SOllivier Robert 	 */
2026c0b746e5SOllivier Robert 	offset = *ts;
2027c0b746e5SOllivier Robert 	if (L_ISNEG(&offset)) {
2028c0b746e5SOllivier Robert 		isneg = 1;
2029c0b746e5SOllivier Robert 		L_NEG(&offset);
2030c0b746e5SOllivier Robert 	}
2031c0b746e5SOllivier Robert 
2032c0b746e5SOllivier Robert #ifndef STEP_SLEW
2033c0b746e5SOllivier Robert 	/*
2034c0b746e5SOllivier Robert 	 * Calculate the overshoot.  XXX N.B. This code *knows*
2035c0b746e5SOllivier Robert 	 * ADJ_OVERSHOOT is 1/2.
2036a151a66cSOllivier Robert 	 */
2037a151a66cSOllivier Robert 	overshoot = offset;
2038c0b746e5SOllivier Robert 	L_RSHIFTU(&overshoot);
2039c0b746e5SOllivier Robert 	if (overshoot.l_ui != 0 || (overshoot.l_uf > ADJ_MAXOVERSHOOT)) {
2040c0b746e5SOllivier Robert 		overshoot.l_ui = 0;
2041c0b746e5SOllivier Robert 		overshoot.l_uf = ADJ_MAXOVERSHOOT;
2042c0b746e5SOllivier Robert 	}
2043c0b746e5SOllivier Robert 	L_ADD(&offset, &overshoot);
2044c0b746e5SOllivier Robert #endif
2045c0b746e5SOllivier Robert 	TSTOTV(&offset, &adjtv);
2046c0b746e5SOllivier Robert 
2047c0b746e5SOllivier Robert 	if (isneg) {
2048c0b746e5SOllivier Robert 		adjtv.tv_sec = -adjtv.tv_sec;
2049c0b746e5SOllivier Robert 		adjtv.tv_usec = -adjtv.tv_usec;
2050c0b746e5SOllivier Robert 	}
2051c0b746e5SOllivier Robert 
2052c0b746e5SOllivier Robert 	if (!debug && (adjtv.tv_usec != 0)) {
2053c0b746e5SOllivier Robert 		/* A time correction needs to be applied. */
2054c0b746e5SOllivier Robert #if !defined SYS_WINNT && !defined SYS_CYGWIN32
2055c0b746e5SOllivier Robert 		/* Slew the time on systems that support this. */
2056c0b746e5SOllivier Robert 		struct timeval oadjtv;
2057c0b746e5SOllivier Robert 		if (adjtime(&adjtv, &oadjtv) < 0) {
2058c0b746e5SOllivier Robert 			msyslog(LOG_ERR, "Can't adjust the time of day: %m");
2059c0b746e5SOllivier Robert 			exit(1);
2060c0b746e5SOllivier Robert 		}
2061c0b746e5SOllivier Robert #else	/* SYS_WINNT or SYS_CYGWIN32 is defined */
2062c0b746e5SOllivier Robert 		/*
2063c0b746e5SOllivier Robert 		 * The NT SetSystemTimeAdjustment() call achieves slewing by
2064c0b746e5SOllivier Robert 		 * changing the clock frequency. This means that we cannot specify
2065c0b746e5SOllivier Robert 		 * it to slew the clock by a definite amount and then stop like
2066c0b746e5SOllivier Robert 		 * the Unix adjtime() routine. We can technically adjust the clock
2067c0b746e5SOllivier Robert 		 * frequency, have ntpdate sleep for a while, and then wake
2068c0b746e5SOllivier Robert 		 * up and reset the clock frequency, but this might cause some
2069c0b746e5SOllivier Robert 		 * grief if the user attempts to run ntpd immediately after
2070c0b746e5SOllivier Robert 		 * ntpdate and the socket is in use.
2071c0b746e5SOllivier Robert 		 */
2072c0b746e5SOllivier Robert 		printf("\nSlewing the system time is not supported on Windows. Use the -b option to step the time.\n");
2073c0b746e5SOllivier Robert #endif	/* defined SYS_WINNT || defined SYS_CYGWIN32 */
2074c0b746e5SOllivier Robert 	}
2075c0b746e5SOllivier Robert 	return 1;
2076c0b746e5SOllivier Robert }
2077c0b746e5SOllivier Robert 
2078c0b746e5SOllivier Robert 
2079c0b746e5SOllivier Robert /*
2080c0b746e5SOllivier Robert  * This fuction is not the same as lib/systime step_systime!!!
2081c0b746e5SOllivier Robert  */
2082c0b746e5SOllivier Robert static int
l_step_systime(l_fp * ts)2083c0b746e5SOllivier Robert l_step_systime(
2084c0b746e5SOllivier Robert 	l_fp *ts
20859c2daa00SOllivier Robert 	)
2086c0b746e5SOllivier Robert {
2087c0b746e5SOllivier Robert 	double dtemp;
2088c0b746e5SOllivier Robert 
2089c0b746e5SOllivier Robert #ifdef SLEWALWAYS
2090c0b746e5SOllivier Robert #ifdef STEP_SLEW
20919c2daa00SOllivier Robert 	l_fp ftmp;
2092c0b746e5SOllivier Robert 	int isneg;
2093c0b746e5SOllivier Robert 	int n;
2094c0b746e5SOllivier Robert 
2095c0b746e5SOllivier Robert 	if (debug)
2096c0b746e5SOllivier Robert 		return 1;
2097c0b746e5SOllivier Robert 
2098c0b746e5SOllivier Robert 	/*
2099c0b746e5SOllivier Robert 	 * Take the absolute value of the offset
2100c0b746e5SOllivier Robert 	 */
2101c0b746e5SOllivier Robert 	ftmp = *ts;
2102c0b746e5SOllivier Robert 
2103c0b746e5SOllivier Robert 	if (L_ISNEG(&ftmp)) {
21049c2daa00SOllivier Robert 		L_NEG(&ftmp);
2105c0b746e5SOllivier Robert 		isneg = 1;
2106c0b746e5SOllivier Robert 	} else
2107c0b746e5SOllivier Robert 		isneg = 0;
2108c0b746e5SOllivier Robert 
2109c0b746e5SOllivier Robert 	if (ftmp.l_ui >= 3) {		/* Step it and slew - we might win */
2110c0b746e5SOllivier Robert 		LFPTOD(ts, dtemp);
2111c0b746e5SOllivier Robert 		n = step_systime(dtemp);
2112c0b746e5SOllivier Robert 		if (n == 0)
2113c0b746e5SOllivier Robert 			return 0;
2114c0b746e5SOllivier Robert 		if (isneg)		/* WTF! */
2115c0b746e5SOllivier Robert 			ts->l_ui = ~0;
2116c0b746e5SOllivier Robert 		else
2117c0b746e5SOllivier Robert 			ts->l_ui = ~0;
2118c0b746e5SOllivier Robert 	}
2119c0b746e5SOllivier Robert 	/*
2120c0b746e5SOllivier Robert 	 * Just add adjustment into the current offset.  The update
2121c0b746e5SOllivier Robert 	 * routine will take care of bringing the system clock into
2122c0b746e5SOllivier Robert 	 * line.
2123c0b746e5SOllivier Robert 	 */
2124c0b746e5SOllivier Robert #endif
2125c0b746e5SOllivier Robert 	if (debug)
2126c0b746e5SOllivier Robert 		return 1;
2127c0b746e5SOllivier Robert #ifdef FORCE_NTPDATE_STEP
2128c0b746e5SOllivier Robert 	LFPTOD(ts, dtemp);
2129c0b746e5SOllivier Robert 	return step_systime(dtemp);
2130c0b746e5SOllivier Robert #else
2131c0b746e5SOllivier Robert 	l_adj_systime(ts);
2132c0b746e5SOllivier Robert 	return 1;
2133c0b746e5SOllivier Robert #endif
2134c0b746e5SOllivier Robert #else /* SLEWALWAYS */
2135c0b746e5SOllivier Robert 	if (debug)
2136c0b746e5SOllivier Robert 		return 1;
2137c0b746e5SOllivier Robert 	LFPTOD(ts, dtemp);
2138c0b746e5SOllivier Robert 	return step_systime(dtemp);
2139c0b746e5SOllivier Robert #endif	/* SLEWALWAYS */
2140c0b746e5SOllivier Robert }
2141c0b746e5SOllivier Robert 
2142c0b746e5SOllivier Robert 
2143c0b746e5SOllivier Robert /* XXX ELIMINATE print_server similar in ntptrace.c, ntpdate.c */
2144c0b746e5SOllivier Robert /*
2145c0b746e5SOllivier Robert  * print_server - print detail information for a server
2146c0b746e5SOllivier Robert  */
2147c0b746e5SOllivier Robert static void
print_server(register struct server * pp,FILE * fp)2148c0b746e5SOllivier Robert print_server(
2149c0b746e5SOllivier Robert 	register struct server *pp,
2150c0b746e5SOllivier Robert 	FILE *fp
2151c0b746e5SOllivier Robert 	)
2152c0b746e5SOllivier Robert {
2153c0b746e5SOllivier Robert 	register int i;
2154c0b746e5SOllivier Robert 	char junk[5];
2155c0b746e5SOllivier Robert 	const char *str;
2156c0b746e5SOllivier Robert 
2157c0b746e5SOllivier Robert 	if (pp->stratum == 0)		/* Nothing received => nothing to print */
2158c0b746e5SOllivier Robert 		return;
2159c0b746e5SOllivier Robert 
2160c0b746e5SOllivier Robert 	if (!debug) {
2161c0b746e5SOllivier Robert 		(void) fprintf(fp, "server %s, stratum %d, offset %s, delay %s\n",
2162c0b746e5SOllivier Robert 				   stoa(&pp->srcadr), pp->stratum,
2163c0b746e5SOllivier Robert 				   lfptoa(&pp->offset, 6), fptoa((s_fp)pp->delay, 5));
2164c0b746e5SOllivier Robert 		return;
2165c0b746e5SOllivier Robert 	}
2166c0b746e5SOllivier Robert 
2167c0b746e5SOllivier Robert 	(void) fprintf(fp, "server %s, port %d\n",
2168c0b746e5SOllivier Robert 			   stoa(&pp->srcadr), ntohs(((struct sockaddr_in*)&(pp->srcadr))->sin_port));
2169c0b746e5SOllivier Robert 
2170c0b746e5SOllivier Robert 	(void) fprintf(fp, "stratum %d, precision %d, leap %c%c, trust %03o\n",
2171c0b746e5SOllivier Robert 			   pp->stratum, pp->precision,
2172c0b746e5SOllivier Robert 			   pp->leap & 0x2 ? '1' : '0',
2173c0b746e5SOllivier Robert 			   pp->leap & 0x1 ? '1' : '0',
2174c0b746e5SOllivier Robert 			   pp->trust);
2175c0b746e5SOllivier Robert 
2176c0b746e5SOllivier Robert 	if (REFID_ISTEXT(pp->stratum)) {
2177c0b746e5SOllivier Robert 		str = (char *) &pp->refid;
2178c0b746e5SOllivier Robert 		for (i=0; i<4 && str[i]; i++) {
2179c0b746e5SOllivier Robert 			junk[i] = (isprint(str[i]) ? str[i] : '.');
2180c0b746e5SOllivier Robert 		}
2181c0b746e5SOllivier Robert 		junk[i] = 0; // force terminating 0
2182c0b746e5SOllivier Robert 		str = junk;
2183c0b746e5SOllivier Robert 	} else {
2184c0b746e5SOllivier Robert 		str = numtoa(pp->refid);
2185c0b746e5SOllivier Robert 	}
2186c0b746e5SOllivier Robert 	(void) fprintf(fp,
2187c0b746e5SOllivier Robert 			"refid [%s], root delay %s, root dispersion %s\n",
2188c0b746e5SOllivier Robert 			str, fptoa((s_fp)pp->rootdelay, 6),
2189c0b746e5SOllivier Robert 			ufptoa(pp->rootdisp, 6));
2190c0b746e5SOllivier Robert 
2191c0b746e5SOllivier Robert 	if (pp->xmtcnt != pp->filter_nextpt)
2192c0b746e5SOllivier Robert 		(void) fprintf(fp, "transmitted %d, in filter %d\n",
2193c0b746e5SOllivier Robert 			   pp->xmtcnt, pp->filter_nextpt);
2194c0b746e5SOllivier Robert 
2195c0b746e5SOllivier Robert 	(void) fprintf(fp, "reference time:      %s\n",
2196c0b746e5SOllivier Robert 			   prettydate(&pp->reftime));
2197c0b746e5SOllivier Robert 	(void) fprintf(fp, "originate timestamp: %s\n",
2198c0b746e5SOllivier Robert 			   prettydate(&pp->org));
2199c0b746e5SOllivier Robert 	(void) fprintf(fp, "transmit timestamp:  %s\n",
2200c0b746e5SOllivier Robert 			   prettydate(&pp->xmt));
2201c0b746e5SOllivier Robert 
2202c0b746e5SOllivier Robert 	if (sys_samples > 1) {
2203c0b746e5SOllivier Robert 		(void) fprintf(fp, "filter delay: ");
2204c0b746e5SOllivier Robert 		for (i = 0; i < NTP_SHIFT; i++) {
2205c0b746e5SOllivier Robert 			if (i == (NTP_SHIFT>>1))
2206c0b746e5SOllivier Robert 				(void) fprintf(fp, "\n              ");
2207c0b746e5SOllivier Robert 			(void) fprintf(fp, " %-10.10s",
2208c0b746e5SOllivier Robert 				(i<sys_samples ? fptoa(pp->filter_delay[i], 5) : "----"));
2209c0b746e5SOllivier Robert 		}
2210c0b746e5SOllivier Robert 		(void) fprintf(fp, "\n");
2211c0b746e5SOllivier Robert 
2212c0b746e5SOllivier Robert 		(void) fprintf(fp, "filter offset:");
2213c0b746e5SOllivier Robert 		for (i = 0; i < PEER_SHIFT; i++) {
2214c0b746e5SOllivier Robert 			if (i == (PEER_SHIFT>>1))
2215c0b746e5SOllivier Robert 				(void) fprintf(fp, "\n              ");
2216c0b746e5SOllivier Robert 			(void) fprintf(fp, " %-10.10s",
2217c0b746e5SOllivier Robert 				(i<sys_samples ? lfptoa(&pp->filter_offset[i], 6): "----"));
2218c0b746e5SOllivier Robert 		}
2219c0b746e5SOllivier Robert 		(void) fprintf(fp, "\n");
2220c0b746e5SOllivier Robert 	}
2221c0b746e5SOllivier Robert 
2222c0b746e5SOllivier Robert 	(void) fprintf(fp, "delay %s, dispersion %s, ",
2223c0b746e5SOllivier Robert 			   fptoa((s_fp)pp->delay, 5), ufptoa(pp->dispersion, 5));
2224c0b746e5SOllivier Robert 
2225c0b746e5SOllivier Robert 	(void) fprintf(fp, "offset %s\n\n",
2226 			   lfptoa(&pp->offset, 6));
2227 }
2228 
2229 
2230 #ifdef HAVE_NETINFO
2231 static ni_namelist *
getnetinfoservers(void)2232 getnetinfoservers(void)
2233 {
2234 	ni_status status;
2235 	void *domain;
2236 	ni_id confdir;
2237 	ni_namelist *namelist = emalloc(sizeof(ni_namelist));
2238 
2239 	/* Find a time server in NetInfo */
2240 	if ((status = ni_open(NULL, ".", &domain)) != NI_OK) return NULL;
2241 
2242 	while (status = ni_pathsearch(domain, &confdir, NETINFO_CONFIG_DIR) == NI_NODIR) {
2243 		void *next_domain;
2244 		if (ni_open(domain, "..", &next_domain) != NI_OK) break;
2245 		ni_free(domain);
2246 		domain = next_domain;
2247 	}
2248 	if (status != NI_OK) return NULL;
2249 
2250 	NI_INIT(namelist);
2251 	if (ni_lookupprop(domain, &confdir, "server", namelist) != NI_OK) {
2252 		ni_namelist_free(namelist);
2253 		free(namelist);
2254 		return NULL;
2255 	}
2256 
2257 	return(namelist);
2258 }
2259 #endif
2260 
2261 #ifdef SYS_WINNT
ntp_port_inuse(int af,u_short port)2262 isc_boolean_t ntp_port_inuse(int af, u_short port)
2263 {
2264 	/*
2265 	 * Check if NTP socket is already in use on this system
2266 	 * This is only for Windows Systems, as they tend not to fail on the real bind() below
2267 	 */
2268 
2269 	SOCKET checksocket;
2270 	struct sockaddr_in checkservice;
2271 	checksocket = socket(af, SOCK_DGRAM, 0);
2272 	if (checksocket == INVALID_SOCKET) {
2273 		return (ISC_TRUE);
2274 	}
2275 
2276 	checkservice.sin_family = (short) AF_INET;
2277 	checkservice.sin_addr.s_addr = INADDR_LOOPBACK;
2278 	checkservice.sin_port = htons(port);
2279 
2280 	if (bind(checksocket, (struct sockaddr *)&checkservice,
2281 		sizeof(checkservice)) == SOCKET_ERROR) {
2282 		if ( WSAGetLastError() == WSAEADDRINUSE ){
2283 			closesocket(checksocket);
2284 			return (ISC_TRUE);
2285 		}
2286 	}
2287 	closesocket(checksocket);
2288 	return (ISC_FALSE);
2289 }
2290 #endif
2291