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