154359Sroberto/*
254359Sroberto * ntpdate - set the time of day by polling one or more NTP servers
354359Sroberto */
454359Sroberto
554359Sroberto#ifdef HAVE_CONFIG_H
654359Sroberto# include <config.h>
754359Sroberto#endif
854359Sroberto
982498Sroberto#ifdef HAVE_NETINFO
1082498Sroberto#include <netinfo/ni.h>
1154359Sroberto#endif
1282498Sroberto
13106163Sroberto#include "ntp_machine.h"
1482498Sroberto#include "ntp_fp.h"
1582498Sroberto#include "ntp.h"
1682498Sroberto#include "ntp_io.h"
17285612Sdelphij#include "timevalops.h"
1882498Sroberto#include "ntpdate.h"
1982498Sroberto#include "ntp_string.h"
2082498Sroberto#include "ntp_syslog.h"
2182498Sroberto#include "ntp_select.h"
2282498Sroberto#include "ntp_stdlib.h"
23285612Sdelphij#include <ssl_applink.c>
2482498Sroberto
25182007Sroberto#include "isc/net.h"
26182007Sroberto#include "isc/result.h"
27182007Sroberto#include "isc/sockaddr.h"
28182007Sroberto
2954359Sroberto#ifdef HAVE_UNISTD_H
3054359Sroberto# include <unistd.h>
3154359Sroberto#endif
3254359Sroberto
3354359Sroberto#include <stdio.h>
3454359Sroberto#include <signal.h>
3554359Sroberto#include <ctype.h>
3654359Sroberto#ifdef HAVE_POLL_H
3782498Sroberto# include <poll.h>
3854359Sroberto#endif
39285612Sdelphij#ifdef HAVE_SYS_SIGNAL_H
40285612Sdelphij# include <sys/signal.h>
41285612Sdelphij#endif
42285612Sdelphij#ifdef HAVE_SYS_IOCTL_H
43285612Sdelphij# include <sys/ioctl.h>
44285612Sdelphij#endif
4554359Sroberto#ifdef HAVE_SYS_RESOURCE_H
4654359Sroberto# include <sys/resource.h>
47285612Sdelphij#endif
4854359Sroberto
49132451Sroberto#include <arpa/inet.h>
50132451Sroberto
5154359Sroberto#ifdef SYS_VXWORKS
5254359Sroberto# include "ioLib.h"
5354359Sroberto# include "sockLib.h"
5454359Sroberto# include "timers.h"
5554359Sroberto
5654359Sroberto/* select wants a zero structure ... */
5754359Srobertostruct timeval timeout = {0,0};
58182007Sroberto#elif defined(SYS_WINNT)
59182007Sroberto/*
60182007Sroberto * Windows does not abort a select select call if SIGALRM goes off
61285612Sdelphij * so a 200 ms timeout is needed (TIMER_HZ is 5).
62182007Sroberto */
63285612Sdelphijstruct sock_timeval timeout = {0,1000000/TIMER_HZ};
6454359Sroberto#else
6554359Srobertostruct timeval timeout = {60,0};
6654359Sroberto#endif
6754359Sroberto
68132451Sroberto#ifdef HAVE_NETINFO
69132451Sroberto#include <netinfo/ni.h>
70132451Sroberto#endif
71132451Sroberto
7254359Sroberto#include "recvbuff.h"
7354359Sroberto
7454359Sroberto#ifdef SYS_WINNT
75132451Sroberto#define TARGET_RESOLUTION 1  /* Try for 1-millisecond accuracy
7654359Sroberto				on Windows NT timers. */
7754359Sroberto#pragma comment(lib, "winmm")
78182007Srobertoisc_boolean_t ntp_port_inuse(int af, u_short port);
79182007SrobertoUINT wTimerRes;
8054359Sroberto#endif /* SYS_WINNT */
8154359Sroberto
8254359Sroberto/*
8354359Sroberto * Scheduling priority we run at
8454359Sroberto */
8554359Sroberto#ifndef SYS_VXWORKS
8654359Sroberto# define	NTPDATE_PRIO	(-12)
8754359Sroberto#else
8854359Sroberto# define	NTPDATE_PRIO	(100)
8954359Sroberto#endif
9054359Sroberto
91285612Sdelphij#ifdef HAVE_TIMER_CREATE
9254359Sroberto/* POSIX TIMERS - vxWorks doesn't have itimer - casey */
9354359Srobertostatic timer_t ntpdate_timerid;
9454359Sroberto#endif
9554359Sroberto
9654359Sroberto/*
9754359Sroberto * Compatibility stuff for Version 2
9854359Sroberto */
9954359Sroberto#define NTP_MAXSKW	0x28f	/* 0.01 sec in fp format */
100182007Sroberto#define NTP_MINDIST	0x51f	/* 0.02 sec in fp format */
10154359Sroberto#define PEER_MAXDISP	(64*FP_SECOND)	/* maximum dispersion (fp 64) */
10254359Sroberto#define NTP_INFIN	15	/* max stratum, infinity a la Bellman-Ford */
10354359Sroberto#define NTP_MAXWGT	(8*FP_SECOND)	/* maximum select weight 8 seconds */
104182007Sroberto#define NTP_MAXLIST	5	/* maximum select list size */
10554359Sroberto#define PEER_SHIFT	8	/* 8 suitable for crystal time base */
10654359Sroberto
10754359Sroberto/*
108182007Sroberto * for get_systime()
109182007Sroberto */
110182007Srobertos_char	sys_precision;		/* local clock precision (log2 s) */
111182007Sroberto
112182007Sroberto/*
11354359Sroberto * File descriptor masks etc. for call to select
11454359Sroberto */
115132451Sroberto
116132451Srobertoint ai_fam_templ;
117285612Sdelphijint nbsock;			/* the number of sockets used */
118182007SrobertoSOCKET fd[MAX_AF];
119285612Sdelphijint fd_family[MAX_AF];		/* to remember the socket family */
12054359Sroberto#ifdef HAVE_POLL_H
121132451Srobertostruct pollfd fdmask[MAX_AF];
12254359Sroberto#else
12354359Srobertofd_set fdmask;
124182007SrobertoSOCKET maxfd;
12554359Sroberto#endif
126132451Srobertoint polltest = 0;
12754359Sroberto
12854359Sroberto/*
12954359Sroberto * Initializing flag.  All async routines watch this and only do their
13054359Sroberto * thing when it is clear.
13154359Sroberto */
13254359Srobertoint initializing = 1;
13354359Sroberto
13454359Sroberto/*
13554359Sroberto * Alarm flag.	Set when an alarm occurs
13654359Sroberto */
13754359Srobertovolatile int alarm_flag = 0;
13854359Sroberto
13954359Sroberto/*
14054359Sroberto * Simple query flag.
14154359Sroberto */
14254359Srobertoint simple_query = 0;
14354359Sroberto
14454359Sroberto/*
145182007Sroberto * Unprivileged port flag.
14654359Sroberto */
14754359Srobertoint unpriv_port = 0;
14854359Sroberto
14954359Sroberto/*
15054359Sroberto * Program name.
15154359Sroberto */
152289997Sglebiuschar const *progname;
15354359Sroberto
15454359Sroberto/*
15554359Sroberto * Systemwide parameters and flags
15654359Sroberto */
15754359Srobertoint sys_samples = DEFSAMPLES;	/* number of samples/server */
15854359Srobertou_long sys_timeout = DEFTIMEOUT; /* timeout time, in TIMER_HZ units */
15956746Srobertostruct server *sys_servers;	/* the server list */
16054359Srobertoint sys_numservers = 0; 	/* number of servers to poll */
16154359Srobertoint sys_authenticate = 0;	/* true when authenticating */
16254359Srobertou_int32 sys_authkey = 0;	/* set to authentication key in use */
16354359Srobertou_long sys_authdelay = 0;	/* authentication delay */
16454359Srobertoint sys_version = NTP_VERSION;	/* version to poll with */
16554359Sroberto
16654359Sroberto/*
16754359Sroberto * The current internal time
16854359Sroberto */
16954359Srobertou_long current_time = 0;
17054359Sroberto
17154359Sroberto/*
17254359Sroberto * Counter for keeping track of completed servers
17354359Sroberto */
17454359Srobertoint complete_servers = 0;
17554359Sroberto
17654359Sroberto/*
17754359Sroberto * File of encryption keys
17854359Sroberto */
17954359Sroberto
18054359Sroberto#ifndef KEYFILE
18154359Sroberto# ifndef SYS_WINNT
18254359Sroberto#define KEYFILE 	"/etc/ntp.keys"
18354359Sroberto# else
18454359Sroberto#define KEYFILE 	"%windir%\\ntp.keys"
18554359Sroberto# endif /* SYS_WINNT */
18654359Sroberto#endif /* KEYFILE */
18754359Sroberto
18854359Sroberto#ifndef SYS_WINNT
18954359Srobertoconst char *key_file = KEYFILE;
19054359Sroberto#else
19154359Srobertochar key_file_storage[MAX_PATH+1], *key_file ;
19254359Sroberto#endif	 /* SYS_WINNT */
19354359Sroberto
19454359Sroberto/*
19554359Sroberto * Miscellaneous flags
19654359Sroberto */
19754359Srobertoint verbose = 0;
19854359Srobertoint always_step = 0;
19954359Srobertoint never_step = 0;
20054359Sroberto
201285612Sdelphijint 	ntpdatemain (int, char **);
202132451Sroberto
203285612Sdelphijstatic	void	transmit	(struct server *);
204285612Sdelphijstatic	void	receive 	(struct recvbuf *);
205285612Sdelphijstatic	void	server_data (struct server *, s_fp, l_fp *, u_fp);
206285612Sdelphijstatic	void	clock_filter	(struct server *);
207285612Sdelphijstatic	struct server *clock_select (void);
208285612Sdelphijstatic	int clock_adjust	(void);
209285612Sdelphijstatic	void	addserver	(char *);
210285612Sdelphijstatic	struct server *findserver (sockaddr_u *);
211285612Sdelphij		void	timer		(void);
212285612Sdelphijstatic	void	init_alarm	(void);
21354359Sroberto#ifndef SYS_WINNT
214285612Sdelphijstatic	RETSIGTYPE alarming (int);
21554359Sroberto#endif /* SYS_WINNT */
216285612Sdelphijstatic	void	init_io 	(void);
217285612Sdelphijstatic	void	sendpkt 	(sockaddr_u *, struct pkt *, int);
218285612Sdelphijvoid	input_handler	(void);
21954359Sroberto
220285612Sdelphijstatic	int l_adj_systime	(l_fp *);
221285612Sdelphijstatic	int l_step_systime	(l_fp *);
22254359Sroberto
223285612Sdelphijstatic	void	printserver (struct server *, FILE *);
22454359Sroberto
22554359Sroberto#ifdef SYS_WINNT
22654359Srobertoint 	on = 1;
22754359SrobertoWORD	wVersionRequested;
228182007SrobertoWSADATA	wsaData;
22954359Sroberto#endif /* SYS_WINNT */
23054359Sroberto
23154359Sroberto#ifdef NO_MAIN_ALLOWED
23254359SrobertoCALL(ntpdate,"ntpdate",ntpdatemain);
23354359Sroberto
23454359Srobertovoid clear_globals()
23554359Sroberto{
23654359Sroberto  /*
23754359Sroberto   * Debugging flag
23854359Sroberto   */
23954359Sroberto  debug = 0;
24054359Sroberto
24154359Sroberto  ntp_optind = 0;
24254359Sroberto  /*
24354359Sroberto   * Initializing flag.  All async routines watch this and only do their
24454359Sroberto   * thing when it is clear.
24554359Sroberto   */
24654359Sroberto  initializing = 1;
24754359Sroberto
24854359Sroberto  /*
24954359Sroberto   * Alarm flag.  Set when an alarm occurs
25054359Sroberto   */
25154359Sroberto  alarm_flag = 0;
25254359Sroberto
25354359Sroberto  /*
25454359Sroberto   * Simple query flag.
25554359Sroberto   */
25654359Sroberto  simple_query = 0;
25754359Sroberto
25854359Sroberto  /*
259182007Sroberto   * Unprivileged port flag.
26054359Sroberto   */
26154359Sroberto  unpriv_port = 0;
26254359Sroberto
26354359Sroberto  /*
26454359Sroberto   * Systemwide parameters and flags
26554359Sroberto   */
26654359Sroberto  sys_numservers = 0;	  /* number of servers to poll */
26754359Sroberto  sys_authenticate = 0;   /* true when authenticating */
26854359Sroberto  sys_authkey = 0;	   /* set to authentication key in use */
26954359Sroberto  sys_authdelay = 0;   /* authentication delay */
27054359Sroberto  sys_version = NTP_VERSION;  /* version to poll with */
27154359Sroberto
27254359Sroberto  /*
27354359Sroberto   * The current internal time
27454359Sroberto   */
27554359Sroberto  current_time = 0;
27654359Sroberto
27754359Sroberto  /*
27854359Sroberto   * Counter for keeping track of completed servers
27954359Sroberto   */
28054359Sroberto  complete_servers = 0;
28154359Sroberto  verbose = 0;
28254359Sroberto  always_step = 0;
28354359Sroberto  never_step = 0;
28454359Sroberto}
28554359Sroberto#endif
28654359Sroberto
28754359Sroberto#ifdef HAVE_NETINFO
288285612Sdelphijstatic ni_namelist *getnetinfoservers (void);
28954359Sroberto#endif
29054359Sroberto
29154359Sroberto/*
29254359Sroberto * Main program.  Initialize us and loop waiting for I/O and/or
29354359Sroberto * timer expiries.
29454359Sroberto */
29554359Sroberto#ifndef NO_MAIN_ALLOWED
29654359Srobertoint
29754359Srobertomain(
29854359Sroberto	int argc,
29954359Sroberto	char *argv[]
30054359Sroberto	)
30154359Sroberto{
30254359Sroberto	return ntpdatemain (argc, argv);
30354359Sroberto}
30454359Sroberto#endif /* NO_MAIN_ALLOWED */
30554359Sroberto
30654359Srobertoint
30754359Srobertontpdatemain (
30854359Sroberto	int argc,
30954359Sroberto	char *argv[]
31054359Sroberto	)
31154359Sroberto{
31254359Sroberto	int was_alarmed;
313182007Sroberto	int tot_recvbufs;
31454359Sroberto	struct recvbuf *rbuf;
31554359Sroberto	l_fp tmp;
31654359Sroberto	int errflg;
31754359Sroberto	int c;
318182007Sroberto	int nfound;
319132451Sroberto
32054359Sroberto#ifdef HAVE_NETINFO
32154359Sroberto	ni_namelist *netinfoservers;
32254359Sroberto#endif
32354359Sroberto#ifdef SYS_WINNT
32454359Sroberto	key_file = key_file_storage;
32554359Sroberto
32654359Sroberto	if (!ExpandEnvironmentStrings(KEYFILE, key_file, MAX_PATH))
327285612Sdelphij		msyslog(LOG_ERR, "ExpandEnvironmentStrings(KEYFILE) failed: %m");
328285612Sdelphij
329285612Sdelphij	ssl_applink();
33054359Sroberto#endif /* SYS_WINNT */
33154359Sroberto
33254359Sroberto#ifdef NO_MAIN_ALLOWED
33354359Sroberto	clear_globals();
33454359Sroberto#endif
33554359Sroberto
336285612Sdelphij	init_lib();	/* sets up ipv4_works, ipv6_works */
337182007Sroberto
338285612Sdelphij	/* Check to see if we have IPv6. Otherwise default to IPv4 */
339285612Sdelphij	if (!ipv6_works)
340182007Sroberto		ai_fam_templ = AF_INET;
341182007Sroberto
34254359Sroberto	errflg = 0;
34354359Sroberto	progname = argv[0];
34454359Sroberto	syslogit = 0;
34554359Sroberto
34654359Sroberto	/*
34754359Sroberto	 * Decode argument list
34854359Sroberto	 */
349182007Sroberto	while ((c = ntp_getopt(argc, argv, "46a:bBde:k:o:p:qst:uv")) != EOF)
35054359Sroberto		switch (c)
35154359Sroberto		{
352132451Sroberto		case '4':
353132451Sroberto			ai_fam_templ = AF_INET;
354132451Sroberto			break;
355132451Sroberto		case '6':
356132451Sroberto			ai_fam_templ = AF_INET6;
357132451Sroberto			break;
35854359Sroberto		case 'a':
35954359Sroberto			c = atoi(ntp_optarg);
36054359Sroberto			sys_authenticate = 1;
36154359Sroberto			sys_authkey = c;
36254359Sroberto			break;
36354359Sroberto		case 'b':
36454359Sroberto			always_step++;
36554359Sroberto			never_step = 0;
36654359Sroberto			break;
36754359Sroberto		case 'B':
36854359Sroberto			never_step++;
36954359Sroberto			always_step = 0;
37054359Sroberto			break;
37154359Sroberto		case 'd':
37254359Sroberto			++debug;
37354359Sroberto			break;
37454359Sroberto		case 'e':
37554359Sroberto			if (!atolfp(ntp_optarg, &tmp)
37654359Sroberto			|| tmp.l_ui != 0) {
37754359Sroberto				(void) fprintf(stderr,
37854359Sroberto					   "%s: encryption delay %s is unlikely\n",
37954359Sroberto					   progname, ntp_optarg);
38054359Sroberto				errflg++;
38154359Sroberto			} else {
38254359Sroberto				sys_authdelay = tmp.l_uf;
38354359Sroberto			}
38454359Sroberto			break;
38554359Sroberto		case 'k':
38654359Sroberto			key_file = ntp_optarg;
38754359Sroberto			break;
38854359Sroberto		case 'o':
38954359Sroberto			sys_version = atoi(ntp_optarg);
39054359Sroberto			break;
39154359Sroberto		case 'p':
39254359Sroberto			c = atoi(ntp_optarg);
39354359Sroberto			if (c <= 0 || c > NTP_SHIFT) {
39454359Sroberto				(void) fprintf(stderr,
39554359Sroberto					   "%s: number of samples (%d) is invalid\n",
39654359Sroberto					   progname, c);
39754359Sroberto				errflg++;
39854359Sroberto			} else {
39954359Sroberto				sys_samples = c;
40054359Sroberto			}
40154359Sroberto			break;
40254359Sroberto		case 'q':
40354359Sroberto			simple_query = 1;
40454359Sroberto			break;
40554359Sroberto		case 's':
40654359Sroberto			syslogit = 1;
40754359Sroberto			break;
40854359Sroberto		case 't':
40954359Sroberto			if (!atolfp(ntp_optarg, &tmp)) {
41054359Sroberto				(void) fprintf(stderr,
41154359Sroberto					   "%s: timeout %s is undecodeable\n",
41254359Sroberto					   progname, ntp_optarg);
41354359Sroberto				errflg++;
41454359Sroberto			} else {
41554359Sroberto				sys_timeout = ((LFPTOFP(&tmp) * TIMER_HZ)
41654359Sroberto					   + 0x8000) >> 16;
417285612Sdelphij				sys_timeout = max(sys_timeout, MINTIMEOUT);
41854359Sroberto			}
41954359Sroberto			break;
42054359Sroberto		case 'v':
42154359Sroberto			verbose = 1;
42254359Sroberto			break;
42354359Sroberto		case 'u':
42454359Sroberto			unpriv_port = 1;
42554359Sroberto			break;
42654359Sroberto		case '?':
42754359Sroberto			++errflg;
42854359Sroberto			break;
42954359Sroberto		default:
43054359Sroberto			break;
43154359Sroberto	    }
43254359Sroberto
43354359Sroberto	if (errflg) {
43454359Sroberto		(void) fprintf(stderr,
435182007Sroberto		    "usage: %s [-46bBdqsuv] [-a key#] [-e delay] [-k file] [-p samples] [-o version#] [-t timeo] server ...\n",
436132451Sroberto		    progname);
43754359Sroberto		exit(2);
43854359Sroberto	}
43954359Sroberto
44054359Sroberto	if (debug || simple_query) {
44154359Sroberto#ifdef HAVE_SETVBUF
44254359Sroberto		static char buf[BUFSIZ];
44354359Sroberto		setvbuf(stdout, buf, _IOLBF, BUFSIZ);
44454359Sroberto#else
44554359Sroberto		setlinebuf(stdout);
44654359Sroberto#endif
44754359Sroberto	}
44854359Sroberto
44954359Sroberto	/*
45054359Sroberto	 * Logging.  Open the syslog if we have to
45154359Sroberto	 */
45254359Sroberto	if (syslogit) {
45354359Sroberto#if !defined (SYS_WINNT) && !defined (SYS_VXWORKS) && !defined SYS_CYGWIN32
45454359Sroberto# ifndef	LOG_DAEMON
45554359Sroberto		openlog("ntpdate", LOG_PID);
45654359Sroberto# else
45754359Sroberto
45854359Sroberto#  ifndef	LOG_NTP
45954359Sroberto#	define	LOG_NTP LOG_DAEMON
46054359Sroberto#  endif
46154359Sroberto		openlog("ntpdate", LOG_PID | LOG_NDELAY, LOG_NTP);
46254359Sroberto		if (debug)
46354359Sroberto			setlogmask(LOG_UPTO(LOG_DEBUG));
46454359Sroberto		else
46554359Sroberto			setlogmask(LOG_UPTO(LOG_INFO));
46654359Sroberto# endif /* LOG_DAEMON */
46754359Sroberto#endif	/* SYS_WINNT */
46854359Sroberto	}
46954359Sroberto
47054359Sroberto	if (debug || verbose)
47154359Sroberto		msyslog(LOG_NOTICE, "%s", Version);
47254359Sroberto
47354359Sroberto	/*
47454359Sroberto	 * Add servers we are going to be polling
47554359Sroberto	 */
47654359Sroberto#ifdef HAVE_NETINFO
47782498Sroberto	netinfoservers = getnetinfoservers();
47854359Sroberto#endif
47954359Sroberto
48054359Sroberto	for ( ; ntp_optind < argc; ntp_optind++)
48154359Sroberto		addserver(argv[ntp_optind]);
48254359Sroberto
48354359Sroberto#ifdef HAVE_NETINFO
48454359Sroberto	if (netinfoservers) {
48554359Sroberto		if ( netinfoservers->ni_namelist_len &&
48654359Sroberto		    *netinfoservers->ni_namelist_val ) {
48754359Sroberto			u_int servercount = 0;
48854359Sroberto			while (servercount < netinfoservers->ni_namelist_len) {
48954359Sroberto				if (debug) msyslog(LOG_DEBUG,
49054359Sroberto						   "Adding time server %s from NetInfo configuration.",
49154359Sroberto						   netinfoservers->ni_namelist_val[servercount]);
49254359Sroberto				addserver(netinfoservers->ni_namelist_val[servercount++]);
49354359Sroberto			}
49454359Sroberto		}
49554359Sroberto		ni_namelist_free(netinfoservers);
49654359Sroberto		free(netinfoservers);
49754359Sroberto	}
49854359Sroberto#endif
49954359Sroberto
50054359Sroberto	if (sys_numservers == 0) {
50154359Sroberto		msyslog(LOG_ERR, "no servers can be used, exiting");
50254359Sroberto		exit(1);
50354359Sroberto	}
50454359Sroberto
50554359Sroberto	/*
50654359Sroberto	 * Initialize the time of day routines and the I/O subsystem
50754359Sroberto	 */
50854359Sroberto	if (sys_authenticate) {
50954359Sroberto		init_auth();
51054359Sroberto		if (!authreadkeys(key_file)) {
51182498Sroberto			msyslog(LOG_ERR, "no key file <%s>, exiting", key_file);
51254359Sroberto			exit(1);
51354359Sroberto		}
51482498Sroberto		authtrust(sys_authkey, 1);
51554359Sroberto		if (!authistrusted(sys_authkey)) {
516182007Sroberto			msyslog(LOG_ERR, "authentication key %lu unknown",
517182007Sroberto				(unsigned long) sys_authkey);
51854359Sroberto			exit(1);
51954359Sroberto		}
52054359Sroberto	}
52154359Sroberto	init_io();
52254359Sroberto	init_alarm();
52354359Sroberto
52454359Sroberto	/*
52554359Sroberto	 * Set the priority.
52654359Sroberto	 */
52754359Sroberto#ifdef SYS_VXWORKS
52854359Sroberto	taskPrioritySet( taskIdSelf(), NTPDATE_PRIO);
52954359Sroberto#endif
53054359Sroberto#if defined(HAVE_ATT_NICE)
53154359Sroberto	nice (NTPDATE_PRIO);
53254359Sroberto#endif
53354359Sroberto#if defined(HAVE_BSD_NICE)
53454359Sroberto	(void) setpriority(PRIO_PROCESS, 0, NTPDATE_PRIO);
53554359Sroberto#endif
53654359Sroberto
537132451Sroberto
53854359Sroberto	initializing = 0;
53954359Sroberto	was_alarmed = 0;
540132451Sroberto
54154359Sroberto	while (complete_servers < sys_numservers) {
54254359Sroberto#ifdef HAVE_POLL_H
543182007Sroberto		struct pollfd* rdfdes;
544182007Sroberto		rdfdes = fdmask;
54554359Sroberto#else
54654359Sroberto		fd_set rdfdes;
547182007Sroberto		rdfdes = fdmask;
54854359Sroberto#endif
54954359Sroberto
55054359Sroberto		if (alarm_flag) {		/* alarmed? */
55154359Sroberto			was_alarmed = 1;
55254359Sroberto			alarm_flag = 0;
55354359Sroberto		}
554182007Sroberto		tot_recvbufs = full_recvbuffs();	/* get received buffers */
55554359Sroberto
556182007Sroberto		if (!was_alarmed && tot_recvbufs == 0) {
55754359Sroberto			/*
55854359Sroberto			 * Nothing to do.	 Wait for something.
55954359Sroberto			 */
56054359Sroberto#ifdef HAVE_POLL_H
561182007Sroberto			nfound = poll(rdfdes, (unsigned int)nbsock, timeout.tv_sec * 1000);
562132451Sroberto
56354359Sroberto#else
564293650Sglebius			nfound = select(maxfd, &rdfdes, NULL, NULL,
565293650Sglebius					&timeout);
56654359Sroberto#endif
56754359Sroberto			if (nfound > 0)
56854359Sroberto				input_handler();
569182007Sroberto			else if (nfound == SOCKET_ERROR)
570182007Sroberto			{
57154359Sroberto#ifndef SYS_WINNT
572182007Sroberto				if (errno != EINTR)
57354359Sroberto#else
574182007Sroberto				if (WSAGetLastError() != WSAEINTR)
57554359Sroberto#endif
576285612Sdelphij					msyslog(LOG_ERR,
57754359Sroberto#ifdef HAVE_POLL_H
57854359Sroberto						"poll() error: %m"
57954359Sroberto#else
58054359Sroberto						"select() error: %m"
58154359Sroberto#endif
58254359Sroberto						);
583182007Sroberto			} else if (errno != 0) {
58454359Sroberto#ifndef SYS_VXWORKS
585285612Sdelphij				msyslog(LOG_DEBUG,
58654359Sroberto#ifdef HAVE_POLL_H
58754359Sroberto					"poll(): nfound = %d, error: %m",
58854359Sroberto#else
58954359Sroberto					"select(): nfound = %d, error: %m",
59054359Sroberto#endif
59154359Sroberto					nfound);
59254359Sroberto#endif
59354359Sroberto			}
59454359Sroberto			if (alarm_flag) {		/* alarmed? */
59554359Sroberto				was_alarmed = 1;
59654359Sroberto				alarm_flag = 0;
59754359Sroberto			}
598182007Sroberto			tot_recvbufs = full_recvbuffs();	/* get received buffers */
59954359Sroberto		}
60054359Sroberto
60154359Sroberto		/*
60254359Sroberto		 * Out here, signals are unblocked.  Call receive
60354359Sroberto		 * procedure for each incoming packet.
60454359Sroberto		 */
605182007Sroberto		rbuf = get_full_recv_buffer();
606182007Sroberto		while (rbuf != NULL)
607182007Sroberto		{
60854359Sroberto			receive(rbuf);
60954359Sroberto			freerecvbuf(rbuf);
610182007Sroberto			rbuf = get_full_recv_buffer();
61154359Sroberto		}
61254359Sroberto
61354359Sroberto		/*
61454359Sroberto		 * Call timer to process any timeouts
61554359Sroberto		 */
61654359Sroberto		if (was_alarmed) {
61754359Sroberto			timer();
61854359Sroberto			was_alarmed = 0;
61954359Sroberto		}
62054359Sroberto
62154359Sroberto		/*
62254359Sroberto		 * Go around again
62354359Sroberto		 */
62454359Sroberto	}
62554359Sroberto
62654359Sroberto	/*
62754359Sroberto	 * When we get here we've completed the polling of all servers.
62854359Sroberto	 * Adjust the clock, then exit.
62954359Sroberto	 */
63054359Sroberto#ifdef SYS_WINNT
63154359Sroberto	WSACleanup();
63254359Sroberto#endif
63354359Sroberto#ifdef SYS_VXWORKS
63454359Sroberto	close (fd);
63554359Sroberto	timer_delete(ntpdate_timerid);
63654359Sroberto#endif
637132451Sroberto
63854359Sroberto	return clock_adjust();
63954359Sroberto}
64054359Sroberto
64154359Sroberto
64254359Sroberto/*
64354359Sroberto * transmit - transmit a packet to the given server, or mark it completed.
644182007Sroberto *		This is called by the timeout routine and by the receive
645182007Sroberto *		procedure.
64654359Sroberto */
64754359Srobertostatic void
64854359Srobertotransmit(
64954359Sroberto	register struct server *server
65054359Sroberto	)
65154359Sroberto{
65254359Sroberto	struct pkt xpkt;
65354359Sroberto
65454359Sroberto	if (debug)
655285612Sdelphij		printf("transmit(%s)\n", stoa(&server->srcadr));
65654359Sroberto
65754359Sroberto	if (server->filter_nextpt < server->xmtcnt) {
65854359Sroberto		l_fp ts;
65954359Sroberto		/*
66054359Sroberto		 * Last message to this server timed out.  Shift
66154359Sroberto		 * zeros into the filter.
66254359Sroberto		 */
66354359Sroberto		L_CLR(&ts);
66454359Sroberto		server_data(server, 0, &ts, 0);
66554359Sroberto	}
66654359Sroberto
66754359Sroberto	if ((int)server->filter_nextpt >= sys_samples) {
66854359Sroberto		/*
66954359Sroberto		 * Got all the data we need.  Mark this guy
67054359Sroberto		 * completed and return.
67154359Sroberto		 */
67254359Sroberto		server->event_time = 0;
67354359Sroberto		complete_servers++;
67454359Sroberto		return;
67554359Sroberto	}
67654359Sroberto
67754359Sroberto	/*
678182007Sroberto	 * If we're here, send another message to the server.  Fill in
67954359Sroberto	 * the packet and let 'er rip.
68054359Sroberto	 */
68154359Sroberto	xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOTINSYNC,
68254359Sroberto					 sys_version, MODE_CLIENT);
68354359Sroberto	xpkt.stratum = STRATUM_TO_PKT(STRATUM_UNSPEC);
68454359Sroberto	xpkt.ppoll = NTP_MINPOLL;
68554359Sroberto	xpkt.precision = NTPDATE_PRECISION;
68654359Sroberto	xpkt.rootdelay = htonl(NTPDATE_DISTANCE);
687285612Sdelphij	xpkt.rootdisp = htonl(NTPDATE_DISP);
68854359Sroberto	xpkt.refid = htonl(NTPDATE_REFID);
68954359Sroberto	L_CLR(&xpkt.reftime);
69054359Sroberto	L_CLR(&xpkt.org);
69154359Sroberto	L_CLR(&xpkt.rec);
69254359Sroberto
69354359Sroberto	/*
69454359Sroberto	 * Determine whether to authenticate or not.	If so,
69554359Sroberto	 * fill in the extended part of the packet and do it.
69654359Sroberto	 * If not, just timestamp it and send it away.
69754359Sroberto	 */
69854359Sroberto	if (sys_authenticate) {
699293650Sglebius		size_t len;
70054359Sroberto
70182498Sroberto		xpkt.exten[0] = htonl(sys_authkey);
70254359Sroberto		get_systime(&server->xmt);
70354359Sroberto		L_ADDUF(&server->xmt, sys_authdelay);
70454359Sroberto		HTONL_FP(&server->xmt, &xpkt.xmt);
70554359Sroberto		len = authencrypt(sys_authkey, (u_int32 *)&xpkt, LEN_PKT_NOMAC);
706285612Sdelphij		sendpkt(&server->srcadr, &xpkt, (int)(LEN_PKT_NOMAC + len));
70754359Sroberto
70854359Sroberto		if (debug > 1)
70954359Sroberto			printf("transmit auth to %s\n",
710285612Sdelphij			   stoa(&server->srcadr));
71154359Sroberto	} else {
71254359Sroberto		get_systime(&(server->xmt));
71354359Sroberto		HTONL_FP(&server->xmt, &xpkt.xmt);
714285612Sdelphij		sendpkt(&server->srcadr, &xpkt, LEN_PKT_NOMAC);
71554359Sroberto
71654359Sroberto		if (debug > 1)
717285612Sdelphij			printf("transmit to %s\n", stoa(&server->srcadr));
71854359Sroberto	}
71954359Sroberto
72054359Sroberto	/*
72154359Sroberto	 * Update the server timeout and transmit count
72254359Sroberto	 */
72354359Sroberto	server->event_time = current_time + sys_timeout;
72454359Sroberto	server->xmtcnt++;
72554359Sroberto}
72654359Sroberto
72754359Sroberto
72854359Sroberto/*
72954359Sroberto * receive - receive and process an incoming frame
73054359Sroberto */
73154359Srobertostatic void
73254359Srobertoreceive(
73354359Sroberto	struct recvbuf *rbufp
73454359Sroberto	)
73554359Sroberto{
73654359Sroberto	register struct pkt *rpkt;
73754359Sroberto	register struct server *server;
73854359Sroberto	register s_fp di;
739106163Sroberto	l_fp t10, t23, tmp;
74054359Sroberto	l_fp org;
74154359Sroberto	l_fp rec;
74254359Sroberto	l_fp ci;
74354359Sroberto	int has_mac;
74454359Sroberto	int is_authentic;
74554359Sroberto
74654359Sroberto	if (debug)
747182007Sroberto		printf("receive(%s)\n", stoa(&rbufp->recv_srcadr));
74854359Sroberto	/*
74954359Sroberto	 * Check to see if the packet basically looks like something
75054359Sroberto	 * intended for us.
75154359Sroberto	 */
75254359Sroberto	if (rbufp->recv_length == LEN_PKT_NOMAC)
75354359Sroberto		has_mac = 0;
754285612Sdelphij	else if (rbufp->recv_length >= (int)LEN_PKT_NOMAC)
75554359Sroberto		has_mac = 1;
75654359Sroberto	else {
75754359Sroberto		if (debug)
75854359Sroberto			printf("receive: packet length %d\n",
75954359Sroberto			   rbufp->recv_length);
76054359Sroberto		return; 		/* funny length packet */
76154359Sroberto	}
76254359Sroberto
76354359Sroberto	rpkt = &(rbufp->recv_pkt);
76454359Sroberto	if (PKT_VERSION(rpkt->li_vn_mode) < NTP_OLDVERSION ||
76554359Sroberto		PKT_VERSION(rpkt->li_vn_mode) > NTP_VERSION) {
76654359Sroberto		return;
76754359Sroberto	}
76854359Sroberto
76954359Sroberto	if ((PKT_MODE(rpkt->li_vn_mode) != MODE_SERVER
77054359Sroberto		 && PKT_MODE(rpkt->li_vn_mode) != MODE_PASSIVE)
77182498Sroberto		|| rpkt->stratum >= STRATUM_UNSPEC) {
77254359Sroberto		if (debug)
77354359Sroberto			printf("receive: mode %d stratum %d\n",
77454359Sroberto			   PKT_MODE(rpkt->li_vn_mode), rpkt->stratum);
77554359Sroberto		return;
77654359Sroberto	}
77754359Sroberto
77854359Sroberto	/*
77954359Sroberto	 * So far, so good.  See if this is from a server we know.
78054359Sroberto	 */
78154359Sroberto	server = findserver(&(rbufp->recv_srcadr));
78254359Sroberto	if (server == NULL) {
78354359Sroberto		if (debug)
78454359Sroberto			printf("receive: server not found\n");
78554359Sroberto		return;
78654359Sroberto	}
78754359Sroberto
78854359Sroberto	/*
78954359Sroberto	 * Decode the org timestamp and make sure we're getting a response
79054359Sroberto	 * to our last request.
79154359Sroberto	 */
79254359Sroberto	NTOHL_FP(&rpkt->org, &org);
79354359Sroberto	if (!L_ISEQU(&org, &server->xmt)) {
79454359Sroberto		if (debug)
79554359Sroberto			printf("receive: pkt.org and peer.xmt differ\n");
79654359Sroberto		return;
79754359Sroberto	}
79854359Sroberto
79954359Sroberto	/*
80054359Sroberto	 * Check out the authenticity if we're doing that.
80154359Sroberto	 */
80254359Sroberto	if (!sys_authenticate)
80354359Sroberto		is_authentic = 1;
80454359Sroberto	else {
80554359Sroberto		is_authentic = 0;
80654359Sroberto
80754359Sroberto		if (debug > 3)
80854359Sroberto			printf("receive: rpkt keyid=%ld sys_authkey=%ld decrypt=%ld\n",
80982498Sroberto			   (long int)ntohl(rpkt->exten[0]), (long int)sys_authkey,
81054359Sroberto			   (long int)authdecrypt(sys_authkey, (u_int32 *)rpkt,
811293650Sglebius				LEN_PKT_NOMAC, (size_t)(rbufp->recv_length - LEN_PKT_NOMAC)));
81254359Sroberto
81382498Sroberto		if (has_mac && ntohl(rpkt->exten[0]) == sys_authkey &&
81454359Sroberto			authdecrypt(sys_authkey, (u_int32 *)rpkt, LEN_PKT_NOMAC,
815293650Sglebius			(size_t)(rbufp->recv_length - LEN_PKT_NOMAC)))
81654359Sroberto			is_authentic = 1;
81754359Sroberto		if (debug)
81854359Sroberto			printf("receive: authentication %s\n",
81954359Sroberto			   is_authentic ? "passed" : "failed");
82054359Sroberto	}
82154359Sroberto	server->trust <<= 1;
82254359Sroberto	if (!is_authentic)
82354359Sroberto		server->trust |= 1;
82454359Sroberto
82554359Sroberto	/*
826285612Sdelphij	 * Check for a KoD (rate limiting) response, cease and decist.
827285612Sdelphij	 */
828285612Sdelphij	if (LEAP_NOTINSYNC == PKT_LEAP(rpkt->li_vn_mode) &&
829285612Sdelphij	    STRATUM_PKT_UNSPEC == rpkt->stratum &&
830285612Sdelphij	    !memcmp("RATE", &rpkt->refid, 4)) {
831285612Sdelphij		msyslog(LOG_ERR, "%s rate limit response from server.",
832285612Sdelphij			stoa(&rbufp->recv_srcadr));
833285612Sdelphij		server->event_time = 0;
834285612Sdelphij		complete_servers++;
835285612Sdelphij		return;
836285612Sdelphij	}
837285612Sdelphij
838285612Sdelphij	/*
83954359Sroberto	 * Looks good.	Record info from the packet.
84054359Sroberto	 */
84154359Sroberto	server->leap = PKT_LEAP(rpkt->li_vn_mode);
84254359Sroberto	server->stratum = PKT_TO_STRATUM(rpkt->stratum);
84354359Sroberto	server->precision = rpkt->precision;
84454359Sroberto	server->rootdelay = ntohl(rpkt->rootdelay);
845285612Sdelphij	server->rootdisp = ntohl(rpkt->rootdisp);
84654359Sroberto	server->refid = rpkt->refid;
84754359Sroberto	NTOHL_FP(&rpkt->reftime, &server->reftime);
84854359Sroberto	NTOHL_FP(&rpkt->rec, &rec);
84954359Sroberto	NTOHL_FP(&rpkt->xmt, &server->org);
85054359Sroberto
85154359Sroberto	/*
85254359Sroberto	 * Make sure the server is at least somewhat sane.	If not, try
85354359Sroberto	 * again.
85454359Sroberto	 */
85554359Sroberto	if (L_ISZERO(&rec) || !L_ISHIS(&server->org, &rec)) {
856285612Sdelphij		server->event_time = current_time + sys_timeout;
85754359Sroberto		return;
85854359Sroberto	}
85954359Sroberto
86054359Sroberto	/*
86154359Sroberto	 * Calculate the round trip delay (di) and the clock offset (ci).
86254359Sroberto	 * We use the equations (reordered from those in the spec):
86354359Sroberto	 *
86454359Sroberto	 * d = (t2 - t3) - (t1 - t0)
86554359Sroberto	 * c = ((t2 - t3) + (t1 - t0)) / 2
86654359Sroberto	 */
86754359Sroberto	t10 = server->org;		/* pkt.xmt == t1 */
86854359Sroberto	L_SUB(&t10, &rbufp->recv_time); /* recv_time == t0*/
86954359Sroberto
87054359Sroberto	t23 = rec;			/* pkt.rec == t2 */
87154359Sroberto	L_SUB(&t23, &org);		/* pkt->org == t3 */
87254359Sroberto
87354359Sroberto	/* now have (t2 - t3) and (t0 - t1).	Calculate (ci) and (di) */
874106163Sroberto	/*
875106163Sroberto	 * Calculate (ci) = ((t1 - t0) / 2) + ((t2 - t3) / 2)
876106163Sroberto	 * For large offsets this may prevent an overflow on '+'
877106163Sroberto	 */
87854359Sroberto	ci = t10;
87954359Sroberto	L_RSHIFT(&ci);
880106163Sroberto	tmp = t23;
881106163Sroberto	L_RSHIFT(&tmp);
882106163Sroberto	L_ADD(&ci, &tmp);
88354359Sroberto
88454359Sroberto	/*
88554359Sroberto	 * Calculate di in t23 in full precision, then truncate
88654359Sroberto	 * to an s_fp.
88754359Sroberto	 */
88854359Sroberto	L_SUB(&t23, &t10);
88954359Sroberto	di = LFPTOFP(&t23);
89054359Sroberto
89154359Sroberto	if (debug > 3)
89254359Sroberto		printf("offset: %s, delay %s\n", lfptoa(&ci, 6), fptoa(di, 5));
89354359Sroberto
89454359Sroberto	di += (FP_SECOND >> (-(int)NTPDATE_PRECISION))
89554359Sroberto		+ (FP_SECOND >> (-(int)server->precision)) + NTP_MAXSKW;
89654359Sroberto
89754359Sroberto	if (di <= 0) {		/* value still too raunchy to use? */
89854359Sroberto		L_CLR(&ci);
89954359Sroberto		di = 0;
90054359Sroberto	} else {
90154359Sroberto		di = max(di, NTP_MINDIST);
90254359Sroberto	}
90354359Sroberto
90454359Sroberto	/*
905285612Sdelphij	 * Shift this data in, then schedule another transmit.
90654359Sroberto	 */
90754359Sroberto	server_data(server, (s_fp) di, &ci, 0);
908285612Sdelphij
909285612Sdelphij	if ((int)server->filter_nextpt >= sys_samples) {
910285612Sdelphij		/*
911285612Sdelphij		 * Got all the data we need.  Mark this guy
912285612Sdelphij		 * completed and return.
913285612Sdelphij		 */
914285612Sdelphij		server->event_time = 0;
915285612Sdelphij		complete_servers++;
916285612Sdelphij		return;
917285612Sdelphij	}
918285612Sdelphij
919285612Sdelphij	server->event_time = current_time + sys_timeout;
92054359Sroberto}
92154359Sroberto
92254359Sroberto
92354359Sroberto/*
92454359Sroberto * server_data - add a sample to the server's filter registers
92554359Sroberto */
92654359Srobertostatic void
92754359Srobertoserver_data(
92854359Sroberto	register struct server *server,
92954359Sroberto	s_fp d,
93054359Sroberto	l_fp *c,
93154359Sroberto	u_fp e
93254359Sroberto	)
93354359Sroberto{
934132451Sroberto	u_short i;
93554359Sroberto
93654359Sroberto	i = server->filter_nextpt;
93754359Sroberto	if (i < NTP_SHIFT) {
93854359Sroberto		server->filter_delay[i] = d;
93954359Sroberto		server->filter_offset[i] = *c;
94054359Sroberto		server->filter_soffset[i] = LFPTOFP(c);
94154359Sroberto		server->filter_error[i] = e;
942132451Sroberto		server->filter_nextpt = (u_short)(i + 1);
94354359Sroberto	}
94454359Sroberto}
94554359Sroberto
94654359Sroberto
94754359Sroberto/*
94854359Sroberto * clock_filter - determine a server's delay, dispersion and offset
94954359Sroberto */
95054359Srobertostatic void
95154359Srobertoclock_filter(
95254359Sroberto	register struct server *server
95354359Sroberto	)
95454359Sroberto{
95554359Sroberto	register int i, j;
95654359Sroberto	int ord[NTP_SHIFT];
95754359Sroberto
958316722Sdelphij	INSIST((0 < sys_samples) && (sys_samples <= NTP_SHIFT));
959316722Sdelphij
96054359Sroberto	/*
96154359Sroberto	 * Sort indices into increasing delay order
96254359Sroberto	 */
96354359Sroberto	for (i = 0; i < sys_samples; i++)
96454359Sroberto		ord[i] = i;
96554359Sroberto
96654359Sroberto	for (i = 0; i < (sys_samples-1); i++) {
96754359Sroberto		for (j = i+1; j < sys_samples; j++) {
96854359Sroberto			if (server->filter_delay[ord[j]] == 0)
96954359Sroberto				continue;
97054359Sroberto			if (server->filter_delay[ord[i]] == 0
97154359Sroberto				|| (server->filter_delay[ord[i]]
97254359Sroberto				> server->filter_delay[ord[j]])) {
97354359Sroberto				register int tmp;
97454359Sroberto
97554359Sroberto				tmp = ord[i];
97654359Sroberto				ord[i] = ord[j];
97754359Sroberto				ord[j] = tmp;
97854359Sroberto			}
97954359Sroberto		}
98054359Sroberto	}
98154359Sroberto
98254359Sroberto	/*
98354359Sroberto	 * Now compute the dispersion, and assign values to delay and
98454359Sroberto	 * offset.	If there are no samples in the register, delay and
98554359Sroberto	 * offset go to zero and dispersion is set to the maximum.
98654359Sroberto	 */
98754359Sroberto	if (server->filter_delay[ord[0]] == 0) {
98854359Sroberto		server->delay = 0;
98954359Sroberto		L_CLR(&server->offset);
99054359Sroberto		server->soffset = 0;
99154359Sroberto		server->dispersion = PEER_MAXDISP;
99254359Sroberto	} else {
99354359Sroberto		register s_fp d;
99454359Sroberto
99554359Sroberto		server->delay = server->filter_delay[ord[0]];
99654359Sroberto		server->offset = server->filter_offset[ord[0]];
99754359Sroberto		server->soffset = LFPTOFP(&server->offset);
99854359Sroberto		server->dispersion = 0;
99954359Sroberto		for (i = 1; i < sys_samples; i++) {
100054359Sroberto			if (server->filter_delay[ord[i]] == 0)
100154359Sroberto				d = PEER_MAXDISP;
100254359Sroberto			else {
100354359Sroberto				d = server->filter_soffset[ord[i]]
100454359Sroberto					- server->filter_soffset[ord[0]];
100554359Sroberto				if (d < 0)
100654359Sroberto					d = -d;
100754359Sroberto				if (d > PEER_MAXDISP)
100854359Sroberto					d = PEER_MAXDISP;
100954359Sroberto			}
101054359Sroberto			/*
101154359Sroberto			 * XXX This *knows* PEER_FILTER is 1/2
101254359Sroberto			 */
101354359Sroberto			server->dispersion += (u_fp)(d) >> i;
101454359Sroberto		}
101554359Sroberto	}
101654359Sroberto	/*
101754359Sroberto	 * We're done
101854359Sroberto	 */
101954359Sroberto}
102054359Sroberto
102154359Sroberto
102254359Sroberto/*
102354359Sroberto * clock_select - select the pick-of-the-litter clock from the samples
102454359Sroberto *		  we've got.
102554359Sroberto */
102654359Srobertostatic struct server *
102754359Srobertoclock_select(void)
102854359Sroberto{
1029285612Sdelphij	struct server *server;
1030285612Sdelphij	u_int nlist;
1031285612Sdelphij	s_fp d;
1032285612Sdelphij	u_int count;
1033285612Sdelphij	u_int i;
1034285612Sdelphij	u_int j;
1035285612Sdelphij	u_int k;
1036285612Sdelphij	int n;
103754359Sroberto	s_fp local_threshold;
103854359Sroberto	struct server *server_list[NTP_MAXCLOCK];
103954359Sroberto	u_fp server_badness[NTP_MAXCLOCK];
104054359Sroberto	struct server *sys_server;
104154359Sroberto
104254359Sroberto	/*
104354359Sroberto	 * This first chunk of code is supposed to go through all
104454359Sroberto	 * servers we know about to find the NTP_MAXLIST servers which
104554359Sroberto	 * are most likely to succeed.	We run through the list
104654359Sroberto	 * doing the sanity checks and trying to insert anyone who
104754359Sroberto	 * looks okay.	We are at all times aware that we should
104854359Sroberto	 * only keep samples from the top two strata and we only need
104954359Sroberto	 * NTP_MAXLIST of them.
105054359Sroberto	 */
105154359Sroberto	nlist = 0;	/* none yet */
105256746Sroberto	for (server = sys_servers; server != NULL; server = server->next_server) {
1053106163Sroberto		if (server->delay == 0) {
1054106163Sroberto			if (debug)
1055106163Sroberto				printf("%s: Server dropped: no data\n", ntoa(&server->srcadr));
1056182007Sroberto			continue;	/* no data */
1057106163Sroberto		}
1058106163Sroberto		if (server->stratum > NTP_INFIN) {
1059106163Sroberto			if (debug)
1060106163Sroberto				printf("%s: Server dropped: strata too high\n", ntoa(&server->srcadr));
1061182007Sroberto			continue;	/* stratum no good */
1062106163Sroberto		}
106354359Sroberto		if (server->delay > NTP_MAXWGT) {
1064106163Sroberto			if (debug)
1065106163Sroberto				printf("%s: Server dropped: server too far away\n",
1066182007Sroberto					ntoa(&server->srcadr));
1067182007Sroberto			continue;	/* too far away */
106854359Sroberto		}
1069106163Sroberto		if (server->leap == LEAP_NOTINSYNC) {
1070106163Sroberto			if (debug)
1071106163Sroberto				printf("%s: Server dropped: Leap not in sync\n", ntoa(&server->srcadr));
1072182007Sroberto			continue;	/* he's in trouble */
1073106163Sroberto		}
107454359Sroberto		if (!L_ISHIS(&server->org, &server->reftime)) {
1075106163Sroberto			if (debug)
1076106163Sroberto				printf("%s: Server dropped: server is very broken\n",
1077106163Sroberto				       ntoa(&server->srcadr));
1078182007Sroberto			continue;	/* very broken host */
107954359Sroberto		}
108054359Sroberto		if ((server->org.l_ui - server->reftime.l_ui)
1081106163Sroberto		    >= NTP_MAXAGE) {
1082106163Sroberto			if (debug)
1083106163Sroberto				printf("%s: Server dropped: Server has gone too long without sync\n",
1084106163Sroberto				       ntoa(&server->srcadr));
108554359Sroberto			continue;	/* too long without sync */
108654359Sroberto		}
108754359Sroberto		if (server->trust != 0) {
1088106163Sroberto			if (debug)
1089106163Sroberto				printf("%s: Server dropped: Server is untrusted\n",
1090106163Sroberto				       ntoa(&server->srcadr));
109154359Sroberto			continue;
109254359Sroberto		}
109354359Sroberto
109454359Sroberto		/*
109554359Sroberto		 * This one seems sane.  Find where he belongs
109654359Sroberto		 * on the list.
109754359Sroberto		 */
109854359Sroberto		d = server->dispersion + server->dispersion;
109954359Sroberto		for (i = 0; i < nlist; i++)
110054359Sroberto			if (server->stratum <= server_list[i]->stratum)
110154359Sroberto			break;
110254359Sroberto		for ( ; i < nlist; i++) {
110354359Sroberto			if (server->stratum < server_list[i]->stratum)
110454359Sroberto				break;
110554359Sroberto			if (d < (s_fp) server_badness[i])
110654359Sroberto				break;
110754359Sroberto		}
110854359Sroberto
110954359Sroberto		/*
111054359Sroberto		 * If i points past the end of the list, this
111154359Sroberto		 * guy is a loser, else stick him in.
111254359Sroberto		 */
111354359Sroberto		if (i >= NTP_MAXLIST)
111454359Sroberto			continue;
111554359Sroberto		for (j = nlist; j > i; j--)
111654359Sroberto			if (j < NTP_MAXLIST) {
111754359Sroberto				server_list[j] = server_list[j-1];
111854359Sroberto				server_badness[j]
111954359Sroberto					= server_badness[j-1];
112054359Sroberto			}
112154359Sroberto
112254359Sroberto		server_list[i] = server;
112354359Sroberto		server_badness[i] = d;
112454359Sroberto		if (nlist < NTP_MAXLIST)
112554359Sroberto			nlist++;
112654359Sroberto	}
112754359Sroberto
112854359Sroberto	/*
112954359Sroberto	 * Got the five-or-less best.	 Cut the list where the number of
113054359Sroberto	 * strata exceeds two.
113154359Sroberto	 */
1132285612Sdelphij	count = 0;
113354359Sroberto	for (i = 1; i < nlist; i++)
1134285612Sdelphij		if (server_list[i]->stratum > server_list[i-1]->stratum) {
1135285612Sdelphij			count++;
1136285612Sdelphij			if (2 == count) {
1137285612Sdelphij				nlist = i;
1138285612Sdelphij				break;
1139285612Sdelphij			}
114054359Sroberto		}
114154359Sroberto
114254359Sroberto	/*
114354359Sroberto	 * Whew!  What we should have by now is 0 to 5 candidates for
114454359Sroberto	 * the job of syncing us.  If we have none, we're out of luck.
114554359Sroberto	 * If we have one, he's a winner.  If we have more, do falseticker
114654359Sroberto	 * detection.
114754359Sroberto	 */
114854359Sroberto
1149285612Sdelphij	if (0 == nlist)
1150285612Sdelphij		sys_server = NULL;
1151285612Sdelphij	else if (1 == nlist) {
115254359Sroberto		sys_server = server_list[0];
115354359Sroberto	} else {
115454359Sroberto		/*
115554359Sroberto		 * Re-sort by stratum, bdelay estimate quality and
115654359Sroberto		 * server.delay.
115754359Sroberto		 */
115854359Sroberto		for (i = 0; i < nlist-1; i++)
115954359Sroberto			for (j = i+1; j < nlist; j++) {
1160285612Sdelphij				if (server_list[i]->stratum <
1161285612Sdelphij				    server_list[j]->stratum)
1162285612Sdelphij					/* already sorted by stratum */
1163285612Sdelphij					break;
1164285612Sdelphij				if (server_list[i]->delay <
1165285612Sdelphij				    server_list[j]->delay)
1166285612Sdelphij					continue;
116754359Sroberto				server = server_list[i];
116854359Sroberto				server_list[i] = server_list[j];
116954359Sroberto				server_list[j] = server;
117054359Sroberto			}
117154359Sroberto
117254359Sroberto		/*
117354359Sroberto		 * Calculate the fixed part of the dispersion limit
117454359Sroberto		 */
117554359Sroberto		local_threshold = (FP_SECOND >> (-(int)NTPDATE_PRECISION))
117654359Sroberto			+ NTP_MAXSKW;
117754359Sroberto
117854359Sroberto		/*
117954359Sroberto		 * Now drop samples until we're down to one.
118054359Sroberto		 */
118154359Sroberto		while (nlist > 1) {
1182285612Sdelphij			for (k = 0; k < nlist; k++) {
1183285612Sdelphij				server_badness[k] = 0;
118454359Sroberto				for (j = 0; j < nlist; j++) {
1185285612Sdelphij					if (j == k) /* with self? */
118654359Sroberto						continue;
1187285612Sdelphij					d = server_list[j]->soffset -
1188285612Sdelphij					    server_list[k]->soffset;
1189285612Sdelphij					if (d < 0)	/* abs value */
119054359Sroberto						d = -d;
119154359Sroberto					/*
119254359Sroberto					 * XXX This code *knows* that
119354359Sroberto					 * NTP_SELECT is 3/4
119454359Sroberto					 */
119554359Sroberto					for (i = 0; i < j; i++)
119654359Sroberto						d = (d>>1) + (d>>2);
1197285612Sdelphij					server_badness[k] += d;
119854359Sroberto				}
119954359Sroberto			}
120054359Sroberto
120154359Sroberto			/*
120254359Sroberto			 * We now have an array of nlist badness
120354359Sroberto			 * coefficients.	Find the badest.  Find
120454359Sroberto			 * the minimum precision while we're at
120554359Sroberto			 * it.
120654359Sroberto			 */
120754359Sroberto			i = 0;
120854359Sroberto			n = server_list[0]->precision;;
120954359Sroberto			for (j = 1; j < nlist; j++) {
121054359Sroberto				if (server_badness[j] >= server_badness[i])
121154359Sroberto					i = j;
121254359Sroberto				if (n > server_list[j]->precision)
121354359Sroberto					n = server_list[j]->precision;
121454359Sroberto			}
121554359Sroberto
121654359Sroberto			/*
121754359Sroberto			 * i is the index of the server with the worst
121854359Sroberto			 * dispersion.	If his dispersion is less than
121954359Sroberto			 * the threshold, stop now, else delete him and
122054359Sroberto			 * continue around again.
122154359Sroberto			 */
122254359Sroberto			if ( (s_fp) server_badness[i] < (local_threshold
122354359Sroberto							 + (FP_SECOND >> (-n))))
122454359Sroberto				break;
122554359Sroberto			for (j = i + 1; j < nlist; j++)
122654359Sroberto				server_list[j-1] = server_list[j];
122754359Sroberto			nlist--;
122854359Sroberto		}
122954359Sroberto
123054359Sroberto		/*
123154359Sroberto		 * What remains is a list of less than 5 servers.  Take
123254359Sroberto		 * the best.
123354359Sroberto		 */
123454359Sroberto		sys_server = server_list[0];
123554359Sroberto	}
123654359Sroberto
123754359Sroberto	/*
1238182007Sroberto	 * That's it.  Return our server.
123954359Sroberto	 */
124054359Sroberto	return sys_server;
124154359Sroberto}
124254359Sroberto
124354359Sroberto
124454359Sroberto/*
124554359Sroberto * clock_adjust - process what we've received, and adjust the time
124654359Sroberto *		 if we got anything decent.
124754359Sroberto */
124854359Srobertostatic int
124954359Srobertoclock_adjust(void)
125054359Sroberto{
125156746Sroberto	register struct server *sp, *server;
125254359Sroberto	int dostep;
125354359Sroberto
125456746Sroberto	for (sp = sys_servers; sp != NULL; sp = sp->next_server)
125556746Sroberto		clock_filter(sp);
125654359Sroberto	server = clock_select();
125754359Sroberto
125854359Sroberto	if (debug || simple_query) {
125956746Sroberto		for (sp = sys_servers; sp != NULL; sp = sp->next_server)
126056746Sroberto			printserver(sp, stdout);
126154359Sroberto	}
126254359Sroberto
126354359Sroberto	if (server == 0) {
126454359Sroberto		msyslog(LOG_ERR,
126554359Sroberto			"no server suitable for synchronization found");
126654359Sroberto		return(1);
126754359Sroberto	}
126854359Sroberto
126954359Sroberto	if (always_step) {
127054359Sroberto		dostep = 1;
127154359Sroberto	} else if (never_step) {
127254359Sroberto		dostep = 0;
127354359Sroberto	} else {
1274298770Sdelphij		/* [Bug 3023] get absolute difference, avoiding signed
1275298770Sdelphij		 * integer overflow like hell.
1276298770Sdelphij		 */
1277298770Sdelphij		u_fp absoffset;
1278298770Sdelphij		if (server->soffset < 0)
1279298770Sdelphij			absoffset = 1u + (u_fp)(-(server->soffset + 1));
1280298770Sdelphij		else
1281298770Sdelphij			absoffset = (u_fp)server->soffset;
1282298770Sdelphij		dostep = (absoffset >= NTPDATE_THRESHOLD);
128354359Sroberto	}
128454359Sroberto
128554359Sroberto	if (dostep) {
1286182007Sroberto		if (simple_query || debug || l_step_systime(&server->offset)){
128754359Sroberto			msyslog(LOG_NOTICE, "step time server %s offset %s sec",
1288132451Sroberto				stoa(&server->srcadr),
128954359Sroberto				lfptoa(&server->offset, 6));
129054359Sroberto		}
129154359Sroberto	} else {
1292285612Sdelphij#ifndef SYS_WINNT
129354359Sroberto		if (simple_query || l_adj_systime(&server->offset)) {
129454359Sroberto			msyslog(LOG_NOTICE, "adjust time server %s offset %s sec",
1295132451Sroberto				stoa(&server->srcadr),
129654359Sroberto				lfptoa(&server->offset, 6));
129754359Sroberto		}
129854359Sroberto#else
129954359Sroberto		/* The NT SetSystemTimeAdjustment() call achieves slewing by
130054359Sroberto		 * changing the clock frequency. This means that we cannot specify
130154359Sroberto		 * it to slew the clock by a definite amount and then stop like
130254359Sroberto		 * the Unix adjtime() routine. We can technically adjust the clock
130354359Sroberto		 * frequency, have ntpdate sleep for a while, and then wake
130454359Sroberto		 * up and reset the clock frequency, but this might cause some
130554359Sroberto		 * grief if the user attempts to run ntpd immediately after
130654359Sroberto		 * ntpdate and the socket is in use.
130754359Sroberto		 */
130854359Sroberto		printf("\nThe -b option is required by ntpdate on Windows NT platforms\n");
130954359Sroberto		exit(1);
131054359Sroberto#endif /* SYS_WINNT */
131154359Sroberto	}
131254359Sroberto	return(0);
131354359Sroberto}
131454359Sroberto
131554359Sroberto
1316182007Sroberto/*
1317182007Sroberto * is_unreachable - check to see if we have a route to given destination
1318182007Sroberto *		    (non-blocking).
1319182007Sroberto */
1320182007Srobertostatic int
1321285612Sdelphijis_reachable (sockaddr_u *dst)
1322182007Sroberto{
1323182007Sroberto	SOCKET sockfd;
1324182007Sroberto
1325285612Sdelphij	sockfd = socket(AF(dst), SOCK_DGRAM, 0);
1326182007Sroberto	if (sockfd == -1) {
1327182007Sroberto		return 0;
1328182007Sroberto	}
1329182007Sroberto
1330285612Sdelphij	if (connect(sockfd, &dst->sa, SOCKLEN(dst))) {
1331182007Sroberto		closesocket(sockfd);
1332182007Sroberto		return 0;
1333182007Sroberto	}
1334182007Sroberto	closesocket(sockfd);
1335182007Sroberto	return 1;
1336182007Sroberto}
1337182007Sroberto
1338182007Sroberto
1339182007Sroberto
134054359Sroberto/* XXX ELIMINATE: merge BIG slew into adj_systime in lib/systime.c */
134154359Sroberto/*
134254359Sroberto * addserver - determine a server's address and allocate a new structure
1343182007Sroberto *		for it.
134454359Sroberto */
134554359Srobertostatic void
134654359Srobertoaddserver(
134754359Sroberto	char *serv
134854359Sroberto	)
134954359Sroberto{
135054359Sroberto	register struct server *server;
1351182007Sroberto	/* Address infos structure to store result of getaddrinfo */
1352182007Sroberto	struct addrinfo *addrResult, *ptr;
1353182007Sroberto	/* Address infos structure to store hints for getaddrinfo */
1354182007Sroberto	struct addrinfo hints;
1355182007Sroberto	/* Error variable for getaddrinfo */
1356182007Sroberto	int error;
1357182007Sroberto	/* Service name */
1358182007Sroberto	char service[5];
1359285612Sdelphij	sockaddr_u addr;
136054359Sroberto
1361285612Sdelphij	strlcpy(service, "ntp", sizeof(service));
1362285612Sdelphij
1363182007Sroberto	/* Get host address. Looking for UDP datagram connection. */
1364285612Sdelphij	ZERO(hints);
1365182007Sroberto	hints.ai_family = ai_fam_templ;
1366182007Sroberto	hints.ai_socktype = SOCK_DGRAM;
1367132451Sroberto
1368138451Sroberto#ifdef DEBUG
1369182007Sroberto	if (debug)
1370182007Sroberto		printf("Looking for host %s and service %s\n", serv, service);
1371138451Sroberto#endif
1372132451Sroberto
1373182007Sroberto	error = getaddrinfo(serv, service, &hints, &addrResult);
1374182007Sroberto	if (error != 0) {
1375182007Sroberto		/* Conduct more refined error analysis */
1376182007Sroberto		if (error == EAI_FAIL || error == EAI_AGAIN){
1377182007Sroberto			/* Name server is unusable. Exit after failing on the
1378182007Sroberto			   first server, in order to shorten the timeout caused
1379182007Sroberto			   by waiting for resolution of several servers */
1380285612Sdelphij			fprintf(stderr, "Exiting, name server cannot be used: %s (%d)",
1381285612Sdelphij				gai_strerror(error), error);
1382285612Sdelphij			msyslog(LOG_ERR, "name server cannot be used: %s (%d)",
1383285612Sdelphij				gai_strerror(error), error);
1384182007Sroberto			exit(1);
1385182007Sroberto		}
1386285612Sdelphij		fprintf(stderr, "Error resolving %s: %s (%d)\n", serv,
1387285612Sdelphij			gai_strerror(error), error);
1388285612Sdelphij		msyslog(LOG_ERR, "Can't find host %s: %s (%d)", serv,
1389285612Sdelphij			gai_strerror(error), error);
139054359Sroberto		return;
139154359Sroberto	}
1392138451Sroberto#ifdef DEBUG
1393285612Sdelphij	if (debug) {
1394285612Sdelphij		ZERO(addr);
1395285612Sdelphij		INSIST(addrResult->ai_addrlen <= sizeof(addr));
1396285612Sdelphij		memcpy(&addr, addrResult->ai_addr, addrResult->ai_addrlen);
1397285612Sdelphij		fprintf(stderr, "host found : %s\n", stohost(&addr));
1398182007Sroberto	}
1399138451Sroberto#endif
140054359Sroberto
1401182007Sroberto	/* We must get all returned server in case the first one fails */
1402182007Sroberto	for (ptr = addrResult; ptr != NULL; ptr = ptr->ai_next) {
1403285612Sdelphij		ZERO(addr);
1404285612Sdelphij		INSIST(ptr->ai_addrlen <= sizeof(addr));
1405285612Sdelphij		memcpy(&addr, ptr->ai_addr, ptr->ai_addrlen);
1406285612Sdelphij		if (is_reachable(&addr)) {
1407285612Sdelphij			server = emalloc_zero(sizeof(*server));
1408285612Sdelphij			memcpy(&server->srcadr, ptr->ai_addr, ptr->ai_addrlen);
1409182007Sroberto			server->event_time = ++sys_numservers;
1410182007Sroberto			if (sys_servers == NULL)
1411182007Sroberto				sys_servers = server;
1412182007Sroberto			else {
1413182007Sroberto				struct server *sp;
141456746Sroberto
1415182007Sroberto				for (sp = sys_servers; sp->next_server != NULL;
1416285612Sdelphij				     sp = sp->next_server)
1417285612Sdelphij					/* empty */;
1418182007Sroberto				sp->next_server = server;
1419182007Sroberto			}
1420182007Sroberto		}
142156746Sroberto	}
1422182007Sroberto
1423182007Sroberto	freeaddrinfo(addrResult);
142454359Sroberto}
142554359Sroberto
142654359Sroberto
142754359Sroberto/*
142854359Sroberto * findserver - find a server in the list given its address
1429132451Sroberto * ***(For now it isn't totally AF-Independant, to check later..)
143054359Sroberto */
143154359Srobertostatic struct server *
143254359Srobertofindserver(
1433285612Sdelphij	sockaddr_u *addr
143454359Sroberto	)
143554359Sroberto{
143656746Sroberto	struct server *server;
143756746Sroberto	struct server *mc_server;
143854359Sroberto
143956746Sroberto	mc_server = NULL;
1440285612Sdelphij	if (SRCPORT(addr) != NTP_PORT)
144154359Sroberto		return 0;
144254359Sroberto
144356746Sroberto	for (server = sys_servers; server != NULL;
144456746Sroberto	     server = server->next_server) {
1445285612Sdelphij		if (SOCK_EQ(addr, &server->srcadr))
144656746Sroberto			return server;
1447182007Sroberto
1448285612Sdelphij		if (AF(addr) == AF(&server->srcadr)) {
1449285612Sdelphij			if (IS_MCAST(&server->srcadr))
1450182007Sroberto				mc_server = server;
1451182007Sroberto		}
145254359Sroberto	}
145356746Sroberto
145456746Sroberto	if (mc_server != NULL) {
1455132451Sroberto
145656746Sroberto		struct server *sp;
145756746Sroberto
145856746Sroberto		if (mc_server->event_time != 0) {
145956746Sroberto			mc_server->event_time = 0;
146056746Sroberto			complete_servers++;
146156746Sroberto		}
1462132451Sroberto
1463285612Sdelphij		server = emalloc_zero(sizeof(*server));
146456746Sroberto
1465285612Sdelphij		server->srcadr = *addr;
146656746Sroberto
146756746Sroberto		server->event_time = ++sys_numservers;
1468132451Sroberto
146956746Sroberto		for (sp = sys_servers; sp->next_server != NULL;
1470285612Sdelphij		     sp = sp->next_server)
1471285612Sdelphij			/* empty */;
147256746Sroberto		sp->next_server = server;
147356746Sroberto		transmit(server);
147456746Sroberto	}
147556746Sroberto	return NULL;
147654359Sroberto}
147754359Sroberto
147854359Sroberto
147954359Sroberto/*
148054359Sroberto * timer - process a timer interrupt
148154359Sroberto */
148254359Srobertovoid
148354359Srobertotimer(void)
148454359Sroberto{
148556746Sroberto	struct server *server;
148654359Sroberto
148754359Sroberto	/*
148854359Sroberto	 * Bump the current idea of the time
148954359Sroberto	 */
149054359Sroberto	current_time++;
149154359Sroberto
149254359Sroberto	/*
149354359Sroberto	 * Search through the server list looking for guys
149454359Sroberto	 * who's event timers have expired.  Give these to
149554359Sroberto	 * the transmit routine.
149654359Sroberto	 */
149756746Sroberto	for (server = sys_servers; server != NULL;
149856746Sroberto	     server = server->next_server) {
149956746Sroberto		if (server->event_time != 0
150056746Sroberto		    && server->event_time <= current_time)
150156746Sroberto			transmit(server);
150254359Sroberto	}
150354359Sroberto}
150454359Sroberto
150554359Sroberto
150682498Sroberto/*
150782498Sroberto * The code duplication in the following subroutine sucks, but
150882498Sroberto * we need to appease ansi2knr.
150982498Sroberto */
151082498Sroberto
151154359Sroberto#ifndef SYS_WINNT
151254359Sroberto/*
151354359Sroberto * alarming - record the occurance of an alarm interrupt
151454359Sroberto */
151554359Srobertostatic RETSIGTYPE
151654359Srobertoalarming(
151754359Sroberto	int sig
151854359Sroberto	)
151982498Sroberto{
152082498Sroberto	alarm_flag++;
152182498Sroberto}
1522285612Sdelphij#else	/* SYS_WINNT follows */
152354359Srobertovoid CALLBACK
152454359Srobertoalarming(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
152554359Sroberto{
1526285612Sdelphij	UNUSED_ARG(uTimerID); UNUSED_ARG(uMsg); UNUSED_ARG(dwUser);
1527285612Sdelphij	UNUSED_ARG(dw1); UNUSED_ARG(dw2);
1528285612Sdelphij
152954359Sroberto	alarm_flag++;
153054359Sroberto}
153154359Sroberto
1532182007Srobertostatic void
1533182007SrobertocallTimeEndPeriod(void)
1534182007Sroberto{
1535182007Sroberto	timeEndPeriod( wTimerRes );
1536182007Sroberto	wTimerRes = 0;
1537182007Sroberto}
1538182007Sroberto#endif /* SYS_WINNT */
1539182007Sroberto
1540182007Sroberto
154154359Sroberto/*
154254359Sroberto * init_alarm - set up the timer interrupt
154354359Sroberto */
154454359Srobertostatic void
154554359Srobertoinit_alarm(void)
154654359Sroberto{
154754359Sroberto#ifndef SYS_WINNT
1548285612Sdelphij# ifdef HAVE_TIMER_CREATE
1549285612Sdelphij	struct itimerspec its;
155054359Sroberto# else
1551285612Sdelphij	struct itimerval itv;
155254359Sroberto# endif
1553285612Sdelphij#else	/* SYS_WINNT follows */
155454359Sroberto	TIMECAPS tc;
1555182007Sroberto	UINT wTimerID;
155654359Sroberto	HANDLE hToken;
155754359Sroberto	TOKEN_PRIVILEGES tkp;
155854359Sroberto	DWORD dwUser = 0;
155954359Sroberto#endif /* SYS_WINNT */
156054359Sroberto
156154359Sroberto	alarm_flag = 0;
156254359Sroberto
156354359Sroberto#ifndef SYS_WINNT
1564285612Sdelphij# ifdef HAVE_TIMER_CREATE
156554359Sroberto	alarm_flag = 0;
156654359Sroberto	/* this code was put in as setitimer() is non existant this us the
156754359Sroberto	 * POSIX "equivalents" setup - casey
156854359Sroberto	 */
156954359Sroberto	/* ntpdate_timerid is global - so we can kill timer later */
157054359Sroberto	if (timer_create (CLOCK_REALTIME, NULL, &ntpdate_timerid) ==
157154359Sroberto#  ifdef SYS_VXWORKS
157254359Sroberto		ERROR
157354359Sroberto#  else
157454359Sroberto		-1
157554359Sroberto#  endif
157654359Sroberto		)
157754359Sroberto	{
157854359Sroberto		fprintf (stderr, "init_alarm(): timer_create (...) FAILED\n");
157954359Sroberto		return;
158054359Sroberto	}
158154359Sroberto
158254359Sroberto	/*	TIMER_HZ = (5)
158354359Sroberto	 * Set up the alarm interrupt.	The first comes 1/(2*TIMER_HZ)
158454359Sroberto	 * seconds from now and they continue on every 1/TIMER_HZ seconds.
158554359Sroberto	 */
1586285612Sdelphij	signal_no_reset(SIGALRM, alarming);
1587285612Sdelphij	its.it_interval.tv_sec = 0;
1588285612Sdelphij	its.it_value.tv_sec = 0;
1589285612Sdelphij	its.it_interval.tv_nsec = 1000000000/TIMER_HZ;
1590285612Sdelphij	its.it_value.tv_nsec = 1000000000/(TIMER_HZ<<1);
1591285612Sdelphij	timer_settime(ntpdate_timerid, 0 /* !TIMER_ABSTIME */, &its, NULL);
1592285612Sdelphij# else	/* !HAVE_TIMER_CREATE follows */
159354359Sroberto	/*
159454359Sroberto	 * Set up the alarm interrupt.	The first comes 1/(2*TIMER_HZ)
159554359Sroberto	 * seconds from now and they continue on every 1/TIMER_HZ seconds.
159654359Sroberto	 */
1597285612Sdelphij	signal_no_reset(SIGALRM, alarming);
1598285612Sdelphij	itv.it_interval.tv_sec = 0;
1599285612Sdelphij	itv.it_value.tv_sec = 0;
1600285612Sdelphij	itv.it_interval.tv_usec = 1000000/TIMER_HZ;
1601285612Sdelphij	itv.it_value.tv_usec = 1000000/(TIMER_HZ<<1);
1602132451Sroberto
1603285612Sdelphij	setitimer(ITIMER_REAL, &itv, NULL);
1604285612Sdelphij# endif	/* !HAVE_TIMER_CREATE */
1605285612Sdelphij#else	/* SYS_WINNT follows */
160654359Sroberto	_tzset();
160754359Sroberto
160854359Sroberto	/*
1609182007Sroberto	 * Get privileges needed for fiddling with the clock
161054359Sroberto	 */
161154359Sroberto
161254359Sroberto	/* get the current process token handle */
161354359Sroberto	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
161454359Sroberto		msyslog(LOG_ERR, "OpenProcessToken failed: %m");
161554359Sroberto		exit(1);
161654359Sroberto	}
161754359Sroberto	/* get the LUID for system-time privilege. */
161854359Sroberto	LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid);
1619182007Sroberto	tkp.PrivilegeCount = 1;		/* one privilege to set */
162054359Sroberto	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
162154359Sroberto	/* get set-time privilege for this process. */
162254359Sroberto	AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES) NULL, 0);
162354359Sroberto	/* cannot test return value of AdjustTokenPrivileges. */
162454359Sroberto	if (GetLastError() != ERROR_SUCCESS)
162554359Sroberto		msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m");
162654359Sroberto
162754359Sroberto	/*
162854359Sroberto	 * Set up timer interrupts for every 2**EVENT_TIMEOUT seconds
162954359Sroberto	 * Under Win/NT, expiry of timer interval leads to invocation
163054359Sroberto	 * of a callback function (on a different thread) rather than
163154359Sroberto	 * generating an alarm signal
163254359Sroberto	 */
163354359Sroberto
163454359Sroberto	/* determine max and min resolution supported */
163554359Sroberto	if(timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
163654359Sroberto		msyslog(LOG_ERR, "timeGetDevCaps failed: %m");
163754359Sroberto		exit(1);
163854359Sroberto	}
163954359Sroberto	wTimerRes = min(max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax);
164054359Sroberto	/* establish the minimum timer resolution that we'll use */
164154359Sroberto	timeBeginPeriod(wTimerRes);
1642182007Sroberto	atexit(callTimeEndPeriod);
164354359Sroberto
164454359Sroberto	/* start the timer event */
164554359Sroberto	wTimerID = timeSetEvent(
1646182007Sroberto		(UINT) (1000/TIMER_HZ),		/* Delay */
1647182007Sroberto		wTimerRes,			/* Resolution */
1648182007Sroberto		(LPTIMECALLBACK) alarming,	/* Callback function */
1649182007Sroberto		(DWORD) dwUser,			/* User data */
1650182007Sroberto		TIME_PERIODIC);			/* Event type (periodic) */
165154359Sroberto	if (wTimerID == 0) {
165254359Sroberto		msyslog(LOG_ERR, "timeSetEvent failed: %m");
165354359Sroberto		exit(1);
165454359Sroberto	}
165554359Sroberto#endif /* SYS_WINNT */
165654359Sroberto}
165754359Sroberto
165854359Sroberto
165954359Sroberto
166054359Sroberto
166154359Sroberto/*
166254359Sroberto * We do asynchronous input using the SIGIO facility.  A number of
166354359Sroberto * recvbuf buffers are preallocated for input.	In the signal
166454359Sroberto * handler we poll to see if the socket is ready and read the
166554359Sroberto * packets from it into the recvbuf's along with a time stamp and
166654359Sroberto * an indication of the source host and the interface it was received
166754359Sroberto * through.  This allows us to get as accurate receive time stamps
166854359Sroberto * as possible independent of other processing going on.
166954359Sroberto *
167054359Sroberto * We allocate a number of recvbufs equal to the number of servers
167154359Sroberto * plus 2.	This should be plenty.
167254359Sroberto */
167354359Sroberto
167454359Sroberto
167554359Sroberto/*
167654359Sroberto * init_io - initialize I/O data and open socket
167754359Sroberto */
167854359Srobertostatic void
167954359Srobertoinit_io(void)
168054359Sroberto{
1681182007Sroberto	struct addrinfo *res, *ressave;
1682182007Sroberto	struct addrinfo hints;
1683285612Sdelphij	sockaddr_u addr;
1684132451Sroberto	char service[5];
1685285612Sdelphij	int rc;
1686182007Sroberto	int optval = 1;
1687182007Sroberto	int check_ntp_port_in_use = !debug && !simple_query && !unpriv_port;
1688132451Sroberto
168954359Sroberto	/*
169054359Sroberto	 * Init buffer free list and stat counters
169154359Sroberto	 */
169254359Sroberto	init_recvbuff(sys_numservers + 2);
1693132451Sroberto
169454359Sroberto	/*
169554359Sroberto	 * Open the socket
169654359Sroberto	 */
169754359Sroberto
1698285612Sdelphij	strlcpy(service, "ntp", sizeof(service));
1699132451Sroberto
1700182007Sroberto	/*
1701182007Sroberto	 * Init hints addrinfo structure
1702182007Sroberto	 */
1703285612Sdelphij	ZERO(hints);
1704182007Sroberto	hints.ai_family = ai_fam_templ;
1705182007Sroberto	hints.ai_flags = AI_PASSIVE;
1706182007Sroberto	hints.ai_socktype = SOCK_DGRAM;
1707132451Sroberto
1708285612Sdelphij	if (getaddrinfo(NULL, service, &hints, &res) != 0) {
1709285612Sdelphij		msyslog(LOG_ERR, "getaddrinfo() failed: %m");
1710285612Sdelphij		exit(1);
1711285612Sdelphij		/*NOTREACHED*/
1712182007Sroberto	}
1713132451Sroberto
1714182007Sroberto#ifdef SYS_WINNT
1715182007Sroberto	if (check_ntp_port_in_use && ntp_port_inuse(AF_INET, NTP_PORT)){
1716285612Sdelphij		msyslog(LOG_ERR, "the NTP socket is in use, exiting: %m");
1717182007Sroberto		exit(1);
1718182007Sroberto	}
1719182007Sroberto#endif
1720132451Sroberto
1721182007Sroberto	/* Remember the address of the addrinfo structure chain */
1722182007Sroberto	ressave = res;
1723182007Sroberto
1724182007Sroberto	/*
1725182007Sroberto	 * For each structure returned, open and bind socket
1726182007Sroberto	 */
1727182007Sroberto	for(nbsock = 0; (nbsock < MAX_AF) && res ; res = res->ai_next) {
172854359Sroberto	/* create a datagram (UDP) socket */
1729182007Sroberto		fd[nbsock] = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
1730182007Sroberto		if (fd[nbsock] == SOCKET_ERROR) {
1731182007Sroberto#ifndef SYS_WINNT
1732132451Sroberto		if (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT ||
1733132451Sroberto		    errno == EPFNOSUPPORT)
1734182007Sroberto#else
1735182007Sroberto		int err = WSAGetLastError();
1736182007Sroberto		if (err == WSAEPROTONOSUPPORT || err == WSAEAFNOSUPPORT ||
1737182007Sroberto		    err == WSAEPFNOSUPPORT)
1738182007Sroberto#endif
1739132451Sroberto			continue;
1740285612Sdelphij		msyslog(LOG_ERR, "socket() failed: %m");
174154359Sroberto		exit(1);
174254359Sroberto		/*NOTREACHED*/
1743182007Sroberto		}
1744182007Sroberto		/* set socket to reuse address */
1745182007Sroberto		if (setsockopt(fd[nbsock], SOL_SOCKET, SO_REUSEADDR, (void*) &optval, sizeof(optval)) < 0) {
1746285612Sdelphij				msyslog(LOG_ERR, "setsockopt() SO_REUSEADDR failed: %m");
1747182007Sroberto				exit(1);
1748182007Sroberto				/*NOTREACHED*/
1749182007Sroberto		}
1750132451Sroberto#ifdef IPV6_V6ONLY
1751182007Sroberto		/* Restricts AF_INET6 socket to IPv6 communications (see RFC 2553bis-03) */
1752182007Sroberto		if (res->ai_family == AF_INET6)
1753182007Sroberto			if (setsockopt(fd[nbsock], IPPROTO_IPV6, IPV6_V6ONLY, (void*) &optval, sizeof(optval)) < 0) {
1754285612Sdelphij				   msyslog(LOG_ERR, "setsockopt() IPV6_V6ONLY failed: %m");
1755182007Sroberto					exit(1);
1756182007Sroberto					/*NOTREACHED*/
1757182007Sroberto		}
1758132451Sroberto#endif
175954359Sroberto
1760182007Sroberto		/* Remember the socket family in fd_family structure */
1761182007Sroberto		fd_family[nbsock] = res->ai_family;
1762132451Sroberto
1763182007Sroberto		/*
1764182007Sroberto		 * bind the socket to the NTP port
1765182007Sroberto		 */
1766182007Sroberto		if (check_ntp_port_in_use) {
1767285612Sdelphij			ZERO(addr);
1768285612Sdelphij			INSIST(res->ai_addrlen <= sizeof(addr));
1769285612Sdelphij			memcpy(&addr, res->ai_addr, res->ai_addrlen);
1770285612Sdelphij			rc = bind(fd[nbsock], &addr.sa, SOCKLEN(&addr));
1771285612Sdelphij			if (rc < 0) {
1772285612Sdelphij				if (EADDRINUSE == socket_errno())
1773285612Sdelphij					msyslog(LOG_ERR, "the NTP socket is in use, exiting");
177454359Sroberto				else
1775285612Sdelphij					msyslog(LOG_ERR, "bind() fails: %m");
1776182007Sroberto				exit(1);
1777182007Sroberto			}
177854359Sroberto		}
177954359Sroberto
178054359Sroberto#ifdef HAVE_POLL_H
1781182007Sroberto		fdmask[nbsock].fd = fd[nbsock];
1782182007Sroberto		fdmask[nbsock].events = POLLIN;
178354359Sroberto#else
1784182007Sroberto		FD_SET(fd[nbsock], &fdmask);
1785182007Sroberto		if (maxfd < fd[nbsock]+1) {
1786182007Sroberto			maxfd = fd[nbsock]+1;
1787182007Sroberto		}
178854359Sroberto#endif
178954359Sroberto
1790182007Sroberto		/*
1791182007Sroberto		 * set non-blocking,
1792182007Sroberto		 */
179354359Sroberto#ifndef SYS_WINNT
179454359Sroberto# ifdef SYS_VXWORKS
1795182007Sroberto		{
1796285612Sdelphij			int on = TRUE;
179754359Sroberto
1798285612Sdelphij			if (ioctl(fd[nbsock],FIONBIO, &on) == ERROR) {
1799285612Sdelphij				msyslog(LOG_ERR, "ioctl(FIONBIO) fails: %m");
1800285612Sdelphij				exit(1);
1801285612Sdelphij			}
1802182007Sroberto		}
180354359Sroberto# else /* not SYS_VXWORKS */
180454359Sroberto#  if defined(O_NONBLOCK)
1805182007Sroberto		if (fcntl(fd[nbsock], F_SETFL, O_NONBLOCK) < 0) {
1806285612Sdelphij			msyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails: %m");
1807182007Sroberto			exit(1);
1808182007Sroberto			/*NOTREACHED*/
1809182007Sroberto		}
181054359Sroberto#  else /* not O_NONBLOCK */
181154359Sroberto#	if defined(FNDELAY)
1812182007Sroberto		if (fcntl(fd[nbsock], F_SETFL, FNDELAY) < 0) {
1813285612Sdelphij			msyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails: %m");
1814182007Sroberto			exit(1);
1815182007Sroberto			/*NOTREACHED*/
1816182007Sroberto		}
181754359Sroberto#	else /* FNDELAY */
181854359Sroberto#	 include "Bletch: Need non blocking I/O"
181954359Sroberto#	endif /* FNDELAY */
182054359Sroberto#  endif /* not O_NONBLOCK */
182154359Sroberto# endif /* SYS_VXWORKS */
182254359Sroberto#else /* SYS_WINNT */
1823182007Sroberto		if (ioctlsocket(fd[nbsock], FIONBIO, (u_long *) &on) == SOCKET_ERROR) {
1824285612Sdelphij			msyslog(LOG_ERR, "ioctlsocket(FIONBIO) fails: %m");
1825182007Sroberto			exit(1);
1826182007Sroberto		}
1827182007Sroberto#endif /* SYS_WINNT */
1828182007Sroberto		nbsock++;
182954359Sroberto	}
1830182007Sroberto	freeaddrinfo(ressave);
183154359Sroberto}
183254359Sroberto
183354359Sroberto/*
183454359Sroberto * sendpkt - send a packet to the specified destination
183554359Sroberto */
183654359Srobertostatic void
183754359Srobertosendpkt(
1838285612Sdelphij	sockaddr_u *dest,
183954359Sroberto	struct pkt *pkt,
184054359Sroberto	int len
184154359Sroberto	)
184254359Sroberto{
1843182007Sroberto	int i;
184454359Sroberto	int cc;
1845182007Sroberto	SOCKET sock = INVALID_SOCKET;
184654359Sroberto
184754359Sroberto#ifdef SYS_WINNT
184854359Sroberto	DWORD err;
184954359Sroberto#endif /* SYS_WINNT */
185054359Sroberto
1851182007Sroberto	/* Find a local family compatible socket to send ntp packet to ntp server */
1852182007Sroberto	for(i = 0; (i < MAX_AF); i++) {
1853285612Sdelphij		if(AF(dest) == fd_family[i]) {
1854182007Sroberto			sock = fd[i];
1855182007Sroberto		break;
1856182007Sroberto		}
1857182007Sroberto	}
1858132451Sroberto
1859285612Sdelphij	if (INVALID_SOCKET == sock) {
1860285612Sdelphij		msyslog(LOG_ERR, "cannot find family compatible socket to send ntp packet");
1861182007Sroberto		exit(1);
1862182007Sroberto		/*NOTREACHED*/
1863182007Sroberto	}
1864132451Sroberto
1865132451Sroberto	cc = sendto(sock, (char *)pkt, len, 0, (struct sockaddr *)dest,
1866132451Sroberto			SOCKLEN(dest));
1867132451Sroberto
1868285612Sdelphij	if (SOCKET_ERROR == cc) {
186954359Sroberto#ifndef SYS_WINNT
187054359Sroberto		if (errno != EWOULDBLOCK && errno != ENOBUFS)
187154359Sroberto#else
187254359Sroberto		err = WSAGetLastError();
187354359Sroberto		if (err != WSAEWOULDBLOCK && err != WSAENOBUFS)
187454359Sroberto#endif /* SYS_WINNT */
1875285612Sdelphij			msyslog(LOG_ERR, "sendto(%s): %m", stohost(dest));
187654359Sroberto	}
187754359Sroberto}
187854359Sroberto
187954359Sroberto
188054359Sroberto/*
188154359Sroberto * input_handler - receive packets asynchronously
188254359Sroberto */
188354359Srobertovoid
188454359Srobertoinput_handler(void)
188554359Sroberto{
188654359Sroberto	register int n;
188754359Sroberto	register struct recvbuf *rb;
1888285612Sdelphij	struct sock_timeval tvzero;
1889285612Sdelphij	GETSOCKNAME_SOCKLEN_TYPE fromlen;
189054359Sroberto	l_fp ts;
1891182007Sroberto	int i;
189254359Sroberto#ifdef HAVE_POLL_H
1893132451Sroberto	struct pollfd fds[MAX_AF];
189454359Sroberto#else
189554359Sroberto	fd_set fds;
189654359Sroberto#endif
1897293650Sglebius	SOCKET fdc = 0;
189854359Sroberto
189954359Sroberto	/*
190054359Sroberto	 * Do a poll to see if we have data
190154359Sroberto	 */
190254359Sroberto	for (;;) {
190354359Sroberto		tvzero.tv_sec = tvzero.tv_usec = 0;
190454359Sroberto#ifdef HAVE_POLL_H
1905132451Sroberto		memcpy(fds, fdmask, sizeof(fdmask));
1906182007Sroberto		n = poll(fds, (unsigned int)nbsock, tvzero.tv_sec * 1000);
1907132451Sroberto
1908182007Sroberto		/*
1909182007Sroberto		 * Determine which socket received data
1910182007Sroberto		 */
1911132451Sroberto
1912182007Sroberto		for(i=0; i < nbsock; i++) {
1913182007Sroberto			if(fds[i].revents & POLLIN) {
1914182007Sroberto				fdc = fd[i];
1915182007Sroberto				break;
1916182007Sroberto			}
1917182007Sroberto		}
1918132451Sroberto
191954359Sroberto#else
1920132451Sroberto		fds = fdmask;
1921293650Sglebius		n = select(maxfd, &fds, NULL, NULL, &tvzero);
1922132451Sroberto
1923182007Sroberto		/*
1924182007Sroberto		 * Determine which socket received data
1925182007Sroberto		 */
1926132451Sroberto
1927182007Sroberto		for(i=0; i < nbsock; i++) {
1928182007Sroberto			if(FD_ISSET(fd[i], &fds)) {
1929182007Sroberto				 fdc = fd[i];
1930182007Sroberto				 break;
1931182007Sroberto			}
1932182007Sroberto		}
1933132451Sroberto
193454359Sroberto#endif
193554359Sroberto
193654359Sroberto		/*
193754359Sroberto		 * If nothing to do, just return.  If an error occurred,
193854359Sroberto		 * complain and return.  If we've got some, freeze a
193954359Sroberto		 * timestamp.
194054359Sroberto		 */
194154359Sroberto		if (n == 0)
194254359Sroberto			return;
194354359Sroberto		else if (n == -1) {
194454359Sroberto			if (errno != EINTR)
1945285612Sdelphij				msyslog(LOG_ERR,
194654359Sroberto#ifdef HAVE_POLL_H
194754359Sroberto					"poll() error: %m"
194854359Sroberto#else
194954359Sroberto					"select() error: %m"
195054359Sroberto#endif
195154359Sroberto					);
195254359Sroberto			return;
195354359Sroberto		}
195454359Sroberto		get_systime(&ts);
195554359Sroberto
195654359Sroberto		/*
195754359Sroberto		 * Get a buffer and read the frame.  If we
195854359Sroberto		 * haven't got a buffer, or this is received
195954359Sroberto		 * on the wild card socket, just dump the packet.
196054359Sroberto		 */
196154359Sroberto		if (initializing || free_recvbuffs() == 0) {
196254359Sroberto			char buf[100];
196354359Sroberto
1964132451Sroberto
196554359Sroberto#ifndef SYS_WINNT
1966132451Sroberto			(void) read(fdc, buf, sizeof buf);
196754359Sroberto#else
196854359Sroberto			/* NT's _read does not operate on nonblocking sockets
196954359Sroberto			 * either recvfrom or ReadFile() has to be used here.
197054359Sroberto			 * ReadFile is used in [ntpd]ntp_intres() and ntpdc,
197154359Sroberto			 * just to be different use recvfrom() here
197254359Sroberto			 */
1973132451Sroberto			recvfrom(fdc, buf, sizeof(buf), 0, (struct sockaddr *)0, NULL);
197454359Sroberto#endif /* SYS_WINNT */
197554359Sroberto			continue;
197654359Sroberto		}
197754359Sroberto
197854359Sroberto		rb = get_free_recv_buffer();
197954359Sroberto
1980285612Sdelphij		fromlen = sizeof(rb->recv_srcadr);
1981132451Sroberto		rb->recv_length = recvfrom(fdc, (char *)&rb->recv_pkt,
198254359Sroberto		   sizeof(rb->recv_pkt), 0,
198354359Sroberto		   (struct sockaddr *)&rb->recv_srcadr, &fromlen);
198454359Sroberto		if (rb->recv_length == -1) {
198554359Sroberto			freerecvbuf(rb);
198654359Sroberto			continue;
198754359Sroberto		}
198854359Sroberto
198954359Sroberto		/*
199054359Sroberto		 * Got one.  Mark how and when it got here,
199154359Sroberto		 * put it on the full list.
199254359Sroberto		 */
199354359Sroberto		rb->recv_time = ts;
199454359Sroberto		add_full_recv_buffer(rb);
199554359Sroberto	}
199654359Sroberto}
199754359Sroberto
199854359Sroberto
199954359Sroberto#if !defined SYS_WINNT && !defined SYS_CYGWIN32
200054359Sroberto/*
200154359Sroberto * adj_systime - do a big long slew of the system time
200254359Sroberto */
200354359Srobertostatic int
200454359Srobertol_adj_systime(
200554359Sroberto	l_fp *ts
200654359Sroberto	)
200754359Sroberto{
200854359Sroberto	struct timeval adjtv, oadjtv;
200954359Sroberto	int isneg = 0;
201054359Sroberto	l_fp offset;
201154359Sroberto#ifndef STEP_SLEW
201254359Sroberto	l_fp overshoot;
201354359Sroberto#endif
201454359Sroberto
201554359Sroberto	/*
201654359Sroberto	 * Take the absolute value of the offset
201754359Sroberto	 */
201854359Sroberto	offset = *ts;
201954359Sroberto	if (L_ISNEG(&offset)) {
202054359Sroberto		isneg = 1;
202154359Sroberto		L_NEG(&offset);
202254359Sroberto	}
202354359Sroberto
202454359Sroberto#ifndef STEP_SLEW
202554359Sroberto	/*
202654359Sroberto	 * Calculate the overshoot.  XXX N.B. This code *knows*
202754359Sroberto	 * ADJ_OVERSHOOT is 1/2.
202854359Sroberto	 */
202954359Sroberto	overshoot = offset;
203054359Sroberto	L_RSHIFTU(&overshoot);
203154359Sroberto	if (overshoot.l_ui != 0 || (overshoot.l_uf > ADJ_MAXOVERSHOOT)) {
203254359Sroberto		overshoot.l_ui = 0;
203354359Sroberto		overshoot.l_uf = ADJ_MAXOVERSHOOT;
203454359Sroberto	}
203554359Sroberto	L_ADD(&offset, &overshoot);
203654359Sroberto#endif
203754359Sroberto	TSTOTV(&offset, &adjtv);
203854359Sroberto
203954359Sroberto	if (isneg) {
204054359Sroberto		adjtv.tv_sec = -adjtv.tv_sec;
204154359Sroberto		adjtv.tv_usec = -adjtv.tv_usec;
204254359Sroberto	}
204354359Sroberto
204454359Sroberto	if (adjtv.tv_usec != 0 && !debug) {
204554359Sroberto		if (adjtime(&adjtv, &oadjtv) < 0) {
204654359Sroberto			msyslog(LOG_ERR, "Can't adjust the time of day: %m");
2047285612Sdelphij			exit(1);
204854359Sroberto		}
204954359Sroberto	}
205054359Sroberto	return 1;
205154359Sroberto}
205254359Sroberto#endif /* SYS_WINNT */
205354359Sroberto
205454359Sroberto
205554359Sroberto/*
205654359Sroberto * This fuction is not the same as lib/systime step_systime!!!
205754359Sroberto */
205854359Srobertostatic int
205954359Srobertol_step_systime(
206054359Sroberto	l_fp *ts
206154359Sroberto	)
206254359Sroberto{
206354359Sroberto	double dtemp;
206454359Sroberto
206554359Sroberto#ifdef SLEWALWAYS
206654359Sroberto#ifdef STEP_SLEW
206754359Sroberto	l_fp ftmp;
206854359Sroberto	int isneg;
206954359Sroberto	int n;
207054359Sroberto
207154359Sroberto	if (debug) return 1;
207254359Sroberto	/*
207354359Sroberto	 * Take the absolute value of the offset
207454359Sroberto	 */
207554359Sroberto	ftmp = *ts;
207654359Sroberto	if (L_ISNEG(&ftmp)) {
207754359Sroberto		L_NEG(&ftmp);
207854359Sroberto		isneg = 1;
207954359Sroberto	} else
208054359Sroberto		isneg = 0;
208154359Sroberto
208254359Sroberto	if (ftmp.l_ui >= 3) {		/* Step it and slew - we might win */
208356746Sroberto		LFPTOD(ts, dtemp);
208456746Sroberto		n = step_systime(dtemp);
208554359Sroberto		if (!n)
208654359Sroberto			return n;
208754359Sroberto		if (isneg)
208854359Sroberto			ts->l_ui = ~0;
208954359Sroberto		else
209054359Sroberto			ts->l_ui = ~0;
209154359Sroberto	}
209254359Sroberto	/*
209354359Sroberto	 * Just add adjustment into the current offset.  The update
209454359Sroberto	 * routine will take care of bringing the system clock into
209554359Sroberto	 * line.
209654359Sroberto	 */
209754359Sroberto#endif
209854359Sroberto	if (debug)
209954359Sroberto		return 1;
210054359Sroberto#ifdef FORCE_NTPDATE_STEP
210154359Sroberto	LFPTOD(ts, dtemp);
210254359Sroberto	return step_systime(dtemp);
210354359Sroberto#else
210454359Sroberto	l_adj_systime(ts);
210554359Sroberto	return 1;
210654359Sroberto#endif
2107182007Sroberto#else /* SLEWALWAYS */
210854359Sroberto	if (debug)
210954359Sroberto		return 1;
211054359Sroberto	LFPTOD(ts, dtemp);
211154359Sroberto	return step_systime(dtemp);
211254359Sroberto#endif	/* SLEWALWAYS */
211354359Sroberto}
211454359Sroberto
211554359Sroberto
211654359Sroberto/* XXX ELIMINATE printserver similar in ntptrace.c, ntpdate.c */
211754359Sroberto/*
211854359Sroberto * printserver - print detail information for a server
211954359Sroberto */
212054359Srobertostatic void
212154359Srobertoprintserver(
212254359Sroberto	register struct server *pp,
212354359Sroberto	FILE *fp
212454359Sroberto	)
212554359Sroberto{
212654359Sroberto	register int i;
212754359Sroberto	char junk[5];
2128285612Sdelphij	const char *str;
212954359Sroberto
213054359Sroberto	if (!debug) {
213154359Sroberto		(void) fprintf(fp, "server %s, stratum %d, offset %s, delay %s\n",
2132132451Sroberto				   stoa(&pp->srcadr), pp->stratum,
213354359Sroberto				   lfptoa(&pp->offset, 6), fptoa((s_fp)pp->delay, 5));
213454359Sroberto		return;
213554359Sroberto	}
213654359Sroberto
213754359Sroberto	(void) fprintf(fp, "server %s, port %d\n",
2138132451Sroberto			   stoa(&pp->srcadr), ntohs(((struct sockaddr_in*)&(pp->srcadr))->sin_port));
213954359Sroberto
214054359Sroberto	(void) fprintf(fp, "stratum %d, precision %d, leap %c%c, trust %03o\n",
214154359Sroberto			   pp->stratum, pp->precision,
214254359Sroberto			   pp->leap & 0x2 ? '1' : '0',
214354359Sroberto			   pp->leap & 0x1 ? '1' : '0',
214454359Sroberto			   pp->trust);
214554359Sroberto
214654359Sroberto	if (pp->stratum == 1) {
214754359Sroberto		junk[4] = 0;
214854359Sroberto		memmove(junk, (char *)&pp->refid, 4);
214954359Sroberto		str = junk;
215054359Sroberto	} else {
2151132451Sroberto		str = stoa(&pp->srcadr);
215254359Sroberto	}
215354359Sroberto	(void) fprintf(fp,
215454359Sroberto			   "refid [%s], delay %s, dispersion %s\n",
215554359Sroberto			   str, fptoa((s_fp)pp->delay, 5),
215654359Sroberto			   ufptoa(pp->dispersion, 5));
215754359Sroberto
215854359Sroberto	(void) fprintf(fp, "transmitted %d, in filter %d\n",
215954359Sroberto			   pp->xmtcnt, pp->filter_nextpt);
216054359Sroberto
216154359Sroberto	(void) fprintf(fp, "reference time:    %s\n",
216254359Sroberto			   prettydate(&pp->reftime));
216354359Sroberto	(void) fprintf(fp, "originate timestamp: %s\n",
216454359Sroberto			   prettydate(&pp->org));
216554359Sroberto	(void) fprintf(fp, "transmit timestamp:  %s\n",
216654359Sroberto			   prettydate(&pp->xmt));
216754359Sroberto
216854359Sroberto	(void) fprintf(fp, "filter delay: ");
216954359Sroberto	for (i = 0; i < NTP_SHIFT; i++) {
217054359Sroberto		(void) fprintf(fp, " %-8.8s", fptoa(pp->filter_delay[i], 5));
217154359Sroberto		if (i == (NTP_SHIFT>>1)-1)
217254359Sroberto			(void) fprintf(fp, "\n        ");
217354359Sroberto	}
217454359Sroberto	(void) fprintf(fp, "\n");
217554359Sroberto
217654359Sroberto	(void) fprintf(fp, "filter offset:");
217754359Sroberto	for (i = 0; i < PEER_SHIFT; i++) {
217854359Sroberto		(void) fprintf(fp, " %-8.8s", lfptoa(&pp->filter_offset[i], 6));
217954359Sroberto		if (i == (PEER_SHIFT>>1)-1)
218054359Sroberto			(void) fprintf(fp, "\n        ");
218154359Sroberto	}
218254359Sroberto	(void) fprintf(fp, "\n");
218354359Sroberto
218454359Sroberto	(void) fprintf(fp, "delay %s, dispersion %s\n",
218554359Sroberto			   fptoa((s_fp)pp->delay, 5), ufptoa(pp->dispersion, 5));
218654359Sroberto
218754359Sroberto	(void) fprintf(fp, "offset %s\n\n",
218854359Sroberto			   lfptoa(&pp->offset, 6));
218954359Sroberto}
219054359Sroberto
219154359Sroberto
219254359Sroberto#ifdef HAVE_NETINFO
219354359Srobertostatic ni_namelist *
219454359Srobertogetnetinfoservers(void)
219554359Sroberto{
219654359Sroberto	ni_status status;
219754359Sroberto	void *domain;
219854359Sroberto	ni_id confdir;
2199285612Sdelphij	ni_namelist *namelist = emalloc(sizeof(ni_namelist));
220054359Sroberto
220154359Sroberto	/* Find a time server in NetInfo */
220254359Sroberto	if ((status = ni_open(NULL, ".", &domain)) != NI_OK) return NULL;
220354359Sroberto
220454359Sroberto	while (status = ni_pathsearch(domain, &confdir, NETINFO_CONFIG_DIR) == NI_NODIR) {
220554359Sroberto		void *next_domain;
220654359Sroberto		if (ni_open(domain, "..", &next_domain) != NI_OK) break;
220754359Sroberto		ni_free(domain);
220854359Sroberto		domain = next_domain;
220954359Sroberto	}
221054359Sroberto	if (status != NI_OK) return NULL;
221154359Sroberto
221254359Sroberto	NI_INIT(namelist);
221354359Sroberto	if (ni_lookupprop(domain, &confdir, "server", namelist) != NI_OK) {
221454359Sroberto		ni_namelist_free(namelist);
221554359Sroberto		free(namelist);
221654359Sroberto		return NULL;
221754359Sroberto	}
221854359Sroberto
221954359Sroberto	return(namelist);
222054359Sroberto}
222154359Sroberto#endif
2222182007Sroberto
2223182007Sroberto#ifdef SYS_WINNT
2224182007Srobertoisc_boolean_t ntp_port_inuse(int af, u_short port)
2225182007Sroberto{
2226182007Sroberto	/*
2227182007Sroberto	 * Check if NTP socket is already in use on this system
2228182007Sroberto	 * This is only for Windows Systems, as they tend not to fail on the real bind() below
2229182007Sroberto	 */
2230182007Sroberto
2231182007Sroberto	SOCKET checksocket;
2232182007Sroberto	struct sockaddr_in checkservice;
2233182007Sroberto	checksocket = socket(af, SOCK_DGRAM, 0);
2234182007Sroberto	if (checksocket == INVALID_SOCKET) {
2235182007Sroberto		return (ISC_TRUE);
2236182007Sroberto	}
2237182007Sroberto
2238182007Sroberto	checkservice.sin_family = (short) AF_INET;
2239182007Sroberto	checkservice.sin_addr.s_addr = INADDR_LOOPBACK;
2240182007Sroberto	checkservice.sin_port = htons(port);
2241182007Sroberto
2242182007Sroberto	if (bind(checksocket, (struct sockaddr *)&checkservice,
2243182007Sroberto		sizeof(checkservice)) == SOCKET_ERROR) {
2244182007Sroberto		if ( WSAGetLastError() == WSAEADDRINUSE ){
2245182007Sroberto			closesocket(checksocket);
2246182007Sroberto			return (ISC_TRUE);
2247182007Sroberto		}
2248182007Sroberto	}
2249182007Sroberto	closesocket(checksocket);
2250182007Sroberto	return (ISC_FALSE);
2251182007Sroberto}
2252182007Sroberto#endif
2253