ntp_timer.c revision 285612
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 45static 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 */ 57volatile int interface_interval; /* init_io() sets def. 300s */ 58 59/* 60 * Alarm flag. The mainline code imports this. 61 */ 62volatile int alarm_flag; 63 64/* 65 * The counters and timeouts 66 */ 67static u_long interface_timer; /* interface update timer */ 68static u_long adjust_timer; /* second timer */ 69static u_long stats_timer; /* stats timer */ 70static u_long leapf_timer; /* Report leapfile problems once/day */ 71static u_long huffpuff_timer; /* huff-n'-puff timer */ 72static u_long worker_idle_timer;/* next check for idle intres */ 73u_long leapsec; /* seconds to next leap (proximity class) */ 74int leapdif; /* TAI difference step at next leap second*/ 75u_long orphwait; /* orphan wait time */ 76#ifdef AUTOKEY 77static u_long revoke_timer; /* keys revoke timer */ 78static u_long keys_timer; /* session key timer */ 79u_long sys_revoke = KEY_REVOKE; /* keys revoke timeout (log2 s) */ 80u_long sys_automax = NTP_AUTOMAX; /* key list timeout (log2 s) */ 81#endif /* AUTOKEY */ 82 83/* 84 * Statistics counter for the interested. 85 */ 86volatile u_long alarm_overflow; 87 88u_long current_time; /* seconds since startup */ 89 90/* 91 * Stats. Number of overflows and number of calls to transmit(). 92 */ 93u_long timer_timereset; 94u_long timer_overflows; 95u_long timer_xmtcalls; 96 97#if defined(VMS) 98static int vmstimer[2]; /* time for next timer AST */ 99static int vmsinc[2]; /* timer increment */ 100#endif /* VMS */ 101 102#ifdef SYS_WINNT 103HANDLE WaitableTimerHandle; 104#else 105static 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 111static timer_t timer_id; 112typedef struct itimerspec intervaltimer; 113# define itv_frac tv_nsec 114# else 115typedef struct itimerval intervaltimer; 116# define itv_frac tv_usec 117# endif 118intervaltimer itimer; 119# endif 120#endif 121 122#if !defined(SYS_WINNT) && !defined(VMS) 123void set_timer_or_die(const intervaltimer *); 124#endif 125 126 127#if !defined(SYS_WINNT) && !defined(VMS) 128void 129set_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 */ 155void 156reinit_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 */ 183void 184init_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 */ 268void 269intres_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 */ 284void 285timer(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 */ 443static RETSIGTYPE 444alarming( 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 482void 483timer_interfacetimeout(u_long timeout) 484{ 485 interface_timer = timeout; 486} 487 488 489/* 490 * timer_clr_stats - clear timer module stat counters 491 */ 492void 493timer_clr_stats(void) 494{ 495 timer_overflows = 0; 496 timer_xmtcalls = 0; 497 timer_timereset = current_time; 498} 499 500 501static void 502check_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 512static void 513check_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