1 /*	$OpenBSD: ntp.c,v 1.92 2006/10/21 07:30:58 henning Exp $ */
2 
3 /*
4  * Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2014
5  *	Thorsten Glaser <tg@mirbsd.org>
6  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
7  * Copyright (c) 2004 Alexander Guy <alexander.guy@andern.org>
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * The following disclaimer must also be retained:
14  *
15  * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
16  * the utmost extent permitted by applicable law, neither express nor
17  * implied; without malicious intent or gross negligence. In no event
18  * may a licensor, author or contributor be held liable for indirect,
19  * direct, other damage, loss, or other issues arising in any way out
20  * of dealing in the work, even if advised of the possibility of such
21  * damage or existence of a defect, except proven that it results out
22  * of said person's immediate fault when using the work as intended.
23  */
24 
25 #include <sys/param.h>
26 #include <sys/time.h>
27 #include <sys/stat.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <paths.h>
31 #include <poll.h>
32 #include <pwd.h>
33 #include <signal.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <time.h>
37 #include <unistd.h>
38 
39 #include "ntpd.h"
40 #include "ntp.h"
41 
42 __RCSID("$MirOS: src/usr.sbin/ntpd/ntp.c,v 1.30 2014/03/13 05:48:24 tg Exp $");
43 
44 extern void arc4random_ctl(unsigned int);
45 
46 #define	PFD_PIPE_MAIN	0
47 #define	PFD_MAX		1
48 
49 volatile sig_atomic_t	 ntp_quit = 0;
50 volatile sig_atomic_t	 ntp_arc4push = 0;
51 struct imsgbuf		*ibuf_main;
52 struct ntpd_conf	*conf;
53 u_int			 peer_cnt;
54 
55 void	ntp_sighdlr(int);
56 int	ntp_dispatch_imsg(void);
57 void	peer_add(struct ntp_peer *);
58 void	peer_remove(struct ntp_peer *);
59 int	offset_compare(const void *, const void *);
60 
61 void
ntp_sighdlr(int sig)62 ntp_sighdlr(int sig)
63 {
64 	switch (sig) {
65 	case SIGINT:
66 	case SIGTERM:
67 		ntp_quit = 1;
68 		break;
69 	case SIGHUP:
70 	case SIGUSR1:
71 		ntp_arc4push = 1;
72 		break;
73 	}
74 }
75 
76 pid_t
ntp_main(int pipe_prnt[2],struct ntpd_conf * nconf)77 ntp_main(int pipe_prnt[2], struct ntpd_conf *nconf)
78 {
79 	int			 a, b, nfds, i, j, idx_peers, timeout, nullfd;
80 	u_int			 pfd_elms = 0, idx2peer_elms = 0;
81 	u_int			 listener_cnt, new_cnt, sent_cnt, trial_cnt;
82 	pid_t			 pid;
83 	struct pollfd		*pfd = NULL;
84 	struct passwd		*pw;
85 	struct servent		*se;
86 	struct listen_addr	*la;
87 	struct ntp_peer		*p;
88 	struct ntp_peer		**idx2peer = NULL;
89 	struct timespec		 tp;
90 	struct stat		 stb;
91 	time_t			 nextaction;
92 	void			*newp;
93 	time_t			 nextstir, nextshuf, now;
94 
95 	switch (pid = fork()) {
96 	case -1:
97 		fatal("cannot fork");
98 		break;
99 	case 0:
100 		break;
101 	default:
102 		return (pid);
103 	}
104 
105 	/* force re-stir directly after fork, before chroot */
106 	(void)arc4random();
107 	nextstir = (now = time(NULL)) + 5400;
108 	nextshuf = now + 120;
109 
110 	if ((se = getservbyname("ntp", "udp")) == NULL)
111 		fatal("getservbyname");
112 
113 	if ((pw = getpwnam(NTPD_USER)) == NULL)
114 		fatal("getpwnam");
115 
116 	if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1)
117 		fatal(NULL);
118 
119 	if (stat(pw->pw_dir, &stb) == -1)
120 		fatal("stat");
121 	if (stb.st_uid != 0 || (stb.st_mode & (S_IWGRP|S_IWOTH)) != 0)
122 		fatal("bad privsep dir permissions");
123 	if (chroot(pw->pw_dir) == -1)
124 		fatal("chroot");
125 	if (chdir("/") == -1)
126 		fatal("chdir(\"/\")");
127 
128 	if (!nconf->debug) {
129 		dup2(nullfd, STDIN_FILENO);
130 		dup2(nullfd, STDOUT_FILENO);
131 		dup2(nullfd, STDERR_FILENO);
132 	}
133 	close(nullfd);
134 
135 	setproctitle("ntp engine");
136 
137 	conf = nconf;
138 	setup_listeners(se, conf, &listener_cnt);
139 
140 	if (setgroups(1, &pw->pw_gid) ||
141 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
142 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
143 		fatal("can't drop privileges");
144 
145 	endservent();
146 
147 	signal(SIGTERM, ntp_sighdlr);
148 	signal(SIGINT, ntp_sighdlr);
149 	signal(SIGPIPE, SIG_IGN);
150 	signal(SIGUSR1, ntp_sighdlr);
151 	signal(SIGHUP, ntp_sighdlr);
152 
153 	close(pipe_prnt[0]);
154 	if ((ibuf_main = malloc(sizeof(struct imsgbuf))) == NULL)
155 		fatal(NULL);
156 	imsg_init(ibuf_main, pipe_prnt[1]);
157 
158 	TAILQ_FOREACH(p, &conf->ntp_peers, entry)
159 		client_peer_init(p);
160 
161 	bzero(&conf->status, sizeof(conf->status));
162 	conf->status.synced = 0;
163 	clock_getres(CLOCK_REALTIME, &tp);
164 	b = 1000000000 / tp.tv_nsec;	/* convert to Hz */
165 	for (a = 0; b > 1; a--, b >>= 1)
166 		;
167 	conf->status.precision = a;
168 	conf->scale = 1;
169 
170 	log_info("ntp engine ready");
171 
172 	peer_cnt = 0;
173 	TAILQ_FOREACH(p, &conf->ntp_peers, entry)
174 		peer_cnt++;
175 
176 	while (ntp_quit == 0) {
177 		if (ntp_arc4push) {
178 			nextstir = 0;
179 			ntp_arc4push = 0;
180 		}
181 
182 		if (nextstir < (now = time(NULL))) {
183 			/* 1.5 hours after start, then every 2 hrs */
184 			arc4random_ctl(2);
185 			nextstir = now + 7200;
186 			nextshuf = now + 600;
187 		} else if (nextshuf < now) {
188 			/* 2min after start, then every 5min except past stir */
189 			arc4random_ctl(0);
190 			nextshuf = now + 300;
191 		}
192 
193 		if (peer_cnt > idx2peer_elms) {
194 			if ((newp = realloc(idx2peer, sizeof(void *) *
195 			    peer_cnt)) == NULL) {
196 				/* panic for now */
197 				log_warn("could not resize idx2peer from %u -> "
198 				    "%u entries", idx2peer_elms, peer_cnt);
199 				fatalx("exiting");
200 			}
201 			idx2peer = newp;
202 			idx2peer_elms = peer_cnt;
203 		}
204 
205 		new_cnt = PFD_MAX + peer_cnt + listener_cnt;
206 		if (new_cnt > pfd_elms) {
207 			if ((newp = realloc(pfd, sizeof(struct pollfd) *
208 			    new_cnt)) == NULL) {
209 				/* panic for now */
210 				log_warn("could not resize pfd from %u -> "
211 				    "%u entries", pfd_elms, new_cnt);
212 				fatalx("exiting");
213 			}
214 			pfd = newp;
215 			pfd_elms = new_cnt;
216 		}
217 
218 		bzero(pfd, sizeof(struct pollfd) * pfd_elms);
219 		bzero(idx2peer, sizeof(void *) * idx2peer_elms);
220 		nextaction = now + 3600;
221 		pfd[PFD_PIPE_MAIN].fd = ibuf_main->fd;
222 		pfd[PFD_PIPE_MAIN].events = POLLIN;
223 
224 		i = 1;
225 		TAILQ_FOREACH(la, &conf->listen_addrs, entry) {
226 			pfd[i].fd = la->fd;
227 			pfd[i].events = POLLIN;
228 			i++;
229 		}
230 
231 		idx_peers = i;
232 		sent_cnt = trial_cnt = 0;
233 		TAILQ_FOREACH(p, &conf->ntp_peers, entry) {
234 			if (p->next > 0 && p->next <= now) {
235 				if (p->state > STATE_DNS_INPROGRESS)
236 					trial_cnt++;
237 				if (client_query(p) == 0)
238 					sent_cnt++;
239 			}
240 			if (p->next > 0 && p->next < nextaction)
241 				nextaction = p->next;
242 
243 			if (p->deadline > 0 && p->deadline < nextaction)
244 				nextaction = p->deadline;
245 			if (p->deadline > 0 && p->deadline <= now) {
246 				timeout = error_interval();
247 				log_debug("no reply from %s received in time, "
248 				    "next query %ds", log_sockaddr(
249 				    (struct sockaddr *)&p->addr->ss), timeout);
250 				if (p->trustlevel >= TRUSTLEVEL_BADPEER &&
251 				    (p->trustlevel /= 2) < TRUSTLEVEL_BADPEER)
252 					chpeertrust(p, false);
253 				client_nextaddr(p);
254 				set_next(p, timeout);
255 			}
256 
257 			if (p->state == STATE_QUERY_SENT &&
258 			    p->query->fd != -1) {
259 				pfd[i].fd = p->query->fd;
260 				pfd[i].events = POLLIN;
261 				idx2peer[i - idx_peers] = p;
262 				i++;
263 			}
264 		}
265 
266 		if (conf->settime &&
267 		    ((trial_cnt > 0 && sent_cnt == 0) || peer_cnt == 0))
268 			priv_settime(0);	/* no good peers, don't wait */
269 
270 		if (ibuf_main->w.queued > 0)
271 			pfd[PFD_PIPE_MAIN].events |= POLLOUT;
272 
273 		timeout = nextaction - now;
274 		if (timeout < 0)
275 			timeout = 0;
276 
277 		if ((nfds = poll(pfd, i, timeout * 1000)) == -1)
278 			if (errno != EINTR) {
279 				log_warn("poll error");
280 				ntp_quit = 1;
281 			}
282 
283 		if (nfds > 0 && (pfd[PFD_PIPE_MAIN].revents & POLLOUT))
284 			if (msgbuf_write(&ibuf_main->w) < 0) {
285 				log_warn("pipe write error (to parent)");
286 				ntp_quit = 1;
287 			}
288 
289 		if (nfds > 0 && pfd[PFD_PIPE_MAIN].revents & (POLLIN|POLLERR)) {
290 			nfds--;
291 			if (ntp_dispatch_imsg() == -1)
292 				ntp_quit = 1;
293 		}
294 
295 		for (j = 1; nfds > 0 && j < idx_peers; j++)
296 			if (pfd[j].revents & (POLLIN|POLLERR)) {
297 				nfds--;
298 				if (server_dispatch(pfd[j].fd, conf) == -1)
299 					ntp_quit = 1;
300 			}
301 
302 		for (; nfds > 0 && j < i; j++)
303 			if (pfd[j].revents & (POLLIN|POLLERR)) {
304 				nfds--;
305 				if (client_dispatch(idx2peer[j - idx_peers],
306 				    conf->settime, conf->trace) == -1)
307 					ntp_quit = 1;
308 			}
309 	}
310 
311 	msgbuf_write(&ibuf_main->w);
312 	msgbuf_clear(&ibuf_main->w);
313 	free(ibuf_main);
314 
315 	log_info("ntp engine exiting");
316 	_exit(0);
317 }
318 
319 int
ntp_dispatch_imsg(void)320 ntp_dispatch_imsg(void)
321 {
322 	struct imsg		 imsg;
323 	int			 n;
324 	struct ntp_peer		*peer, *npeer;
325 	u_int16_t		 dlen;
326 	u_char			*p;
327 	struct ntp_addr		*h;
328 
329 	if ((n = imsg_read(ibuf_main)) == -1)
330 		return (-1);
331 
332 	if (n == 0) {	/* connection closed */
333 		log_warnx("ntp_dispatch_imsg in ntp engine: pipe closed");
334 		return (-1);
335 	}
336 
337 	for (;;) {
338 		if ((n = imsg_get(ibuf_main, &imsg)) == -1)
339 			return (-1);
340 
341 		if (n == 0)
342 			break;
343 
344 		switch (imsg.hdr.type) {
345 		case IMSG_ADJTIME:
346 			memcpy(&n, imsg.data, sizeof(n));
347 			if (n == 1 && !conf->status.synced) {
348 				log_info("clock is now synced");
349 				conf->status.synced = 1;
350 			} else if (n == 0 && conf->status.synced) {
351 				log_info("clock is now unsynced");
352 				conf->status.synced = 0;
353 			}
354 			break;
355 		case IMSG_HOST_DNS:
356 			TAILQ_FOREACH(peer, &conf->ntp_peers, entry)
357 				if (peer->id == imsg.hdr.peerid)
358 					break;
359 			if (peer == NULL) {
360 				log_warnx("IMSG_HOST_DNS with invalid peerID");
361 				break;
362 			}
363 			if (peer->addr != NULL) {
364 				log_warnx("IMSG_HOST_DNS but addr != NULL!");
365 				break;
366 			}
367 
368 			dlen = imsg.hdr.len - IMSG_HEADER_SIZE;
369 			if (dlen == 0) {	/* no data -> temp error */
370 				peer->state = STATE_DNS_TEMPFAIL;
371 				break;
372 			}
373 
374 			p = (u_char *)imsg.data;
375 			while (dlen >= sizeof(struct sockaddr_storage)) {
376 				if ((h = calloc(1, sizeof(struct ntp_addr))) ==
377 				    NULL)
378 					fatal(NULL);
379 				memcpy(&h->ss, p, sizeof(h->ss));
380 				p += sizeof(h->ss);
381 				dlen -= sizeof(h->ss);
382 				if (peer->addr_head.pool) {
383 					npeer = new_peer();
384 					h->next = NULL;
385 					npeer->addr = h;
386 					npeer->addr_head.a = h;
387 					client_peer_init(npeer);
388 					npeer->state = STATE_DNS_DONE;
389 					peer_add(npeer);
390 				} else {
391 					h->next = peer->addr;
392 					peer->addr = h;
393 					peer->addr_head.a = peer->addr;
394 					peer->state = STATE_DNS_DONE;
395 				}
396 			}
397 			if (dlen != 0)
398 				fatalx("IMSG_HOST_DNS: dlen != 0");
399 			if (peer->addr_head.pool)
400 				peer_remove(peer);
401 			else
402 				client_addr_init(peer);
403 			break;
404 		case IMSG_RESET:
405 #if 0	/* XXX maybe use type 1 (n == 1) for SIGHUP? */
406 			memcpy(&n, imsg.data, sizeof(n));
407 			if (n) {
408 				log_warn("invalid IMSG_RESET(%u) received", n);
409 				break;
410 			}
411 #endif
412 			conf->scale = 1;
413 			TAILQ_FOREACH(peer, &conf->ntp_peers, entry) {
414 				bzero(peer->reply, sizeof (peer->reply));
415 				peer->shift = 0;
416 				if (peer->trustlevel > TRUSTLEVEL_RESET)
417 					peer->trustlevel = TRUSTLEVEL_RESET;
418 				set_next(peer, -1);
419 			}
420 			break;
421 		default:
422 			break;
423 		}
424 		imsg_free(&imsg);
425 	}
426 	return (0);
427 }
428 
429 void
peer_add(struct ntp_peer * p)430 peer_add(struct ntp_peer *p)
431 {
432 	TAILQ_INSERT_TAIL(&conf->ntp_peers, p, entry);
433 	peer_cnt++;
434 }
435 
436 void
peer_remove(struct ntp_peer * p)437 peer_remove(struct ntp_peer *p)
438 {
439 	TAILQ_REMOVE(&conf->ntp_peers, p, entry);
440 	free(p);
441 	peer_cnt--;
442 }
443 
444 int
priv_adjtime(void)445 priv_adjtime(void)
446 {
447 	struct ntp_peer	 *p;
448 	int		  offset_cnt = 0, i = 0;
449 	struct ntp_peer	**peers;
450 	double		  offset_median;
451 	int		  weight_cnt, weight_half;
452 
453 	TAILQ_FOREACH(p, &conf->ntp_peers, entry) {
454 		if (conf->trace > 5)
455 			log_info("priv_adjtime, #%02d %s peer, trust %d %s,"
456 			    " st %2d dst %3dms ofs %6.1fms addr %s",
457 			    offset_cnt,
458 			    p->update.good ? "good" : "bad ",
459 			    p->trustlevel,
460 			    p->trustlevel < TRUSTLEVEL_BADPEER ? "bad" : "ok",
461 			    p->update.status.stratum,
462 			    (int)((p->update.delay + .0005) * 1000.),
463 			    p->update.offset * 1000.,
464 			    log_sockaddr((struct sockaddr *)&p->addr->ss));
465 		else if (conf->trace > 3)
466 			log_info("priv_adjtime, #%02d, peer"
467 			    " trustlevel %d %s, %sgood",
468 			    offset_cnt,
469 			    p->trustlevel,
470 			    p->trustlevel < TRUSTLEVEL_BADPEER ? "bad" : "ok",
471 			    p->update.good ? "" : "not ");
472 
473 		if (p->trustlevel < TRUSTLEVEL_BADPEER)
474 			continue;
475 		if (!p->update.good)
476 			return (1);
477 		offset_cnt++;
478 	}
479 
480 	if (offset_cnt == 0) {
481 		if (conf->trace > 2)
482 			log_info("priv_adjtime, no peers");
483 		return (1);
484 	}
485 
486 	if ((peers = calloc(offset_cnt, sizeof(struct ntp_peer *))) == NULL)
487 		fatal("calloc priv_adjtime");
488 
489 	TAILQ_FOREACH(p, &conf->ntp_peers, entry) {
490 		if (p->trustlevel < TRUSTLEVEL_BADPEER)
491 			continue;
492 		peers[i++] = p;
493 	}
494 
495 	qsort(peers, offset_cnt, sizeof(struct ntp_peer *), offset_compare);
496 
497 	if (conf->trace > 2)
498 		log_info("priv_adjtime, %d peers", offset_cnt);
499 
500 	weight_cnt = 0;
501 	weight_half = 0;
502 	offset_median = peers[offset_cnt / 2]->update.offset;
503 	for (i = 0; i < offset_cnt; ++i) {
504 		int peer_weight = (i + 1) * (offset_cnt - i);
505 		double peer_delta;
506 
507 		if (weight_half) {
508 			/* even number of samples, II. median sample */
509 			peer_weight += weight_half;
510 			weight_half = 0;
511 		} else if ((i + 1) * 2 == offset_cnt) {
512 			/* even number of samples, I. median sample */
513 			weight_half = weight_cnt;
514 			peer_weight += weight_half;
515 		} else if (i * 2 + 1 == offset_cnt) {
516 			/* uneven number of samples, median sample */
517 			peer_weight += 2 * weight_cnt;
518 		}
519 
520 		/* ignore false-tickers (off by a second from median) */
521 		peer_delta = offset_median - peers[i]->update.offset;
522 		if (peer_delta > 1. || peer_delta < -1.)
523 			peer_weight = 0;
524 
525 		/* this is safe here despite shallow copy */
526 		peers[i]->update.good = peer_weight;
527 		weight_cnt += peer_weight;
528 	}
529 	offset_median = 0.0;
530 	for (i = 0; i < offset_cnt; ++i)
531 		if (peers[i]->update.good)
532 			offset_median += peers[i]->update.offset *
533 			    ((double)(peers[i]->update.good) / weight_cnt);
534 
535 	if (conf->trace > 4 || (conf->trace && conf->debug))
536 		for (i = 0; i < offset_cnt; ++i)
537 			log_info("peer %2d: trust %s (%d) st %2d dst %3dms"
538 			    " ofs %6.1fms weight %4d addr %s", i,
539 			    peers[i]->trustlevel < TRUSTLEVEL_BADPEER ?
540 			    "bad" : "good", peers[i]->trustlevel,
541 			    peers[i]->update.status.stratum,
542 			    (int)((peers[i]->update.delay + .0005) * 1000.),
543 			    peers[i]->update.offset * 1000.,
544 			    peers[i]->update.good,
545 			    log_sockaddr((struct sockaddr *)&peers[i]->addr->ss));
546 
547 	if (offset_cnt > 1 && offset_cnt % 2 == 0) {
548 		conf->status.rootdelay =
549 		    (peers[offset_cnt / 2 - 1]->update.delay +
550 		    peers[offset_cnt / 2]->update.delay) / 2;
551 		conf->status.stratum = MAX(
552 		    peers[offset_cnt / 2 - 1]->update.status.stratum,
553 		    peers[offset_cnt / 2]->update.status.stratum);
554 		if (conf->trace)
555 			log_info("adj%c stc %d dst %3d ofs %6.1f srv %s", '1',
556 			    peers[offset_cnt / 2 - 1]->update.status.stratum,
557 			    (int)((peers[offset_cnt / 2 - 1]->update.delay + .0005) * 1000.),
558 			    peers[offset_cnt / 2 - 1]->update.offset * 1000.,
559 			    log_sockaddr((struct sockaddr *)&peers[offset_cnt / 2 - 1]->addr->ss));
560 	} else {
561 		conf->status.rootdelay =
562 		    peers[offset_cnt / 2]->update.delay;
563 		conf->status.stratum =
564 		    peers[offset_cnt / 2]->update.status.stratum;
565 	}
566 	if (conf->trace)
567 		log_info("adj%c stc %d dst %3d ofs %6.1f srv %s",
568 		    (offset_cnt > 1 && offset_cnt % 2 == 0) ? '2' : 'x',
569 		    peers[offset_cnt / 2]->update.status.stratum,
570 		    (int)((peers[offset_cnt / 2]->update.delay + .0005) * 1000.),
571 		    peers[offset_cnt / 2]->update.offset * 1000.,
572 		    log_sockaddr((struct sockaddr *)&peers[offset_cnt / 2]->addr->ss));
573 	conf->status.leap = peers[offset_cnt / 2]->update.status.leap;
574 
575 	imsg_compose(ibuf_main, IMSG_ADJTIME, 0, 0,
576 	    &offset_median, sizeof(offset_median));
577 
578 	conf->status.reftime = gettime();
579 	/* one more than selected peer, but cap */
580 	conf->status.stratum = MIN(conf->status.stratum, 254) + 1;
581 	update_scale(offset_median);
582 
583 	conf->status.refid4 =
584 	    peers[offset_cnt / 2]->update.status.refid4;
585 	if (peers[offset_cnt / 2]->addr->ss.ss_family == AF_INET)
586 		conf->status.refid = ((struct sockaddr_in *)
587 		    &peers[offset_cnt / 2]->addr->ss)->sin_addr.s_addr;
588 	else
589 		conf->status.refid = conf->status.refid4;
590 	if (peers[offset_cnt / 2]->update.status.stratum < 1)
591 		conf->status.refid =
592 		    peers[offset_cnt / 2]->update.status.refid;
593 
594 	free(peers);
595 
596 	TAILQ_FOREACH(p, &conf->ntp_peers, entry)
597 		p->update.good = 0;
598 
599 	return (0);
600 }
601 
602 int
offset_compare(const void * aa,const void * bb)603 offset_compare(const void *aa, const void *bb)
604 {
605 	const struct ntp_peer * const *a;
606 	const struct ntp_peer * const *b;
607 
608 	a = aa;
609 	b = bb;
610 
611 	if ((*a)->update.offset < (*b)->update.offset)
612 		return (-1);
613 	else if ((*a)->update.offset > (*b)->update.offset)
614 		return (1);
615 	else
616 		return (0);
617 }
618 
619 void
priv_settime(double offset)620 priv_settime(double offset)
621 {
622 	struct ntp_peer *p;
623 
624 	imsg_compose(ibuf_main, IMSG_SETTIME, 0, 0, &offset, sizeof(offset));
625 	conf->settime = 0;
626 
627 	TAILQ_FOREACH(p, &conf->ntp_peers, entry) {
628 		if (p->next)
629 			p->next -= offset;
630 		if (p->deadline)
631 			p->deadline -= offset;
632 	}
633 }
634 
635 void
priv_host_dns(char * name,u_int32_t peerid)636 priv_host_dns(char *name, u_int32_t peerid)
637 {
638 	u_int16_t	dlen;
639 
640 	dlen = strlen(name) + 1;
641 	imsg_compose(ibuf_main, IMSG_HOST_DNS, peerid, 0, name, dlen);
642 }
643 
644 void
update_scale(double offset)645 update_scale(double offset)
646 {
647 	if (offset < 0)
648 		offset = -offset;
649 
650 	if (offset > QSCALE_OFF_MAX)
651 		conf->scale = 1;
652 	else if (offset < QSCALE_OFF_MIN)
653 		conf->scale = QSCALE_OFF_MAX / QSCALE_OFF_MIN;
654 	else
655 		conf->scale = QSCALE_OFF_MAX / offset;
656 }
657 
658 time_t
scale_interval(time_t requested)659 scale_interval(time_t requested)
660 {
661 	double interval = requested, r;
662 
663 	r = (interval *= conf->scale) / 10.;
664 	if (r > 7.)
665 		r = 7.;
666 	return (interval + arc4random_uniform((int)(r + .5)) - (r / 2.));
667 }
668 
669 time_t
error_interval(void)670 error_interval(void)
671 {
672 	double interval = INTERVAL_QUERY_PATHETIC, r;
673 
674 	r = (interval *= QSCALE_OFF_MAX / QSCALE_OFF_MIN) / 10.;
675 	return (interval + arc4random_uniform((int)(r + .5)) - (r / 2.));
676 }
677 
678 void
chpeertrust(struct ntp_peer * p,bool nowvalid)679 chpeertrust(struct ntp_peer *p, bool nowvalid)
680 {
681 	static u_int nvpeers;
682 	const char *s = "";
683 
684 	if (nowvalid)
685 		++nvpeers;
686 	else {
687 		if (nvpeers)
688 			--nvpeers;
689 		else
690 			log_warn("trying to decrease nvpeers below 0");
691 		s = "in";
692 	}
693 
694 	log_info("peer %s now %svalid, %u valid peers total",
695 	    log_sockaddr((struct sockaddr *)&p->addr->ss),
696 	    s, nvpeers);
697 }
698