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