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