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(¤t, 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, ¤t) == -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