]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ntp/ntpd/ntp_timer.c
Update Makefiles and other build glue for llvm/clang 3.7.0, as of trunk
[FreeBSD/FreeBSD.git] / contrib / ntp / ntpd / ntp_timer.c
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 }