1 #include <config.h> 2 3 #include <event2/util.h> 4 #include <event2/event.h> 5 6 #include "ntp_workimpl.h" 7 #ifdef WORK_THREAD 8 # include <event2/thread.h> 9 #endif 10 11 #ifdef HAVE_SYSEXITS_H 12 # include <sysexits.h> 13 #endif 14 15 #include "main.h" 16 #include "ntp_libopts.h" 17 #include "kod_management.h" 18 #include "networking.h" 19 #include "utilities.h" 20 #include "log.h" 21 #include "libntp.h" 22 23 extern const char *progname; 24 25 int shutting_down; 26 int time_derived; 27 int time_adjusted; 28 int n_pending_dns = 0; 29 int n_pending_ntp = 0; 30 int ai_fam_pref = AF_UNSPEC; 31 int ntpver = 4; 32 double steplimit = -1; 33 SOCKET sock4 = -1; /* Socket for IPv4 */ 34 SOCKET sock6 = -1; /* Socket for IPv6 */ 35 /* 36 ** BCAST *must* listen on port 123 (by default), so we can only 37 ** use the UCST sockets (above) if they too are using port 123 38 */ 39 SOCKET bsock4 = -1; /* Broadcast Socket for IPv4 */ 40 SOCKET bsock6 = -1; /* Broadcast Socket for IPv6 */ 41 struct event_base *base; 42 struct event *ev_sock4; 43 struct event *ev_sock6; 44 struct event *ev_worker_timeout; 45 struct event *ev_xmt_timer; 46 47 struct dns_ctx { 48 const char * name; 49 int flags; 50 #define CTX_BCST 0x0001 51 #define CTX_UCST 0x0002 52 #define CTX_xCST 0x0003 53 #define CTX_CONC 0x0004 54 #define CTX_unused 0xfffd 55 int key_id; 56 struct timeval timeout; 57 struct key * key; 58 }; 59 60 typedef struct sent_pkt_tag sent_pkt; 61 struct sent_pkt_tag { 62 sent_pkt * link; 63 struct dns_ctx * dctx; 64 sockaddr_u addr; 65 time_t stime; 66 int done; 67 struct pkt x_pkt; 68 }; 69 70 typedef struct xmt_ctx_tag xmt_ctx; 71 struct xmt_ctx_tag { 72 xmt_ctx * link; 73 SOCKET sock; 74 time_t sched; 75 sent_pkt * spkt; 76 }; 77 78 struct timeval gap; 79 xmt_ctx * xmt_q; 80 struct key * keys = NULL; 81 int response_timeout; 82 struct timeval response_tv; 83 struct timeval start_tv; 84 /* check the timeout at least once per second */ 85 struct timeval wakeup_tv = { 0, 888888 }; 86 87 sent_pkt * fam_listheads[2]; 88 #define v4_pkts_list (fam_listheads[0]) 89 #define v6_pkts_list (fam_listheads[1]) 90 91 static union { 92 struct pkt pkt; 93 char buf[LEN_PKT_NOMAC + NTP_MAXEXTEN + MAX_MAC_LEN]; 94 } rbuf; 95 96 #define r_pkt rbuf.pkt 97 98 #ifdef HAVE_DROPROOT 99 int droproot; /* intres imports these */ 100 int root_dropped; 101 #endif 102 u_long current_time; /* libntp/authkeys.c */ 103 104 void open_sockets(void); 105 void handle_lookup(const char *name, int flags); 106 void sntp_addremove_fd(int fd, int is_pipe, int remove_it); 107 void worker_timeout(evutil_socket_t, short, void *); 108 void worker_resp_cb(evutil_socket_t, short, void *); 109 void sntp_name_resolved(int, int, void *, const char *, const char *, 110 const struct addrinfo *, 111 const struct addrinfo *); 112 void queue_xmt(SOCKET sock, struct dns_ctx *dctx, sent_pkt *spkt, 113 u_int xmt_delay); 114 void xmt_timer_cb(evutil_socket_t, short, void *ptr); 115 void xmt(xmt_ctx *xctx); 116 int check_kod(const struct addrinfo *ai); 117 void timeout_query(sent_pkt *); 118 void timeout_queries(void); 119 void sock_cb(evutil_socket_t, short, void *); 120 void check_exit_conditions(void); 121 void sntp_libevent_log_cb(int, const char *); 122 void set_li_vn_mode(struct pkt *spkt, char leap, char version, char mode); 123 int set_time(double offset); 124 void dec_pending_ntp(const char *, sockaddr_u *); 125 int libevent_version_ok(void); 126 int gettimeofday_cached(struct event_base *b, struct timeval *tv); 127 128 129 /* 130 * The actual main function. 131 */ 132 int 133 sntp_main ( 134 int argc, 135 char **argv, 136 const char *sntpVersion 137 ) 138 { 139 int i; 140 int exitcode; 141 int optct; 142 struct event_config * evcfg; 143 144 /* Initialize logging system - sets up progname */ 145 sntp_init_logging(argv[0]); 146 147 if (!libevent_version_ok()) 148 exit(EX_SOFTWARE); 149 150 init_lib(); 151 init_auth(); 152 153 optct = ntpOptionProcess(&sntpOptions, argc, argv); 154 argc -= optct; 155 argv += optct; 156 157 158 debug = OPT_VALUE_SET_DEBUG_LEVEL; 159 160 TRACE(2, ("init_lib() done, %s%s\n", 161 (ipv4_works) 162 ? "ipv4_works " 163 : "", 164 (ipv6_works) 165 ? "ipv6_works " 166 : "")); 167 ntpver = OPT_VALUE_NTPVERSION; 168 steplimit = OPT_VALUE_STEPLIMIT / 1e3; 169 gap.tv_usec = max(0, OPT_VALUE_GAP * 1000); 170 gap.tv_usec = min(gap.tv_usec, 999999); 171 172 if (HAVE_OPT(LOGFILE)) 173 open_logfile(OPT_ARG(LOGFILE)); 174 175 msyslog(LOG_INFO, "%s", sntpVersion); 176 177 if (0 == argc && !HAVE_OPT(BROADCAST) && !HAVE_OPT(CONCURRENT)) { 178 printf("%s: Must supply at least one of -b hostname, -c hostname, or hostname.\n", 179 progname); 180 exit(EX_USAGE); 181 } 182 183 184 /* 185 ** Eventually, we probably want: 186 ** - separate bcst and ucst timeouts (why?) 187 ** - multiple --timeout values in the commandline 188 */ 189 190 response_timeout = OPT_VALUE_TIMEOUT; 191 response_tv.tv_sec = response_timeout; 192 response_tv.tv_usec = 0; 193 194 /* IPv6 available? */ 195 if (isc_net_probeipv6() != ISC_R_SUCCESS) { 196 ai_fam_pref = AF_INET; 197 TRACE(1, ("No ipv6 support available, forcing ipv4\n")); 198 } else { 199 /* Check for options -4 and -6 */ 200 if (HAVE_OPT(IPV4)) 201 ai_fam_pref = AF_INET; 202 else if (HAVE_OPT(IPV6)) 203 ai_fam_pref = AF_INET6; 204 } 205 206 /* TODO: Parse config file if declared */ 207 208 /* 209 ** Init the KOD system. 210 ** For embedded systems with no writable filesystem, 211 ** -K /dev/null can be used to disable KoD storage. 212 */ 213 kod_init_kod_db(OPT_ARG(KOD), FALSE); 214 215 /* HMS: Check and see what happens if KEYFILE doesn't exist */ 216 auth_init(OPT_ARG(KEYFILE), &keys); 217 218 /* 219 ** Considering employing a variable that prevents functions of doing 220 ** anything until everything is initialized properly 221 ** 222 ** HMS: What exactly does the above mean? 223 */ 224 event_set_log_callback(&sntp_libevent_log_cb); 225 if (debug > 0) 226 event_enable_debug_mode(); 227 #ifdef WORK_THREAD 228 evthread_use_pthreads(); 229 /* we use libevent from main thread only, locks should be academic */ 230 if (debug > 0) 231 evthread_enable_lock_debuging(); 232 #endif 233 evcfg = event_config_new(); 234 if (NULL == evcfg) { 235 printf("%s: event_config_new() failed!\n", progname); 236 return -1; 237 } 238 #ifndef HAVE_SOCKETPAIR 239 event_config_require_features(evcfg, EV_FEATURE_FDS); 240 #endif 241 /* all libevent calls are from main thread */ 242 /* event_config_set_flag(evcfg, EVENT_BASE_FLAG_NOLOCK); */ 243 base = event_base_new_with_config(evcfg); 244 event_config_free(evcfg); 245 if (NULL == base) { 246 printf("%s: event_base_new() failed!\n", progname); 247 return -1; 248 } 249 250 /* wire into intres resolver */ 251 worker_per_query = TRUE; 252 addremove_io_fd = &sntp_addremove_fd; 253 254 open_sockets(); 255 256 if (HAVE_OPT(BROADCAST)) { 257 int cn = STACKCT_OPT( BROADCAST ); 258 const char ** cp = STACKLST_OPT( BROADCAST ); 259 260 while (cn-- > 0) { 261 handle_lookup(*cp, CTX_BCST); 262 cp++; 263 } 264 } 265 266 if (HAVE_OPT(CONCURRENT)) { 267 int cn = STACKCT_OPT( CONCURRENT ); 268 const char ** cp = STACKLST_OPT( CONCURRENT ); 269 270 while (cn-- > 0) { 271 handle_lookup(*cp, CTX_UCST | CTX_CONC); 272 cp++; 273 } 274 } 275 276 for (i = 0; i < argc; ++i) 277 handle_lookup(argv[i], CTX_UCST); 278 279 gettimeofday_cached(base, &start_tv); 280 event_base_dispatch(base); 281 event_base_free(base); 282 283 if (!time_adjusted && 284 (ENABLED_OPT(STEP) || ENABLED_OPT(SLEW))) 285 exitcode = 1; 286 else 287 exitcode = 0; 288 289 return exitcode; 290 } 291 292 293 /* 294 ** open sockets and make them non-blocking 295 */ 296 void 297 open_sockets( 298 void 299 ) 300 { 301 sockaddr_u name; 302 303 if (-1 == sock4) { 304 sock4 = socket(PF_INET, SOCK_DGRAM, 0); 305 if (-1 == sock4) { 306 /* error getting a socket */ 307 msyslog(LOG_ERR, "open_sockets: socket(PF_INET) failed: %m"); 308 exit(1); 309 } 310 /* Make it non-blocking */ 311 make_socket_nonblocking(sock4); 312 313 /* Let's try using a wildcard... */ 314 ZERO(name); 315 AF(&name) = AF_INET; 316 SET_ADDR4N(&name, INADDR_ANY); 317 SET_PORT(&name, (HAVE_OPT(USERESERVEDPORT) ? 123 : 0)); 318 319 if (-1 == bind(sock4, &name.sa, 320 SOCKLEN(&name))) { 321 msyslog(LOG_ERR, "open_sockets: bind(sock4) failed: %m"); 322 exit(1); 323 } 324 325 /* Register an NTP callback for recv/timeout */ 326 ev_sock4 = event_new(base, sock4, 327 EV_TIMEOUT | EV_READ | EV_PERSIST, 328 &sock_cb, NULL); 329 if (NULL == ev_sock4) { 330 msyslog(LOG_ERR, 331 "open_sockets: event_new(base, sock4) failed!"); 332 } else { 333 event_add(ev_sock4, &wakeup_tv); 334 } 335 } 336 337 /* We may not always have IPv6... */ 338 if (-1 == sock6 && ipv6_works) { 339 sock6 = socket(PF_INET6, SOCK_DGRAM, 0); 340 if (-1 == sock6 && ipv6_works) { 341 /* error getting a socket */ 342 msyslog(LOG_ERR, "open_sockets: socket(PF_INET6) failed: %m"); 343 exit(1); 344 } 345 /* Make it non-blocking */ 346 make_socket_nonblocking(sock6); 347 348 /* Let's try using a wildcard... */ 349 ZERO(name); 350 AF(&name) = AF_INET6; 351 SET_ADDR6N(&name, in6addr_any); 352 SET_PORT(&name, (HAVE_OPT(USERESERVEDPORT) ? 123 : 0)); 353 354 if (-1 == bind(sock6, &name.sa, 355 SOCKLEN(&name))) { 356 msyslog(LOG_ERR, "open_sockets: bind(sock6) failed: %m"); 357 exit(1); 358 } 359 /* Register an NTP callback for recv/timeout */ 360 ev_sock6 = event_new(base, sock6, 361 EV_TIMEOUT | EV_READ | EV_PERSIST, 362 &sock_cb, NULL); 363 if (NULL == ev_sock6) { 364 msyslog(LOG_ERR, 365 "open_sockets: event_new(base, sock6) failed!"); 366 } else { 367 event_add(ev_sock6, &wakeup_tv); 368 } 369 } 370 371 return; 372 } 373 374 375 /* 376 ** handle_lookup 377 */ 378 void 379 handle_lookup( 380 const char *name, 381 int flags 382 ) 383 { 384 struct addrinfo hints; /* Local copy is OK */ 385 struct dns_ctx *ctx; 386 char * name_copy; 387 size_t name_sz; 388 size_t octets; 389 390 TRACE(1, ("handle_lookup(%s,%#x)\n", name, flags)); 391 392 ZERO(hints); 393 hints.ai_family = ai_fam_pref; 394 hints.ai_flags = AI_CANONNAME | Z_AI_NUMERICSERV; 395 /* 396 ** Unless we specify a socktype, we'll get at least two 397 ** entries for each address: one for TCP and one for 398 ** UDP. That's not what we want. 399 */ 400 hints.ai_socktype = SOCK_DGRAM; 401 hints.ai_protocol = IPPROTO_UDP; 402 403 name_sz = 1 + strlen(name); 404 octets = sizeof(*ctx) + name_sz; // Space for a ctx and the name 405 ctx = emalloc_zero(octets); // ctx at ctx[0] 406 name_copy = (char *)(ctx + 1); // Put the name at ctx[1] 407 memcpy(name_copy, name, name_sz); // copy the name to ctx[1] 408 ctx->name = name_copy; // point to it... 409 ctx->flags = flags; 410 ctx->timeout = response_tv; 411 ctx->key = NULL; 412 413 /* The following should arguably be passed in... */ 414 if (ENABLED_OPT(AUTHENTICATION)) { 415 ctx->key_id = OPT_VALUE_AUTHENTICATION; 416 get_key(ctx->key_id, &ctx->key); 417 if (NULL == ctx->key) { 418 fprintf(stderr, "%s: Authentication with keyID %d requested, but no matching keyID found in <%s>!\n", 419 progname, ctx->key_id, OPT_ARG(KEYFILE)); 420 exit(1); 421 } 422 } else { 423 ctx->key_id = -1; 424 } 425 426 ++n_pending_dns; 427 getaddrinfo_sometime(name, "123", &hints, 0, 428 &sntp_name_resolved, ctx); 429 } 430 431 432 /* 433 ** DNS Callback: 434 ** - For each IP: 435 ** - - open a socket 436 ** - - increment n_pending_ntp 437 ** - - send a request if this is a Unicast callback 438 ** - - queue wait for response 439 ** - decrement n_pending_dns 440 */ 441 void 442 sntp_name_resolved( 443 int rescode, 444 int gai_errno, 445 void * context, 446 const char * name, 447 const char * service, 448 const struct addrinfo * hints, 449 const struct addrinfo * addr 450 ) 451 { 452 struct dns_ctx * dctx; 453 sent_pkt * spkt; 454 const struct addrinfo * ai; 455 SOCKET sock; 456 u_int xmt_delay_v4; 457 u_int xmt_delay_v6; 458 u_int xmt_delay; 459 size_t octets; 460 461 xmt_delay_v4 = 0; 462 xmt_delay_v6 = 0; 463 dctx = context; 464 if (rescode) { 465 #ifdef EAI_SYSTEM 466 if (EAI_SYSTEM == rescode) { 467 errno = gai_errno; 468 mfprintf(stderr, "%s lookup error %m\n", 469 dctx->name); 470 } else 471 #endif 472 fprintf(stderr, "%s lookup error %s\n", 473 dctx->name, gai_strerror(rescode)); 474 } else { 475 TRACE(3, ("%s [%s]\n", dctx->name, 476 (addr->ai_canonname != NULL) 477 ? addr->ai_canonname 478 : "")); 479 480 for (ai = addr; ai != NULL; ai = ai->ai_next) { 481 482 if (check_kod(ai)) 483 continue; 484 485 switch (ai->ai_family) { 486 487 case AF_INET: 488 sock = sock4; 489 xmt_delay = xmt_delay_v4; 490 xmt_delay_v4++; 491 break; 492 493 case AF_INET6: 494 if (!ipv6_works) 495 continue; 496 497 sock = sock6; 498 xmt_delay = xmt_delay_v6; 499 xmt_delay_v6++; 500 break; 501 502 default: 503 msyslog(LOG_ERR, "sntp_name_resolved: unexpected ai_family: %d", 504 ai->ai_family); 505 exit(1); 506 break; 507 } 508 509 /* 510 ** We're waiting for a response for either unicast 511 ** or broadcast, so... 512 */ 513 ++n_pending_ntp; 514 515 /* If this is for a unicast IP, queue a request */ 516 if (dctx->flags & CTX_UCST) { 517 spkt = emalloc_zero(sizeof(*spkt)); 518 spkt->dctx = dctx; 519 octets = min(ai->ai_addrlen, sizeof(spkt->addr)); 520 memcpy(&spkt->addr, ai->ai_addr, octets); 521 queue_xmt(sock, dctx, spkt, xmt_delay); 522 } 523 } 524 } 525 /* n_pending_dns really should be >0 here... */ 526 --n_pending_dns; 527 check_exit_conditions(); 528 } 529 530 531 /* 532 ** queue_xmt 533 */ 534 void 535 queue_xmt( 536 SOCKET sock, 537 struct dns_ctx * dctx, 538 sent_pkt * spkt, 539 u_int xmt_delay 540 ) 541 { 542 sockaddr_u * dest; 543 sent_pkt ** pkt_listp; 544 sent_pkt * match; 545 xmt_ctx * xctx; 546 struct timeval start_cb; 547 struct timeval delay; 548 549 dest = &spkt->addr; 550 if (IS_IPV6(dest)) 551 pkt_listp = &v6_pkts_list; 552 else 553 pkt_listp = &v4_pkts_list; 554 555 /* reject attempts to add address already listed */ 556 for (match = *pkt_listp; match != NULL; match = match->link) { 557 if (ADDR_PORT_EQ(&spkt->addr, &match->addr)) { 558 if (strcasecmp(spkt->dctx->name, 559 match->dctx->name)) 560 printf("%s %s duplicate address from %s ignored.\n", 561 sptoa(&match->addr), 562 match->dctx->name, 563 spkt->dctx->name); 564 else 565 printf("%s %s, duplicate address ignored.\n", 566 sptoa(&match->addr), 567 match->dctx->name); 568 dec_pending_ntp(spkt->dctx->name, &spkt->addr); 569 free(spkt); 570 return; 571 } 572 } 573 574 LINK_SLIST(*pkt_listp, spkt, link); 575 576 xctx = emalloc_zero(sizeof(*xctx)); 577 xctx->sock = sock; 578 xctx->spkt = spkt; 579 gettimeofday_cached(base, &start_cb); 580 xctx->sched = start_cb.tv_sec + (2 * xmt_delay); 581 582 LINK_SORT_SLIST(xmt_q, xctx, (xctx->sched < L_S_S_CUR()->sched), 583 link, xmt_ctx); 584 if (xmt_q == xctx) { 585 /* 586 * The new entry is the first scheduled. The timer is 587 * either not active or is set for the second xmt 588 * context in xmt_q. 589 */ 590 if (NULL == ev_xmt_timer) 591 ev_xmt_timer = event_new(base, INVALID_SOCKET, 592 EV_TIMEOUT, 593 &xmt_timer_cb, NULL); 594 if (NULL == ev_xmt_timer) { 595 msyslog(LOG_ERR, 596 "queue_xmt: event_new(base, -1, EV_TIMEOUT) failed!"); 597 exit(1); 598 } 599 ZERO(delay); 600 if (xctx->sched > start_cb.tv_sec) 601 delay.tv_sec = xctx->sched - start_cb.tv_sec; 602 event_add(ev_xmt_timer, &delay); 603 TRACE(2, ("queue_xmt: xmt timer for %u usec\n", 604 (u_int)delay.tv_usec)); 605 } 606 } 607 608 609 /* 610 ** xmt_timer_cb 611 */ 612 void 613 xmt_timer_cb( 614 evutil_socket_t fd, 615 short what, 616 void * ctx 617 ) 618 { 619 struct timeval start_cb; 620 struct timeval delay; 621 xmt_ctx * x; 622 623 UNUSED_ARG(fd); 624 UNUSED_ARG(ctx); 625 DEBUG_INSIST(EV_TIMEOUT == what); 626 627 if (NULL == xmt_q || shutting_down) 628 return; 629 gettimeofday_cached(base, &start_cb); 630 if (xmt_q->sched <= start_cb.tv_sec) { 631 UNLINK_HEAD_SLIST(x, xmt_q, link); 632 TRACE(2, ("xmt_timer_cb: at .%6.6u -> %s\n", 633 (u_int)start_cb.tv_usec, stoa(&x->spkt->addr))); 634 xmt(x); 635 free(x); 636 if (NULL == xmt_q) 637 return; 638 } 639 if (xmt_q->sched <= start_cb.tv_sec) { 640 event_add(ev_xmt_timer, &gap); 641 TRACE(2, ("xmt_timer_cb: at .%6.6u gap %6.6u\n", 642 (u_int)start_cb.tv_usec, 643 (u_int)gap.tv_usec)); 644 } else { 645 delay.tv_sec = xmt_q->sched - start_cb.tv_sec; 646 delay.tv_usec = 0; 647 event_add(ev_xmt_timer, &delay); 648 TRACE(2, ("xmt_timer_cb: at .%6.6u next %ld seconds\n", 649 (u_int)start_cb.tv_usec, 650 (long)delay.tv_sec)); 651 } 652 } 653 654 655 /* 656 ** xmt() 657 */ 658 void 659 xmt( 660 xmt_ctx * xctx 661 ) 662 { 663 SOCKET sock = xctx->sock; 664 struct dns_ctx *dctx = xctx->spkt->dctx; 665 sent_pkt * spkt = xctx->spkt; 666 sockaddr_u * dst = &spkt->addr; 667 struct timeval tv_xmt; 668 struct pkt x_pkt; 669 size_t pkt_len; 670 int sent; 671 672 if (0 != gettimeofday(&tv_xmt, NULL)) { 673 msyslog(LOG_ERR, 674 "xmt: gettimeofday() failed: %m"); 675 exit(1); 676 } 677 tv_xmt.tv_sec += JAN_1970; 678 679 pkt_len = generate_pkt(&x_pkt, &tv_xmt, dctx->key_id, 680 dctx->key); 681 682 sent = sendpkt(sock, dst, &x_pkt, pkt_len); 683 if (sent) { 684 /* Save the packet we sent... */ 685 memcpy(&spkt->x_pkt, &x_pkt, min(sizeof(spkt->x_pkt), 686 pkt_len)); 687 spkt->stime = tv_xmt.tv_sec - JAN_1970; 688 689 TRACE(2, ("xmt: %lx.%6.6u %s %s\n", (u_long)tv_xmt.tv_sec, 690 (u_int)tv_xmt.tv_usec, dctx->name, stoa(dst))); 691 } else { 692 dec_pending_ntp(dctx->name, dst); 693 } 694 695 return; 696 } 697 698 699 /* 700 * timeout_queries() -- give up on unrequited NTP queries 701 */ 702 void 703 timeout_queries(void) 704 { 705 struct timeval start_cb; 706 u_int idx; 707 sent_pkt * head; 708 sent_pkt * spkt; 709 sent_pkt * spkt_next; 710 long age; 711 int didsomething = 0; 712 713 TRACE(3, ("timeout_queries: called to check %u items\n", 714 (unsigned)COUNTOF(fam_listheads))); 715 716 gettimeofday_cached(base, &start_cb); 717 for (idx = 0; idx < COUNTOF(fam_listheads); idx++) { 718 head = fam_listheads[idx]; 719 for (spkt = head; spkt != NULL; spkt = spkt_next) { 720 char xcst; 721 722 didsomething = 1; 723 switch (spkt->dctx->flags & CTX_xCST) { 724 case CTX_BCST: 725 xcst = 'B'; 726 break; 727 728 case CTX_UCST: 729 xcst = 'U'; 730 break; 731 732 default: 733 INSIST(!"spkt->dctx->flags neither UCST nor BCST"); 734 break; 735 } 736 737 spkt_next = spkt->link; 738 if (0 == spkt->stime || spkt->done) 739 continue; 740 age = start_cb.tv_sec - spkt->stime; 741 TRACE(3, ("%s %s %cCST age %ld\n", 742 stoa(&spkt->addr), 743 spkt->dctx->name, xcst, age)); 744 if (age > response_timeout) 745 timeout_query(spkt); 746 } 747 } 748 // Do we care about didsomething? 749 TRACE(3, ("timeout_queries: didsomething is %d, age is %ld\n", 750 didsomething, (long) (start_cb.tv_sec - start_tv.tv_sec))); 751 if (start_cb.tv_sec - start_tv.tv_sec > response_timeout) { 752 TRACE(3, ("timeout_queries: bail!\n")); 753 event_base_loopexit(base, NULL); 754 shutting_down = TRUE; 755 } 756 } 757 758 759 void dec_pending_ntp( 760 const char * name, 761 sockaddr_u * server 762 ) 763 { 764 if (n_pending_ntp > 0) { 765 --n_pending_ntp; 766 check_exit_conditions(); 767 } else { 768 INSIST(0 == n_pending_ntp); 769 TRACE(1, ("n_pending_ntp was zero before decrement for %s\n", 770 hostnameaddr(name, server))); 771 } 772 } 773 774 775 void timeout_query( 776 sent_pkt * spkt 777 ) 778 { 779 sockaddr_u * server; 780 char xcst; 781 782 783 switch (spkt->dctx->flags & CTX_xCST) { 784 case CTX_BCST: 785 xcst = 'B'; 786 break; 787 788 case CTX_UCST: 789 xcst = 'U'; 790 break; 791 792 default: 793 INSIST(!"spkt->dctx->flags neither UCST nor BCST"); 794 break; 795 } 796 spkt->done = TRUE; 797 server = &spkt->addr; 798 msyslog(LOG_INFO, "%s no %cCST response after %d seconds", 799 hostnameaddr(spkt->dctx->name, server), xcst, 800 response_timeout); 801 dec_pending_ntp(spkt->dctx->name, server); 802 return; 803 } 804 805 806 /* 807 ** check_kod 808 */ 809 int 810 check_kod( 811 const struct addrinfo * ai 812 ) 813 { 814 char *hostname; 815 struct kod_entry *reason; 816 817 /* Is there a KoD on file for this address? */ 818 hostname = addrinfo_to_str(ai); 819 TRACE(2, ("check_kod: checking <%s>\n", hostname)); 820 if (search_entry(hostname, &reason)) { 821 printf("prior KoD for %s, skipping.\n", 822 hostname); 823 free(reason); 824 free(hostname); 825 826 return 1; 827 } 828 free(hostname); 829 830 return 0; 831 } 832 833 834 /* 835 ** Socket readable/timeout Callback: 836 ** Read in the packet 837 ** Unicast: 838 ** - close socket 839 ** - decrement n_pending_ntp 840 ** - If packet is good, set the time and "exit" 841 ** Broadcast: 842 ** - If packet is good, set the time and "exit" 843 */ 844 void 845 sock_cb( 846 evutil_socket_t fd, 847 short what, 848 void *ptr 849 ) 850 { 851 sockaddr_u sender; 852 sockaddr_u * psau; 853 sent_pkt ** p_pktlist; 854 sent_pkt * spkt; 855 int rpktl; 856 int rc; 857 858 INSIST(sock4 == fd || sock6 == fd); 859 860 TRACE(3, ("sock_cb: event on sock%s:%s%s%s%s\n", 861 (fd == sock6) 862 ? "6" 863 : "4", 864 (what & EV_TIMEOUT) ? " timeout" : "", 865 (what & EV_READ) ? " read" : "", 866 (what & EV_WRITE) ? " write" : "", 867 (what & EV_SIGNAL) ? " signal" : "")); 868 869 if (!(EV_READ & what)) { 870 if (EV_TIMEOUT & what) 871 timeout_queries(); 872 873 return; 874 } 875 876 /* Read in the packet */ 877 rpktl = recvdata(fd, &sender, &rbuf, sizeof(rbuf)); 878 if (rpktl < 0) { 879 msyslog(LOG_DEBUG, "recvfrom error %m"); 880 return; 881 } 882 883 if (sock6 == fd) 884 p_pktlist = &v6_pkts_list; 885 else 886 p_pktlist = &v4_pkts_list; 887 888 for (spkt = *p_pktlist; spkt != NULL; spkt = spkt->link) { 889 psau = &spkt->addr; 890 if (SOCK_EQ(&sender, psau)) 891 break; 892 } 893 if (NULL == spkt) { 894 msyslog(LOG_WARNING, 895 "Packet from unexpected source %s dropped", 896 sptoa(&sender)); 897 return; 898 } 899 900 TRACE(1, ("sock_cb: %s %s\n", spkt->dctx->name, 901 sptoa(&sender))); 902 903 rpktl = process_pkt(&r_pkt, &sender, rpktl, MODE_SERVER, 904 &spkt->x_pkt, "sock_cb"); 905 906 TRACE(2, ("sock_cb: process_pkt returned %d\n", rpktl)); 907 908 /* If this is a Unicast packet, one down ... */ 909 if (!spkt->done && (CTX_UCST & spkt->dctx->flags)) { 910 dec_pending_ntp(spkt->dctx->name, &spkt->addr); 911 spkt->done = TRUE; 912 } 913 914 915 /* If the packet is good, set the time and we're all done */ 916 rc = handle_pkt(rpktl, &r_pkt, &spkt->addr, spkt->dctx->name); 917 if (0 != rc) 918 TRACE(1, ("sock_cb: handle_pkt() returned %d\n", rc)); 919 check_exit_conditions(); 920 } 921 922 923 /* 924 * check_exit_conditions() 925 * 926 * If sntp has a reply, ask the event loop to stop after this round of 927 * callbacks, unless --wait was used. 928 */ 929 void 930 check_exit_conditions(void) 931 { 932 if ((0 == n_pending_ntp && 0 == n_pending_dns) || 933 (time_derived && !HAVE_OPT(WAIT))) { 934 event_base_loopexit(base, NULL); 935 shutting_down = TRUE; 936 } else { 937 TRACE(2, ("%d NTP and %d name queries pending\n", 938 n_pending_ntp, n_pending_dns)); 939 } 940 } 941 942 943 /* 944 * sntp_addremove_fd() is invoked by the intres blocking worker code 945 * to read from a pipe, or to stop same. 946 */ 947 void sntp_addremove_fd( 948 int fd, 949 int is_pipe, 950 int remove_it 951 ) 952 { 953 u_int idx; 954 blocking_child *c; 955 struct event * ev; 956 957 #ifdef HAVE_SOCKETPAIR 958 if (is_pipe) { 959 /* sntp only asks for EV_FEATURE_FDS without HAVE_SOCKETPAIR */ 960 msyslog(LOG_ERR, "fatal: pipes not supported on systems with socketpair()"); 961 exit(1); 962 } 963 #endif 964 965 c = NULL; 966 for (idx = 0; idx < blocking_children_alloc; idx++) { 967 c = blocking_children[idx]; 968 if (NULL == c) 969 continue; 970 if (fd == c->resp_read_pipe) 971 break; 972 } 973 if (idx == blocking_children_alloc) 974 return; 975 976 if (remove_it) { 977 ev = c->resp_read_ctx; 978 c->resp_read_ctx = NULL; 979 event_del(ev); 980 event_free(ev); 981 982 return; 983 } 984 985 ev = event_new(base, fd, EV_READ | EV_PERSIST, 986 &worker_resp_cb, c); 987 if (NULL == ev) { 988 msyslog(LOG_ERR, 989 "sntp_addremove_fd: event_new(base, fd) failed!"); 990 return; 991 } 992 c->resp_read_ctx = ev; 993 event_add(ev, NULL); 994 } 995 996 997 /* called by forked intres child to close open descriptors */ 998 #ifdef WORK_FORK 999 void 1000 kill_asyncio( 1001 int startfd 1002 ) 1003 { 1004 if (INVALID_SOCKET != sock4) { 1005 closesocket(sock4); 1006 sock4 = INVALID_SOCKET; 1007 } 1008 if (INVALID_SOCKET != sock6) { 1009 closesocket(sock6); 1010 sock6 = INVALID_SOCKET; 1011 } 1012 if (INVALID_SOCKET != bsock4) { 1013 closesocket(sock4); 1014 sock4 = INVALID_SOCKET; 1015 } 1016 if (INVALID_SOCKET != bsock6) { 1017 closesocket(sock6); 1018 sock6 = INVALID_SOCKET; 1019 } 1020 } 1021 #endif 1022 1023 1024 /* 1025 * worker_resp_cb() is invoked when resp_read_pipe is readable. 1026 */ 1027 void 1028 worker_resp_cb( 1029 evutil_socket_t fd, 1030 short what, 1031 void * ctx /* blocking_child * */ 1032 ) 1033 { 1034 blocking_child * c; 1035 1036 DEBUG_INSIST(EV_READ & what); 1037 c = ctx; 1038 DEBUG_INSIST(fd == c->resp_read_pipe); 1039 process_blocking_resp(c); 1040 } 1041 1042 1043 /* 1044 * intres_timeout_req(s) is invoked in the parent to schedule an idle 1045 * timeout to fire in s seconds, if not reset earlier by a call to 1046 * intres_timeout_req(0), which clears any pending timeout. When the 1047 * timeout expires, worker_idle_timer_fired() is invoked (again, in the 1048 * parent). 1049 * 1050 * sntp and ntpd each provide implementations adapted to their timers. 1051 */ 1052 void 1053 intres_timeout_req( 1054 u_int seconds /* 0 cancels */ 1055 ) 1056 { 1057 struct timeval tv_to; 1058 1059 if (NULL == ev_worker_timeout) { 1060 ev_worker_timeout = event_new(base, -1, 1061 EV_TIMEOUT | EV_PERSIST, 1062 &worker_timeout, NULL); 1063 DEBUG_INSIST(NULL != ev_worker_timeout); 1064 } else { 1065 event_del(ev_worker_timeout); 1066 } 1067 if (0 == seconds) 1068 return; 1069 tv_to.tv_sec = seconds; 1070 tv_to.tv_usec = 0; 1071 event_add(ev_worker_timeout, &tv_to); 1072 } 1073 1074 1075 void 1076 worker_timeout( 1077 evutil_socket_t fd, 1078 short what, 1079 void * ctx 1080 ) 1081 { 1082 UNUSED_ARG(fd); 1083 UNUSED_ARG(ctx); 1084 1085 DEBUG_REQUIRE(EV_TIMEOUT & what); 1086 worker_idle_timer_fired(); 1087 } 1088 1089 1090 void 1091 sntp_libevent_log_cb( 1092 int severity, 1093 const char * msg 1094 ) 1095 { 1096 int level; 1097 1098 switch (severity) { 1099 1100 default: 1101 case _EVENT_LOG_DEBUG: 1102 level = LOG_DEBUG; 1103 break; 1104 1105 case _EVENT_LOG_MSG: 1106 level = LOG_NOTICE; 1107 break; 1108 1109 case _EVENT_LOG_WARN: 1110 level = LOG_WARNING; 1111 break; 1112 1113 case _EVENT_LOG_ERR: 1114 level = LOG_ERR; 1115 break; 1116 } 1117 1118 msyslog(level, "%s", msg); 1119 } 1120 1121 1122 int 1123 generate_pkt ( 1124 struct pkt *x_pkt, 1125 const struct timeval *tv_xmt, 1126 int key_id, 1127 struct key *pkt_key 1128 ) 1129 { 1130 l_fp xmt_fp; 1131 int pkt_len; 1132 int mac_size; 1133 1134 pkt_len = LEN_PKT_NOMAC; 1135 ZERO(*x_pkt); 1136 TVTOTS(tv_xmt, &xmt_fp); 1137 HTONL_FP(&xmt_fp, &x_pkt->xmt); 1138 x_pkt->stratum = STRATUM_TO_PKT(STRATUM_UNSPEC); 1139 x_pkt->ppoll = 8; 1140 /* FIXME! Modus broadcast + adr. check -> bdr. pkt */ 1141 set_li_vn_mode(x_pkt, LEAP_NOTINSYNC, ntpver, 3); 1142 if (debug > 0) { 1143 printf("generate_pkt: key_id %d, key pointer %p\n", key_id, pkt_key); 1144 } 1145 if (pkt_key != NULL) { 1146 x_pkt->exten[0] = htonl(key_id); 1147 mac_size = make_mac(x_pkt, pkt_len, MAX_MDG_LEN, 1148 pkt_key, (char *)&x_pkt->exten[1]); 1149 if (mac_size > 0) 1150 pkt_len += mac_size + KEY_MAC_LEN; 1151 #ifdef DEBUG 1152 if (debug > 0) { 1153 printf("generate_pkt: mac_size is %d\n", mac_size); 1154 } 1155 #endif 1156 1157 } 1158 return pkt_len; 1159 } 1160 1161 1162 int 1163 handle_pkt( 1164 int rpktl, 1165 struct pkt * rpkt, 1166 sockaddr_u * host, 1167 const char * hostname 1168 ) 1169 { 1170 char disptxt[32]; 1171 const char * addrtxt; 1172 struct timeval tv_dst; 1173 int cnt; 1174 int sw_case; 1175 int digits; 1176 int stratum; 1177 char * ref; 1178 char * ts_str; 1179 const char * leaptxt; 1180 double offset; 1181 double precision; 1182 double synch_distance; 1183 char * p_SNTP_PRETEND_TIME; 1184 time_t pretend_time; 1185 #if SIZEOF_TIME_T == 8 1186 long long ll; 1187 #else 1188 long l; 1189 #endif 1190 1191 ts_str = NULL; 1192 1193 if (rpktl > 0) 1194 sw_case = 1; 1195 else 1196 sw_case = rpktl; 1197 1198 switch (sw_case) { 1199 1200 case SERVER_UNUSEABLE: 1201 return -1; 1202 break; 1203 1204 case PACKET_UNUSEABLE: 1205 break; 1206 1207 case SERVER_AUTH_FAIL: 1208 break; 1209 1210 case KOD_DEMOBILIZE: 1211 /* Received a DENY or RESTR KOD packet */ 1212 addrtxt = stoa(host); 1213 ref = (char *)&rpkt->refid; 1214 add_entry(addrtxt, ref); 1215 msyslog(LOG_WARNING, "KOD code %c%c%c%c from %s %s", 1216 ref[0], ref[1], ref[2], ref[3], addrtxt, hostname); 1217 break; 1218 1219 case KOD_RATE: 1220 /* 1221 ** Hmm... 1222 ** We should probably call add_entry() with an 1223 ** expiration timestamp of several seconds in the future, 1224 ** and back-off even more if we get more RATE responses. 1225 */ 1226 break; 1227 1228 case 1: 1229 TRACE(3, ("handle_pkt: %d bytes from %s %s\n", 1230 rpktl, stoa(host), hostname)); 1231 1232 gettimeofday_cached(base, &tv_dst); 1233 1234 p_SNTP_PRETEND_TIME = getenv("SNTP_PRETEND_TIME"); 1235 if (p_SNTP_PRETEND_TIME) { 1236 pretend_time = 0; 1237 #if SIZEOF_TIME_T == 4 1238 if (1 == sscanf(p_SNTP_PRETEND_TIME, "%ld", &l)) 1239 pretend_time = (time_t)l; 1240 #elif SIZEOF_TIME_T == 8 1241 if (1 == sscanf(p_SNTP_PRETEND_TIME, "%lld", &ll)) 1242 pretend_time = (time_t)ll; 1243 #else 1244 # include "GRONK: unexpected value for SIZEOF_TIME_T" 1245 #endif 1246 if (0 != pretend_time) 1247 tv_dst.tv_sec = pretend_time; 1248 } 1249 1250 offset_calculation(rpkt, rpktl, &tv_dst, &offset, 1251 &precision, &synch_distance); 1252 time_derived = TRUE; 1253 1254 for (digits = 0; (precision *= 10.) < 1.; ++digits) 1255 /* empty */ ; 1256 if (digits > 6) 1257 digits = 6; 1258 1259 ts_str = tv_to_str(&tv_dst); 1260 stratum = rpkt->stratum; 1261 if (0 == stratum) 1262 stratum = 16; 1263 1264 if (synch_distance > 0.) { 1265 cnt = snprintf(disptxt, sizeof(disptxt), 1266 " +/- %f", synch_distance); 1267 if ((size_t)cnt >= sizeof(disptxt)) 1268 snprintf(disptxt, sizeof(disptxt), 1269 "ERROR %d >= %d", cnt, 1270 (int)sizeof(disptxt)); 1271 } else { 1272 disptxt[0] = '\0'; 1273 } 1274 1275 switch (PKT_LEAP(rpkt->li_vn_mode)) { 1276 case LEAP_NOWARNING: 1277 leaptxt = "no-leap"; 1278 break; 1279 case LEAP_ADDSECOND: 1280 leaptxt = "add-leap"; 1281 break; 1282 case LEAP_DELSECOND: 1283 leaptxt = "del-leap"; 1284 break; 1285 case LEAP_NOTINSYNC: 1286 leaptxt = "unsync"; 1287 break; 1288 default: 1289 leaptxt = "LEAP-ERROR"; 1290 break; 1291 } 1292 1293 msyslog(LOG_INFO, "%s %+.*f%s %s s%d %s%s", ts_str, 1294 digits, offset, disptxt, 1295 hostnameaddr(hostname, host), stratum, 1296 leaptxt, 1297 (time_adjusted) 1298 ? " [excess]" 1299 : ""); 1300 free(ts_str); 1301 1302 if (p_SNTP_PRETEND_TIME) 1303 return 0; 1304 1305 if (!time_adjusted && 1306 (ENABLED_OPT(STEP) || ENABLED_OPT(SLEW))) 1307 return set_time(offset); 1308 1309 return EX_OK; 1310 } 1311 1312 return 1; 1313 } 1314 1315 1316 void 1317 offset_calculation( 1318 struct pkt *rpkt, 1319 int rpktl, 1320 struct timeval *tv_dst, 1321 double *offset, 1322 double *precision, 1323 double *synch_distance 1324 ) 1325 { 1326 l_fp p_rec, p_xmt, p_ref, p_org, tmp, dst; 1327 u_fp p_rdly, p_rdsp; 1328 double t21, t34, delta; 1329 1330 /* Convert timestamps from network to host byte order */ 1331 p_rdly = NTOHS_FP(rpkt->rootdelay); 1332 p_rdsp = NTOHS_FP(rpkt->rootdisp); 1333 NTOHL_FP(&rpkt->reftime, &p_ref); 1334 NTOHL_FP(&rpkt->org, &p_org); 1335 NTOHL_FP(&rpkt->rec, &p_rec); 1336 NTOHL_FP(&rpkt->xmt, &p_xmt); 1337 1338 *precision = LOGTOD(rpkt->precision); 1339 1340 TRACE(3, ("offset_calculation: LOGTOD(rpkt->precision): %f\n", *precision)); 1341 1342 /* Compute offset etc. */ 1343 tmp = p_rec; 1344 L_SUB(&tmp, &p_org); 1345 LFPTOD(&tmp, t21); 1346 TVTOTS(tv_dst, &dst); 1347 dst.l_ui += JAN_1970; 1348 tmp = p_xmt; 1349 L_SUB(&tmp, &dst); 1350 LFPTOD(&tmp, t34); 1351 *offset = (t21 + t34) / 2.; 1352 delta = t21 - t34; 1353 1354 // synch_distance is: 1355 // (peer->delay + peer->rootdelay) / 2 + peer->disp 1356 // + peer->rootdisp + clock_phi * (current_time - peer->update) 1357 // + peer->jitter; 1358 // 1359 // and peer->delay = fabs(peer->offset - p_offset) * 2; 1360 // and peer->offset needs history, so we're left with 1361 // p_offset = (t21 + t34) / 2.; 1362 // peer->disp = 0; (we have no history to augment this) 1363 // clock_phi = 15e-6; 1364 // peer->jitter = LOGTOD(sys_precision); (we have no history to augment this) 1365 // and ntp_proto.c:set_sys_tick_precision() should get us sys_precision. 1366 // 1367 // so our answer seems to be: 1368 // 1369 // (fabs(t21 + t34) + peer->rootdelay) / 3. 1370 // + 0 (peer->disp) 1371 // + peer->rootdisp 1372 // + 15e-6 (clock_phi) 1373 // + LOGTOD(sys_precision) 1374 1375 INSIST( FPTOD(p_rdly) >= 0. ); 1376 #if 1 1377 *synch_distance = (fabs(t21 + t34) + FPTOD(p_rdly)) / 3. 1378 + 0. 1379 + FPTOD(p_rdsp) 1380 + 15e-6 1381 + 0. /* LOGTOD(sys_precision) when we can get it */ 1382 ; 1383 INSIST( *synch_distance >= 0. ); 1384 #else 1385 *synch_distance = (FPTOD(p_rdly) + FPTOD(p_rdsp))/2.0; 1386 #endif 1387 1388 #ifdef DEBUG 1389 if (debug > 3) { 1390 printf("sntp rootdelay: %f\n", FPTOD(p_rdly)); 1391 printf("sntp rootdisp: %f\n", FPTOD(p_rdsp)); 1392 printf("sntp syncdist: %f\n", *synch_distance); 1393 1394 pkt_output(rpkt, rpktl, stdout); 1395 1396 printf("sntp offset_calculation: rpkt->reftime:\n"); 1397 l_fp_output(&p_ref, stdout); 1398 printf("sntp offset_calculation: rpkt->org:\n"); 1399 l_fp_output(&p_org, stdout); 1400 printf("sntp offset_calculation: rpkt->rec:\n"); 1401 l_fp_output(&p_rec, stdout); 1402 printf("sntp offset_calculation: rpkt->xmt:\n"); 1403 l_fp_output(&p_xmt, stdout); 1404 } 1405 #endif 1406 1407 TRACE(3, ("sntp offset_calculation:\trec - org t21: %.6f\n" 1408 "\txmt - dst t34: %.6f\tdelta: %.6f\toffset: %.6f\n", 1409 t21, t34, delta, *offset)); 1410 1411 return; 1412 } 1413 1414 1415 1416 /* Compute the 8 bits for li_vn_mode */ 1417 void 1418 set_li_vn_mode ( 1419 struct pkt *spkt, 1420 char leap, 1421 char version, 1422 char mode 1423 ) 1424 { 1425 if (leap > 3) { 1426 msyslog(LOG_DEBUG, "set_li_vn_mode: leap > 3, using max. 3"); 1427 leap = 3; 1428 } 1429 1430 if ((unsigned char)version > 7) { 1431 msyslog(LOG_DEBUG, "set_li_vn_mode: version < 0 or > 7, using 4"); 1432 version = 4; 1433 } 1434 1435 if (mode > 7) { 1436 msyslog(LOG_DEBUG, "set_li_vn_mode: mode > 7, using client mode 3"); 1437 mode = 3; 1438 } 1439 1440 spkt->li_vn_mode = leap << 6; 1441 spkt->li_vn_mode |= version << 3; 1442 spkt->li_vn_mode |= mode; 1443 } 1444 1445 1446 /* 1447 ** set_time applies 'offset' to the local clock. 1448 */ 1449 int 1450 set_time( 1451 double offset 1452 ) 1453 { 1454 int rc; 1455 1456 if (time_adjusted) 1457 return EX_OK; 1458 1459 /* 1460 ** If we can step but we cannot slew, then step. 1461 ** If we can step or slew and and |offset| > steplimit, then step. 1462 */ 1463 if (ENABLED_OPT(STEP) && 1464 ( !ENABLED_OPT(SLEW) 1465 || (ENABLED_OPT(SLEW) && (fabs(offset) > steplimit)) 1466 )) { 1467 rc = step_systime(offset); 1468 1469 /* If there was a problem, can we rely on errno? */ 1470 if (1 == rc) 1471 time_adjusted = TRUE; 1472 return (time_adjusted) 1473 ? EX_OK 1474 : 1; 1475 /* 1476 ** In case of error, what should we use? 1477 ** EX_UNAVAILABLE? 1478 ** EX_OSERR? 1479 ** EX_NOPERM? 1480 */ 1481 } 1482 1483 if (ENABLED_OPT(SLEW)) { 1484 rc = adj_systime(offset); 1485 1486 /* If there was a problem, can we rely on errno? */ 1487 if (1 == rc) 1488 time_adjusted = TRUE; 1489 return (time_adjusted) 1490 ? EX_OK 1491 : 1; 1492 /* 1493 ** In case of error, what should we use? 1494 ** EX_UNAVAILABLE? 1495 ** EX_OSERR? 1496 ** EX_NOPERM? 1497 */ 1498 } 1499 1500 return EX_SOFTWARE; 1501 } 1502 1503 1504 int 1505 libevent_version_ok(void) 1506 { 1507 ev_uint32_t v_compile_maj; 1508 ev_uint32_t v_run_maj; 1509 1510 v_compile_maj = LIBEVENT_VERSION_NUMBER & 0xffff0000; 1511 v_run_maj = event_get_version_number() & 0xffff0000; 1512 if (v_compile_maj != v_run_maj) { 1513 fprintf(stderr, 1514 "Incompatible libevent versions: have %s, built with %s\n", 1515 event_get_version(), 1516 LIBEVENT_VERSION); 1517 return 0; 1518 } 1519 return 1; 1520 } 1521 1522 /* 1523 * gettimeofday_cached() 1524 * 1525 * Clones the event_base_gettimeofday_cached() interface but ensures the 1526 * times are always on the gettimeofday() 1970 scale. Older libevent 2 1527 * sometimes used gettimeofday(), sometimes the since-system-start 1528 * clock_gettime(CLOCK_MONOTONIC), depending on the platform. 1529 * 1530 * It is not cleanly possible to tell which timescale older libevent is 1531 * using. 1532 * 1533 * The strategy involves 1 hour thresholds chosen to be far longer than 1534 * the duration of a round of libevent callbacks, which share a cached 1535 * start-of-round time. First compare the last cached time with the 1536 * current gettimeofday() time. If they are within one hour, libevent 1537 * is using the proper timescale so leave the offset 0. Otherwise, 1538 * compare libevent's cached time and the current time on the monotonic 1539 * scale. If they are within an hour, libevent is using the monotonic 1540 * scale so calculate the offset to add to such times to bring them to 1541 * gettimeofday()'s scale. 1542 */ 1543 int 1544 gettimeofday_cached( 1545 struct event_base * b, 1546 struct timeval * caller_tv 1547 ) 1548 { 1549 #if defined(_EVENT_HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) 1550 static struct event_base * cached_b; 1551 static struct timeval cached; 1552 static struct timeval adj_cached; 1553 static struct timeval offset; 1554 static int offset_ready; 1555 struct timeval latest; 1556 struct timeval systemt; 1557 struct timespec ts; 1558 struct timeval mono; 1559 struct timeval diff; 1560 int cgt_rc; 1561 int gtod_rc; 1562 1563 event_base_gettimeofday_cached(b, &latest); 1564 if (b == cached_b && 1565 !memcmp(&latest, &cached, sizeof(latest))) { 1566 *caller_tv = adj_cached; 1567 return 0; 1568 } 1569 cached = latest; 1570 cached_b = b; 1571 if (!offset_ready) { 1572 cgt_rc = clock_gettime(CLOCK_MONOTONIC, &ts); 1573 gtod_rc = gettimeofday(&systemt, NULL); 1574 if (0 != gtod_rc) { 1575 msyslog(LOG_ERR, 1576 "%s: gettimeofday() error %m", 1577 progname); 1578 exit(1); 1579 } 1580 diff = sub_tval(systemt, latest); 1581 if (debug > 1) 1582 printf("system minus cached %+ld.%06ld\n", 1583 (long)diff.tv_sec, (long)diff.tv_usec); 1584 if (0 != cgt_rc || labs((long)diff.tv_sec) < 3600) { 1585 /* 1586 * Either use_monotonic == 0, or this libevent 1587 * has been repaired. Leave offset at zero. 1588 */ 1589 } else { 1590 mono.tv_sec = ts.tv_sec; 1591 mono.tv_usec = ts.tv_nsec / 1000; 1592 diff = sub_tval(latest, mono); 1593 if (debug > 1) 1594 printf("cached minus monotonic %+ld.%06ld\n", 1595 (long)diff.tv_sec, (long)diff.tv_usec); 1596 if (labs((long)diff.tv_sec) < 3600) { 1597 /* older libevent2 using monotonic */ 1598 offset = sub_tval(systemt, mono); 1599 TRACE(1, ("%s: Offsetting libevent CLOCK_MONOTONIC times by %+ld.%06ld\n", 1600 "gettimeofday_cached", 1601 (long)offset.tv_sec, 1602 (long)offset.tv_usec)); 1603 } 1604 } 1605 offset_ready = TRUE; 1606 } 1607 adj_cached = add_tval(cached, offset); 1608 *caller_tv = adj_cached; 1609 1610 return 0; 1611 #else 1612 return event_base_gettimeofday_cached(b, caller_tv); 1613 #endif 1614 } 1615 1616 /* Dummy function to satisfy libntp/work_fork.c */ 1617 extern int set_user_group_ids(void); 1618 int set_user_group_ids(void) 1619 { 1620 return 1; 1621 } 1622