xref: /openbsd/usr.sbin/ntpd/ntpd.c (revision 8932bfb7)
1 /*	$OpenBSD: ntpd.c,v 1.69 2011/03/19 23:40:11 okan Exp $ */
2 
3 /*
4  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include <sys/wait.h>
22 #include <netinet/in.h>
23 #include <errno.h>
24 #include <poll.h>
25 #include <pwd.h>
26 #include <signal.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <err.h>
32 
33 #include "ntpd.h"
34 
35 void		sighdlr(int);
36 __dead void	usage(void);
37 int		main(int, char *[]);
38 int		check_child(pid_t, const char *);
39 int		dispatch_imsg(struct ntpd_conf *);
40 void		reset_adjtime(void);
41 int		ntpd_adjtime(double);
42 void		ntpd_adjfreq(double, int);
43 void		ntpd_settime(double);
44 void		readfreq(void);
45 int		writefreq(double);
46 
47 volatile sig_atomic_t	 quit = 0;
48 volatile sig_atomic_t	 reconfig = 0;
49 volatile sig_atomic_t	 sigchld = 0;
50 struct imsgbuf		*ibuf;
51 int			 debugsyslog = 0;
52 int			 timeout = INFTIM;
53 
54 void
55 sighdlr(int sig)
56 {
57 	switch (sig) {
58 	case SIGTERM:
59 	case SIGINT:
60 		quit = 1;
61 		break;
62 	case SIGCHLD:
63 		sigchld = 1;
64 		break;
65 	case SIGHUP:
66 		reconfig = 1;
67 		break;
68 	}
69 }
70 
71 __dead void
72 usage(void)
73 {
74 	extern char *__progname;
75 
76 	fprintf(stderr, "usage: %s [-dnSsv] [-f file]\n", __progname);
77 	exit(1);
78 }
79 
80 #define POLL_MAX		8
81 #define PFD_PIPE		0
82 
83 int
84 main(int argc, char *argv[])
85 {
86 	struct ntpd_conf	 lconf;
87 	struct pollfd		 pfd[POLL_MAX];
88 	pid_t			 chld_pid = 0, pid;
89 	const char		*conffile;
90 	int			 ch, nfds;
91 	int			 pipe_chld[2];
92 	struct passwd		*pw;
93 
94 	conffile = CONFFILE;
95 
96 	bzero(&lconf, sizeof(lconf));
97 
98 	log_init(1);		/* log to stderr until daemonized */
99 
100 	while ((ch = getopt(argc, argv, "df:nsSv")) != -1) {
101 		switch (ch) {
102 		case 'd':
103 			lconf.debug = 1;
104 			break;
105 		case 'f':
106 			conffile = optarg;
107 			break;
108 		case 'n':
109 			lconf.noaction = 1;
110 			break;
111 		case 's':
112 			lconf.settime = 1;
113 			break;
114 		case 'S':
115 			lconf.settime = 0;
116 			break;
117 		case 'v':
118 			debugsyslog = 1;
119 			break;
120 		default:
121 			usage();
122 			/* NOTREACHED */
123 		}
124 	}
125 
126 	argc -= optind;
127 	argv += optind;
128 	if (argc > 0)
129 		usage();
130 
131 	if (parse_config(conffile, &lconf))
132 		exit(1);
133 
134 	if (lconf.noaction) {
135 		fprintf(stderr, "configuration OK\n");
136 		exit(0);
137 	}
138 
139 	if (geteuid())
140 		errx(1, "need root privileges");
141 
142 	if ((pw = getpwnam(NTPD_USER)) == NULL)
143 		errx(1, "unknown user %s", NTPD_USER);
144 
145 	reset_adjtime();
146 	if (!lconf.settime) {
147 		log_init(lconf.debug);
148 		if (!lconf.debug)
149 			if (daemon(1, 0))
150 				fatal("daemon");
151 	} else
152 		timeout = SETTIME_TIMEOUT * 1000;
153 
154 	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_chld) == -1)
155 		fatal("socketpair");
156 
157 	signal(SIGCHLD, sighdlr);
158 	/* fork child process */
159 	chld_pid = ntp_main(pipe_chld, &lconf, pw);
160 
161 	setproctitle("[priv]");
162 	readfreq();
163 
164 	signal(SIGTERM, sighdlr);
165 	signal(SIGINT, sighdlr);
166 	signal(SIGHUP, sighdlr);
167 
168 	close(pipe_chld[1]);
169 
170 	if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
171 		fatal(NULL);
172 	imsg_init(ibuf, pipe_chld[0]);
173 
174 	while (quit == 0) {
175 		pfd[PFD_PIPE].fd = ibuf->fd;
176 		pfd[PFD_PIPE].events = POLLIN;
177 		if (ibuf->w.queued)
178 			pfd[PFD_PIPE].events |= POLLOUT;
179 
180 		if ((nfds = poll(pfd, 1, timeout)) == -1)
181 			if (errno != EINTR) {
182 				log_warn("poll error");
183 				quit = 1;
184 			}
185 
186 		if (nfds == 0 && lconf.settime) {
187 			lconf.settime = 0;
188 			timeout = INFTIM;
189 			log_init(lconf.debug);
190 			log_debug("no reply received in time, skipping initial "
191 			    "time setting");
192 			if (!lconf.debug)
193 				if (daemon(1, 0))
194 					fatal("daemon");
195 		}
196 
197 		if (nfds > 0 && (pfd[PFD_PIPE].revents & POLLOUT))
198 			if (msgbuf_write(&ibuf->w) < 0) {
199 				log_warn("pipe write error (to child)");
200 				quit = 1;
201 			}
202 
203 		if (nfds > 0 && pfd[PFD_PIPE].revents & POLLIN) {
204 			nfds--;
205 			if (dispatch_imsg(&lconf) == -1)
206 				quit = 1;
207 		}
208 
209 		if (sigchld) {
210 			if (check_child(chld_pid, "child")) {
211 				quit = 1;
212 				chld_pid = 0;
213 			}
214 			sigchld = 0;
215 		}
216 
217 	}
218 
219 	signal(SIGCHLD, SIG_DFL);
220 
221 	if (chld_pid)
222 		kill(chld_pid, SIGTERM);
223 
224 	do {
225 		if ((pid = wait(NULL)) == -1 &&
226 		    errno != EINTR && errno != ECHILD)
227 			fatal("wait");
228 	} while (pid != -1 || (pid == -1 && errno == EINTR));
229 
230 	msgbuf_clear(&ibuf->w);
231 	free(ibuf);
232 	log_info("Terminating");
233 	return (0);
234 }
235 
236 int
237 check_child(pid_t pid, const char *pname)
238 {
239 	int	 status, sig;
240 	char	*signame;
241 
242 	if (waitpid(pid, &status, WNOHANG) > 0) {
243 		if (WIFEXITED(status)) {
244 			log_warnx("Lost child: %s exited", pname);
245 			return (1);
246 		}
247 		if (WIFSIGNALED(status)) {
248 			sig = WTERMSIG(status);
249 			signame = strsignal(sig) ? strsignal(sig) : "unknown";
250 			log_warnx("Lost child: %s terminated; signal %d (%s)",
251 			    pname, sig, signame);
252 			return (1);
253 		}
254 	}
255 
256 	return (0);
257 }
258 
259 int
260 dispatch_imsg(struct ntpd_conf *lconf)
261 {
262 	struct imsg		 imsg;
263 	int			 n, cnt;
264 	double			 d;
265 	char			*name;
266 	struct ntp_addr		*h, *hn;
267 	struct ibuf		*buf;
268 
269 	if ((n = imsg_read(ibuf)) == -1)
270 		return (-1);
271 
272 	if (n == 0) {	/* connection closed */
273 		log_warnx("dispatch_imsg in main: pipe closed");
274 		return (-1);
275 	}
276 
277 	for (;;) {
278 		if ((n = imsg_get(ibuf, &imsg)) == -1)
279 			return (-1);
280 
281 		if (n == 0)
282 			break;
283 
284 		switch (imsg.hdr.type) {
285 		case IMSG_ADJTIME:
286 			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(d))
287 				fatalx("invalid IMSG_ADJTIME received");
288 			memcpy(&d, imsg.data, sizeof(d));
289 			n = ntpd_adjtime(d);
290 			imsg_compose(ibuf, IMSG_ADJTIME, 0, 0, -1,
291 			     &n, sizeof(n));
292 			break;
293 		case IMSG_ADJFREQ:
294 			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(d))
295 				fatalx("invalid IMSG_ADJFREQ received");
296 			memcpy(&d, imsg.data, sizeof(d));
297 			ntpd_adjfreq(d, 1);
298 			break;
299 		case IMSG_SETTIME:
300 			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(d))
301 				fatalx("invalid IMSG_SETTIME received");
302 			if (!lconf->settime)
303 				break;
304 			log_init(lconf->debug);
305 			memcpy(&d, imsg.data, sizeof(d));
306 			ntpd_settime(d);
307 			/* daemonize now */
308 			if (!lconf->debug)
309 				if (daemon(1, 0))
310 					fatal("daemon");
311 			lconf->settime = 0;
312 			timeout = INFTIM;
313 			break;
314 		case IMSG_HOST_DNS:
315 			name = imsg.data;
316 			if (imsg.hdr.len < 1 + IMSG_HEADER_SIZE)
317 				fatalx("invalid IMSG_HOST_DNS received");
318 			imsg.hdr.len -= 1 + IMSG_HEADER_SIZE;
319 			if (name[imsg.hdr.len] != '\0' ||
320 			    strlen(name) != imsg.hdr.len)
321 				fatalx("invalid IMSG_HOST_DNS received");
322 			if ((cnt = host_dns(name, &hn)) == -1)
323 				break;
324 			buf = imsg_create(ibuf, IMSG_HOST_DNS,
325 			    imsg.hdr.peerid, 0,
326 			    cnt * sizeof(struct sockaddr_storage));
327 			if (buf == NULL)
328 				break;
329 			if (cnt > 0)
330 				for (h = hn; h != NULL; h = h->next)
331 					imsg_add(buf, &h->ss, sizeof(h->ss));
332 
333 			imsg_close(ibuf, buf);
334 			break;
335 		default:
336 			break;
337 		}
338 		imsg_free(&imsg);
339 	}
340 	return (0);
341 }
342 
343 void
344 reset_adjtime(void)
345 {
346 	struct timeval	tv;
347 
348 	timerclear(&tv);
349 	if (adjtime(&tv, NULL) == -1)
350 		log_warn("reset adjtime failed");
351 }
352 
353 int
354 ntpd_adjtime(double d)
355 {
356 	struct timeval	tv, olddelta;
357 	int		synced = 0;
358 	static int	firstadj = 1;
359 
360 	d += getoffset();
361 	if (d >= (double)LOG_NEGLIGIBLE_ADJTIME / 1000 ||
362 	    d <= -1 * (double)LOG_NEGLIGIBLE_ADJTIME / 1000)
363 		log_info("adjusting local clock by %fs", d);
364 	else
365 		log_debug("adjusting local clock by %fs", d);
366 	d_to_tv(d, &tv);
367 	if (adjtime(&tv, &olddelta) == -1)
368 		log_warn("adjtime failed");
369 	else if (!firstadj && olddelta.tv_sec == 0 && olddelta.tv_usec == 0)
370 		synced = 1;
371 	firstadj = 0;
372 	return (synced);
373 }
374 
375 void
376 ntpd_adjfreq(double relfreq, int wrlog)
377 {
378 	int64_t curfreq;
379 	double ppmfreq;
380 	int r;
381 
382 	if (adjfreq(NULL, &curfreq) == -1) {
383 		log_warn("adjfreq failed");
384 		return;
385 	}
386 
387 	/*
388 	 * adjfreq's unit is ns/s shifted left 32; convert relfreq to
389 	 * that unit before adding. We log values in part per million.
390 	 */
391 	curfreq += relfreq * 1e9 * (1LL << 32);
392 	r = writefreq(curfreq / 1e9 / (1LL << 32));
393 	ppmfreq = relfreq * 1e6;
394 	if (wrlog) {
395 		if (ppmfreq >= LOG_NEGLIGIBLE_ADJFREQ ||
396 		    ppmfreq <= -LOG_NEGLIGIBLE_ADJFREQ)
397 			log_info("adjusting clock frequency by %f to %fppm%s",
398 			    ppmfreq, curfreq / 1e3 / (1LL << 32),
399 			    r ? "" : " (no drift file)");
400 		else
401 			log_debug("adjusting clock frequency by %f to %fppm%s",
402 			    ppmfreq, curfreq / 1e3 / (1LL << 32),
403 			    r ? "" : " (no drift file)");
404 	}
405 
406 	if (adjfreq(&curfreq, NULL) == -1)
407 		log_warn("adjfreq failed");
408 }
409 
410 void
411 ntpd_settime(double d)
412 {
413 	struct timeval	tv, curtime;
414 	char		buf[80];
415 	time_t		tval;
416 
417 	if (gettimeofday(&curtime, NULL) == -1) {
418 		log_warn("gettimeofday");
419 		return;
420 	}
421 	d_to_tv(d, &tv);
422 	curtime.tv_usec += tv.tv_usec + 1000000;
423 	curtime.tv_sec += tv.tv_sec - 1 + (curtime.tv_usec / 1000000);
424 	curtime.tv_usec %= 1000000;
425 
426 	if (settimeofday(&curtime, NULL) == -1) {
427 		log_warn("settimeofday");
428 		return;
429 	}
430 	tval = curtime.tv_sec;
431 	strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y",
432 	    localtime(&tval));
433 	log_info("set local clock to %s (offset %fs)", buf, d);
434 }
435 
436 void
437 readfreq(void)
438 {
439 	FILE *fp;
440 	int64_t current;
441 	double d;
442 
443 	fp = fopen(DRIFTFILE, "r");
444 	if (fp == NULL) {
445 		/* if the drift file has been deleted by the user, reset */
446 		current = 0;
447 		if (adjfreq(&current, NULL) == -1)
448 			log_warn("adjfreq reset failed");
449 		return;
450 	}
451 
452 	/* if we're adjusting frequency already, don't override */
453 	if (adjfreq(NULL, &current) == -1)
454 		log_warn("adjfreq failed");
455 	else if (current == 0) {
456 		if (fscanf(fp, "%le", &d) == 1)
457 			ntpd_adjfreq(d, 0);
458 		else
459 			log_warnx("can't read %s", DRIFTFILE);
460 	}
461 	fclose(fp);
462 }
463 
464 int
465 writefreq(double d)
466 {
467 	int r;
468 	FILE *fp;
469 	static int warnonce = 1;
470 
471 	fp = fopen(DRIFTFILE, "w");
472 	if (fp == NULL) {
473 		if (warnonce) {
474 			log_warn("can't open %s", DRIFTFILE);
475 			warnonce = 0;
476 		}
477 		return 0;
478 	}
479 
480 	fprintf(fp, "%e\n", d);
481 	r = ferror(fp);
482 	if (fclose(fp) != 0 || r != 0) {
483 		if (warnonce) {
484 			log_warnx("can't write %s", DRIFTFILE);
485 			warnonce = 0;
486 		}
487 		unlink(DRIFTFILE);
488 		return 0;
489 	}
490 	return 1;
491 }
492