/* * timer - event timer */ void timer(void) { register struct peer *peer, *next_peer; u_int n; long delta; /* * The basic timerevent is one second. This is used to adjust * the system clock in time and frequency, implement the * kiss-o'-deatch function and implement the association * polling function.. */ current_time += nap_time; get_systime(&sys_time); nap_time = (u_long)-1; if (do_adjtime) { if (adjust_timer <= current_time) { adjust_timer += 1; adj_host_clock(); #ifdef REFCLOCK for (n = 0; n < NTP_HASH_SIZE; n++) { for (peer = peer_hash[n]; peer != 0; peer = next_peer) { next_peer = peer->next; if (peer->flags & FLAG_REFCLOCK) refclock_timer(peer); } } #endif /* REFCLOCK */ } nap_time = 1; } if (awake_timer) { if (awake_timer <= current_time) { for (n = 0; n < NTP_HASH_SIZE; n++) { for (peer = peer_hash[n]; peer != 0; peer = peer->next) { peer->burst = NSTAGE; peer->nextdate = current_time; peer->throttle = 0; } } allow_panic = TRUE; /* Allow for large time offsets */ init_loopfilter(); state = EVNT_NSET; awake_timer = 0; } else { delta = awake_timer - current_time; if (delta < nap_time) { nap_time = delta; } } } /* * Now dispatch any peers whose event timer has expired. Be * careful here, since the peer structure might go away as the * result of the call. */ for (n = 0; n < NTP_HASH_SIZE; n++) { for (peer = peer_hash[n]; peer != 0; peer = next_peer) { next_peer = peer->next; if (peer->action && peer->nextaction <= current_time) peer->action(peer); /* * Restrain the non-burst packet rate not more * than one packet every 16 seconds. This is * usually tripped using iburst and minpoll of * 128 s or less. */ if (peer->throttle > 0) peer->throttle--; if (peer->nextdate <= current_time) { #ifdef REFCLOCK if (peer->flags & FLAG_REFCLOCK) refclock_transmit(peer); else transmit(peer); #else /* REFCLOCK */ transmit(peer); #endif /* REFCLOCK */ } if (peer->action && peer->nextaction >= current_time) { delta = peer->nextaction - current_time; if (delta < nap_time) { nap_time = delta; } } else if (peer->nextdate >= current_time) { delta = peer->nextdate - current_time; if (delta < nap_time) { nap_time = delta; } } } } /* * Orphan mode is active when enabled and when no servers less * than the orphan statum are available. A server with no other * synchronization source is an orphan It shows offset zero and * reference ID the loopback address. */ if (sys_orphan < STRATUM_UNSPEC && sys_peer == NULL) { if (sys_leap == LEAP_NOTINSYNC) { sys_leap = LEAP_NOWARNING; #ifdef OPENSSL if (crypto_flags) crypto_update(); #endif /* OPENSSL */ } sys_stratum = (u_char)sys_orphan; if (sys_stratum > 1) sys_refid = htonl(LOOPBACKADR); else memcpy(&sys_refid, "LOOP", 4); sys_offset = 0; sys_rootdelay = 0; sys_rootdisp = 0; } /* * Leapseconds. If a leap is pending, decrement the time * remaining. If less than one day remains, set the leap bits. * When no time remains, clear the leap bits and increment the * TAI. If kernel suppport is not available, do the leap * crudely. Note a leap cannot be pending unless the clock is * set. */ if (leapsec > 0) { leapsec--; if (leapsec == 0) { sys_leap = LEAP_NOWARNING; sys_tai = leap_tai; #ifdef KERNEL_PLL if (!(pll_control && kern_enable)) step_systime(-1.0); #else /* KERNEL_PLL */ #ifndef SYS_WINNT /* WinNT port has its own leap second handling */ step_systime(-1.0); #endif /* SYS_WINNT */ #endif /* KERNEL_PLL */ report_event(EVNT_LEAP, NULL, NULL); } else { if (leapsec < DAY) sys_leap = LEAP_ADDSECOND; if (leap_tai > 0) sys_tai = leap_tai - 1; } } /* * Update huff-n'-puff filter. */ if (huffpuff_timer <= current_time) { huffpuff_timer += HUFFPUFF; huffpuff(); } if (huffpuff_timer >= current_time) { delta = huffpuff_timer - current_time; if (delta < nap_time) { nap_time = delta; } } #ifdef OPENSSL /* * Garbage collect expired keys. */ if (keys_timer <= current_time) { keys_timer += 1 << sys_automax; auth_agekeys(); } if (keys_timer >= current_time) { delta = keys_timer - current_time; if (delta < nap_time) { nap_time = delta; } } /* * Garbage collect key list and generate new private value. The * timer runs only after initial synchronization and fires about * once per day. */ if (revoke_timer <= current_time && sys_leap != LEAP_NOTINSYNC) { revoke_timer += 1 << sys_revoke; RAND_bytes((u_char *)&sys_private, 4); } if (revoke_timer >= current_time) { delta = revoke_timer - current_time; if (delta < nap_time) { nap_time = delta; } } #endif /* OPENSSL */ /* * Interface update timer */ if (interface_interval && interface_timer <= current_time) { timer_interfacetimeout(current_time + interface_interval); DPRINTF(2, ("timer: interface update\n")); interface_update(NULL, NULL); } if (interface_interval && interface_timer >= current_time) { delta = interface_timer - current_time; if (delta < nap_time) { nap_time = delta; } } if (dns_timer && (dns_timer <= current_time)) { dns_timer = update_dns_peers(); } if (dns_timer >= current_time) { delta = dns_timer - current_time; if (delta < nap_time) { nap_time = delta; } } /* * Finally, write hourly stats. */ if (stats_timer <= current_time) { stats_timer += HOUR; write_stats(); if (sys_tai != 0 && sys_time.l_ui > leap_expire) report_event(EVNT_LEAPVAL, NULL, NULL); } else if (!do_adjtime && drift_file_sw) { write_stats(); /* update more frequently for pacemaker */ } if (stats_timer >= current_time) { delta = stats_timer - current_time; if (delta < nap_time) { nap_time = delta; } } if (nap_time == 0) { nap_time = 1; } if (debug) { msyslog(LOG_INFO, "%s: current_time: %ld, nap_time: %ld", __FUNCTION__, current_time, nap_time); } itimer.it_interval.tv_sec = itimer.it_value.tv_sec = nap_time; setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0); }
/* * timer - event timer */ void timer(void) { struct peer * p; struct peer * next_peer; l_fp now; time_t tnow; /* * The basic timerevent is one second. This is used to adjust the * system clock in time and frequency, implement the kiss-o'-death * function and the association polling function. */ current_time++; if (adjust_timer <= current_time) { adjust_timer += 1; adj_host_clock(); #ifdef REFCLOCK for (p = peer_list; p != NULL; p = next_peer) { next_peer = p->p_link; if (FLAG_REFCLOCK & p->flags) refclock_timer(p); } #endif /* REFCLOCK */ } /* * Now dispatch any peers whose event timer has expired. Be * careful here, since the peer structure might go away as the * result of the call. */ for (p = peer_list; p != NULL; p = next_peer) { next_peer = p->p_link; /* * Restrain the non-burst packet rate not more * than one packet every 16 seconds. This is * usually tripped using iburst and minpoll of * 128 s or less. */ if (p->throttle > 0) p->throttle--; if (p->nextdate <= current_time) { #ifdef REFCLOCK if (FLAG_REFCLOCK & p->flags) refclock_transmit(p); else #endif /* REFCLOCK */ transmit(p); } } /* * Orphan mode is active when enabled and when no servers less * than the orphan stratum are available. A server with no other * synchronization source is an orphan. It shows offset zero and * reference ID the loopback address. */ if (sys_orphan < STRATUM_UNSPEC && sys_peer == NULL && current_time > orphwait) { if (sys_leap == LEAP_NOTINSYNC) { set_sys_leap(LEAP_NOWARNING); #ifdef AUTOKEY if (crypto_flags) crypto_update(); #endif /* AUTOKEY */ } sys_stratum = (u_char)sys_orphan; if (sys_stratum > 1) sys_refid = htonl(LOOPBACKADR); else memcpy(&sys_refid, "LOOP", 4); sys_offset = 0; sys_rootdelay = 0; sys_rootdisp = 0; } get_systime(&now); time(&tnow); /* * Leapseconds. Get time and defer to worker if either something * is imminent or every 8th second. */ if (leapsec > LSPROX_NOWARN || 0 == (current_time & 7)) check_leapsec(now.l_ui, &tnow, (sys_leap == LEAP_NOTINSYNC)); if (sys_leap != LEAP_NOTINSYNC) { if (leapsec >= LSPROX_ANNOUNCE && leapdif) { if (leapdif > 0) set_sys_leap(LEAP_ADDSECOND); else set_sys_leap(LEAP_DELSECOND); } else { set_sys_leap(LEAP_NOWARNING); } } /* * Update huff-n'-puff filter. */ if (huffpuff_timer <= current_time) { huffpuff_timer += HUFFPUFF; huffpuff(); } #ifdef AUTOKEY /* * Garbage collect expired keys. */ if (keys_timer <= current_time) { keys_timer += 1 << sys_automax; auth_agekeys(); } /* * Generate new private value. This causes all associations * to regenerate cookies. */ if (revoke_timer && revoke_timer <= current_time) { revoke_timer += 1 << sys_revoke; RAND_bytes((u_char *)&sys_private, 4); } #endif /* AUTOKEY */ /* * Interface update timer */ if (interface_interval && interface_timer <= current_time) { timer_interfacetimeout(current_time + interface_interval); DPRINTF(2, ("timer: interface update\n")); interface_update(NULL, NULL); } if (worker_idle_timer && worker_idle_timer <= current_time) worker_idle_timer_fired(); /* * Finally, write hourly stats and do the hourly * and daily leapfile checks. */ if (stats_timer <= current_time) { stats_timer += SECSPERHR; write_stats(); if (leapf_timer <= current_time) { leapf_timer += SECSPERDAY; check_leap_file(TRUE, now.l_ui, &tnow); } else { check_leap_file(FALSE, now.l_ui, &tnow); } } }