/* * ntp_timer.c - event timer support routines */ #ifdef HAVE_CONFIG_H # include #endif #include "ntp_machine.h" #include "ntpd.h" #include "ntp_stdlib.h" #include #include #ifdef HAVE_SYS_SIGNAL_H # include #endif #ifdef HAVE_UNISTD_H # include #endif #if defined(HAVE_IO_COMPLETION_PORT) # include "ntp_iocompletionport.h" # include "ntp_timer.h" #endif /* * These routines provide support for the event timer. The timer is * implemented by an interrupt routine which sets a flag once every * 2**EVENT_TIMEOUT seconds (currently 4), and a timer routine which * is called when the mainline code gets around to seeing the flag. * The timer routine dispatches the clock adjustment code if its time * has come, then searches the timer queue for expiries which are * dispatched to the transmit procedure. Finally, we call the hourly * procedure to do cleanup and print a message. */ volatile int interface_interval = 300; /* update interface every 5 minutes as default */ /* * Alarm flag. The mainline code imports this. */ volatile int alarm_flag; /* * The counters */ static u_long adjust_timer; /* second timer */ static u_long keys_timer; /* minute timer */ static u_long stats_timer; /* stats timer */ static u_long huffpuff_timer; /* huff-n'-puff timer */ static u_long interface_timer; /* interface update timer */ #ifdef OPENSSL static u_long revoke_timer; /* keys revoke timer */ u_char sys_revoke = KEY_REVOKE; /* keys revoke timeout (log2 s) */ #endif /* OPENSSL */ /* * Statistics counter for the interested. */ volatile u_long alarm_overflow; #define MINUTE 60 #define HOUR (60*60) u_long current_time; /* * Stats. Number of overflows and number of calls to transmit(). */ u_long timer_timereset; u_long timer_overflows; u_long timer_xmtcalls; #if defined(VMS) static int vmstimer[2]; /* time for next timer AST */ static int vmsinc[2]; /* timer increment */ #endif /* VMS */ #if defined SYS_WINNT static HANDLE WaitableTimerHandle = NULL; #else static RETSIGTYPE alarming P((int)); #endif /* SYS_WINNT */ #if !defined(VMS) # if !defined SYS_WINNT || defined(SYS_CYGWIN32) # ifndef HAVE_TIMER_SETTIME struct itimerval itimer; # else static timer_t ntpd_timerid; struct itimerspec itimer; # endif /* HAVE_TIMER_SETTIME */ # endif /* SYS_WINNT */ #endif /* VMS */ /* * reinit_timer - reinitialize interval timer. */ void reinit_timer(void) { #if !defined(SYS_WINNT) && !defined(VMS) # if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME) timer_gettime(ntpd_timerid, &itimer); if (itimer.it_value.tv_sec < 0 || itimer.it_value.tv_sec > (1< (1<next; if (peer->flags & FLAG_REFCLOCK) refclock_timer(peer); } } #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 (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); if (peer->nextdate <= current_time) { #ifdef REFCLOCK if (peer->flags & FLAG_REFCLOCK) refclock_transmit(peer); else transmit(peer); #else /* REFCLOCK */ transmit(peer); #endif /* REFCLOCK */ } } } /* * Garbage collect expired keys. */ if (keys_timer <= current_time) { keys_timer += MINUTE; auth_agekeys(); } /* * Huff-n'-puff filter */ if (huffpuff_timer <= current_time) { huffpuff_timer += HUFFPUFF; huffpuff(); } #ifdef OPENSSL /* * Garbage collect old keys and generate new private value */ if (revoke_timer <= current_time) { revoke_timer += RANDPOLL(sys_revoke); expire_all(); sprintf(statstr, "refresh ts %u", ntohl(hostval.tstamp)); record_crypto_stats(NULL, statstr); #ifdef DEBUG if (debug) printf("timer: %s\n", statstr); #endif } #endif /* OPENSSL */ /* * interface update timer */ if (interface_interval && interface_timer <= current_time) { timer_interfacetimeout(current_time + interface_interval); DPRINTF(1, ("timer: interface update\n")); interface_update(NULL, NULL); } /* * Finally, periodically write stats. */ if (stats_timer <= current_time) { if (stats_timer != 0) write_stats(); stats_timer += stats_write_period; } } #ifndef SYS_WINNT /* * alarming - tell the world we've been alarmed */ static RETSIGTYPE alarming( int sig ) { #if !defined(VMS) if (initializing) return; if (alarm_flag) alarm_overflow++; else alarm_flag++; #else /* VMS AST routine */ if (!initializing) { if (alarm_flag) alarm_overflow++; else alarm_flag = 1; /* increment is no good */ } lib$addx(&vmsinc,&vmstimer,&vmstimer); sys$setimr(0,&vmstimer,alarming,alarming,0); #endif /* VMS */ } #endif /* SYS_WINNT */ void timer_interfacetimeout(u_long timeout) { interface_timer = timeout; } /* * timer_clr_stats - clear timer module stat counters */ void timer_clr_stats(void) { timer_overflows = 0; timer_xmtcalls = 0; timer_timereset = current_time; }