1 /* $OpenBSD: ntpd.c,v 1.142 2024/11/21 13:38:14 claudio Exp $ */
2
3 /*
4 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5 * Copyright (c) 2012 Mike Miller <mmiller@mgm51.com>
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/resource.h>
22 #include <sys/socket.h>
23 #include <sys/sysctl.h>
24 #include <sys/wait.h>
25 #include <sys/un.h>
26 #include <netinet/in.h>
27 #include <errno.h>
28 #include <poll.h>
29 #include <pwd.h>
30 #include <signal.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <syslog.h>
35 #include <tls.h>
36 #include <time.h>
37 #include <unistd.h>
38 #include <fcntl.h>
39 #include <err.h>
40
41 #include "ntpd.h"
42
43 void sighdlr(int);
44 __dead void usage(void);
45 int auto_preconditions(const struct ntpd_conf *);
46 int main(int, char *[]);
47 void check_child(void);
48 int dispatch_imsg(struct ntpd_conf *, int, char **);
49 void reset_adjtime(void);
50 int ntpd_adjtime(double);
51 void ntpd_adjfreq(double, int);
52 void ntpd_settime(double);
53 void readfreq(void);
54 int writefreq(double);
55 void ctl_main(int, char*[]);
56 const char *ctl_lookup_option(char *, const char **);
57 void show_status_msg(struct imsg *);
58 void show_peer_msg(struct imsg *, int);
59 void show_sensor_msg(struct imsg *, int);
60
61 volatile sig_atomic_t quit = 0;
62 volatile sig_atomic_t reconfig = 0;
63 volatile sig_atomic_t sigchld = 0;
64 struct imsgbuf *ibuf;
65 int timeout = INFTIM;
66
67 extern u_int constraint_cnt;
68
69 const char *showopt;
70
71 static const char *ctl_showopt_list[] = {
72 "peers", "Sensors", "status", "all", NULL
73 };
74
75 void
sighdlr(int sig)76 sighdlr(int sig)
77 {
78 switch (sig) {
79 case SIGTERM:
80 case SIGINT:
81 quit = 1;
82 break;
83 case SIGCHLD:
84 sigchld = 1;
85 break;
86 case SIGHUP:
87 reconfig = 1;
88 break;
89 }
90 }
91
92 __dead void
usage(void)93 usage(void)
94 {
95 extern char *__progname;
96
97 if (strcmp(__progname, "ntpctl") == 0)
98 fprintf(stderr,
99 "usage: ntpctl -s all | peers | Sensors | status\n");
100 else
101 fprintf(stderr, "usage: %s [-dnv] [-f file]\n",
102 __progname);
103 exit(1);
104 }
105
106 int
auto_preconditions(const struct ntpd_conf * cnf)107 auto_preconditions(const struct ntpd_conf *cnf)
108 {
109 int mib[2] = { CTL_KERN, KERN_SECURELVL };
110 int constraints, securelevel;
111 size_t sz = sizeof(int);
112
113 if (sysctl(mib, 2, &securelevel, &sz, NULL, 0) == -1)
114 err(1, "sysctl");
115 constraints = !TAILQ_EMPTY(&cnf->constraints);
116 return !cnf->settime && (constraints || cnf->trusted_peers ||
117 conf->trusted_sensors) && securelevel == 0;
118 }
119
120 #define POLL_MAX 8
121 #define PFD_PIPE 0
122 #define PFD_MAX 1
123
124 int
main(int argc,char * argv[])125 main(int argc, char *argv[])
126 {
127 struct ntpd_conf lconf;
128 struct pollfd *pfd = NULL;
129 pid_t pid;
130 const char *conffile;
131 int ch, nfds, i, j;
132 int pipe_chld[2];
133 extern char *__progname;
134 u_int pfd_elms = 0, new_cnt;
135 struct constraint *cstr;
136 struct passwd *pw;
137 void *newp;
138 int argc0 = argc, logdest;
139 char **argv0 = argv;
140 char *pname = NULL;
141 time_t settime_deadline;
142 int sopt = 0;
143
144 if (strcmp(__progname, "ntpctl") == 0) {
145 ctl_main(argc, argv);
146 /* NOTREACHED */
147 }
148
149 conffile = CONFFILE;
150
151 memset(&lconf, 0, sizeof(lconf));
152
153 while ((ch = getopt(argc, argv, "df:nP:sSv")) != -1) {
154 switch (ch) {
155 case 'd':
156 lconf.debug = 1;
157 break;
158 case 'f':
159 conffile = optarg;
160 break;
161 case 'n':
162 lconf.debug = 1;
163 lconf.noaction = 1;
164 break;
165 case 'P':
166 pname = optarg;
167 break;
168 case 's':
169 case 'S':
170 sopt = ch;
171 break;
172 case 'v':
173 lconf.verbose++;
174 break;
175 default:
176 usage();
177 /* NOTREACHED */
178 }
179 }
180
181 /* log to stderr until daemonized */
182 logdest = LOG_TO_STDERR;
183 if (!lconf.debug)
184 logdest |= LOG_TO_SYSLOG;
185
186 log_init(logdest, lconf.verbose, LOG_DAEMON);
187
188 if (sopt) {
189 log_warnx("-%c option no longer works and will be removed soon.",
190 sopt);
191 log_warnx("Please reconfigure to use constraints or trusted servers.");
192 }
193
194 argc -= optind;
195 argv += optind;
196 if (argc > 0)
197 usage();
198
199 if (parse_config(conffile, &lconf))
200 exit(1);
201
202 if (lconf.noaction) {
203 fprintf(stderr, "configuration OK\n");
204 exit(0);
205 }
206
207 if (geteuid())
208 errx(1, "need root privileges");
209
210 if ((pw = getpwnam(NTPD_USER)) == NULL)
211 errx(1, "unknown user %s", NTPD_USER);
212
213 lconf.automatic = auto_preconditions(&lconf);
214 if (lconf.automatic)
215 lconf.settime = 1;
216
217 if (pname != NULL) {
218 /* Remove our proc arguments, so child doesn't need to. */
219 if (sanitize_argv(&argc0, &argv0) == -1)
220 fatalx("sanitize_argv");
221
222 if (strcmp(NTP_PROC_NAME, pname) == 0)
223 ntp_main(&lconf, pw, argc0, argv0);
224 else if (strcmp(NTPDNS_PROC_NAME, pname) == 0)
225 ntp_dns(&lconf, pw);
226 else if (strcmp(CONSTRAINT_PROC_NAME, pname) == 0)
227 priv_constraint_child(pw->pw_dir, pw->pw_uid,
228 pw->pw_gid);
229 else
230 fatalx("%s: invalid process name '%s'", __func__,
231 pname);
232
233 fatalx("%s: process '%s' failed", __func__, pname);
234 } else {
235 if ((control_check(CTLSOCKET)) == -1)
236 fatalx("ntpd already running");
237 }
238
239 if (setpriority(PRIO_PROCESS, 0, -20) == -1)
240 warn("can't set priority");
241 reset_adjtime();
242
243 logdest = lconf.debug ? LOG_TO_STDERR : LOG_TO_SYSLOG;
244 if (!lconf.settime) {
245 log_init(logdest, lconf.verbose, LOG_DAEMON);
246 if (!lconf.debug)
247 if (daemon(1, 0))
248 fatal("daemon");
249 } else {
250 settime_deadline = getmonotime();
251 timeout = 100;
252 }
253
254 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, PF_UNSPEC,
255 pipe_chld) == -1)
256 fatal("socketpair");
257
258 if (chdir("/") == -1)
259 fatal("chdir(\"/\")");
260
261 signal(SIGCHLD, sighdlr);
262
263 /* fork child process */
264 start_child(NTP_PROC_NAME, pipe_chld[1], argc0, argv0);
265
266 log_procinit("[priv]");
267 readfreq();
268
269 signal(SIGTERM, sighdlr);
270 signal(SIGINT, sighdlr);
271 signal(SIGHUP, sighdlr);
272
273 constraint_purge();
274
275 if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
276 fatal(NULL);
277 if (imsgbuf_init(ibuf, pipe_chld[0]) == -1)
278 fatal(NULL);
279
280 constraint_cnt = 0;
281
282 /*
283 * Constraint processes are forked with certificates in memory,
284 * then privdrop into chroot before speaking to the outside world.
285 */
286 if (unveil("/usr/sbin/ntpd", "x") == -1)
287 err(1, "unveil /usr/sbin/ntpd");
288 if (pledge("stdio settime proc exec", NULL) == -1)
289 err(1, "pledge");
290
291 while (quit == 0) {
292 new_cnt = PFD_MAX + constraint_cnt;
293 if (new_cnt > pfd_elms) {
294 if ((newp = reallocarray(pfd, new_cnt,
295 sizeof(*pfd))) == NULL) {
296 /* panic for now */
297 log_warn("could not resize pfd from %u -> "
298 "%u entries", pfd_elms, new_cnt);
299 fatalx("exiting");
300 }
301 pfd = newp;
302 pfd_elms = new_cnt;
303 }
304
305 memset(pfd, 0, sizeof(*pfd) * pfd_elms);
306 pfd[PFD_PIPE].fd = ibuf->fd;
307 pfd[PFD_PIPE].events = POLLIN;
308 if (imsgbuf_queuelen(ibuf) > 0)
309 pfd[PFD_PIPE].events |= POLLOUT;
310
311 i = PFD_MAX;
312 TAILQ_FOREACH(cstr, &conf->constraints, entry) {
313 pfd[i].fd = cstr->fd;
314 pfd[i].events = POLLIN;
315 i++;
316 }
317
318 if ((nfds = poll(pfd, i, timeout)) == -1)
319 if (errno != EINTR) {
320 log_warn("poll error");
321 quit = 1;
322 }
323
324 if (nfds == 0 && lconf.settime &&
325 getmonotime() > settime_deadline + SETTIME_TIMEOUT) {
326 lconf.settime = 0;
327 timeout = INFTIM;
328 log_init(logdest, lconf.verbose, LOG_DAEMON);
329 log_warnx("no reply received in time, skipping initial "
330 "time setting");
331 if (!lconf.debug)
332 if (daemon(1, 0))
333 fatal("daemon");
334 }
335
336 if (nfds > 0 && (pfd[PFD_PIPE].revents & POLLOUT))
337 if (imsgbuf_write(ibuf) == -1) {
338 log_warn("pipe write error (to child)");
339 quit = 1;
340 }
341
342 if (nfds > 0 && pfd[PFD_PIPE].revents & POLLIN) {
343 nfds--;
344 if (dispatch_imsg(&lconf, argc0, argv0) == -1)
345 quit = 1;
346 }
347
348 for (j = PFD_MAX; nfds > 0 && j < i; j++) {
349 nfds -= priv_constraint_dispatch(&pfd[j]);
350 }
351
352 if (sigchld) {
353 check_child();
354 sigchld = 0;
355 }
356 }
357
358 signal(SIGCHLD, SIG_DFL);
359
360 /* Close socket and start shutdown. */
361 close(ibuf->fd);
362
363 do {
364 if ((pid = wait(NULL)) == -1 &&
365 errno != EINTR && errno != ECHILD)
366 fatal("wait");
367 } while (pid != -1 || (pid == -1 && errno == EINTR));
368
369 imsgbuf_clear(ibuf);
370 free(ibuf);
371 log_info("Terminating");
372 return (0);
373 }
374
375 void
check_child(void)376 check_child(void)
377 {
378 int status;
379 pid_t pid;
380
381 do {
382 pid = waitpid(WAIT_ANY, &status, WNOHANG);
383 if (pid <= 0)
384 continue;
385
386 priv_constraint_check_child(pid, status);
387 } while (pid > 0 || (pid == -1 && errno == EINTR));
388 }
389
390 int
dispatch_imsg(struct ntpd_conf * lconf,int argc,char ** argv)391 dispatch_imsg(struct ntpd_conf *lconf, int argc, char **argv)
392 {
393 struct imsg imsg;
394 int n;
395 double d;
396
397 if (imsgbuf_read(ibuf) != 1)
398 return (-1);
399
400 for (;;) {
401 if ((n = imsg_get(ibuf, &imsg)) == -1)
402 return (-1);
403
404 if (n == 0)
405 break;
406
407 switch (imsg.hdr.type) {
408 case IMSG_ADJTIME:
409 if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(d))
410 fatalx("invalid IMSG_ADJTIME received");
411 memcpy(&d, imsg.data, sizeof(d));
412 n = ntpd_adjtime(d);
413 imsg_compose(ibuf, IMSG_ADJTIME, 0, 0, -1,
414 &n, sizeof(n));
415 break;
416 case IMSG_ADJFREQ:
417 if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(d))
418 fatalx("invalid IMSG_ADJFREQ received");
419 memcpy(&d, imsg.data, sizeof(d));
420 ntpd_adjfreq(d, 1);
421 break;
422 case IMSG_SETTIME:
423 if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(d))
424 fatalx("invalid IMSG_SETTIME received");
425 if (!lconf->settime)
426 break;
427 log_init(lconf->debug ? LOG_TO_STDERR : LOG_TO_SYSLOG,
428 lconf->verbose, LOG_DAEMON);
429 memcpy(&d, imsg.data, sizeof(d));
430 ntpd_settime(d);
431 /* daemonize now */
432 if (!lconf->debug)
433 if (daemon(1, 0))
434 fatal("daemon");
435 lconf->settime = 0;
436 timeout = INFTIM;
437 break;
438 case IMSG_CONSTRAINT_QUERY:
439 priv_constraint_msg(imsg.hdr.peerid,
440 imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE,
441 argc, argv);
442 break;
443 case IMSG_CONSTRAINT_KILL:
444 priv_constraint_kill(imsg.hdr.peerid);
445 break;
446 default:
447 break;
448 }
449 imsg_free(&imsg);
450 }
451 return (0);
452 }
453
454 void
reset_adjtime(void)455 reset_adjtime(void)
456 {
457 struct timeval tv;
458
459 timerclear(&tv);
460 if (adjtime(&tv, NULL) == -1)
461 log_warn("reset adjtime failed");
462 }
463
464 int
ntpd_adjtime(double d)465 ntpd_adjtime(double d)
466 {
467 struct timeval tv, olddelta;
468 int synced = 0;
469 static int firstadj = 1;
470
471 d += getoffset();
472 if (d >= (double)LOG_NEGLIGIBLE_ADJTIME / 1000 ||
473 d <= -1 * (double)LOG_NEGLIGIBLE_ADJTIME / 1000)
474 log_info("adjusting local clock by %fs", d);
475 else
476 log_debug("adjusting local clock by %fs", d);
477 d_to_tv(d, &tv);
478 if (adjtime(&tv, &olddelta) == -1)
479 log_warn("adjtime failed");
480 else if (!firstadj && olddelta.tv_sec == 0 && olddelta.tv_usec == 0)
481 synced = 1;
482 firstadj = 0;
483 return (synced);
484 }
485
486 void
ntpd_adjfreq(double relfreq,int wrlog)487 ntpd_adjfreq(double relfreq, int wrlog)
488 {
489 int64_t curfreq;
490 double ppmfreq;
491 int r;
492
493 if (adjfreq(NULL, &curfreq) == -1) {
494 log_warn("adjfreq failed");
495 return;
496 }
497
498 /*
499 * adjfreq's unit is ns/s shifted left 32; convert relfreq to
500 * that unit before adding. We log values in part per million.
501 */
502 curfreq += relfreq * 1e9 * (1LL << 32);
503 r = writefreq(curfreq / 1e9 / (1LL << 32));
504 ppmfreq = relfreq * 1e6;
505 if (wrlog) {
506 if (ppmfreq >= LOG_NEGLIGIBLE_ADJFREQ ||
507 ppmfreq <= -LOG_NEGLIGIBLE_ADJFREQ)
508 log_info("adjusting clock frequency by %f to %fppm%s",
509 ppmfreq, curfreq / 1e3 / (1LL << 32),
510 r ? "" : " (no drift file)");
511 else
512 log_debug("adjusting clock frequency by %f to %fppm%s",
513 ppmfreq, curfreq / 1e3 / (1LL << 32),
514 r ? "" : " (no drift file)");
515 }
516
517 if (adjfreq(&curfreq, NULL) == -1)
518 log_warn("adjfreq failed");
519 }
520
521 void
ntpd_settime(double d)522 ntpd_settime(double d)
523 {
524 struct timeval tv, curtime;
525 char buf[80];
526 time_t tval;
527
528 if (d == 0)
529 return;
530
531 if (gettimeofday(&curtime, NULL) == -1) {
532 log_warn("gettimeofday");
533 return;
534 }
535 d_to_tv(d, &tv);
536 curtime.tv_usec += tv.tv_usec + 1000000;
537 curtime.tv_sec += tv.tv_sec - 1 + (curtime.tv_usec / 1000000);
538 curtime.tv_usec %= 1000000;
539
540 if (settimeofday(&curtime, NULL) == -1) {
541 log_warn("settimeofday");
542 return;
543 }
544 tval = curtime.tv_sec;
545 strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y",
546 localtime(&tval));
547 log_info("set local clock to %s (offset %fs)", buf, d);
548 }
549
550 static FILE *freqfp;
551
552 void
readfreq(void)553 readfreq(void)
554 {
555 int64_t current;
556 int fd;
557 double d;
558
559 fd = open(DRIFTFILE, O_RDWR);
560 if (fd == -1) {
561 log_warnx("creating new %s", DRIFTFILE);
562 current = 0;
563 if (adjfreq(¤t, NULL) == -1)
564 log_warn("adjfreq reset failed");
565 freqfp = fopen(DRIFTFILE, "w");
566 return;
567 }
568
569 freqfp = fdopen(fd, "r+");
570
571 /* if we're adjusting frequency already, don't override */
572 if (adjfreq(NULL, ¤t) == -1)
573 log_warn("adjfreq failed");
574 else if (current == 0 && freqfp) {
575 if (fscanf(freqfp, "%lf", &d) == 1) {
576 d /= 1e6; /* scale from ppm */
577 ntpd_adjfreq(d, 0);
578 } else
579 log_warnx("%s is empty", DRIFTFILE);
580 }
581 }
582
583 int
writefreq(double d)584 writefreq(double d)
585 {
586 int r;
587 static int warnonce = 1;
588
589 if (freqfp == NULL)
590 return 0;
591 rewind(freqfp);
592 r = fprintf(freqfp, "%.3f\n", d * 1e6); /* scale to ppm */
593 if (r < 0 || fflush(freqfp) != 0) {
594 if (warnonce) {
595 log_warnx("can't write %s", DRIFTFILE);
596 warnonce = 0;
597 }
598 clearerr(freqfp);
599 return 0;
600 }
601 ftruncate(fileno(freqfp), ftello(freqfp));
602 fsync(fileno(freqfp));
603 return 1;
604 }
605
606 void
ctl_main(int argc,char * argv[])607 ctl_main(int argc, char *argv[])
608 {
609 struct sockaddr_un sa;
610 struct imsg imsg;
611 struct imsgbuf *ibuf_ctl;
612 int fd, n, done, ch, action;
613 char *sockname;
614
615 sockname = CTLSOCKET;
616
617 if (argc < 2) {
618 usage();
619 /* NOTREACHED */
620 }
621
622 while ((ch = getopt(argc, argv, "s:")) != -1) {
623 switch (ch) {
624 case 's':
625 showopt = ctl_lookup_option(optarg, ctl_showopt_list);
626 if (showopt == NULL) {
627 warnx("Unknown show modifier '%s'", optarg);
628 usage();
629 }
630 break;
631 default:
632 usage();
633 /* NOTREACHED */
634 }
635 }
636
637 action = -1;
638 if (showopt != NULL) {
639 switch (*showopt) {
640 case 'p':
641 action = CTL_SHOW_PEERS;
642 break;
643 case 's':
644 action = CTL_SHOW_STATUS;
645 break;
646 case 'S':
647 action = CTL_SHOW_SENSORS;
648 break;
649 case 'a':
650 action = CTL_SHOW_ALL;
651 break;
652 }
653 }
654 if (action == -1)
655 usage();
656 /* NOTREACHED */
657
658 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
659 err(1, "ntpctl: socket");
660
661 memset(&sa, 0, sizeof(sa));
662 sa.sun_family = AF_UNIX;
663 if (strlcpy(sa.sun_path, sockname, sizeof(sa.sun_path)) >=
664 sizeof(sa.sun_path))
665 errx(1, "ctl socket name too long");
666 if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1)
667 err(1, "connect: %s", sockname);
668
669 if (pledge("stdio", NULL) == -1)
670 err(1, "pledge");
671
672 if ((ibuf_ctl = malloc(sizeof(struct imsgbuf))) == NULL)
673 err(1, NULL);
674 if (imsgbuf_init(ibuf_ctl, fd) == -1)
675 err(1, NULL);
676
677 switch (action) {
678 case CTL_SHOW_STATUS:
679 imsg_compose(ibuf_ctl, IMSG_CTL_SHOW_STATUS,
680 0, 0, -1, NULL, 0);
681 break;
682 case CTL_SHOW_PEERS:
683 imsg_compose(ibuf_ctl, IMSG_CTL_SHOW_PEERS,
684 0, 0, -1, NULL, 0);
685 break;
686 case CTL_SHOW_SENSORS:
687 imsg_compose(ibuf_ctl, IMSG_CTL_SHOW_SENSORS,
688 0, 0, -1, NULL, 0);
689 break;
690 case CTL_SHOW_ALL:
691 imsg_compose(ibuf_ctl, IMSG_CTL_SHOW_ALL,
692 0, 0, -1, NULL, 0);
693 break;
694 default:
695 errx(1, "invalid action");
696 break; /* NOTREACHED */
697 }
698
699 if (imsgbuf_flush(ibuf_ctl) == -1)
700 err(1, "write error");
701
702 done = 0;
703 while (!done) {
704 if ((n = imsgbuf_read(ibuf_ctl)) == -1)
705 err(1, "read error");
706 if (n == 0)
707 errx(1, "pipe closed");
708
709 while (!done) {
710 if ((n = imsg_get(ibuf_ctl, &imsg)) == -1)
711 err(1, "ibuf_ctl: imsg_get error");
712 if (n == 0)
713 break;
714
715 switch (action) {
716 case CTL_SHOW_STATUS:
717 show_status_msg(&imsg);
718 done = 1;
719 break;
720 case CTL_SHOW_PEERS:
721 show_peer_msg(&imsg, 0);
722 if (imsg.hdr.type ==
723 IMSG_CTL_SHOW_PEERS_END)
724 done = 1;
725 break;
726 case CTL_SHOW_SENSORS:
727 show_sensor_msg(&imsg, 0);
728 if (imsg.hdr.type ==
729 IMSG_CTL_SHOW_SENSORS_END)
730 done = 1;
731 break;
732 case CTL_SHOW_ALL:
733 switch (imsg.hdr.type) {
734 case IMSG_CTL_SHOW_STATUS:
735 show_status_msg(&imsg);
736 break;
737 case IMSG_CTL_SHOW_PEERS:
738 show_peer_msg(&imsg, 1);
739 break;
740 case IMSG_CTL_SHOW_SENSORS:
741 show_sensor_msg(&imsg, 1);
742 break;
743 case IMSG_CTL_SHOW_PEERS_END:
744 case IMSG_CTL_SHOW_SENSORS_END:
745 /* do nothing */
746 break;
747 case IMSG_CTL_SHOW_ALL_END:
748 done=1;
749 break;
750 default:
751 /* no action taken */
752 break;
753 }
754 default:
755 /* no action taken */
756 break;
757 }
758 imsg_free(&imsg);
759 }
760 }
761 close(fd);
762 free(ibuf_ctl);
763 exit(0);
764 }
765
766 const char *
ctl_lookup_option(char * cmd,const char ** list)767 ctl_lookup_option(char *cmd, const char **list)
768 {
769 const char *item = NULL;
770 if (cmd != NULL && *cmd)
771 for (; *list; list++)
772 if (!strncmp(cmd, *list, strlen(cmd))) {
773 if (item == NULL)
774 item = *list;
775 else
776 errx(1, "%s is ambiguous", cmd);
777 }
778 return (item);
779 }
780
781 void
show_status_msg(struct imsg * imsg)782 show_status_msg(struct imsg *imsg)
783 {
784 struct ctl_show_status *cstatus;
785 double clock_offset;
786 struct timeval tv;
787
788 if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(struct ctl_show_status))
789 fatalx("invalid IMSG_CTL_SHOW_STATUS received");
790
791 cstatus = (struct ctl_show_status *)imsg->data;
792
793 if (cstatus->peercnt > 0)
794 printf("%d/%d peers valid, ",
795 cstatus->valid_peers, cstatus->peercnt);
796
797 if (cstatus->sensorcnt > 0)
798 printf("%d/%d sensors valid, ",
799 cstatus->valid_sensors, cstatus->sensorcnt);
800
801 if (cstatus->constraint_median) {
802 tv.tv_sec = cstatus->constraint_median +
803 (getmonotime() - cstatus->constraint_last);
804 tv.tv_usec = 0;
805 d_to_tv(gettime_from_timeval(&tv) - gettime(), &tv);
806 printf("constraint offset %llds", (long long)tv.tv_sec);
807 if (cstatus->constraint_errors)
808 printf(" (%d errors)",
809 cstatus->constraint_errors);
810 printf(", ");
811 } else if (cstatus->constraints)
812 printf("constraints configured but none available, ");
813
814 if (cstatus->peercnt + cstatus->sensorcnt == 0)
815 printf("no peers and no sensors configured\n");
816
817 if (cstatus->synced == 1)
818 printf("clock synced, stratum %u\n", cstatus->stratum);
819 else {
820 printf("clock unsynced");
821 clock_offset = cstatus->clock_offset < 0 ?
822 -1.0 * cstatus->clock_offset : cstatus->clock_offset;
823 if (clock_offset > 5e-7)
824 printf(", clock offset is %.3fms\n",
825 cstatus->clock_offset);
826 else
827 printf("\n");
828 }
829 }
830
831 void
show_peer_msg(struct imsg * imsg,int calledfromshowall)832 show_peer_msg(struct imsg *imsg, int calledfromshowall)
833 {
834 struct ctl_show_peer *cpeer;
835 int cnt;
836 char stratum[3];
837 static int firsttime = 1;
838
839 if (imsg->hdr.type == IMSG_CTL_SHOW_PEERS_END) {
840 if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(cnt))
841 fatalx("invalid IMSG_CTL_SHOW_PEERS_END received");
842 memcpy(&cnt, imsg->data, sizeof(cnt));
843 if (cnt == 0)
844 printf("no peers configured\n");
845 return;
846 }
847
848 if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(struct ctl_show_peer))
849 fatalx("invalid IMSG_CTL_SHOW_PEERS received");
850
851 cpeer = (struct ctl_show_peer *)imsg->data;
852
853 if (strlen(cpeer->peer_desc) > MAX_DISPLAY_WIDTH - 1)
854 fatalx("peer_desc is too long");
855
856 if (firsttime) {
857 firsttime = 0;
858 if (calledfromshowall)
859 printf("\n");
860 printf("peer\n wt tl st next poll "
861 "offset delay jitter\n");
862 }
863
864 if (cpeer->stratum > 0)
865 snprintf(stratum, sizeof(stratum), "%2u", cpeer->stratum);
866 else
867 strlcpy(stratum, " -", sizeof (stratum));
868
869 printf("%s\n %1s %2u %2u %2s %4llds %4llds",
870 cpeer->peer_desc, cpeer->syncedto == 1 ? "*" : " ",
871 cpeer->weight, cpeer->trustlevel, stratum,
872 (long long)cpeer->next, (long long)cpeer->poll);
873
874 if (cpeer->trustlevel >= TRUSTLEVEL_BADPEER)
875 printf(" %12.3fms %9.3fms %8.3fms\n", cpeer->offset,
876 cpeer->delay, cpeer->jitter);
877 else
878 printf(" ---- peer not valid ----\n");
879
880 }
881
882 void
show_sensor_msg(struct imsg * imsg,int calledfromshowall)883 show_sensor_msg(struct imsg *imsg, int calledfromshowall)
884 {
885 struct ctl_show_sensor *csensor;
886 int cnt;
887 static int firsttime = 1;
888
889 if (imsg->hdr.type == IMSG_CTL_SHOW_SENSORS_END) {
890 if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(cnt))
891 fatalx("invalid IMSG_CTL_SHOW_SENSORS_END received");
892 memcpy(&cnt, imsg->data, sizeof(cnt));
893 if (cnt == 0)
894 printf("no sensors configured\n");
895 return;
896 }
897
898 if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(struct ctl_show_sensor))
899 fatalx("invalid IMSG_CTL_SHOW_SENSORS received");
900
901 csensor = (struct ctl_show_sensor *)imsg->data;
902
903 if (strlen(csensor->sensor_desc) > MAX_DISPLAY_WIDTH - 1)
904 fatalx("sensor_desc is too long");
905
906 if (firsttime) {
907 firsttime = 0;
908 if (calledfromshowall)
909 printf("\n");
910 printf("sensor\n wt gd st next poll "
911 "offset correction\n");
912 }
913
914 printf("%s\n %1s %2u %2u %2u %4llds %4llds",
915 csensor->sensor_desc, csensor->syncedto == 1 ? "*" : " ",
916 csensor->weight, csensor->good, csensor->stratum,
917 (long long)csensor->next, (long long)csensor->poll);
918
919 if (csensor->good == 1)
920 printf(" %11.3fms %9.3fms\n",
921 csensor->offset, csensor->correction);
922 else
923 printf(" - sensor not valid -\n");
924
925 }
926