xref: /freebsd/contrib/ntp/sntp/main.c (revision 6419bb52)
1 #include <config.h>
2 
3 #include <event2/util.h>
4 #include <event2/event.h>
5 
6 #include "ntp_workimpl.h"
7 #ifdef WORK_THREAD
8 # include <event2/thread.h>
9 #endif
10 
11 #ifdef HAVE_SYSEXITS_H
12 # include <sysexits.h>
13 #endif
14 
15 #include "main.h"
16 #include "ntp_libopts.h"
17 #include "kod_management.h"
18 #include "networking.h"
19 #include "utilities.h"
20 #include "log.h"
21 #include "libntp.h"
22 
23 
24 int shutting_down;
25 int time_derived;
26 int time_adjusted;
27 int n_pending_dns = 0;
28 int n_pending_ntp = 0;
29 int ai_fam_pref = AF_UNSPEC;
30 int ntpver = 4;
31 double steplimit = -1;
32 SOCKET sock4 = -1;		/* Socket for IPv4 */
33 SOCKET sock6 = -1;		/* Socket for IPv6 */
34 /*
35 ** BCAST *must* listen on port 123 (by default), so we can only
36 ** use the UCST sockets (above) if they too are using port 123
37 */
38 SOCKET bsock4 = -1;		/* Broadcast Socket for IPv4 */
39 SOCKET bsock6 = -1;		/* Broadcast Socket for IPv6 */
40 struct event_base *base;
41 struct event *ev_sock4;
42 struct event *ev_sock6;
43 struct event *ev_worker_timeout;
44 struct event *ev_xmt_timer;
45 
46 struct dns_ctx {
47 	const char *	name;
48 	int		flags;
49 #define CTX_BCST	0x0001
50 #define CTX_UCST	0x0002
51 #define CTX_xCST	0x0003
52 #define CTX_CONC	0x0004
53 #define CTX_unused	0xfffd
54 	int		key_id;
55 	struct timeval	timeout;
56 	struct key *	key;
57 };
58 
59 typedef struct sent_pkt_tag sent_pkt;
60 struct sent_pkt_tag {
61 	sent_pkt *		link;
62 	struct dns_ctx *	dctx;
63 	sockaddr_u		addr;
64 	time_t			stime;
65 	int			done;
66 	struct pkt		x_pkt;
67 };
68 
69 typedef struct xmt_ctx_tag xmt_ctx;
70 struct xmt_ctx_tag {
71 	xmt_ctx *		link;
72 	SOCKET			sock;
73 	time_t			sched;
74 	sent_pkt *		spkt;
75 };
76 
77 struct timeval	gap;
78 xmt_ctx *	xmt_q;
79 struct key *	keys = NULL;
80 int		response_timeout;
81 struct timeval	response_tv;
82 struct timeval	start_tv;
83 /* check the timeout at least once per second */
84 struct timeval	wakeup_tv = { 0, 888888 };
85 
86 sent_pkt *	fam_listheads[2];
87 #define v4_pkts_list	(fam_listheads[0])
88 #define v6_pkts_list	(fam_listheads[1])
89 
90 static union {
91 	struct pkt pkt;
92 	char   buf[LEN_PKT_NOMAC + NTP_MAXEXTEN + MAX_MAC_LEN];
93 } rbuf;
94 
95 #define r_pkt  rbuf.pkt
96 
97 #ifdef HAVE_DROPROOT
98 int droproot;			/* intres imports these */
99 int root_dropped;
100 #endif
101 u_long current_time;		/* libntp/authkeys.c */
102 
103 void open_sockets(void);
104 void handle_lookup(const char *name, int flags);
105 void sntp_addremove_fd(int fd, int is_pipe, int remove_it);
106 void worker_timeout(evutil_socket_t, short, void *);
107 void worker_resp_cb(evutil_socket_t, short, void *);
108 void sntp_name_resolved(int, int, void *, const char *, const char *,
109 			const struct addrinfo *,
110 			const struct addrinfo *);
111 void queue_xmt(SOCKET sock, struct dns_ctx *dctx, sent_pkt *spkt,
112 	       u_int xmt_delay);
113 void xmt_timer_cb(evutil_socket_t, short, void *ptr);
114 void xmt(xmt_ctx *xctx);
115 int  check_kod(const struct addrinfo *ai);
116 void timeout_query(sent_pkt *);
117 void timeout_queries(void);
118 void sock_cb(evutil_socket_t, short, void *);
119 void check_exit_conditions(void);
120 void sntp_libevent_log_cb(int, const char *);
121 void set_li_vn_mode(struct pkt *spkt, char leap, char version, char mode);
122 int  set_time(double offset);
123 void dec_pending_ntp(const char *, sockaddr_u *);
124 int  libevent_version_ok(void);
125 int  gettimeofday_cached(struct event_base *b, struct timeval *tv);
126 
127 
128 /*
129  * The actual main function.
130  */
131 int
132 sntp_main (
133 	int argc,
134 	char **argv,
135 	const char *sntpVersion
136 	)
137 {
138 	int			i;
139 	int			exitcode;
140 	int			optct;
141 	struct event_config *	evcfg;
142 
143 	/* Initialize logging system - sets up progname */
144 	sntp_init_logging(argv[0]);
145 
146 	if (!libevent_version_ok())
147 		exit(EX_SOFTWARE);
148 
149 	init_lib();
150 	init_auth();
151 
152 	optct = ntpOptionProcess(&sntpOptions, argc, argv);
153 	argc -= optct;
154 	argv += optct;
155 
156 
157 	debug = OPT_VALUE_SET_DEBUG_LEVEL;
158 
159 	TRACE(2, ("init_lib() done, %s%s\n",
160 		  (ipv4_works)
161 		      ? "ipv4_works "
162 		      : "",
163 		  (ipv6_works)
164 		      ? "ipv6_works "
165 		      : ""));
166 	ntpver = OPT_VALUE_NTPVERSION;
167 	steplimit = OPT_VALUE_STEPLIMIT / 1e3;
168 	gap.tv_usec = max(0, OPT_VALUE_GAP * 1000);
169 	gap.tv_usec = min(gap.tv_usec, 999999);
170 
171 	if (HAVE_OPT(LOGFILE))
172 		open_logfile(OPT_ARG(LOGFILE));
173 
174 	msyslog(LOG_INFO, "%s", sntpVersion);
175 
176 	if (0 == argc && !HAVE_OPT(BROADCAST) && !HAVE_OPT(CONCURRENT)) {
177 		printf("%s: Must supply at least one of -b hostname, -c hostname, or hostname.\n",
178 		       progname);
179 		exit(EX_USAGE);
180 	}
181 
182 
183 	/*
184 	** Eventually, we probably want:
185 	** - separate bcst and ucst timeouts (why?)
186 	** - multiple --timeout values in the commandline
187 	*/
188 
189 	response_timeout = OPT_VALUE_TIMEOUT;
190 	response_tv.tv_sec = response_timeout;
191 	response_tv.tv_usec = 0;
192 
193 	/* IPv6 available? */
194 	if (isc_net_probeipv6() != ISC_R_SUCCESS) {
195 		ai_fam_pref = AF_INET;
196 		TRACE(1, ("No ipv6 support available, forcing ipv4\n"));
197 	} else {
198 		/* Check for options -4 and -6 */
199 		if (HAVE_OPT(IPV4))
200 			ai_fam_pref = AF_INET;
201 		else if (HAVE_OPT(IPV6))
202 			ai_fam_pref = AF_INET6;
203 	}
204 
205 	/* TODO: Parse config file if declared */
206 
207 	/*
208 	** Init the KOD system.
209 	** For embedded systems with no writable filesystem,
210 	** -K /dev/null can be used to disable KoD storage.
211 	*/
212 	kod_init_kod_db(OPT_ARG(KOD), FALSE);
213 
214 	/* HMS: Check and see what happens if KEYFILE doesn't exist */
215 	auth_init(OPT_ARG(KEYFILE), &keys);
216 
217 	/*
218 	** Considering employing a variable that prevents functions of doing
219 	** anything until everything is initialized properly
220 	**
221 	** HMS: What exactly does the above mean?
222 	*/
223 	event_set_log_callback(&sntp_libevent_log_cb);
224 	if (debug > 0)
225 		event_enable_debug_mode();
226 #ifdef WORK_THREAD
227 	evthread_use_pthreads();
228 	/* we use libevent from main thread only, locks should be academic */
229 	if (debug > 0)
230 		evthread_enable_lock_debuging();
231 #endif
232 	evcfg = event_config_new();
233 	if (NULL == evcfg) {
234 		printf("%s: event_config_new() failed!\n", progname);
235 		return -1;
236 	}
237 #ifndef HAVE_SOCKETPAIR
238 	event_config_require_features(evcfg, EV_FEATURE_FDS);
239 #endif
240 	/* all libevent calls are from main thread */
241 	/* event_config_set_flag(evcfg, EVENT_BASE_FLAG_NOLOCK); */
242 	base = event_base_new_with_config(evcfg);
243 	event_config_free(evcfg);
244 	if (NULL == base) {
245 		printf("%s: event_base_new() failed!\n", progname);
246 		return -1;
247 	}
248 
249 	/* wire into intres resolver */
250 	worker_per_query = TRUE;
251 	addremove_io_fd = &sntp_addremove_fd;
252 
253 	open_sockets();
254 
255 	if (HAVE_OPT(BROADCAST)) {
256 		int		cn = STACKCT_OPT(  BROADCAST );
257 		const char **	cp = STACKLST_OPT( BROADCAST );
258 
259 		while (cn-- > 0) {
260 			handle_lookup(*cp, CTX_BCST);
261 			cp++;
262 		}
263 	}
264 
265 	if (HAVE_OPT(CONCURRENT)) {
266 		int		cn = STACKCT_OPT( CONCURRENT );
267 		const char **	cp = STACKLST_OPT( CONCURRENT );
268 
269 		while (cn-- > 0) {
270 			handle_lookup(*cp, CTX_UCST | CTX_CONC);
271 			cp++;
272 		}
273 	}
274 
275 	for (i = 0; i < argc; ++i)
276 		handle_lookup(argv[i], CTX_UCST);
277 
278 	gettimeofday_cached(base, &start_tv);
279 	event_base_dispatch(base);
280 	event_base_free(base);
281 
282 	if (!time_adjusted &&
283 	    (ENABLED_OPT(STEP) || ENABLED_OPT(SLEW)))
284 		exitcode = 1;
285 	else
286 		exitcode = 0;
287 
288 	return exitcode;
289 }
290 
291 
292 /*
293 ** open sockets and make them non-blocking
294 */
295 void
296 open_sockets(
297 	void
298 	)
299 {
300 	sockaddr_u	name;
301 
302 	if (-1 == sock4) {
303 		sock4 = socket(PF_INET, SOCK_DGRAM, 0);
304 		if (-1 == sock4) {
305 			/* error getting a socket */
306 			msyslog(LOG_ERR, "open_sockets: socket(PF_INET) failed: %m");
307 			exit(1);
308 		}
309 		/* Make it non-blocking */
310 		make_socket_nonblocking(sock4);
311 
312 		/* Let's try using a wildcard... */
313 		ZERO(name);
314 		AF(&name) = AF_INET;
315 		SET_ADDR4N(&name, INADDR_ANY);
316 		SET_PORT(&name, (HAVE_OPT(USERESERVEDPORT) ? 123 : 0));
317 
318 		if (-1 == bind(sock4, &name.sa,
319 			       SOCKLEN(&name))) {
320 			msyslog(LOG_ERR, "open_sockets: bind(sock4) failed: %m");
321 			exit(1);
322 		}
323 
324 		/* Register an NTP callback for recv/timeout */
325 		ev_sock4 = event_new(base, sock4,
326 				     EV_TIMEOUT | EV_READ | EV_PERSIST,
327 				     &sock_cb, NULL);
328 		if (NULL == ev_sock4) {
329 			msyslog(LOG_ERR,
330 				"open_sockets: event_new(base, sock4) failed!");
331 		} else {
332 			event_add(ev_sock4, &wakeup_tv);
333 		}
334 	}
335 
336 	/* We may not always have IPv6... */
337 	if (-1 == sock6 && ipv6_works) {
338 		sock6 = socket(PF_INET6, SOCK_DGRAM, 0);
339 		if (-1 == sock6 && ipv6_works) {
340 			/* error getting a socket */
341 			msyslog(LOG_ERR, "open_sockets: socket(PF_INET6) failed: %m");
342 			exit(1);
343 		}
344 		/* Make it non-blocking */
345 		make_socket_nonblocking(sock6);
346 
347 		/* Let's try using a wildcard... */
348 		ZERO(name);
349 		AF(&name) = AF_INET6;
350 		SET_ADDR6N(&name, in6addr_any);
351 		SET_PORT(&name, (HAVE_OPT(USERESERVEDPORT) ? 123 : 0));
352 
353 		if (-1 == bind(sock6, &name.sa,
354 			       SOCKLEN(&name))) {
355 			msyslog(LOG_ERR, "open_sockets: bind(sock6) failed: %m");
356 			exit(1);
357 		}
358 		/* Register an NTP callback for recv/timeout */
359 		ev_sock6 = event_new(base, sock6,
360 				     EV_TIMEOUT | EV_READ | EV_PERSIST,
361 				     &sock_cb, NULL);
362 		if (NULL == ev_sock6) {
363 			msyslog(LOG_ERR,
364 				"open_sockets: event_new(base, sock6) failed!");
365 		} else {
366 			event_add(ev_sock6, &wakeup_tv);
367 		}
368 	}
369 
370 	return;
371 }
372 
373 
374 /*
375 ** handle_lookup
376 */
377 void
378 handle_lookup(
379 	const char *name,
380 	int flags
381 	)
382 {
383 	struct addrinfo	hints;	/* Local copy is OK */
384 	struct dns_ctx *ctx;
385 	char *		name_copy;
386 	size_t		name_sz;
387 	size_t		octets;
388 
389 	TRACE(1, ("handle_lookup(%s,%#x)\n", name, flags));
390 
391 	ZERO(hints);
392 	hints.ai_family = ai_fam_pref;
393 	hints.ai_flags = AI_CANONNAME | Z_AI_NUMERICSERV;
394 	/*
395 	** Unless we specify a socktype, we'll get at least two
396 	** entries for each address: one for TCP and one for
397 	** UDP. That's not what we want.
398 	*/
399 	hints.ai_socktype = SOCK_DGRAM;
400 	hints.ai_protocol = IPPROTO_UDP;
401 
402 	name_sz = 1 + strlen(name);
403 	octets = sizeof(*ctx) + name_sz;	// Space for a ctx and the name
404 	ctx = emalloc_zero(octets);		// ctx at ctx[0]
405 	name_copy = (char *)(ctx + 1);		// Put the name at ctx[1]
406 	memcpy(name_copy, name, name_sz);	// copy the name to ctx[1]
407 	ctx->name = name_copy;			// point to it...
408 	ctx->flags = flags;
409 	ctx->timeout = response_tv;
410 	ctx->key = NULL;
411 
412 	/* The following should arguably be passed in... */
413 	if (ENABLED_OPT(AUTHENTICATION)) {
414 		ctx->key_id = OPT_VALUE_AUTHENTICATION;
415 		get_key(ctx->key_id, &ctx->key);
416 		if (NULL == ctx->key) {
417 			fprintf(stderr, "%s: Authentication with keyID %d requested, but no matching keyID found in <%s>!\n",
418 				progname, ctx->key_id, OPT_ARG(KEYFILE));
419 			exit(1);
420 		}
421 	} else {
422 		ctx->key_id = -1;
423 	}
424 
425 	++n_pending_dns;
426 	getaddrinfo_sometime(name, "123", &hints, 0,
427 			     &sntp_name_resolved, ctx);
428 }
429 
430 
431 /*
432 ** DNS Callback:
433 ** - For each IP:
434 ** - - open a socket
435 ** - - increment n_pending_ntp
436 ** - - send a request if this is a Unicast callback
437 ** - - queue wait for response
438 ** - decrement n_pending_dns
439 */
440 void
441 sntp_name_resolved(
442 	int			rescode,
443 	int			gai_errno,
444 	void *			context,
445 	const char *		name,
446 	const char *		service,
447 	const struct addrinfo *	hints,
448 	const struct addrinfo *	addr
449 	)
450 {
451 	struct dns_ctx *	dctx;
452 	sent_pkt *		spkt;
453 	const struct addrinfo *	ai;
454 	SOCKET			sock;
455 	u_int			xmt_delay_v4;
456 	u_int			xmt_delay_v6;
457 	u_int			xmt_delay;
458 	size_t			octets;
459 
460 	xmt_delay_v4 = 0;
461 	xmt_delay_v6 = 0;
462 	dctx = context;
463 	if (rescode) {
464 #ifdef EAI_SYSTEM
465 		if (EAI_SYSTEM == rescode) {
466 			errno = gai_errno;
467 			mfprintf(stderr, "%s lookup error %m\n",
468 				 dctx->name);
469 		} else
470 #endif
471 			fprintf(stderr, "%s lookup error %s\n",
472 				dctx->name, gai_strerror(rescode));
473 	} else {
474 		TRACE(3, ("%s [%s]\n", dctx->name,
475 			  (addr->ai_canonname != NULL)
476 			      ? addr->ai_canonname
477 			      : ""));
478 
479 		for (ai = addr; ai != NULL; ai = ai->ai_next) {
480 
481 			if (check_kod(ai))
482 				continue;
483 
484 			switch (ai->ai_family) {
485 
486 			case AF_INET:
487 				sock = sock4;
488 				xmt_delay = xmt_delay_v4;
489 				xmt_delay_v4++;
490 				break;
491 
492 			case AF_INET6:
493 				if (!ipv6_works)
494 					continue;
495 
496 				sock = sock6;
497 				xmt_delay = xmt_delay_v6;
498 				xmt_delay_v6++;
499 				break;
500 
501 			default:
502 				msyslog(LOG_ERR, "sntp_name_resolved: unexpected ai_family: %d",
503 					ai->ai_family);
504 				exit(1);
505 				break;
506 			}
507 
508 			/*
509 			** We're waiting for a response for either unicast
510 			** or broadcast, so...
511 			*/
512 			++n_pending_ntp;
513 
514 			/* If this is for a unicast IP, queue a request */
515 			if (dctx->flags & CTX_UCST) {
516 				spkt = emalloc_zero(sizeof(*spkt));
517 				spkt->dctx = dctx;
518 				octets = min(ai->ai_addrlen, sizeof(spkt->addr));
519 				memcpy(&spkt->addr, ai->ai_addr, octets);
520 				queue_xmt(sock, dctx, spkt, xmt_delay);
521 			}
522 		}
523 	}
524 	/* n_pending_dns really should be >0 here... */
525 	--n_pending_dns;
526 	check_exit_conditions();
527 }
528 
529 
530 /*
531 ** queue_xmt
532 */
533 void
534 queue_xmt(
535 	SOCKET			sock,
536 	struct dns_ctx *	dctx,
537 	sent_pkt *		spkt,
538 	u_int			xmt_delay
539 	)
540 {
541 	sockaddr_u *	dest;
542 	sent_pkt **	pkt_listp;
543 	sent_pkt *	match;
544 	xmt_ctx *	xctx;
545 	struct timeval	start_cb;
546 	struct timeval	delay;
547 
548 	dest = &spkt->addr;
549 	if (IS_IPV6(dest))
550 		pkt_listp = &v6_pkts_list;
551 	else
552 		pkt_listp = &v4_pkts_list;
553 
554 	/* reject attempts to add address already listed */
555 	for (match = *pkt_listp; match != NULL; match = match->link) {
556 		if (ADDR_PORT_EQ(&spkt->addr, &match->addr)) {
557 			if (strcasecmp(spkt->dctx->name,
558 				       match->dctx->name))
559 				printf("%s %s duplicate address from %s ignored.\n",
560 				       sptoa(&match->addr),
561 				       match->dctx->name,
562 				       spkt->dctx->name);
563 			else
564 				printf("%s %s, duplicate address ignored.\n",
565 				       sptoa(&match->addr),
566 				       match->dctx->name);
567 			dec_pending_ntp(spkt->dctx->name, &spkt->addr);
568 			free(spkt);
569 			return;
570 		}
571 	}
572 
573 	LINK_SLIST(*pkt_listp, spkt, link);
574 
575 	xctx = emalloc_zero(sizeof(*xctx));
576 	xctx->sock = sock;
577 	xctx->spkt = spkt;
578 	gettimeofday_cached(base, &start_cb);
579 	xctx->sched = start_cb.tv_sec + (2 * xmt_delay);
580 
581 	LINK_SORT_SLIST(xmt_q, xctx, (xctx->sched < L_S_S_CUR()->sched),
582 			link, xmt_ctx);
583 	if (xmt_q == xctx) {
584 		/*
585 		 * The new entry is the first scheduled.  The timer is
586 		 * either not active or is set for the second xmt
587 		 * context in xmt_q.
588 		 */
589 		if (NULL == ev_xmt_timer)
590 			ev_xmt_timer = event_new(base, INVALID_SOCKET,
591 						 EV_TIMEOUT,
592 						 &xmt_timer_cb, NULL);
593 		if (NULL == ev_xmt_timer) {
594 			msyslog(LOG_ERR,
595 				"queue_xmt: event_new(base, -1, EV_TIMEOUT) failed!");
596 			exit(1);
597 		}
598 		ZERO(delay);
599 		if (xctx->sched > start_cb.tv_sec)
600 			delay.tv_sec = xctx->sched - start_cb.tv_sec;
601 		event_add(ev_xmt_timer, &delay);
602 		TRACE(2, ("queue_xmt: xmt timer for %u usec\n",
603 			  (u_int)delay.tv_usec));
604 	}
605 }
606 
607 
608 /*
609 ** xmt_timer_cb
610 */
611 void
612 xmt_timer_cb(
613 	evutil_socket_t	fd,
614 	short		what,
615 	void *		ctx
616 	)
617 {
618 	struct timeval	start_cb;
619 	struct timeval	delay;
620 	xmt_ctx *	x;
621 
622 	UNUSED_ARG(fd);
623 	UNUSED_ARG(ctx);
624 	DEBUG_INSIST(EV_TIMEOUT == what);
625 
626 	if (NULL == xmt_q || shutting_down)
627 		return;
628 	gettimeofday_cached(base, &start_cb);
629 	if (xmt_q->sched <= start_cb.tv_sec) {
630 		UNLINK_HEAD_SLIST(x, xmt_q, link);
631 		TRACE(2, ("xmt_timer_cb: at .%6.6u -> %s\n",
632 			  (u_int)start_cb.tv_usec, stoa(&x->spkt->addr)));
633 		xmt(x);
634 		free(x);
635 		if (NULL == xmt_q)
636 			return;
637 	}
638 	if (xmt_q->sched <= start_cb.tv_sec) {
639 		event_add(ev_xmt_timer, &gap);
640 		TRACE(2, ("xmt_timer_cb: at .%6.6u gap %6.6u\n",
641 			  (u_int)start_cb.tv_usec,
642 			  (u_int)gap.tv_usec));
643 	} else {
644 		delay.tv_sec = xmt_q->sched - start_cb.tv_sec;
645 		delay.tv_usec = 0;
646 		event_add(ev_xmt_timer, &delay);
647 		TRACE(2, ("xmt_timer_cb: at .%6.6u next %ld seconds\n",
648 			  (u_int)start_cb.tv_usec,
649 			  (long)delay.tv_sec));
650 	}
651 }
652 
653 
654 /*
655 ** xmt()
656 */
657 void
658 xmt(
659 	xmt_ctx *	xctx
660 	)
661 {
662 	SOCKET		sock = xctx->sock;
663 	struct dns_ctx *dctx = xctx->spkt->dctx;
664 	sent_pkt *	spkt = xctx->spkt;
665 	sockaddr_u *	dst = &spkt->addr;
666 	struct timeval	tv_xmt;
667 	struct pkt	x_pkt;
668 	size_t		pkt_len;
669 	int		sent;
670 
671 	if (0 != gettimeofday(&tv_xmt, NULL)) {
672 		msyslog(LOG_ERR,
673 			"xmt: gettimeofday() failed: %m");
674 		exit(1);
675 	}
676 	tv_xmt.tv_sec += JAN_1970;
677 
678 	pkt_len = generate_pkt(&x_pkt, &tv_xmt, dctx->key_id,
679 			       dctx->key);
680 
681 	sent = sendpkt(sock, dst, &x_pkt, pkt_len);
682 	if (sent) {
683 		/* Save the packet we sent... */
684 		memcpy(&spkt->x_pkt, &x_pkt, min(sizeof(spkt->x_pkt),
685 		       pkt_len));
686 		spkt->stime = tv_xmt.tv_sec - JAN_1970;
687 
688 		TRACE(2, ("xmt: %lx.%6.6u %s %s\n", (u_long)tv_xmt.tv_sec,
689 			  (u_int)tv_xmt.tv_usec, dctx->name, stoa(dst)));
690 	} else {
691 		dec_pending_ntp(dctx->name, dst);
692 	}
693 
694 	return;
695 }
696 
697 
698 /*
699  * timeout_queries() -- give up on unrequited NTP queries
700  */
701 void
702 timeout_queries(void)
703 {
704 	struct timeval	start_cb;
705 	u_int		idx;
706 	sent_pkt *	head;
707 	sent_pkt *	spkt;
708 	sent_pkt *	spkt_next;
709 	long		age;
710 	int didsomething = 0;
711 
712 	TRACE(3, ("timeout_queries: called to check %u items\n",
713 		  (unsigned)COUNTOF(fam_listheads)));
714 
715 	gettimeofday_cached(base, &start_cb);
716 	for (idx = 0; idx < COUNTOF(fam_listheads); idx++) {
717 		head = fam_listheads[idx];
718 		for (spkt = head; spkt != NULL; spkt = spkt_next) {
719 			char xcst;
720 
721 			didsomething = 1;
722 			switch (spkt->dctx->flags & CTX_xCST) {
723 			    case CTX_BCST:
724 				xcst = 'B';
725 				break;
726 
727 			    case CTX_UCST:
728 				xcst = 'U';
729 				break;
730 
731 			    default:
732 				INSIST(!"spkt->dctx->flags neither UCST nor BCST");
733 				break;
734 			}
735 
736 			spkt_next = spkt->link;
737 			if (0 == spkt->stime || spkt->done)
738 				continue;
739 			age = start_cb.tv_sec - spkt->stime;
740 			TRACE(3, ("%s %s %cCST age %ld\n",
741 				  stoa(&spkt->addr),
742 				  spkt->dctx->name, xcst, age));
743 			if (age > response_timeout)
744 				timeout_query(spkt);
745 		}
746 	}
747 	// Do we care about didsomething?
748 	TRACE(3, ("timeout_queries: didsomething is %d, age is %ld\n",
749 		  didsomething, (long) (start_cb.tv_sec - start_tv.tv_sec)));
750 	if (start_cb.tv_sec - start_tv.tv_sec > response_timeout) {
751 		TRACE(3, ("timeout_queries: bail!\n"));
752 		event_base_loopexit(base, NULL);
753 		shutting_down = TRUE;
754 	}
755 }
756 
757 
758 void dec_pending_ntp(
759 	const char *	name,
760 	sockaddr_u *	server
761 	)
762 {
763 	if (n_pending_ntp > 0) {
764 		--n_pending_ntp;
765 		check_exit_conditions();
766 	} else {
767 		INSIST(0 == n_pending_ntp);
768 		TRACE(1, ("n_pending_ntp was zero before decrement for %s\n",
769 			  hostnameaddr(name, server)));
770 	}
771 }
772 
773 
774 void timeout_query(
775 	sent_pkt *	spkt
776 	)
777 {
778 	sockaddr_u *	server;
779 	char		xcst;
780 
781 
782 	switch (spkt->dctx->flags & CTX_xCST) {
783 	    case CTX_BCST:
784 		xcst = 'B';
785 		break;
786 
787 	    case CTX_UCST:
788 		xcst = 'U';
789 		break;
790 
791 	    default:
792 		INSIST(!"spkt->dctx->flags neither UCST nor BCST");
793 		break;
794 	}
795 	spkt->done = TRUE;
796 	server = &spkt->addr;
797 	msyslog(LOG_INFO, "%s no %cCST response after %d seconds",
798 		hostnameaddr(spkt->dctx->name, server), xcst,
799 		response_timeout);
800 	dec_pending_ntp(spkt->dctx->name, server);
801 	return;
802 }
803 
804 
805 /*
806 ** check_kod
807 */
808 int
809 check_kod(
810 	const struct addrinfo *	ai
811 	)
812 {
813 	char *hostname;
814 	struct kod_entry *reason;
815 
816 	/* Is there a KoD on file for this address? */
817 	hostname = addrinfo_to_str(ai);
818 	TRACE(2, ("check_kod: checking <%s>\n", hostname));
819 	if (search_entry(hostname, &reason)) {
820 		printf("prior KoD for %s, skipping.\n",
821 			hostname);
822 		free(reason);
823 		free(hostname);
824 
825 		return 1;
826 	}
827 	free(hostname);
828 
829 	return 0;
830 }
831 
832 
833 /*
834 ** Socket readable/timeout Callback:
835 ** Read in the packet
836 ** Unicast:
837 ** - close socket
838 ** - decrement n_pending_ntp
839 ** - If packet is good, set the time and "exit"
840 ** Broadcast:
841 ** - If packet is good, set the time and "exit"
842 */
843 void
844 sock_cb(
845 	evutil_socket_t fd,
846 	short what,
847 	void *ptr
848 	)
849 {
850 	sockaddr_u	sender;
851 	sockaddr_u *	psau;
852 	sent_pkt **	p_pktlist;
853 	sent_pkt *	spkt;
854 	int		rpktl;
855 	int		rc;
856 
857 	INSIST(sock4 == fd || sock6 == fd);
858 
859 	TRACE(3, ("sock_cb: event on sock%s:%s%s%s%s\n",
860 		  (fd == sock6)
861 		      ? "6"
862 		      : "4",
863 		  (what & EV_TIMEOUT) ? " timeout" : "",
864 		  (what & EV_READ)    ? " read" : "",
865 		  (what & EV_WRITE)   ? " write" : "",
866 		  (what & EV_SIGNAL)  ? " signal" : ""));
867 
868 	if (!(EV_READ & what)) {
869 		if (EV_TIMEOUT & what)
870 			timeout_queries();
871 
872 		return;
873 	}
874 
875 	/* Read in the packet */
876 	rpktl = recvdata(fd, &sender, &rbuf, sizeof(rbuf));
877 	if (rpktl < 0) {
878 		msyslog(LOG_DEBUG, "recvfrom error %m");
879 		return;
880 	}
881 
882 	if (sock6 == fd)
883 		p_pktlist = &v6_pkts_list;
884 	else
885 		p_pktlist = &v4_pkts_list;
886 
887 	for (spkt = *p_pktlist; spkt != NULL; spkt = spkt->link) {
888 		psau = &spkt->addr;
889 		if (SOCK_EQ(&sender, psau))
890 			break;
891 	}
892 	if (NULL == spkt) {
893 		msyslog(LOG_WARNING,
894 			"Packet from unexpected source %s dropped",
895 			sptoa(&sender));
896 		return;
897 	}
898 
899 	TRACE(1, ("sock_cb: %s %s\n", spkt->dctx->name,
900 		  sptoa(&sender)));
901 
902 	rpktl = process_pkt(&r_pkt, &sender, rpktl, MODE_SERVER,
903 			    &spkt->x_pkt, "sock_cb");
904 
905 	TRACE(2, ("sock_cb: process_pkt returned %d\n", rpktl));
906 
907 	/* If this is a Unicast packet, one down ... */
908 	if (!spkt->done && (CTX_UCST & spkt->dctx->flags)) {
909 		dec_pending_ntp(spkt->dctx->name, &spkt->addr);
910 		spkt->done = TRUE;
911 	}
912 
913 
914 	/* If the packet is good, set the time and we're all done */
915 	rc = handle_pkt(rpktl, &r_pkt, &spkt->addr, spkt->dctx->name);
916 	if (0 != rc)
917 		TRACE(1, ("sock_cb: handle_pkt() returned %d\n", rc));
918 	check_exit_conditions();
919 }
920 
921 
922 /*
923  * check_exit_conditions()
924  *
925  * If sntp has a reply, ask the event loop to stop after this round of
926  * callbacks, unless --wait was used.
927  */
928 void
929 check_exit_conditions(void)
930 {
931 	if ((0 == n_pending_ntp && 0 == n_pending_dns) ||
932 	    (time_derived && !HAVE_OPT(WAIT))) {
933 		event_base_loopexit(base, NULL);
934 		shutting_down = TRUE;
935 	} else {
936 		TRACE(2, ("%d NTP and %d name queries pending\n",
937 			  n_pending_ntp, n_pending_dns));
938 	}
939 }
940 
941 
942 /*
943  * sntp_addremove_fd() is invoked by the intres blocking worker code
944  * to read from a pipe, or to stop same.
945  */
946 void sntp_addremove_fd(
947 	int	fd,
948 	int	is_pipe,
949 	int	remove_it
950 	)
951 {
952 	u_int		idx;
953 	blocking_child *c;
954 	struct event *	ev;
955 
956 #ifdef HAVE_SOCKETPAIR
957 	if (is_pipe) {
958 		/* sntp only asks for EV_FEATURE_FDS without HAVE_SOCKETPAIR */
959 		msyslog(LOG_ERR, "fatal: pipes not supported on systems with socketpair()");
960 		exit(1);
961 	}
962 #endif
963 
964 	c = NULL;
965 	for (idx = 0; idx < blocking_children_alloc; idx++) {
966 		c = blocking_children[idx];
967 		if (NULL == c)
968 			continue;
969 		if (fd == c->resp_read_pipe)
970 			break;
971 	}
972 	if (idx == blocking_children_alloc)
973 		return;
974 
975 	if (remove_it) {
976 		ev = c->resp_read_ctx;
977 		c->resp_read_ctx = NULL;
978 		event_del(ev);
979 		event_free(ev);
980 
981 		return;
982 	}
983 
984 	ev = event_new(base, fd, EV_READ | EV_PERSIST,
985 		       &worker_resp_cb, c);
986 	if (NULL == ev) {
987 		msyslog(LOG_ERR,
988 			"sntp_addremove_fd: event_new(base, fd) failed!");
989 		return;
990 	}
991 	c->resp_read_ctx = ev;
992 	event_add(ev, NULL);
993 }
994 
995 
996 /* called by forked intres child to close open descriptors */
997 #ifdef WORK_FORK
998 void
999 kill_asyncio(
1000 	int	startfd
1001 	)
1002 {
1003 	if (INVALID_SOCKET != sock4) {
1004 		closesocket(sock4);
1005 		sock4 = INVALID_SOCKET;
1006 	}
1007 	if (INVALID_SOCKET != sock6) {
1008 		closesocket(sock6);
1009 		sock6 = INVALID_SOCKET;
1010 	}
1011 	if (INVALID_SOCKET != bsock4) {
1012 		closesocket(sock4);
1013 		sock4 = INVALID_SOCKET;
1014 	}
1015 	if (INVALID_SOCKET != bsock6) {
1016 		closesocket(sock6);
1017 		sock6 = INVALID_SOCKET;
1018 	}
1019 }
1020 #endif
1021 
1022 
1023 /*
1024  * worker_resp_cb() is invoked when resp_read_pipe is readable.
1025  */
1026 void
1027 worker_resp_cb(
1028 	evutil_socket_t	fd,
1029 	short		what,
1030 	void *		ctx	/* blocking_child * */
1031 	)
1032 {
1033 	blocking_child *	c;
1034 
1035 	DEBUG_INSIST(EV_READ & what);
1036 	c = ctx;
1037 	DEBUG_INSIST(fd == c->resp_read_pipe);
1038 	process_blocking_resp(c);
1039 }
1040 
1041 
1042 /*
1043  * intres_timeout_req(s) is invoked in the parent to schedule an idle
1044  * timeout to fire in s seconds, if not reset earlier by a call to
1045  * intres_timeout_req(0), which clears any pending timeout.  When the
1046  * timeout expires, worker_idle_timer_fired() is invoked (again, in the
1047  * parent).
1048  *
1049  * sntp and ntpd each provide implementations adapted to their timers.
1050  */
1051 void
1052 intres_timeout_req(
1053 	u_int	seconds		/* 0 cancels */
1054 	)
1055 {
1056 	struct timeval	tv_to;
1057 
1058 	if (NULL == ev_worker_timeout) {
1059 		ev_worker_timeout = event_new(base, -1,
1060 					      EV_TIMEOUT | EV_PERSIST,
1061 					      &worker_timeout, NULL);
1062 		DEBUG_INSIST(NULL != ev_worker_timeout);
1063 	} else {
1064 		event_del(ev_worker_timeout);
1065 	}
1066 	if (0 == seconds)
1067 		return;
1068 	tv_to.tv_sec = seconds;
1069 	tv_to.tv_usec = 0;
1070 	event_add(ev_worker_timeout, &tv_to);
1071 }
1072 
1073 
1074 void
1075 worker_timeout(
1076 	evutil_socket_t	fd,
1077 	short		what,
1078 	void *		ctx
1079 	)
1080 {
1081 	UNUSED_ARG(fd);
1082 	UNUSED_ARG(ctx);
1083 
1084 	DEBUG_REQUIRE(EV_TIMEOUT & what);
1085 	worker_idle_timer_fired();
1086 }
1087 
1088 
1089 void
1090 sntp_libevent_log_cb(
1091 	int		severity,
1092 	const char *	msg
1093 	)
1094 {
1095 	int		level;
1096 
1097 	switch (severity) {
1098 
1099 	default:
1100 	case _EVENT_LOG_DEBUG:
1101 		level = LOG_DEBUG;
1102 		break;
1103 
1104 	case _EVENT_LOG_MSG:
1105 		level = LOG_NOTICE;
1106 		break;
1107 
1108 	case _EVENT_LOG_WARN:
1109 		level = LOG_WARNING;
1110 		break;
1111 
1112 	case _EVENT_LOG_ERR:
1113 		level = LOG_ERR;
1114 		break;
1115 	}
1116 
1117 	msyslog(level, "%s", msg);
1118 }
1119 
1120 
1121 int
1122 generate_pkt (
1123 	struct pkt *x_pkt,
1124 	const struct timeval *tv_xmt,
1125 	int key_id,
1126 	struct key *pkt_key
1127 	)
1128 {
1129 	l_fp	xmt_fp;
1130 	int	pkt_len;
1131 	int	mac_size;
1132 
1133 	pkt_len = LEN_PKT_NOMAC;
1134 	ZERO(*x_pkt);
1135 	TVTOTS(tv_xmt, &xmt_fp);
1136 	HTONL_FP(&xmt_fp, &x_pkt->xmt);
1137 	x_pkt->stratum = STRATUM_TO_PKT(STRATUM_UNSPEC);
1138 	x_pkt->ppoll = 8;
1139 	/* FIXME! Modus broadcast + adr. check -> bdr. pkt */
1140 	set_li_vn_mode(x_pkt, LEAP_NOTINSYNC, ntpver, 3);
1141 	if (debug > 0) {
1142 		printf("generate_pkt: key_id %d, key pointer %p\n", key_id, pkt_key);
1143 	}
1144 	if (pkt_key != NULL) {
1145 		x_pkt->exten[0] = htonl(key_id);
1146 		mac_size = make_mac(x_pkt, pkt_len, MAX_MDG_LEN,
1147 				    pkt_key, (char *)&x_pkt->exten[1]);
1148 		if (mac_size > 0)
1149 			pkt_len += mac_size + KEY_MAC_LEN;
1150 #ifdef DEBUG
1151 		if (debug > 0) {
1152 			printf("generate_pkt: mac_size is %d\n", mac_size);
1153 		}
1154 #endif
1155 
1156 	}
1157 	return pkt_len;
1158 }
1159 
1160 
1161 int
1162 handle_pkt(
1163 	int		rpktl,
1164 	struct pkt *	rpkt,
1165 	sockaddr_u *	host,
1166 	const char *	hostname
1167 	)
1168 {
1169 	char		disptxt[32];
1170 	const char *	addrtxt;
1171 	struct timeval	tv_dst;
1172 	int		cnt;
1173 	int		sw_case;
1174 	int		digits;
1175 	int		stratum;
1176 	char *		ref;
1177 	char *		ts_str;
1178 	const char *	leaptxt;
1179 	double		offset;
1180 	double		precision;
1181 	double		synch_distance;
1182 	char *		p_SNTP_PRETEND_TIME;
1183 	time_t		pretend_time;
1184 #if SIZEOF_TIME_T == 8
1185 	long long	ll;
1186 #else
1187 	long		l;
1188 #endif
1189 
1190 	ts_str = NULL;
1191 
1192 	if (rpktl > 0)
1193 		sw_case = 1;
1194 	else
1195 		sw_case = rpktl;
1196 
1197 	switch (sw_case) {
1198 
1199 	case SERVER_UNUSEABLE:
1200 		return -1;
1201 		break;
1202 
1203 	case PACKET_UNUSEABLE:
1204 		break;
1205 
1206 	case SERVER_AUTH_FAIL:
1207 		break;
1208 
1209 	case KOD_DEMOBILIZE:
1210 		/* Received a DENY or RESTR KOD packet */
1211 		addrtxt = stoa(host);
1212 		ref = (char *)&rpkt->refid;
1213 		add_entry(addrtxt, ref);
1214 		msyslog(LOG_WARNING, "KOD code %c%c%c%c from %s %s",
1215 			ref[0], ref[1], ref[2], ref[3], addrtxt, hostname);
1216 		break;
1217 
1218 	case KOD_RATE:
1219 		/*
1220 		** Hmm...
1221 		** We should probably call add_entry() with an
1222 		** expiration timestamp of several seconds in the future,
1223 		** and back-off even more if we get more RATE responses.
1224 		*/
1225 		break;
1226 
1227 	case 1:
1228 		TRACE(3, ("handle_pkt: %d bytes from %s %s\n",
1229 			  rpktl, stoa(host), hostname));
1230 
1231 		gettimeofday_cached(base, &tv_dst);
1232 
1233 		p_SNTP_PRETEND_TIME = getenv("SNTP_PRETEND_TIME");
1234 		if (p_SNTP_PRETEND_TIME) {
1235 			pretend_time = 0;
1236 #if SIZEOF_TIME_T == 4
1237 			if (1 == sscanf(p_SNTP_PRETEND_TIME, "%ld", &l))
1238 				pretend_time = (time_t)l;
1239 #elif SIZEOF_TIME_T == 8
1240 			if (1 == sscanf(p_SNTP_PRETEND_TIME, "%lld", &ll))
1241 				pretend_time = (time_t)ll;
1242 #else
1243 # include "GRONK: unexpected value for SIZEOF_TIME_T"
1244 #endif
1245 			if (0 != pretend_time)
1246 				tv_dst.tv_sec = pretend_time;
1247 		}
1248 
1249 		offset_calculation(rpkt, rpktl, &tv_dst, &offset,
1250 				   &precision, &synch_distance);
1251 		time_derived = TRUE;
1252 
1253 		for (digits = 0; (precision *= 10.) < 1.; ++digits)
1254 			/* empty */ ;
1255 		if (digits > 6)
1256 			digits = 6;
1257 
1258 		ts_str = tv_to_str(&tv_dst);
1259 		stratum = rpkt->stratum;
1260 		if (0 == stratum)
1261 				stratum = 16;
1262 
1263 		if (synch_distance > 0.) {
1264 			cnt = snprintf(disptxt, sizeof(disptxt),
1265 				       " +/- %f", synch_distance);
1266 			if ((size_t)cnt >= sizeof(disptxt))
1267 				snprintf(disptxt, sizeof(disptxt),
1268 					 "ERROR %d >= %d", cnt,
1269 					 (int)sizeof(disptxt));
1270 		} else {
1271 			disptxt[0] = '\0';
1272 		}
1273 
1274 		switch (PKT_LEAP(rpkt->li_vn_mode)) {
1275 		    case LEAP_NOWARNING:
1276 		    	leaptxt = "no-leap";
1277 			break;
1278 		    case LEAP_ADDSECOND:
1279 		    	leaptxt = "add-leap";
1280 			break;
1281 		    case LEAP_DELSECOND:
1282 		    	leaptxt = "del-leap";
1283 			break;
1284 		    case LEAP_NOTINSYNC:
1285 		    	leaptxt = "unsync";
1286 			break;
1287 		    default:
1288 		    	leaptxt = "LEAP-ERROR";
1289 			break;
1290 		}
1291 
1292 		msyslog(LOG_INFO, "%s %+.*f%s %s s%d %s%s", ts_str,
1293 			digits, offset, disptxt,
1294 			hostnameaddr(hostname, host), stratum,
1295 			leaptxt,
1296 			(time_adjusted)
1297 			    ? " [excess]"
1298 			    : "");
1299 		free(ts_str);
1300 
1301 		if (p_SNTP_PRETEND_TIME)
1302 			return 0;
1303 
1304 		if (!time_adjusted &&
1305 		    (ENABLED_OPT(STEP) || ENABLED_OPT(SLEW)))
1306 			return set_time(offset);
1307 
1308 		return EX_OK;
1309 	}
1310 
1311 	return 1;
1312 }
1313 
1314 
1315 void
1316 offset_calculation(
1317 	struct pkt *rpkt,
1318 	int rpktl,
1319 	struct timeval *tv_dst,
1320 	double *offset,
1321 	double *precision,
1322 	double *synch_distance
1323 	)
1324 {
1325 	l_fp p_rec, p_xmt, p_ref, p_org, tmp, dst;
1326 	u_fp p_rdly, p_rdsp;
1327 	double t21, t34, delta;
1328 
1329 	/* Convert timestamps from network to host byte order */
1330 	p_rdly = NTOHS_FP(rpkt->rootdelay);
1331 	p_rdsp = NTOHS_FP(rpkt->rootdisp);
1332 	NTOHL_FP(&rpkt->reftime, &p_ref);
1333 	NTOHL_FP(&rpkt->org, &p_org);
1334 	NTOHL_FP(&rpkt->rec, &p_rec);
1335 	NTOHL_FP(&rpkt->xmt, &p_xmt);
1336 
1337 	*precision = LOGTOD(rpkt->precision);
1338 
1339 	TRACE(3, ("offset_calculation: LOGTOD(rpkt->precision): %f\n", *precision));
1340 
1341 	/* Compute offset etc. */
1342 	tmp = p_rec;
1343 	L_SUB(&tmp, &p_org);
1344 	LFPTOD(&tmp, t21);
1345 	TVTOTS(tv_dst, &dst);
1346 	dst.l_ui += JAN_1970;
1347 	tmp = p_xmt;
1348 	L_SUB(&tmp, &dst);
1349 	LFPTOD(&tmp, t34);
1350 	*offset = (t21 + t34) / 2.;
1351 	delta = t21 - t34;
1352 
1353 	// synch_distance is:
1354 	// (peer->delay + peer->rootdelay) / 2 + peer->disp
1355 	// + peer->rootdisp + clock_phi * (current_time - peer->update)
1356 	// + peer->jitter;
1357 	//
1358 	// and peer->delay = fabs(peer->offset - p_offset) * 2;
1359 	// and peer->offset needs history, so we're left with
1360 	// p_offset = (t21 + t34) / 2.;
1361 	// peer->disp = 0; (we have no history to augment this)
1362 	// clock_phi = 15e-6;
1363 	// peer->jitter = LOGTOD(sys_precision); (we have no history to augment this)
1364 	// and ntp_proto.c:set_sys_tick_precision() should get us sys_precision.
1365 	//
1366 	// so our answer seems to be:
1367 	//
1368 	// (fabs(t21 + t34) + peer->rootdelay) / 3.
1369 	// + 0 (peer->disp)
1370 	// + peer->rootdisp
1371 	// + 15e-6 (clock_phi)
1372 	// + LOGTOD(sys_precision)
1373 
1374 	INSIST( FPTOD(p_rdly) >= 0. );
1375 #if 1
1376 	*synch_distance = (fabs(t21 + t34) + FPTOD(p_rdly)) / 3.
1377 		+ 0.
1378 		+ FPTOD(p_rdsp)
1379 		+ 15e-6
1380 		+ 0.	/* LOGTOD(sys_precision) when we can get it */
1381 		;
1382 	INSIST( *synch_distance >= 0. );
1383 #else
1384 	*synch_distance = (FPTOD(p_rdly) + FPTOD(p_rdsp))/2.0;
1385 #endif
1386 
1387 #ifdef DEBUG
1388 	if (debug > 3) {
1389 		printf("sntp rootdelay: %f\n", FPTOD(p_rdly));
1390 		printf("sntp rootdisp: %f\n", FPTOD(p_rdsp));
1391 		printf("sntp syncdist: %f\n", *synch_distance);
1392 
1393 		pkt_output(rpkt, rpktl, stdout);
1394 
1395 		printf("sntp offset_calculation: rpkt->reftime:\n");
1396 		l_fp_output(&p_ref, stdout);
1397 		printf("sntp offset_calculation: rpkt->org:\n");
1398 		l_fp_output(&p_org, stdout);
1399 		printf("sntp offset_calculation: rpkt->rec:\n");
1400 		l_fp_output(&p_rec, stdout);
1401 		printf("sntp offset_calculation: rpkt->xmt:\n");
1402 		l_fp_output(&p_xmt, stdout);
1403 	}
1404 #endif
1405 
1406 	TRACE(3, ("sntp offset_calculation:\trec - org t21: %.6f\n"
1407 		  "\txmt - dst t34: %.6f\tdelta: %.6f\toffset: %.6f\n",
1408 		  t21, t34, delta, *offset));
1409 
1410 	return;
1411 }
1412 
1413 
1414 
1415 /* Compute the 8 bits for li_vn_mode */
1416 void
1417 set_li_vn_mode (
1418 	struct pkt *spkt,
1419 	char leap,
1420 	char version,
1421 	char mode
1422 	)
1423 {
1424 	if (leap > 3) {
1425 		msyslog(LOG_DEBUG, "set_li_vn_mode: leap > 3, using max. 3");
1426 		leap = 3;
1427 	}
1428 
1429 	if ((unsigned char)version > 7) {
1430 		msyslog(LOG_DEBUG, "set_li_vn_mode: version < 0 or > 7, using 4");
1431 		version = 4;
1432 	}
1433 
1434 	if (mode > 7) {
1435 		msyslog(LOG_DEBUG, "set_li_vn_mode: mode > 7, using client mode 3");
1436 		mode = 3;
1437 	}
1438 
1439 	spkt->li_vn_mode  = leap << 6;
1440 	spkt->li_vn_mode |= version << 3;
1441 	spkt->li_vn_mode |= mode;
1442 }
1443 
1444 
1445 /*
1446 ** set_time applies 'offset' to the local clock.
1447 */
1448 int
1449 set_time(
1450 	double offset
1451 	)
1452 {
1453 	int rc;
1454 
1455 	if (time_adjusted)
1456 		return EX_OK;
1457 
1458 	/*
1459 	** If we can step but we cannot slew, then step.
1460 	** If we can step or slew and and |offset| > steplimit, then step.
1461 	*/
1462 	if (ENABLED_OPT(STEP) &&
1463 	    (   !ENABLED_OPT(SLEW)
1464 	     || (ENABLED_OPT(SLEW) && (fabs(offset) > steplimit))
1465 	    )) {
1466 		rc = step_systime(offset);
1467 
1468 		/* If there was a problem, can we rely on errno? */
1469 		if (1 == rc)
1470 			time_adjusted = TRUE;
1471 		return (time_adjusted)
1472 			   ? EX_OK
1473 			   : 1;
1474 		/*
1475 		** In case of error, what should we use?
1476 		** EX_UNAVAILABLE?
1477 		** EX_OSERR?
1478 		** EX_NOPERM?
1479 		*/
1480 	}
1481 
1482 	if (ENABLED_OPT(SLEW)) {
1483 		rc = adj_systime(offset);
1484 
1485 		/* If there was a problem, can we rely on errno? */
1486 		if (1 == rc)
1487 			time_adjusted = TRUE;
1488 		return (time_adjusted)
1489 			   ? EX_OK
1490 			   : 1;
1491 		/*
1492 		** In case of error, what should we use?
1493 		** EX_UNAVAILABLE?
1494 		** EX_OSERR?
1495 		** EX_NOPERM?
1496 		*/
1497 	}
1498 
1499 	return EX_SOFTWARE;
1500 }
1501 
1502 
1503 int
1504 libevent_version_ok(void)
1505 {
1506 	ev_uint32_t v_compile_maj;
1507 	ev_uint32_t v_run_maj;
1508 
1509 	v_compile_maj = LIBEVENT_VERSION_NUMBER & 0xffff0000;
1510 	v_run_maj = event_get_version_number() & 0xffff0000;
1511 	if (v_compile_maj != v_run_maj) {
1512 		fprintf(stderr,
1513 			"Incompatible libevent versions: have %s, built with %s\n",
1514 			event_get_version(),
1515 			LIBEVENT_VERSION);
1516 		return 0;
1517 	}
1518 	return 1;
1519 }
1520 
1521 /*
1522  * gettimeofday_cached()
1523  *
1524  * Clones the event_base_gettimeofday_cached() interface but ensures the
1525  * times are always on the gettimeofday() 1970 scale.  Older libevent 2
1526  * sometimes used gettimeofday(), sometimes the since-system-start
1527  * clock_gettime(CLOCK_MONOTONIC), depending on the platform.
1528  *
1529  * It is not cleanly possible to tell which timescale older libevent is
1530  * using.
1531  *
1532  * The strategy involves 1 hour thresholds chosen to be far longer than
1533  * the duration of a round of libevent callbacks, which share a cached
1534  * start-of-round time.  First compare the last cached time with the
1535  * current gettimeofday() time.  If they are within one hour, libevent
1536  * is using the proper timescale so leave the offset 0.  Otherwise,
1537  * compare libevent's cached time and the current time on the monotonic
1538  * scale.  If they are within an hour, libevent is using the monotonic
1539  * scale so calculate the offset to add to such times to bring them to
1540  * gettimeofday()'s scale.
1541  */
1542 int
1543 gettimeofday_cached(
1544 	struct event_base *	b,
1545 	struct timeval *	caller_tv
1546 	)
1547 {
1548 #if defined(_EVENT_HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
1549 	static struct event_base *	cached_b;
1550 	static struct timeval		cached;
1551 	static struct timeval		adj_cached;
1552 	static struct timeval		offset;
1553 	static int			offset_ready;
1554 	struct timeval			latest;
1555 	struct timeval			systemt;
1556 	struct timespec			ts;
1557 	struct timeval			mono;
1558 	struct timeval			diff;
1559 	int				cgt_rc;
1560 	int				gtod_rc;
1561 
1562 	event_base_gettimeofday_cached(b, &latest);
1563 	if (b == cached_b &&
1564 	    !memcmp(&latest, &cached, sizeof(latest))) {
1565 		*caller_tv = adj_cached;
1566 		return 0;
1567 	}
1568 	cached = latest;
1569 	cached_b = b;
1570 	if (!offset_ready) {
1571 		cgt_rc = clock_gettime(CLOCK_MONOTONIC, &ts);
1572 		gtod_rc = gettimeofday(&systemt, NULL);
1573 		if (0 != gtod_rc) {
1574 			msyslog(LOG_ERR,
1575 				"%s: gettimeofday() error %m",
1576 				progname);
1577 			exit(1);
1578 		}
1579 		diff = sub_tval(systemt, latest);
1580 		if (debug > 1)
1581 			printf("system minus cached %+ld.%06ld\n",
1582 			       (long)diff.tv_sec, (long)diff.tv_usec);
1583 		if (0 != cgt_rc || labs((long)diff.tv_sec) < 3600) {
1584 			/*
1585 			 * Either use_monotonic == 0, or this libevent
1586 			 * has been repaired.  Leave offset at zero.
1587 			 */
1588 		} else {
1589 			mono.tv_sec = ts.tv_sec;
1590 			mono.tv_usec = ts.tv_nsec / 1000;
1591 			diff = sub_tval(latest, mono);
1592 			if (debug > 1)
1593 				printf("cached minus monotonic %+ld.%06ld\n",
1594 				       (long)diff.tv_sec, (long)diff.tv_usec);
1595 			if (labs((long)diff.tv_sec) < 3600) {
1596 				/* older libevent2 using monotonic */
1597 				offset = sub_tval(systemt, mono);
1598 				TRACE(1, ("%s: Offsetting libevent CLOCK_MONOTONIC times  by %+ld.%06ld\n",
1599 					 "gettimeofday_cached",
1600 					 (long)offset.tv_sec,
1601 					 (long)offset.tv_usec));
1602 			}
1603 		}
1604 		offset_ready = TRUE;
1605 	}
1606 	adj_cached = add_tval(cached, offset);
1607 	*caller_tv = adj_cached;
1608 
1609 	return 0;
1610 #else
1611 	return event_base_gettimeofday_cached(b, caller_tv);
1612 #endif
1613 }
1614 
1615 /* Dummy function to satisfy libntp/work_fork.c */
1616 extern int set_user_group_ids(void);
1617 int set_user_group_ids(void)
1618 {
1619     return 1;
1620 }
1621