GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ntpd/ntp.c Lines: 0 432 0.0 %
Date: 2017-11-13 Branches: 0 320 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: ntp.c,v 1.146 2017/05/30 23:30:48 benno Exp $ */
2
3
/*
4
 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5
 * Copyright (c) 2004 Alexander Guy <alexander.guy@andern.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <sys/types.h>
21
#include <sys/time.h>
22
#include <sys/stat.h>
23
#include <errno.h>
24
#include <fcntl.h>
25
#include <paths.h>
26
#include <poll.h>
27
#include <pwd.h>
28
#include <signal.h>
29
#include <stdlib.h>
30
#include <string.h>
31
#include <syslog.h>
32
#include <time.h>
33
#include <unistd.h>
34
#include <err.h>
35
36
#include "ntpd.h"
37
38
#define	PFD_PIPE_MAIN	0
39
#define	PFD_PIPE_DNS	1
40
#define	PFD_SOCK_CTL	2
41
#define	PFD_MAX		3
42
43
volatile sig_atomic_t	 ntp_quit = 0;
44
struct imsgbuf		*ibuf_main;
45
struct imsgbuf		*ibuf_dns;
46
struct ntpd_conf	*conf;
47
struct ctl_conns	 ctl_conns;
48
u_int			 peer_cnt;
49
u_int			 sensors_cnt;
50
extern u_int		 constraint_cnt;
51
52
void	ntp_sighdlr(int);
53
int	ntp_dispatch_imsg(void);
54
int	ntp_dispatch_imsg_dns(void);
55
void	peer_add(struct ntp_peer *);
56
void	peer_remove(struct ntp_peer *);
57
58
void
59
ntp_sighdlr(int sig)
60
{
61
	switch (sig) {
62
	case SIGINT:
63
	case SIGTERM:
64
		ntp_quit = 1;
65
		break;
66
	}
67
}
68
69
void
70
ntp_main(struct ntpd_conf *nconf, struct passwd *pw, int argc, char **argv)
71
{
72
	int			 a, b, nfds, i, j, idx_peers, timeout;
73
	int			 nullfd, pipe_dns[2], idx_clients;
74
	int			 ctls;
75
	int			 fd_ctl;
76
	u_int			 pfd_elms = 0, idx2peer_elms = 0;
77
	u_int			 listener_cnt, new_cnt, sent_cnt, trial_cnt;
78
	u_int			 ctl_cnt;
79
	struct pollfd		*pfd = NULL;
80
	struct servent		*se;
81
	struct listen_addr	*la;
82
	struct ntp_peer		*p;
83
	struct ntp_peer		**idx2peer = NULL;
84
	struct ntp_sensor	*s, *next_s;
85
	struct constraint	*cstr;
86
	struct timespec		 tp;
87
	struct stat		 stb;
88
	struct ctl_conn		*cc;
89
	time_t			 nextaction, last_sensor_scan = 0, now;
90
	void			*newp;
91
92
	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, PF_UNSPEC,
93
	    pipe_dns) == -1)
94
		fatal("socketpair");
95
96
	start_child(NTPDNS_PROC_NAME, pipe_dns[1], argc, argv);
97
98
	/* in this case the parent didn't init logging and didn't daemonize */
99
	if (nconf->settime && !nconf->debug) {
100
		log_init(nconf->debug, LOG_DAEMON);
101
		if (setsid() == -1)
102
			fatal("setsid");
103
	}
104
	log_procinit("ntp");
105
106
	if ((se = getservbyname("ntp", "udp")) == NULL)
107
		fatal("getservbyname");
108
109
	/* Start control socket. */
110
	if ((fd_ctl = control_init(CTLSOCKET)) == -1)
111
		fatalx("control socket init failed");
112
	if (control_listen(fd_ctl) == -1)
113
		fatalx("control socket listen failed");
114
	if ((nullfd = open("/dev/null", O_RDWR, 0)) == -1)
115
		fatal(NULL);
116
117
	if (stat(pw->pw_dir, &stb) == -1) {
118
		fatal("privsep dir %s could not be opened", pw->pw_dir);
119
	}
120
	if (stb.st_uid != 0 || (stb.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
121
		fatalx("bad privsep dir %s permissions: %o",
122
		    pw->pw_dir, stb.st_mode);
123
	}
124
	if (chroot(pw->pw_dir) == -1)
125
		fatal("chroot");
126
	if (chdir("/") == -1)
127
		fatal("chdir(\"/\")");
128
129
	if (!nconf->debug) {
130
		dup2(nullfd, STDIN_FILENO);
131
		dup2(nullfd, STDOUT_FILENO);
132
		dup2(nullfd, STDERR_FILENO);
133
	}
134
	close(nullfd);
135
136
	setproctitle("ntp engine");
137
138
	conf = nconf;
139
	setup_listeners(se, conf, &listener_cnt);
140
141
	if (setgroups(1, &pw->pw_gid) ||
142
	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
143
	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
144
		fatal("can't drop privileges");
145
146
	endservent();
147
148
	/* The ntp process will want to open NTP client sockets -> "inet" */
149
	if (pledge("stdio inet flock rpath cpath wpath", NULL) == -1)
150
		err(1, "pledge");
151
152
	signal(SIGTERM, ntp_sighdlr);
153
	signal(SIGINT, ntp_sighdlr);
154
	signal(SIGPIPE, SIG_IGN);
155
	signal(SIGHUP, SIG_IGN);
156
	signal(SIGCHLD, SIG_DFL);
157
158
	if ((ibuf_main = malloc(sizeof(struct imsgbuf))) == NULL)
159
		fatal(NULL);
160
	imsg_init(ibuf_main, PARENT_SOCK_FILENO);
161
	if ((ibuf_dns = malloc(sizeof(struct imsgbuf))) == NULL)
162
		fatal(NULL);
163
	imsg_init(ibuf_dns, pipe_dns[0]);
164
165
	constraint_cnt = 0;
166
	conf->constraint_median = 0;
167
	conf->constraint_last = getmonotime();
168
	TAILQ_FOREACH(cstr, &conf->constraints, entry)
169
		constraint_cnt += constraint_init(cstr);
170
171
	TAILQ_FOREACH(p, &conf->ntp_peers, entry)
172
		client_peer_init(p);
173
174
	memset(&conf->status, 0, sizeof(conf->status));
175
176
	conf->freq.num = 0;
177
	conf->freq.samples = 0;
178
	conf->freq.x = 0.0;
179
	conf->freq.xx = 0.0;
180
	conf->freq.xy = 0.0;
181
	conf->freq.y = 0.0;
182
	conf->freq.overall_offset = 0.0;
183
184
	conf->status.synced = 0;
185
	clock_getres(CLOCK_REALTIME, &tp);
186
	b = 1000000000 / tp.tv_nsec;	/* convert to Hz */
187
	for (a = 0; b > 1; a--, b >>= 1)
188
		;
189
	conf->status.precision = a;
190
	conf->scale = 1;
191
192
	TAILQ_INIT(&ctl_conns);
193
	sensor_init();
194
195
	log_info("ntp engine ready");
196
197
	ctl_cnt = 0;
198
	peer_cnt = 0;
199
	TAILQ_FOREACH(p, &conf->ntp_peers, entry)
200
		peer_cnt++;
201
202
	while (ntp_quit == 0) {
203
		if (peer_cnt > idx2peer_elms) {
204
			if ((newp = reallocarray(idx2peer, peer_cnt,
205
			    sizeof(*idx2peer))) == NULL) {
206
				/* panic for now */
207
				log_warn("could not resize idx2peer from %u -> "
208
				    "%u entries", idx2peer_elms, peer_cnt);
209
				fatalx("exiting");
210
			}
211
			idx2peer = newp;
212
			idx2peer_elms = peer_cnt;
213
		}
214
215
		new_cnt = PFD_MAX +
216
		    peer_cnt + listener_cnt + ctl_cnt;
217
		if (new_cnt > pfd_elms) {
218
			if ((newp = reallocarray(pfd, new_cnt,
219
			    sizeof(*pfd))) == NULL) {
220
				/* panic for now */
221
				log_warn("could not resize pfd from %u -> "
222
				    "%u entries", pfd_elms, new_cnt);
223
				fatalx("exiting");
224
			}
225
			pfd = newp;
226
			pfd_elms = new_cnt;
227
		}
228
229
		memset(pfd, 0, sizeof(*pfd) * pfd_elms);
230
		memset(idx2peer, 0, sizeof(*idx2peer) * idx2peer_elms);
231
		nextaction = getmonotime() + 3600;
232
		pfd[PFD_PIPE_MAIN].fd = ibuf_main->fd;
233
		pfd[PFD_PIPE_MAIN].events = POLLIN;
234
		pfd[PFD_PIPE_DNS].fd = ibuf_dns->fd;
235
		pfd[PFD_PIPE_DNS].events = POLLIN;
236
		pfd[PFD_SOCK_CTL].fd = fd_ctl;
237
		pfd[PFD_SOCK_CTL].events = POLLIN;
238
239
		i = PFD_MAX;
240
		TAILQ_FOREACH(la, &conf->listen_addrs, entry) {
241
			pfd[i].fd = la->fd;
242
			pfd[i].events = POLLIN;
243
			i++;
244
		}
245
246
		idx_peers = i;
247
		sent_cnt = trial_cnt = 0;
248
		TAILQ_FOREACH(p, &conf->ntp_peers, entry) {
249
			if (constraint_cnt && conf->constraint_median == 0)
250
				continue;
251
252
			if (p->next > 0 && p->next <= getmonotime()) {
253
				if (p->state > STATE_DNS_INPROGRESS)
254
					trial_cnt++;
255
				if (client_query(p) == 0)
256
					sent_cnt++;
257
			}
258
			if (p->deadline > 0 && p->deadline <= getmonotime()) {
259
				timeout = 300;
260
				log_debug("no reply from %s received in time, "
261
				    "next query %ds", log_sockaddr(
262
				    (struct sockaddr *)&p->addr->ss), timeout);
263
				if (p->trustlevel >= TRUSTLEVEL_BADPEER &&
264
				    (p->trustlevel /= 2) < TRUSTLEVEL_BADPEER)
265
					log_info("peer %s now invalid",
266
					    log_sockaddr(
267
					    (struct sockaddr *)&p->addr->ss));
268
				client_nextaddr(p);
269
				set_next(p, timeout);
270
			}
271
			if (p->senderrors > MAX_SEND_ERRORS) {
272
				log_debug("failed to send query to %s, "
273
				    "next query %ds", log_sockaddr(
274
				    (struct sockaddr *)&p->addr->ss),
275
				    INTERVAL_QUERY_PATHETIC);
276
				p->senderrors = 0;
277
				client_nextaddr(p);
278
				set_next(p, INTERVAL_QUERY_PATHETIC);
279
			}
280
			if (p->next > 0 && p->next < nextaction)
281
				nextaction = p->next;
282
			if (p->deadline > 0 && p->deadline < nextaction)
283
				nextaction = p->deadline;
284
285
			if (p->state == STATE_QUERY_SENT &&
286
			    p->query->fd != -1) {
287
				pfd[i].fd = p->query->fd;
288
				pfd[i].events = POLLIN;
289
				idx2peer[i - idx_peers] = p;
290
				i++;
291
			}
292
		}
293
		idx_clients = i;
294
295
		if (!TAILQ_EMPTY(&conf->ntp_conf_sensors)) {
296
			if (last_sensor_scan == 0 ||
297
			    last_sensor_scan + SENSOR_SCAN_INTERVAL <= getmonotime()) {
298
				sensors_cnt = sensor_scan();
299
				last_sensor_scan = getmonotime();
300
			}
301
			if (sensors_cnt == 0 &&
302
			    nextaction > last_sensor_scan + SENSOR_SCAN_INTERVAL)
303
				nextaction = last_sensor_scan + SENSOR_SCAN_INTERVAL;
304
			sensors_cnt = 0;
305
			TAILQ_FOREACH(s, &conf->ntp_sensors, entry) {
306
				if (conf->settime && s->offsets[0].offset)
307
					priv_settime(s->offsets[0].offset);
308
				sensors_cnt++;
309
				if (s->next > 0 && s->next < nextaction)
310
					nextaction = s->next;
311
			}
312
		}
313
314
		if (conf->settime &&
315
		    ((trial_cnt > 0 && sent_cnt == 0) ||
316
		    (peer_cnt == 0 && sensors_cnt == 0)))
317
			priv_settime(0);	/* no good peers, don't wait */
318
319
		if (ibuf_main->w.queued > 0)
320
			pfd[PFD_PIPE_MAIN].events |= POLLOUT;
321
		if (ibuf_dns->w.queued > 0)
322
			pfd[PFD_PIPE_DNS].events |= POLLOUT;
323
324
		TAILQ_FOREACH(cc, &ctl_conns, entry) {
325
			pfd[i].fd = cc->ibuf.fd;
326
			pfd[i].events = POLLIN;
327
			if (cc->ibuf.w.queued > 0)
328
				pfd[i].events |= POLLOUT;
329
			i++;
330
		}
331
		ctls = i;
332
333
		TAILQ_FOREACH(cstr, &conf->constraints, entry) {
334
			if (constraint_query(cstr) == -1)
335
				continue;
336
		}
337
338
		now = getmonotime();
339
		if (constraint_cnt)
340
			nextaction = now + 1;
341
342
		timeout = nextaction - now;
343
		if (timeout < 0)
344
			timeout = 0;
345
346
		if ((nfds = poll(pfd, i, timeout * 1000)) == -1)
347
			if (errno != EINTR) {
348
				log_warn("poll error");
349
				ntp_quit = 1;
350
			}
351
352
		if (nfds > 0 && (pfd[PFD_PIPE_MAIN].revents & POLLOUT))
353
			if (msgbuf_write(&ibuf_main->w) <= 0 &&
354
			    errno != EAGAIN) {
355
				log_warn("pipe write error (to parent)");
356
				ntp_quit = 1;
357
			}
358
359
		if (nfds > 0 && pfd[PFD_PIPE_MAIN].revents & (POLLIN|POLLERR)) {
360
			nfds--;
361
			if (ntp_dispatch_imsg() == -1) {
362
				log_warn("pipe write error (from main)");
363
				ntp_quit = 1;
364
			}
365
		}
366
367
		if (nfds > 0 && (pfd[PFD_PIPE_DNS].revents & POLLOUT))
368
			if (msgbuf_write(&ibuf_dns->w) <= 0 &&
369
			    errno != EAGAIN) {
370
				log_warn("pipe write error (to dns engine)");
371
				ntp_quit = 1;
372
			}
373
374
		if (nfds > 0 && pfd[PFD_PIPE_DNS].revents & (POLLIN|POLLERR)) {
375
			nfds--;
376
			if (ntp_dispatch_imsg_dns() == -1) {
377
				log_warn("pipe write error (from dns engine)");
378
				ntp_quit = 1;
379
			}
380
		}
381
382
		if (nfds > 0 && pfd[PFD_SOCK_CTL].revents & (POLLIN|POLLERR)) {
383
			nfds--;
384
			ctl_cnt += control_accept(fd_ctl);
385
		}
386
387
		for (j = PFD_MAX; nfds > 0 && j < idx_peers; j++)
388
			if (pfd[j].revents & (POLLIN|POLLERR)) {
389
				nfds--;
390
				if (server_dispatch(pfd[j].fd, conf) == -1) {
391
					log_warn("pipe write error (conf)");
392
					ntp_quit = 1;
393
				}
394
			}
395
396
		for (; nfds > 0 && j < idx_clients; j++) {
397
			if (pfd[j].revents & (POLLIN|POLLERR)) {
398
				nfds--;
399
				if (client_dispatch(idx2peer[j - idx_peers],
400
				    conf->settime) == -1) {
401
					log_warn("pipe write error (settime)");
402
					ntp_quit = 1;
403
				}
404
			}
405
		}
406
407
		for (; nfds > 0 && j < ctls; j++) {
408
			nfds -= control_dispatch_msg(&pfd[j], &ctl_cnt);
409
		}
410
411
		for (s = TAILQ_FIRST(&conf->ntp_sensors); s != NULL;
412
		    s = next_s) {
413
			next_s = TAILQ_NEXT(s, entry);
414
			if (s->next <= getmonotime())
415
				sensor_query(s);
416
		}
417
	}
418
419
	msgbuf_write(&ibuf_main->w);
420
	msgbuf_clear(&ibuf_main->w);
421
	free(ibuf_main);
422
	msgbuf_write(&ibuf_dns->w);
423
	msgbuf_clear(&ibuf_dns->w);
424
	free(ibuf_dns);
425
426
	log_info("ntp engine exiting");
427
	exit(0);
428
}
429
430
int
431
ntp_dispatch_imsg(void)
432
{
433
	struct imsg		 imsg;
434
	int			 n;
435
436
	if (((n = imsg_read(ibuf_main)) == -1 && errno != EAGAIN) || n == 0)
437
		return (-1);
438
439
	for (;;) {
440
		if ((n = imsg_get(ibuf_main, &imsg)) == -1)
441
			return (-1);
442
443
		if (n == 0)
444
			break;
445
446
		switch (imsg.hdr.type) {
447
		case IMSG_ADJTIME:
448
			memcpy(&n, imsg.data, sizeof(n));
449
			if (n == 1 && !conf->status.synced) {
450
				log_info("clock is now synced");
451
				conf->status.synced = 1;
452
			} else if (n == 0 && conf->status.synced) {
453
				log_info("clock is now unsynced");
454
				conf->status.synced = 0;
455
			}
456
			break;
457
		case IMSG_CONSTRAINT_RESULT:
458
			constraint_msg_result(imsg.hdr.peerid,
459
			    imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
460
			break;
461
		case IMSG_CONSTRAINT_CLOSE:
462
			constraint_msg_close(imsg.hdr.peerid,
463
			    imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
464
			break;
465
		default:
466
			break;
467
		}
468
		imsg_free(&imsg);
469
	}
470
	return (0);
471
}
472
473
int
474
ntp_dispatch_imsg_dns(void)
475
{
476
	struct imsg		 imsg;
477
	struct ntp_peer		*peer, *npeer;
478
	u_int16_t		 dlen;
479
	u_char			*p;
480
	struct ntp_addr		*h;
481
	int			 n;
482
483
	if (((n = imsg_read(ibuf_dns)) == -1 && errno != EAGAIN) || n == 0)
484
		return (-1);
485
486
	for (;;) {
487
		if ((n = imsg_get(ibuf_dns, &imsg)) == -1)
488
			return (-1);
489
490
		if (n == 0)
491
			break;
492
493
		switch (imsg.hdr.type) {
494
		case IMSG_HOST_DNS:
495
			TAILQ_FOREACH(peer, &conf->ntp_peers, entry)
496
				if (peer->id == imsg.hdr.peerid)
497
					break;
498
			if (peer == NULL) {
499
				log_warnx("IMSG_HOST_DNS with invalid peerID");
500
				break;
501
			}
502
			if (peer->addr != NULL) {
503
				log_warnx("IMSG_HOST_DNS but addr != NULL!");
504
				break;
505
			}
506
507
			dlen = imsg.hdr.len - IMSG_HEADER_SIZE;
508
			if (dlen == 0) {	/* no data -> temp error */
509
				peer->state = STATE_DNS_TEMPFAIL;
510
				break;
511
			}
512
513
			p = (u_char *)imsg.data;
514
			while (dlen >= sizeof(struct sockaddr_storage)) {
515
				if ((h = calloc(1, sizeof(struct ntp_addr))) ==
516
				    NULL)
517
					fatal(NULL);
518
				memcpy(&h->ss, p, sizeof(h->ss));
519
				p += sizeof(h->ss);
520
				dlen -= sizeof(h->ss);
521
				if (peer->addr_head.pool) {
522
					npeer = new_peer();
523
					npeer->weight = peer->weight;
524
					npeer->query_addr4 = peer->query_addr4;
525
					npeer->query_addr6 = peer->query_addr6;
526
					h->next = NULL;
527
					npeer->addr = h;
528
					npeer->addr_head.a = h;
529
					npeer->addr_head.name =
530
					    peer->addr_head.name;
531
					npeer->addr_head.pool = 1;
532
					client_peer_init(npeer);
533
					npeer->state = STATE_DNS_DONE;
534
					peer_add(npeer);
535
				} else {
536
					h->next = peer->addr;
537
					peer->addr = h;
538
					peer->addr_head.a = peer->addr;
539
					peer->state = STATE_DNS_DONE;
540
				}
541
			}
542
			if (dlen != 0)
543
				fatalx("IMSG_HOST_DNS: dlen != 0");
544
			if (peer->addr_head.pool)
545
				peer_remove(peer);
546
			else
547
				client_addr_init(peer);
548
			break;
549
		case IMSG_CONSTRAINT_DNS:
550
			constraint_msg_dns(imsg.hdr.peerid,
551
			    imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
552
			break;
553
		default:
554
			break;
555
		}
556
		imsg_free(&imsg);
557
	}
558
	return (0);
559
}
560
561
void
562
peer_add(struct ntp_peer *p)
563
{
564
	TAILQ_INSERT_TAIL(&conf->ntp_peers, p, entry);
565
	peer_cnt++;
566
}
567
568
void
569
peer_remove(struct ntp_peer *p)
570
{
571
	TAILQ_REMOVE(&conf->ntp_peers, p, entry);
572
	free(p);
573
	peer_cnt--;
574
}
575
576
static void
577
priv_adjfreq(double offset)
578
{
579
	double curtime, freq;
580
581
	if (!conf->status.synced){
582
		conf->freq.samples = 0;
583
		return;
584
	}
585
586
	conf->freq.samples++;
587
588
	if (conf->freq.samples <= 0)
589
		return;
590
591
	conf->freq.overall_offset += offset;
592
	offset = conf->freq.overall_offset;
593
594
	curtime = gettime_corrected();
595
	conf->freq.xy += offset * curtime;
596
	conf->freq.x += curtime;
597
	conf->freq.y += offset;
598
	conf->freq.xx += curtime * curtime;
599
600
	if (conf->freq.samples % FREQUENCY_SAMPLES != 0)
601
		return;
602
603
	freq =
604
	    (conf->freq.xy - conf->freq.x * conf->freq.y / conf->freq.samples)
605
	    /
606
	    (conf->freq.xx - conf->freq.x * conf->freq.x / conf->freq.samples);
607
608
	if (freq > MAX_FREQUENCY_ADJUST)
609
		freq = MAX_FREQUENCY_ADJUST;
610
	else if (freq < -MAX_FREQUENCY_ADJUST)
611
		freq = -MAX_FREQUENCY_ADJUST;
612
613
	imsg_compose(ibuf_main, IMSG_ADJFREQ, 0, 0, -1, &freq, sizeof(freq));
614
	conf->filters |= FILTER_ADJFREQ;
615
	conf->freq.xy = 0.0;
616
	conf->freq.x = 0.0;
617
	conf->freq.y = 0.0;
618
	conf->freq.xx = 0.0;
619
	conf->freq.samples = 0;
620
	conf->freq.overall_offset = 0.0;
621
	conf->freq.num++;
622
}
623
624
int
625
priv_adjtime(void)
626
{
627
	struct ntp_peer		 *p;
628
	struct ntp_sensor	 *s;
629
	int			  offset_cnt = 0, i = 0, j;
630
	struct ntp_offset	**offsets;
631
	double			  offset_median;
632
633
	TAILQ_FOREACH(p, &conf->ntp_peers, entry) {
634
		if (p->trustlevel < TRUSTLEVEL_BADPEER)
635
			continue;
636
		if (!p->update.good)
637
			return (1);
638
		offset_cnt += p->weight;
639
	}
640
641
	TAILQ_FOREACH(s, &conf->ntp_sensors, entry) {
642
		if (!s->update.good)
643
			continue;
644
		offset_cnt += s->weight;
645
	}
646
647
	if (offset_cnt == 0)
648
		return (1);
649
650
	if ((offsets = calloc(offset_cnt, sizeof(struct ntp_offset *))) == NULL)
651
		fatal("calloc priv_adjtime");
652
653
	TAILQ_FOREACH(p, &conf->ntp_peers, entry) {
654
		if (p->trustlevel < TRUSTLEVEL_BADPEER)
655
			continue;
656
		for (j = 0; j < p->weight; j++)
657
			offsets[i++] = &p->update;
658
	}
659
660
	TAILQ_FOREACH(s, &conf->ntp_sensors, entry) {
661
		if (!s->update.good)
662
			continue;
663
		for (j = 0; j < s->weight; j++)
664
			offsets[i++] = &s->update;
665
	}
666
667
	qsort(offsets, offset_cnt, sizeof(struct ntp_offset *), offset_compare);
668
669
	i = offset_cnt / 2;
670
	if (offset_cnt % 2 == 0)
671
		if (offsets[i - 1]->delay < offsets[i]->delay)
672
			i -= 1;
673
	offset_median = offsets[i]->offset;
674
	conf->status.rootdelay = offsets[i]->delay;
675
	conf->status.stratum = offsets[i]->status.stratum;
676
	conf->status.leap = offsets[i]->status.leap;
677
678
	imsg_compose(ibuf_main, IMSG_ADJTIME, 0, 0, -1,
679
	    &offset_median, sizeof(offset_median));
680
681
	priv_adjfreq(offset_median);
682
683
	conf->status.reftime = gettime();
684
	conf->status.stratum++;	/* one more than selected peer */
685
	if (conf->status.stratum > NTP_MAXSTRATUM)
686
		conf->status.stratum = NTP_MAXSTRATUM;
687
	update_scale(offset_median);
688
689
	conf->status.refid = offsets[i]->status.send_refid;
690
691
	free(offsets);
692
693
	TAILQ_FOREACH(p, &conf->ntp_peers, entry) {
694
		for (i = 0; i < OFFSET_ARRAY_SIZE; i++)
695
			p->reply[i].offset -= offset_median;
696
		p->update.good = 0;
697
	}
698
	TAILQ_FOREACH(s, &conf->ntp_sensors, entry) {
699
		for (i = 0; i < SENSOR_OFFSETS; i++)
700
			s->offsets[i].offset -= offset_median;
701
		s->update.offset -= offset_median;
702
	}
703
704
	return (0);
705
}
706
707
int
708
offset_compare(const void *aa, const void *bb)
709
{
710
	const struct ntp_offset * const *a;
711
	const struct ntp_offset * const *b;
712
713
	a = aa;
714
	b = bb;
715
716
	if ((*a)->offset < (*b)->offset)
717
		return (-1);
718
	else if ((*a)->offset > (*b)->offset)
719
		return (1);
720
	else
721
		return (0);
722
}
723
724
void
725
priv_settime(double offset)
726
{
727
	imsg_compose(ibuf_main, IMSG_SETTIME, 0, 0, -1,
728
	    &offset, sizeof(offset));
729
	conf->settime = 0;
730
}
731
732
void
733
priv_dns(int cmd, char *name, u_int32_t peerid)
734
{
735
	u_int16_t	dlen;
736
737
	dlen = strlen(name) + 1;
738
	imsg_compose(ibuf_dns, cmd, peerid, 0, -1, name, dlen);
739
}
740
741
void
742
update_scale(double offset)
743
{
744
	offset += getoffset();
745
	if (offset < 0)
746
		offset = -offset;
747
748
	if (offset > QSCALE_OFF_MAX || !conf->status.synced ||
749
	    conf->freq.num < 3)
750
		conf->scale = 1;
751
	else if (offset < QSCALE_OFF_MIN)
752
		conf->scale = QSCALE_OFF_MAX / QSCALE_OFF_MIN;
753
	else
754
		conf->scale = QSCALE_OFF_MAX / offset;
755
}
756
757
time_t
758
scale_interval(time_t requested)
759
{
760
	time_t interval, r;
761
762
	interval = requested * conf->scale;
763
	r = arc4random_uniform(MAXIMUM(5, interval / 10));
764
	return (interval + r);
765
}
766
767
time_t
768
error_interval(void)
769
{
770
	time_t interval, r;
771
772
	interval = INTERVAL_QUERY_PATHETIC * QSCALE_OFF_MAX / QSCALE_OFF_MIN;
773
	r = arc4random_uniform(interval / 10);
774
	return (interval + r);
775
}