"Fossies" - the Fresh Open Source Software Archive

Member "ntp-4.2.8p15/ntpd/ntp_timer.c" (23 Jun 2020, 18112 Bytes) of package /linux/misc/ntp-4.2.8p15.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ntp_timer.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.2.8p14_vs_4.2.8p15.

    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 
   45 static void check_leapsec(u_int32, const time_t*, int/*BOOL*/);
   46 
   47 /*
   48  * These routines provide support for the event timer.  The timer is
   49  * implemented by an interrupt routine which sets a flag once every
   50  * second, and a timer routine which is called when the mainline code
   51  * gets around to seeing the flag.  The timer routine dispatches the
   52  * clock adjustment code if its time has come, then searches the timer
   53  * queue for expiries which are dispatched to the transmit procedure.
   54  * Finally, we call the hourly procedure to do cleanup and print a
   55  * message.
   56  */
   57 volatile int interface_interval;     /* init_io() sets def. 300s */
   58 
   59 /*
   60  * Initializing flag.  All async routines watch this and only do their
   61  * thing when it is clear.
   62  */
   63 int initializing;
   64 
   65 /*
   66  * Alarm flag. The mainline code imports this.
   67  */
   68 volatile int alarm_flag;
   69 
   70 /*
   71  * The counters and timeouts
   72  */
   73 static  u_long interface_timer; /* interface update timer */
   74 static  u_long adjust_timer;    /* second timer */
   75 static  u_long stats_timer; /* stats timer */
   76 static  u_long leapf_timer; /* Report leapfile problems once/day */
   77 static  u_long huffpuff_timer;  /* huff-n'-puff timer */
   78 static  u_long worker_idle_timer;/* next check for idle intres */
   79 u_long  leapsec;            /* seconds to next leap (proximity class) */
   80 int     leapdif;                /* TAI difference step at next leap second*/
   81 u_long  orphwait;       /* orphan wait time */
   82 #ifdef AUTOKEY
   83 static  u_long revoke_timer;    /* keys revoke timer */
   84 static  u_long keys_timer;  /* session key timer */
   85 u_char  sys_revoke = KEY_REVOKE; /* keys revoke timeout (log2 s) */
   86 u_char  sys_automax = NTP_AUTOMAX; /* key list timeout (log2 s) */
   87 #endif  /* AUTOKEY */
   88 
   89 /*
   90  * Statistics counter for the interested.
   91  */
   92 volatile u_long alarm_overflow;
   93 
   94 u_long current_time;        /* seconds since startup */
   95 
   96 /*
   97  * Stats.  Number of overflows and number of calls to transmit().
   98  */
   99 u_long timer_timereset;
  100 u_long timer_overflows;
  101 u_long timer_xmtcalls;
  102 
  103 #if defined(VMS)
  104 static int vmstimer[2];     /* time for next timer AST */
  105 static int vmsinc[2];       /* timer increment */
  106 #endif /* VMS */
  107 
  108 #ifdef SYS_WINNT
  109 HANDLE WaitableTimerHandle;
  110 #else
  111 static  RETSIGTYPE alarming (int);
  112 #endif /* SYS_WINNT */
  113 
  114 #if !defined(VMS)
  115 # if !defined SYS_WINNT || defined(SYS_CYGWIN32)
  116 #  ifdef HAVE_TIMER_CREATE
  117 static timer_t timer_id;
  118 typedef struct itimerspec intervaltimer;
  119 #   define  itv_frac    tv_nsec
  120 #  else
  121 typedef struct itimerval intervaltimer;
  122 #   define  itv_frac    tv_usec
  123 #  endif
  124 intervaltimer itimer;
  125 # endif
  126 #endif
  127 
  128 #if !defined(SYS_WINNT) && !defined(VMS)
  129 void    set_timer_or_die(const intervaltimer *);
  130 #endif
  131 
  132 
  133 #if !defined(SYS_WINNT) && !defined(VMS)
  134 void
  135 set_timer_or_die(
  136     const intervaltimer *   ptimer
  137     )
  138 {
  139     const char *    setfunc;
  140     int     rc;
  141 
  142 # ifdef HAVE_TIMER_CREATE
  143     setfunc = "timer_settime";
  144     rc = timer_settime(timer_id, 0, &itimer, NULL);
  145 # else
  146     setfunc = "setitimer";
  147     rc = setitimer(ITIMER_REAL, &itimer, NULL);
  148 # endif
  149     if (-1 == rc) {
  150         msyslog(LOG_ERR, "interval timer %s failed, %m",
  151             setfunc);
  152         exit(1);
  153     }
  154 }
  155 #endif  /* !SYS_WINNT && !VMS */
  156 
  157 
  158 /*
  159  * reinit_timer - reinitialize interval timer after a clock step.
  160  */
  161 void
  162 reinit_timer(void)
  163 {
  164 #if !defined(SYS_WINNT) && !defined(VMS)
  165     ZERO(itimer);
  166 # ifdef HAVE_TIMER_CREATE
  167     timer_gettime(timer_id, &itimer);
  168 # else
  169     getitimer(ITIMER_REAL, &itimer);
  170 # endif
  171     if (itimer.it_value.tv_sec < 0 ||
  172         itimer.it_value.tv_sec > (1 << EVENT_TIMEOUT))
  173         itimer.it_value.tv_sec = (1 << EVENT_TIMEOUT);
  174     if (itimer.it_value.itv_frac < 0)
  175         itimer.it_value.itv_frac = 0;
  176     if (0 == itimer.it_value.tv_sec &&
  177         0 == itimer.it_value.itv_frac)
  178         itimer.it_value.tv_sec = (1 << EVENT_TIMEOUT);
  179     itimer.it_interval.tv_sec = (1 << EVENT_TIMEOUT);
  180     itimer.it_interval.itv_frac = 0;
  181     set_timer_or_die(&itimer);
  182 # endif /* VMS */
  183 }
  184 
  185 
  186 /*
  187  * init_timer - initialize the timer data structures
  188  */
  189 void
  190 init_timer(void)
  191 {
  192     /*
  193      * Initialize...
  194      */
  195     alarm_flag = FALSE;
  196     alarm_overflow = 0;
  197     adjust_timer = 1;
  198     stats_timer = SECSPERHR;
  199     leapf_timer = SECSPERDAY;
  200     huffpuff_timer = 0;
  201     interface_timer = 0;
  202     current_time = 0;
  203     timer_overflows = 0;
  204     timer_xmtcalls = 0;
  205     timer_timereset = 0;
  206 
  207 #ifndef SYS_WINNT
  208     /*
  209      * Set up the alarm interrupt.  The first comes 2**EVENT_TIMEOUT
  210      * seconds from now and they continue on every 2**EVENT_TIMEOUT
  211      * seconds.
  212      */
  213 # ifndef VMS
  214 #  ifdef HAVE_TIMER_CREATE
  215     if (TC_ERR == timer_create(CLOCK_REALTIME, NULL, &timer_id)) {
  216         msyslog(LOG_ERR, "timer_create failed, %m");
  217         exit(1);
  218     }
  219 #  endif
  220     signal_no_reset(SIGALRM, alarming);
  221     itimer.it_interval.tv_sec =
  222         itimer.it_value.tv_sec = (1 << EVENT_TIMEOUT);
  223     itimer.it_interval.itv_frac = itimer.it_value.itv_frac = 0;
  224     set_timer_or_die(&itimer);
  225 # else  /* VMS follows */
  226     vmsinc[0] = 10000000;       /* 1 sec */
  227     vmsinc[1] = 0;
  228     lib$emul(&(1<<EVENT_TIMEOUT), &vmsinc, &0, &vmsinc);
  229 
  230     sys$gettim(&vmstimer);  /* that's "now" as abstime */
  231 
  232     lib$addx(&vmsinc, &vmstimer, &vmstimer);
  233     sys$setimr(0, &vmstimer, alarming, alarming, 0);
  234 # endif /* VMS */
  235 #else   /* SYS_WINNT follows */
  236     /*
  237      * Set up timer interrupts for every 2**EVENT_TIMEOUT seconds
  238      * Under Windows/NT,
  239      */
  240 
  241     WaitableTimerHandle = CreateWaitableTimer(NULL, FALSE, NULL);
  242     if (WaitableTimerHandle == NULL) {
  243         msyslog(LOG_ERR, "CreateWaitableTimer failed: %m");
  244         exit(1);
  245     }
  246     else {
  247         DWORD       Period;
  248         LARGE_INTEGER   DueTime;
  249         BOOL        rc;
  250 
  251         Period = (1 << EVENT_TIMEOUT) * 1000;
  252         DueTime.QuadPart = Period * 10000i64;
  253         rc = SetWaitableTimer(WaitableTimerHandle, &DueTime,
  254                       Period, NULL, NULL, FALSE);
  255         if (!rc) {
  256             msyslog(LOG_ERR, "SetWaitableTimer failed: %m");
  257             exit(1);
  258         }
  259     }
  260 
  261 #endif  /* SYS_WINNT */
  262 }
  263 
  264 
  265 /*
  266  * intres_timeout_req(s) is invoked in the parent to schedule an idle
  267  * timeout to fire in s seconds, if not reset earlier by a call to
  268  * intres_timeout_req(0), which clears any pending timeout.  When the
  269  * timeout expires, worker_idle_timer_fired() is invoked (again, in the
  270  * parent).
  271  *
  272  * sntp and ntpd each provide implementations adapted to their timers.
  273  */
  274 void
  275 intres_timeout_req(
  276     u_int   seconds     /* 0 cancels */
  277     )
  278 {
  279 #if defined(HAVE_DROPROOT) && defined(NEED_EARLY_FORK)
  280     if (droproot) {
  281         worker_idle_timer = 0;
  282         return;
  283     }
  284 #endif
  285     if (0 == seconds) {
  286         worker_idle_timer = 0;
  287         return;
  288     }
  289     worker_idle_timer = current_time + seconds;
  290 }
  291 
  292 
  293 /*
  294  * timer - event timer
  295  */
  296 void
  297 timer(void)
  298 {
  299     struct peer *   p;
  300     struct peer *   next_peer;
  301     l_fp        now;
  302     time_t          tnow;
  303 
  304     /*
  305      * The basic timerevent is one second.  This is used to adjust the
  306      * system clock in time and frequency, implement the kiss-o'-death
  307      * function and the association polling function.
  308      */
  309     current_time++;
  310     if (adjust_timer <= current_time) {
  311         adjust_timer += 1;
  312         adj_host_clock();
  313 #ifdef REFCLOCK
  314         for (p = peer_list; p != NULL; p = next_peer) {
  315             next_peer = p->p_link;
  316             if (FLAG_REFCLOCK & p->flags)
  317                 refclock_timer(p);
  318         }
  319 #endif /* REFCLOCK */
  320     }
  321 
  322     /*
  323      * Now dispatch any peers whose event timer has expired. Be
  324      * careful here, since the peer structure might go away as the
  325      * result of the call.
  326      */
  327     for (p = peer_list; p != NULL; p = next_peer) {
  328         next_peer = p->p_link;
  329 
  330         /*
  331          * Restrain the non-burst packet rate not more
  332          * than one packet every 16 seconds. This is
  333          * usually tripped using iburst and minpoll of
  334          * 128 s or less.
  335          */
  336         if (p->throttle > 0)
  337             p->throttle--;
  338         if (p->nextdate <= current_time) {
  339 #ifdef REFCLOCK
  340             if (FLAG_REFCLOCK & p->flags)
  341                 refclock_transmit(p);
  342             else
  343 #endif  /* REFCLOCK */
  344                 transmit(p);
  345         }
  346     }
  347 
  348     /*
  349      * Orphan mode is active when enabled and when no servers less
  350      * than the orphan stratum are available. A server with no other
  351      * synchronization source is an orphan. It shows offset zero and
  352      * reference ID the loopback address.
  353      *
  354      * [bug 3644] If the orphan stratum is >= STRATUM_UNSPEC, we
  355      * have to do it a bit different. 'clock_select()' simply
  356      * tiptoed home, but since we're unsync'd and have no peer, we
  357      * should eventually declare we're out of sync. Otherwise we
  358      * would persistently claim we're good, and we're everything but
  359      * that...
  360      *
  361      * XXX: do we want to log an event about this?
  362      */
  363     if (sys_peer == NULL && current_time > orphwait) {
  364         if (sys_orphan < STRATUM_UNSPEC) {
  365             if (sys_leap == LEAP_NOTINSYNC) {
  366                 set_sys_leap(LEAP_NOWARNING);
  367 #ifdef AUTOKEY
  368                 if (crypto_flags)
  369                     crypto_update();
  370 #endif  /* AUTOKEY */
  371             }
  372             sys_stratum = (u_char)sys_orphan;
  373         } else {
  374             if (sys_leap != LEAP_NOTINSYNC) {
  375                 set_sys_leap(LEAP_NOTINSYNC);
  376                 msyslog(LOG_WARNING, "%s",
  377                     "no peer for too long, server running free now");
  378             }
  379             sys_stratum = STRATUM_UNSPEC;
  380         }
  381         if (sys_stratum > 1)
  382             sys_refid = htonl(LOOPBACKADR);
  383         else
  384             memcpy(&sys_refid, "LOOP", 4);
  385         sys_offset = 0;
  386         sys_rootdelay = 0;
  387         sys_rootdisp = 0;
  388     }
  389 
  390     get_systime(&now);
  391     time(&tnow);
  392 
  393     /*
  394      * Leapseconds. Get time and defer to worker if either something
  395      * is imminent or every 8th second.
  396      */
  397     if (leapsec > LSPROX_NOWARN || 0 == (current_time & 7))
  398         check_leapsec(now.l_ui, &tnow,
  399                                 (sys_leap == LEAP_NOTINSYNC));
  400         if (sys_leap != LEAP_NOTINSYNC) {
  401                 if (leapsec >= LSPROX_ANNOUNCE && leapdif) {
  402                 if (leapdif > 0)
  403                     set_sys_leap(LEAP_ADDSECOND);
  404                 else
  405                     set_sys_leap(LEAP_DELSECOND);
  406                 } else {
  407                         set_sys_leap(LEAP_NOWARNING);
  408                 }
  409     }
  410 
  411     /*
  412      * Update huff-n'-puff filter.
  413      */
  414     if (huffpuff_timer <= current_time) {
  415         huffpuff_timer += HUFFPUFF;
  416         huffpuff();
  417     }
  418 
  419 #ifdef AUTOKEY
  420     /*
  421      * Garbage collect expired keys.
  422      */
  423     if (keys_timer <= current_time) {
  424         keys_timer += (1UL << sys_automax);
  425         auth_agekeys();
  426     }
  427 
  428     /*
  429      * Generate new private value. This causes all associations
  430      * to regenerate cookies.
  431      */
  432     if (revoke_timer && revoke_timer <= current_time) {
  433         revoke_timer += (1UL << sys_revoke);
  434         RAND_bytes((u_char *)&sys_private, 4);
  435     }
  436 #endif  /* AUTOKEY */
  437 
  438     /*
  439      * Interface update timer
  440      */
  441     if (interface_interval && interface_timer <= current_time) {
  442         timer_interfacetimeout(current_time +
  443             interface_interval);
  444         DPRINTF(2, ("timer: interface update\n"));
  445         interface_update(NULL, NULL);
  446     }
  447 
  448     if (worker_idle_timer && worker_idle_timer <= current_time)
  449         worker_idle_timer_fired();
  450 
  451     /*
  452      * Finally, write hourly stats and do the hourly
  453      * and daily leapfile checks.
  454      */
  455     if (stats_timer <= current_time) {
  456         stats_timer += SECSPERHR;
  457         write_stats();
  458         if (leapf_timer <= current_time) {
  459             leapf_timer += SECSPERDAY;
  460             check_leap_file(TRUE, now.l_ui, &tnow);
  461         } else {
  462             check_leap_file(FALSE, now.l_ui, &tnow);
  463         }
  464     }
  465 }
  466 
  467 
  468 #ifndef SYS_WINNT
  469 /*
  470  * alarming - tell the world we've been alarmed
  471  */
  472 static RETSIGTYPE
  473 alarming(
  474     int sig
  475     )
  476 {
  477 # ifdef DEBUG
  478     const char *msg = "alarming: initializing TRUE\n";
  479 # endif
  480 
  481     if (!initializing) {
  482         if (alarm_flag) {
  483             alarm_overflow++;
  484 # ifdef DEBUG
  485             msg = "alarming: overflow\n";
  486 # endif
  487         } else {
  488 # ifndef VMS
  489             alarm_flag++;
  490 # else
  491             /* VMS AST routine, increment is no good */
  492             alarm_flag = 1;
  493 # endif
  494 # ifdef DEBUG
  495             msg = "alarming: normal\n";
  496 # endif
  497         }
  498     }
  499 # ifdef VMS
  500     lib$addx(&vmsinc, &vmstimer, &vmstimer);
  501     sys$setimr(0, &vmstimer, alarming, alarming, 0);
  502 # endif
  503 # ifdef DEBUG
  504     if (debug >= 4)
  505         (void)(-1 == write(1, msg, strlen(msg)));
  506 # endif
  507 }
  508 #endif /* SYS_WINNT */
  509 
  510 
  511 void
  512 timer_interfacetimeout(u_long timeout)
  513 {
  514     interface_timer = timeout;
  515 }
  516 
  517 
  518 /*
  519  * timer_clr_stats - clear timer module stat counters
  520  */
  521 void
  522 timer_clr_stats(void)
  523 {
  524     timer_overflows = 0;
  525     timer_xmtcalls = 0;
  526     timer_timereset = current_time;
  527 }
  528 
  529 
  530 static void
  531 check_leap_sec_in_progress( const leap_result_t *lsdata ) {
  532     int prv_leap_sec_in_progress = leap_sec_in_progress;
  533     leap_sec_in_progress = lsdata->tai_diff && (lsdata->ddist < 3);
  534 
  535     /* if changed we may have to update the leap status sent to clients */
  536     if (leap_sec_in_progress != prv_leap_sec_in_progress)
  537         set_sys_leap(sys_leap);
  538 }
  539 
  540 
  541 static void
  542 check_leapsec(
  543     u_int32        now  ,
  544     const time_t * tpiv ,
  545         int/*BOOL*/    reset)
  546 {
  547     static const char leapmsg_p_step[] =
  548         "Positive leap second, stepped backward.";
  549     static const char leapmsg_p_slew[] =
  550         "Positive leap second, no step correction. "
  551         "System clock will be inaccurate for a long time.";
  552 
  553     static const char leapmsg_n_step[] =
  554         "Negative leap second, stepped forward.";
  555     static const char leapmsg_n_slew[] =
  556         "Negative leap second, no step correction. "
  557         "System clock will be inaccurate for a long time.";
  558 
  559     leap_result_t lsdata;
  560     u_int32       lsprox;
  561 #ifdef AUTOKEY
  562     int/*BOOL*/   update_autokey = FALSE;
  563 #endif
  564 
  565 #ifndef SYS_WINNT  /* WinNT port has its own leap second handling */
  566 # ifdef KERNEL_PLL
  567     leapsec_electric(pll_control && kern_enable);
  568 # else
  569     leapsec_electric(0);
  570 # endif
  571 #endif
  572 #ifdef LEAP_SMEAR
  573     leap_smear.enabled = leap_smear_intv != 0;
  574 #endif
  575     if (reset) {
  576         lsprox = LSPROX_NOWARN;
  577         leapsec_reset_frame();
  578         memset(&lsdata, 0, sizeof(lsdata));
  579     } else {
  580       int fired;
  581 
  582       fired = leapsec_query(&lsdata, now, tpiv);
  583 
  584       DPRINTF(3, ("*** leapsec_query: fired %i, now %u (0x%08X), tai_diff %i, ddist %u\n",
  585           fired, now, now, lsdata.tai_diff, lsdata.ddist));
  586 
  587 #ifdef LEAP_SMEAR
  588       leap_smear.in_progress = 0;
  589       leap_smear.doffset = 0.0;
  590 
  591       if (leap_smear.enabled) {
  592         if (lsdata.tai_diff) {
  593             if (leap_smear.interval == 0) {
  594                 leap_smear.interval = leap_smear_intv;
  595                 leap_smear.intv_end = lsdata.ttime.Q_s;
  596                 leap_smear.intv_start = leap_smear.intv_end - leap_smear.interval;
  597                 DPRINTF(1, ("*** leapsec_query: setting leap_smear interval %li, begin %.0f, end %.0f\n",
  598                     leap_smear.interval, leap_smear.intv_start, leap_smear.intv_end));
  599             }
  600         } else {
  601             if (leap_smear.interval)
  602                 DPRINTF(1, ("*** leapsec_query: clearing leap_smear interval\n"));
  603             leap_smear.interval = 0;
  604         }
  605 
  606         if (leap_smear.interval) {
  607             double dtemp = now;
  608             if (dtemp >= leap_smear.intv_start && dtemp <= leap_smear.intv_end) {
  609                 double leap_smear_time = dtemp - leap_smear.intv_start;
  610                 /*
  611                  * For now we just do a linear interpolation over the smear interval
  612                  */
  613 #if 0
  614                 // linear interpolation
  615                 leap_smear.doffset = -(leap_smear_time * lsdata.tai_diff / leap_smear.interval);
  616 #else
  617                 // Google approach: lie(t) = (1.0 - cos(pi * t / w)) / 2.0
  618                 leap_smear.doffset = -((double) lsdata.tai_diff - cos( M_PI * leap_smear_time / leap_smear.interval)) / 2.0;
  619 #endif
  620                 /*
  621                  * TODO see if we're inside an inserted leap second, so we need to compute
  622                  * leap_smear.doffset = 1.0 - leap_smear.doffset
  623                  */
  624                 leap_smear.in_progress = 1;
  625 #if 0 && defined( DEBUG )
  626                 msyslog(LOG_NOTICE, "*** leapsec_query: [%.0f:%.0f] (%li), now %u (%.0f), smear offset %.6f ms\n",
  627                     leap_smear.intv_start, leap_smear.intv_end, leap_smear.interval,
  628                     now, leap_smear_time, leap_smear.doffset);
  629 #else
  630                 DPRINTF(1, ("*** leapsec_query: [%.0f:%.0f] (%li), now %u (%.0f), smear offset %.6f ms\n",
  631                     leap_smear.intv_start, leap_smear.intv_end, leap_smear.interval,
  632                     now, leap_smear_time, leap_smear.doffset));
  633 #endif
  634 
  635             }
  636         }
  637       }
  638       else
  639         leap_smear.interval = 0;
  640 
  641       /*
  642        * Update the current leap smear offset, eventually 0.0 if outside smear interval.
  643        */
  644       DTOLFP(leap_smear.doffset, &leap_smear.offset);
  645 
  646 #endif  /* LEAP_SMEAR */
  647 
  648       if (fired) {
  649         /* Full hit. Eventually step the clock, but always
  650          * announce the leap event has happened.
  651          */
  652         const char *leapmsg = NULL;
  653         double      lswarp  = lsdata.warped;
  654         if (lswarp < 0.0) {
  655             if (clock_max_back > 0.0 &&
  656                 clock_max_back < -lswarp) {
  657                 step_systime(lswarp);
  658                 leapmsg = leapmsg_p_step;
  659             } else {
  660                 leapmsg = leapmsg_p_slew;
  661             }
  662         } else  if (lswarp > 0.0) {
  663             if (clock_max_fwd > 0.0 &&
  664                 clock_max_fwd < lswarp) {
  665                 step_systime(lswarp);
  666                 leapmsg = leapmsg_n_step;
  667             } else {
  668                 leapmsg = leapmsg_n_slew;
  669             }
  670         }
  671         if (leapmsg)
  672             msyslog(LOG_NOTICE, "%s", leapmsg);
  673         report_event(EVNT_LEAP, NULL, NULL);
  674 #ifdef AUTOKEY
  675         update_autokey = TRUE;
  676 #endif
  677         lsprox  = LSPROX_NOWARN;
  678         leapsec = LSPROX_NOWARN;
  679         sys_tai = lsdata.tai_offs;
  680       } else {
  681 #ifdef AUTOKEY
  682           update_autokey = (sys_tai != (u_int)lsdata.tai_offs);
  683 #endif
  684           lsprox  = lsdata.proximity;
  685           sys_tai = lsdata.tai_offs;
  686       }
  687     }
  688 
  689     /* We guard against panic alarming during the red alert phase.
  690      * Strange and evil things might happen if we go from stone cold
  691      * to piping hot in one step. If things are already that wobbly,
  692      * we let the normal clock correction take over, even if a jump
  693      * is involved.
  694          * Also make sure the alarming events are edge-triggered, that is,
  695          * ceated only when the threshold is crossed.
  696          */
  697     if (  (leapsec > 0 || lsprox < LSPROX_ALERT)
  698         && leapsec < lsprox                     ) {
  699         if (  leapsec < LSPROX_SCHEDULE
  700                    && lsprox >= LSPROX_SCHEDULE) {
  701             if (lsdata.dynamic)
  702                 report_event(PEVNT_ARMED, sys_peer, NULL);
  703             else
  704                 report_event(EVNT_ARMED, NULL, NULL);
  705         }
  706         leapsec = lsprox;
  707     }
  708     if (leapsec > lsprox) {
  709         if (  leapsec >= LSPROX_SCHEDULE
  710                    && lsprox   < LSPROX_SCHEDULE) {
  711             report_event(EVNT_DISARMED, NULL, NULL);
  712         }
  713         leapsec = lsprox;
  714     }
  715 
  716     if (leapsec >= LSPROX_SCHEDULE)
  717         leapdif = lsdata.tai_diff;
  718     else
  719         leapdif = 0;
  720 
  721     check_leap_sec_in_progress(&lsdata);
  722 
  723 #ifdef AUTOKEY
  724     if (update_autokey)
  725         crypto_update_taichange();
  726 #endif
  727 }