1 /* 2 * ntp_timer.c - event timer support routines 3 */ 4 #ifdef HAVE_CONFIG_H 5 # include <config.h> 6 #endif 7 8 #include "ntp_machine.h" 9 #include "ntpd.h" 10 #include "ntp_stdlib.h" 11 #include "ntp_calendar.h" 12 #include "ntp_leapsec.h" 13 14 #if defined(HAVE_IO_COMPLETION_PORT) 15 # include "ntp_iocompletionport.h" 16 # include "ntp_timer.h" 17 #endif 18 19 #include <stdio.h> 20 #include <signal.h> 21 #ifdef HAVE_SYS_SIGNAL_H 22 # include <sys/signal.h> 23 #endif 24 #ifdef HAVE_UNISTD_H 25 # include <unistd.h> 26 #endif 27 28 #ifdef KERNEL_PLL 29 #include "ntp_syscall.h" 30 #endif /* KERNEL_PLL */ 31 32 #ifdef AUTOKEY 33 #include <openssl/rand.h> 34 #endif /* AUTOKEY */ 35 36 37 /* TC_ERR represents the timer_create() error return value. */ 38 #ifdef SYS_VXWORKS 39 #define TC_ERR ERROR 40 #else 41 #define TC_ERR (-1) 42 #endif 43 44 45 static void check_leapsec(u_int32, const time_t*, int/*BOOL*/); 46 47 /* 48 * These routines provide support for the event timer. The timer is 49 * implemented by an interrupt routine which sets a flag once every 50 * second, and a timer routine which is called when the mainline code 51 * gets around to seeing the flag. The timer routine dispatches the 52 * clock adjustment code if its time has come, then searches the timer 53 * queue for expiries which are dispatched to the transmit procedure. 54 * Finally, we call the hourly procedure to do cleanup and print a 55 * message. 56 */ 57 volatile int interface_interval; /* init_io() sets def. 300s */ 58 59 /* 60 * Alarm flag. The mainline code imports this. 61 */ 62 volatile int alarm_flag; 63 64 /* 65 * The counters and timeouts 66 */ 67 static u_long interface_timer; /* interface update timer */ 68 static u_long adjust_timer; /* second timer */ 69 static u_long stats_timer; /* stats timer */ 70 static u_long leapf_timer; /* Report leapfile problems once/day */ 71 static u_long huffpuff_timer; /* huff-n'-puff timer */ 72 static u_long worker_idle_timer;/* next check for idle intres */ 73 u_long leapsec; /* seconds to next leap (proximity class) */ 74 int leapdif; /* TAI difference step at next leap second*/ 75 u_long orphwait; /* orphan wait time */ 76 #ifdef AUTOKEY 77 static u_long revoke_timer; /* keys revoke timer */ 78 static u_long keys_timer; /* session key timer */ 79 u_long sys_revoke = KEY_REVOKE; /* keys revoke timeout (log2 s) */ 80 u_long sys_automax = NTP_AUTOMAX; /* key list timeout (log2 s) */ 81 #endif /* AUTOKEY */ 82 83 /* 84 * Statistics counter for the interested. 85 */ 86 volatile u_long alarm_overflow; 87 88 u_long current_time; /* seconds since startup */ 89 90 /* 91 * Stats. Number of overflows and number of calls to transmit(). 92 */ 93 u_long timer_timereset; 94 u_long timer_overflows; 95 u_long timer_xmtcalls; 96 97 #if defined(VMS) 98 static int vmstimer[2]; /* time for next timer AST */ 99 static int vmsinc[2]; /* timer increment */ 100 #endif /* VMS */ 101 102 #ifdef SYS_WINNT 103 HANDLE WaitableTimerHandle; 104 #else 105 static RETSIGTYPE alarming (int); 106 #endif /* SYS_WINNT */ 107 108 #if !defined(VMS) 109 # if !defined SYS_WINNT || defined(SYS_CYGWIN32) 110 # ifdef HAVE_TIMER_CREATE 111 static timer_t timer_id; 112 typedef struct itimerspec intervaltimer; 113 # define itv_frac tv_nsec 114 # else 115 typedef struct itimerval intervaltimer; 116 # define itv_frac tv_usec 117 # endif 118 intervaltimer itimer; 119 # endif 120 #endif 121 122 #if !defined(SYS_WINNT) && !defined(VMS) 123 void set_timer_or_die(const intervaltimer *); 124 #endif 125 126 127 #if !defined(SYS_WINNT) && !defined(VMS) 128 void 129 set_timer_or_die( 130 const intervaltimer * ptimer 131 ) 132 { 133 const char * setfunc; 134 int rc; 135 136 # ifdef HAVE_TIMER_CREATE 137 setfunc = "timer_settime"; 138 rc = timer_settime(timer_id, 0, &itimer, NULL); 139 # else 140 setfunc = "setitimer"; 141 rc = setitimer(ITIMER_REAL, &itimer, NULL); 142 # endif 143 if (-1 == rc) { 144 msyslog(LOG_ERR, "interval timer %s failed, %m", 145 setfunc); 146 exit(1); 147 } 148 } 149 #endif /* !SYS_WINNT && !VMS */ 150 151 152 /* 153 * reinit_timer - reinitialize interval timer after a clock step. 154 */ 155 void 156 reinit_timer(void) 157 { 158 #if !defined(SYS_WINNT) && !defined(VMS) 159 ZERO(itimer); 160 # ifdef HAVE_TIMER_CREATE 161 timer_gettime(timer_id, &itimer); 162 # else 163 getitimer(ITIMER_REAL, &itimer); 164 # endif 165 if (itimer.it_value.tv_sec < 0 || 166 itimer.it_value.tv_sec > (1 << EVENT_TIMEOUT)) 167 itimer.it_value.tv_sec = (1 << EVENT_TIMEOUT); 168 if (itimer.it_value.itv_frac < 0) 169 itimer.it_value.itv_frac = 0; 170 if (0 == itimer.it_value.tv_sec && 171 0 == itimer.it_value.itv_frac) 172 itimer.it_value.tv_sec = (1 << EVENT_TIMEOUT); 173 itimer.it_interval.tv_sec = (1 << EVENT_TIMEOUT); 174 itimer.it_interval.itv_frac = 0; 175 set_timer_or_die(&itimer); 176 # endif /* VMS */ 177 } 178 179 180 /* 181 * init_timer - initialize the timer data structures 182 */ 183 void 184 init_timer(void) 185 { 186 /* 187 * Initialize... 188 */ 189 alarm_flag = FALSE; 190 alarm_overflow = 0; 191 adjust_timer = 1; 192 stats_timer = SECSPERHR; 193 leapf_timer = SECSPERDAY; 194 huffpuff_timer = 0; 195 interface_timer = 0; 196 current_time = 0; 197 timer_overflows = 0; 198 timer_xmtcalls = 0; 199 timer_timereset = 0; 200 201 #ifndef SYS_WINNT 202 /* 203 * Set up the alarm interrupt. The first comes 2**EVENT_TIMEOUT 204 * seconds from now and they continue on every 2**EVENT_TIMEOUT 205 * seconds. 206 */ 207 # ifndef VMS 208 # ifdef HAVE_TIMER_CREATE 209 if (TC_ERR == timer_create(CLOCK_REALTIME, NULL, &timer_id)) { 210 msyslog(LOG_ERR, "timer_create failed, %m"); 211 exit(1); 212 } 213 # endif 214 signal_no_reset(SIGALRM, alarming); 215 itimer.it_interval.tv_sec = 216 itimer.it_value.tv_sec = (1 << EVENT_TIMEOUT); 217 itimer.it_interval.itv_frac = itimer.it_value.itv_frac = 0; 218 set_timer_or_die(&itimer); 219 # else /* VMS follows */ 220 vmsinc[0] = 10000000; /* 1 sec */ 221 vmsinc[1] = 0; 222 lib$emul(&(1<<EVENT_TIMEOUT), &vmsinc, &0, &vmsinc); 223 224 sys$gettim(&vmstimer); /* that's "now" as abstime */ 225 226 lib$addx(&vmsinc, &vmstimer, &vmstimer); 227 sys$setimr(0, &vmstimer, alarming, alarming, 0); 228 # endif /* VMS */ 229 #else /* SYS_WINNT follows */ 230 /* 231 * Set up timer interrupts for every 2**EVENT_TIMEOUT seconds 232 * Under Windows/NT, 233 */ 234 235 WaitableTimerHandle = CreateWaitableTimer(NULL, FALSE, NULL); 236 if (WaitableTimerHandle == NULL) { 237 msyslog(LOG_ERR, "CreateWaitableTimer failed: %m"); 238 exit(1); 239 } 240 else { 241 DWORD Period; 242 LARGE_INTEGER DueTime; 243 BOOL rc; 244 245 Period = (1 << EVENT_TIMEOUT) * 1000; 246 DueTime.QuadPart = Period * 10000i64; 247 rc = SetWaitableTimer(WaitableTimerHandle, &DueTime, 248 Period, NULL, NULL, FALSE); 249 if (!rc) { 250 msyslog(LOG_ERR, "SetWaitableTimer failed: %m"); 251 exit(1); 252 } 253 } 254 255 #endif /* SYS_WINNT */ 256 } 257 258 259 /* 260 * intres_timeout_req(s) is invoked in the parent to schedule an idle 261 * timeout to fire in s seconds, if not reset earlier by a call to 262 * intres_timeout_req(0), which clears any pending timeout. When the 263 * timeout expires, worker_idle_timer_fired() is invoked (again, in the 264 * parent). 265 * 266 * sntp and ntpd each provide implementations adapted to their timers. 267 */ 268 void 269 intres_timeout_req( 270 u_int seconds /* 0 cancels */ 271 ) 272 { 273 if (0 == seconds) { 274 worker_idle_timer = 0; 275 return; 276 } 277 worker_idle_timer = current_time + seconds; 278 } 279 280 281 /* 282 * timer - event timer 283 */ 284 void 285 timer(void) 286 { 287 struct peer * p; 288 struct peer * next_peer; 289 l_fp now; 290 time_t tnow; 291 292 /* 293 * The basic timerevent is one second. This is used to adjust the 294 * system clock in time and frequency, implement the kiss-o'-death 295 * function and the association polling function. 296 */ 297 current_time++; 298 if (adjust_timer <= current_time) { 299 adjust_timer += 1; 300 adj_host_clock(); 301 #ifdef REFCLOCK 302 for (p = peer_list; p != NULL; p = next_peer) { 303 next_peer = p->p_link; 304 if (FLAG_REFCLOCK & p->flags) 305 refclock_timer(p); 306 } 307 #endif /* REFCLOCK */ 308 } 309 310 /* 311 * Now dispatch any peers whose event timer has expired. Be 312 * careful here, since the peer structure might go away as the 313 * result of the call. 314 */ 315 for (p = peer_list; p != NULL; p = next_peer) { 316 next_peer = p->p_link; 317 318 /* 319 * Restrain the non-burst packet rate not more 320 * than one packet every 16 seconds. This is 321 * usually tripped using iburst and minpoll of 322 * 128 s or less. 323 */ 324 if (p->throttle > 0) 325 p->throttle--; 326 if (p->nextdate <= current_time) { 327 #ifdef REFCLOCK 328 if (FLAG_REFCLOCK & p->flags) 329 refclock_transmit(p); 330 else 331 #endif /* REFCLOCK */ 332 transmit(p); 333 } 334 } 335 336 /* 337 * Orphan mode is active when enabled and when no servers less 338 * than the orphan stratum are available. A server with no other 339 * synchronization source is an orphan. It shows offset zero and 340 * reference ID the loopback address. 341 */ 342 if (sys_orphan < STRATUM_UNSPEC && sys_peer == NULL && 343 current_time > orphwait) { 344 if (sys_leap == LEAP_NOTINSYNC) { 345 set_sys_leap(LEAP_NOWARNING); 346 #ifdef AUTOKEY 347 if (crypto_flags) 348 crypto_update(); 349 #endif /* AUTOKEY */ 350 } 351 sys_stratum = (u_char)sys_orphan; 352 if (sys_stratum > 1) 353 sys_refid = htonl(LOOPBACKADR); 354 else 355 memcpy(&sys_refid, "LOOP", 4); 356 sys_offset = 0; 357 sys_rootdelay = 0; 358 sys_rootdisp = 0; 359 } 360 361 get_systime(&now); 362 time(&tnow); 363 364 /* 365 * Leapseconds. Get time and defer to worker if either something 366 * is imminent or every 8th second. 367 */ 368 if (leapsec > LSPROX_NOWARN || 0 == (current_time & 7)) 369 check_leapsec(now.l_ui, &tnow, 370 (sys_leap == LEAP_NOTINSYNC)); 371 if (sys_leap != LEAP_NOTINSYNC) { 372 if (leapsec >= LSPROX_ANNOUNCE && leapdif) { 373 if (leapdif > 0) 374 set_sys_leap(LEAP_ADDSECOND); 375 else 376 set_sys_leap(LEAP_DELSECOND); 377 } else { 378 set_sys_leap(LEAP_NOWARNING); 379 } 380 } 381 382 /* 383 * Update huff-n'-puff filter. 384 */ 385 if (huffpuff_timer <= current_time) { 386 huffpuff_timer += HUFFPUFF; 387 huffpuff(); 388 } 389 390 #ifdef AUTOKEY 391 /* 392 * Garbage collect expired keys. 393 */ 394 if (keys_timer <= current_time) { 395 keys_timer += 1 << sys_automax; 396 auth_agekeys(); 397 } 398 399 /* 400 * Generate new private value. This causes all associations 401 * to regenerate cookies. 402 */ 403 if (revoke_timer && revoke_timer <= current_time) { 404 revoke_timer += 1 << sys_revoke; 405 RAND_bytes((u_char *)&sys_private, 4); 406 } 407 #endif /* AUTOKEY */ 408 409 /* 410 * Interface update timer 411 */ 412 if (interface_interval && interface_timer <= current_time) { 413 timer_interfacetimeout(current_time + 414 interface_interval); 415 DPRINTF(2, ("timer: interface update\n")); 416 interface_update(NULL, NULL); 417 } 418 419 if (worker_idle_timer && worker_idle_timer <= current_time) 420 worker_idle_timer_fired(); 421 422 /* 423 * Finally, write hourly stats and do the hourly 424 * and daily leapfile checks. 425 */ 426 if (stats_timer <= current_time) { 427 stats_timer += SECSPERHR; 428 write_stats(); 429 if (leapf_timer <= current_time) { 430 leapf_timer += SECSPERDAY; 431 check_leap_file(TRUE, now.l_ui, &tnow); 432 } else { 433 check_leap_file(FALSE, now.l_ui, &tnow); 434 } 435 } 436 } 437 438 439 #ifndef SYS_WINNT 440 /* 441 * alarming - tell the world we've been alarmed 442 */ 443 static RETSIGTYPE 444 alarming( 445 int sig 446 ) 447 { 448 # ifdef DEBUG 449 const char *msg = "alarming: initializing TRUE\n"; 450 # endif 451 452 if (!initializing) { 453 if (alarm_flag) { 454 alarm_overflow++; 455 # ifdef DEBUG 456 msg = "alarming: overflow\n"; 457 # endif 458 } else { 459 # ifndef VMS 460 alarm_flag++; 461 # else 462 /* VMS AST routine, increment is no good */ 463 alarm_flag = 1; 464 # endif 465 # ifdef DEBUG 466 msg = "alarming: normal\n"; 467 # endif 468 } 469 } 470 # ifdef VMS 471 lib$addx(&vmsinc, &vmstimer, &vmstimer); 472 sys$setimr(0, &vmstimer, alarming, alarming, 0); 473 # endif 474 # ifdef DEBUG 475 if (debug >= 4) 476 (void)(-1 == write(1, msg, strlen(msg))); 477 # endif 478 } 479 #endif /* SYS_WINNT */ 480 481 482 void 483 timer_interfacetimeout(u_long timeout) 484 { 485 interface_timer = timeout; 486 } 487 488 489 /* 490 * timer_clr_stats - clear timer module stat counters 491 */ 492 void 493 timer_clr_stats(void) 494 { 495 timer_overflows = 0; 496 timer_xmtcalls = 0; 497 timer_timereset = current_time; 498 } 499 500 501 static void 502 check_leap_sec_in_progress( const leap_result_t *lsdata ) { 503 int prv_leap_sec_in_progress = leap_sec_in_progress; 504 leap_sec_in_progress = lsdata->tai_diff && (lsdata->ddist < 3); 505 506 /* if changed we may have to update the leap status sent to clients */ 507 if (leap_sec_in_progress != prv_leap_sec_in_progress) 508 set_sys_leap(sys_leap); 509 } 510 511 512 static void 513 check_leapsec( 514 u_int32 now , 515 const time_t * tpiv , 516 int/*BOOL*/ reset) 517 { 518 static const char leapmsg_p_step[] = 519 "Positive leap second, stepped backward."; 520 static const char leapmsg_p_slew[] = 521 "Positive leap second, no step correction. " 522 "System clock will be inaccurate for a long time."; 523 524 static const char leapmsg_n_step[] = 525 "Negative leap second, stepped forward."; 526 static const char leapmsg_n_slew[] = 527 "Negative leap second, no step correction. " 528 "System clock will be inaccurate for a long time."; 529 530 leap_result_t lsdata; 531 u_int32 lsprox; 532 #ifdef AUTOKEY 533 int/*BOOL*/ update_autokey = FALSE; 534 #endif 535 536 #ifndef SYS_WINNT /* WinNT port has its own leap second handling */ 537 # ifdef KERNEL_PLL 538 leapsec_electric(pll_control && kern_enable); 539 # else 540 leapsec_electric(0); 541 # endif 542 #endif 543 #ifdef LEAP_SMEAR 544 leap_smear.enabled = leap_smear_intv != 0; 545 #endif 546 if (reset) { 547 lsprox = LSPROX_NOWARN; 548 leapsec_reset_frame(); 549 memset(&lsdata, 0, sizeof(lsdata)); 550 } else { 551 int fired = leapsec_query(&lsdata, now, tpiv); 552 553 DPRINTF(1, ("*** leapsec_query: fired %i, now %u (0x%08X), tai_diff %i, ddist %u\n", 554 fired, now, now, lsdata.tai_diff, lsdata.ddist)); 555 556 #ifdef LEAP_SMEAR 557 leap_smear.in_progress = 0; 558 leap_smear.doffset = 0.0; 559 560 if (leap_smear.enabled) { 561 if (lsdata.tai_diff) { 562 if (leap_smear.interval == 0) { 563 leap_smear.interval = leap_smear_intv; 564 leap_smear.intv_end = lsdata.ttime.Q_s; 565 leap_smear.intv_start = leap_smear.intv_end - leap_smear.interval; 566 DPRINTF(1, ("*** leapsec_query: setting leap_smear interval %li, begin %.0f, end %.0f\n", 567 leap_smear.interval, leap_smear.intv_start, leap_smear.intv_end)); 568 } 569 } 570 else { 571 if (leap_smear.interval) 572 DPRINTF(1, ("*** leapsec_query: clearing leap_smear interval\n")); 573 leap_smear.interval = 0; 574 } 575 576 if (leap_smear.interval) { 577 double dtemp = now; 578 if (dtemp >= leap_smear.intv_start && dtemp <= leap_smear.intv_end) { 579 double leap_smear_time = dtemp - leap_smear.intv_start; 580 /* 581 * For now we just do a linear interpolation over the smear interval 582 */ 583 #if 0 584 // linear interpolation 585 leap_smear.doffset = -(leap_smear_time * lsdata.tai_diff / leap_smear.interval); 586 #else 587 // Google approach: lie(t) = (1.0 - cos(pi * t / w)) / 2.0 588 leap_smear.doffset = -((double) lsdata.tai_diff - cos( M_PI * leap_smear_time / leap_smear.interval)) / 2.0; 589 #endif 590 /* 591 * TODO see if we're inside an inserted leap second, so we need to compute 592 * leap_smear.doffset = 1.0 - leap_smear.doffset 593 */ 594 leap_smear.in_progress = 1; 595 #if 0 && defined( DEBUG ) 596 msyslog(LOG_NOTICE, "*** leapsec_query: [%.0f:%.0f] (%li), now %u (%.0f), smear offset %.6f ms\n", 597 leap_smear.intv_start, leap_smear.intv_end, leap_smear.interval, 598 now, leap_smear_time, leap_smear.doffset); 599 #else 600 DPRINTF(1, ("*** leapsec_query: [%.0f:%.0f] (%li), now %u (%.0f), smear offset %.6f ms\n", 601 leap_smear.intv_start, leap_smear.intv_end, leap_smear.interval, 602 now, leap_smear_time, leap_smear.doffset)); 603 #endif 604 605 } 606 } 607 } 608 else 609 leap_smear.interval = 0; 610 611 /* 612 * Update the current leap smear offset, eventually 0.0 if outside smear interval. 613 */ 614 DTOLFP(leap_smear.doffset, &leap_smear.offset); 615 616 #endif /* LEAP_SMEAR */ 617 618 if (fired) { 619 /* Full hit. Eventually step the clock, but always 620 * announce the leap event has happened. 621 */ 622 const char *leapmsg = NULL; 623 if (lsdata.warped < 0) { 624 if (clock_max_back > 0.0 && 625 clock_max_back < fabs(lsdata.warped)) { 626 step_systime(lsdata.warped); 627 leapmsg = leapmsg_p_step; 628 } else { 629 leapmsg = leapmsg_p_slew; 630 } 631 } else if (lsdata.warped > 0) { 632 if (clock_max_fwd > 0.0 && 633 clock_max_fwd < fabs(lsdata.warped)) { 634 step_systime(lsdata.warped); 635 leapmsg = leapmsg_n_step; 636 } else { 637 leapmsg = leapmsg_n_slew; 638 } 639 } 640 if (leapmsg) 641 msyslog(LOG_NOTICE, "%s", leapmsg); 642 report_event(EVNT_LEAP, NULL, NULL); 643 #ifdef AUTOKEY 644 update_autokey = TRUE; 645 #endif 646 lsprox = LSPROX_NOWARN; 647 leapsec = LSPROX_NOWARN; 648 sys_tai = lsdata.tai_offs; 649 } else { 650 #ifdef AUTOKEY 651 update_autokey = (sys_tai != lsdata.tai_offs); 652 #endif 653 lsprox = lsdata.proximity; 654 sys_tai = lsdata.tai_offs; 655 } 656 } 657 658 /* We guard against panic alarming during the red alert phase. 659 * Strange and evil things might happen if we go from stone cold 660 * to piping hot in one step. If things are already that wobbly, 661 * we let the normal clock correction take over, even if a jump 662 * is involved. 663 * Also make sure the alarming events are edge-triggered, that is, 664 * ceated only when the threshold is crossed. 665 */ 666 if ( (leapsec > 0 || lsprox < LSPROX_ALERT) 667 && leapsec < lsprox ) { 668 if ( leapsec < LSPROX_SCHEDULE 669 && lsprox >= LSPROX_SCHEDULE) { 670 if (lsdata.dynamic) 671 report_event(PEVNT_ARMED, sys_peer, NULL); 672 else 673 report_event(EVNT_ARMED, NULL, NULL); 674 } 675 leapsec = lsprox; 676 } 677 if (leapsec > lsprox) { 678 if ( leapsec >= LSPROX_SCHEDULE 679 && lsprox < LSPROX_SCHEDULE) { 680 report_event(EVNT_DISARMED, NULL, NULL); 681 } 682 leapsec = lsprox; 683 } 684 685 if (leapsec >= LSPROX_SCHEDULE) 686 leapdif = lsdata.tai_diff; 687 else 688 leapdif = 0; 689 690 check_leap_sec_in_progress(&lsdata); 691 692 #ifdef AUTOKEY 693 if (update_autokey) 694 crypto_update_taichange(); 695 #endif 696 } 697