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