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