1 /*        $NetBSD: systime.c,v 1.8 2024/08/18 20:47:13 christos Exp $ */
2 
3 /*
4  * systime -- routines to fiddle a UNIX clock.
5  *
6  * ATTENTION: Get approval from Dave Mills on all changes to this file!
7  *
8  */
9 #include <config.h>
10 #include <math.h>
11 
12 #include "ntp.h"
13 #include "ntpd.h"
14 #include "ntp_syslog.h"
15 #include "ntp_stdlib.h"
16 #include "ntp_random.h"
17 #include "iosignal.h"
18 #include "timevalops.h"
19 #include "timespecops.h"
20 #include "ntp_calendar.h"
21 
22 #ifdef HAVE_SYS_PARAM_H
23 # include <sys/param.h>
24 #endif
25 #ifdef HAVE_UTMP_H
26 # include <utmp.h>
27 #endif /* HAVE_UTMP_H */
28 #ifdef HAVE_UTMPX_H
29 # include <utmpx.h>
30 #endif /* HAVE_UTMPX_H */
31 
32 int       allow_panic = FALSE;                    /* allow panic correction (-g) */
33 int       enable_panic_check = TRUE;    /* Can we check allow_panic's state? */
34 
35 u_long    sys_lamport;                            /* Lamport violation */
36 u_long    sys_tsrounding;                         /* timestamp rounding errors */
37 
38 #ifndef USE_COMPILETIME_PIVOT
39 # define USE_COMPILETIME_PIVOT 1
40 #endif
41 
42 /*
43  * These routines (get_systime, step_systime, adj_systime) implement an
44  * interface between the system independent NTP clock and the Unix
45  * system clock in various architectures and operating systems. Time is
46  * a precious quantity in these routines and every effort is made to
47  * minimize errors by unbiased rounding and amortizing adjustment
48  * residues.
49  *
50  * In order to improve the apparent resolution, provide unbiased
51  * rounding and most importantly ensure that the readings cannot be
52  * predicted, the low-order unused portion of the time below the minimum
53  * time to read the clock is filled with an unbiased random fuzz.
54  *
55  * The sys_tick variable specifies the system clock tick interval in
56  * seconds, for stepping clocks, defined as those which return times
57  * less than MINSTEP greater than the previous reading. For systems that
58  * use a high-resolution counter such that each clock reading is always
59  * at least MINSTEP greater than the prior, sys_tick is the time to read
60  * the system clock.
61  *
62  * The sys_fuzz variable measures the minimum time to read the system
63  * clock, regardless of its precision.  When reading the system clock
64  * using get_systime() after sys_tick and sys_fuzz have been determined,
65  * ntpd ensures each unprocessed clock reading is no less than sys_fuzz
66  * later than the prior unprocessed reading, and then fuzzes the bits
67  * below sys_fuzz in the timestamp returned, ensuring each of its
68  * resulting readings is strictly later than the previous.
69  *
70  * When slewing the system clock using adj_systime() (with the kernel
71  * loop discipline unavailable or disabled), adjtime() offsets are
72  * quantized to sys_tick, if sys_tick is greater than sys_fuzz, which
73  * is to say if the OS presents a stepping clock.  Otherwise, offsets
74  * are quantized to the microsecond resolution of adjtime()'s timeval
75  * input.  The remaining correction sys_residual is carried into the
76  * next adjtime() and meanwhile is also factored into get_systime()
77  * readings.
78  */
79 double    sys_tick = 0;                 /* tick size or time to read (s) */
80 double    sys_fuzz = 0;                 /* min. time to read the clock (s) */
81 long      sys_fuzz_nsec = 0;  /* min. time to read the clock (ns) */
82 double    measured_tick;                /* non-overridable sys_tick (s) */
83 double    sys_residual = 0;   /* adjustment residue (s) */
84 int       trunc_os_clock;               /* sys_tick > measured_tick */
85 time_stepped_callback         step_callback;
86 
87 #ifndef SIM
88 /* perlinger@ntp.org: As 'get_sysime()' does it's own check for clock
89  * backstepping, this could probably become a local variable in
90  * 'get_systime()' and the cruft associated with communicating via a
91  * static value could be removed after the v4.2.8 release.
92  */
93 static int lamport_violated;  /* clock was stepped back */
94 #endif    /* !SIM */
95 
96 #ifdef DEBUG
97 static int systime_init_done;
98 # define DONE_SYSTIME_INIT()  systime_init_done = TRUE
99 #else
100 # define DONE_SYSTIME_INIT()  do {} while (FALSE)
101 #endif
102 
103 #ifdef HAVE_SIGNALED_IO
104 int using_sigio;
105 #endif
106 
107 #ifdef SYS_WINNT
108 CRITICAL_SECTION get_systime_cs;
109 #endif
110 
111 
112 void
set_sys_fuzz(double fuzz_val)113 set_sys_fuzz(
114           double    fuzz_val
115           )
116 {
117           sys_fuzz = fuzz_val;
118           INSIST(sys_fuzz >= 0);
119           INSIST(sys_fuzz <= 1.0);
120           /* [Bug 3450] ensure nsec fuzz >= sys_fuzz to reduce chance of
121            * short-falling fuzz advance
122            */
123           sys_fuzz_nsec = (long)ceil(sys_fuzz * 1e9);
124 }
125 
126 
127 void
init_systime(void)128 init_systime(void)
129 {
130           INIT_GET_SYSTIME_CRITSEC();
131           INIT_WIN_PRECISE_TIME();
132           DONE_SYSTIME_INIT();
133 }
134 
135 
136 #ifndef SIM         /* ntpsim.c has get_systime() and friends for sim */
137 
138 static inline void
get_ostime(struct timespec * tsp)139 get_ostime(
140           struct timespec *   tsp
141           )
142 {
143           int       rc;
144           long      ticks;
145 
146 #if defined(HAVE_CLOCK_GETTIME)
147           rc = clock_gettime(CLOCK_REALTIME, tsp);
148 #elif defined(HAVE_GETCLOCK)
149           rc = getclock(TIMEOFDAY, tsp);
150 #else
151           struct timeval                tv;
152 
153           rc = GETTIMEOFDAY(&tv, NULL);
154           tsp->tv_sec = tv.tv_sec;
155           tsp->tv_nsec = tv.tv_usec * 1000;
156 #endif
157           if (rc < 0) {
158                     msyslog(LOG_ERR, "read system clock failed: %m (%d)",
159                               errno);
160                     exit(1);
161           }
162 
163           if (trunc_os_clock) {
164                     ticks = (long)((tsp->tv_nsec * 1e-9) / sys_tick);
165                     tsp->tv_nsec = (long)(ticks * 1e9 * sys_tick);
166           }
167 }
168 
169 
170 /*
171  * get_systime - return system time in NTP timestamp format.
172  */
173 void
get_systime(l_fp * now)174 get_systime(
175           l_fp *now           /* system time */
176           )
177 {
178         static struct timespec  ts_last;        /* last sampled os time */
179           static struct timespec        ts_prev;  /* prior os time */
180           static l_fp                   lfp_prev; /* prior result */
181           struct timespec ts; /* seconds and nanoseconds */
182           struct timespec ts_min;       /* earliest permissible */
183           struct timespec ts_lam;       /* lamport fictional increment */
184           double    dfuzz;
185           l_fp      result;
186           l_fp      lfpfuzz;
187           l_fp      lfpdelta;
188 
189           get_ostime(&ts);
190           DEBUG_REQUIRE(systime_init_done);
191           ENTER_GET_SYSTIME_CRITSEC();
192 
193         /* First check if here was a Lamport violation, that is, two
194          * successive calls to 'get_ostime()' resulted in negative
195          * time difference. Use a few milliseconds of permissible
196          * tolerance -- being too sharp can hurt here. (This is intented
197          * for the Win32 target, where the HPC interpolation might
198          * introduce small steps backward. It should not be an issue on
199          * systems where get_ostime() results in a true syscall.)
200          */
201         if (cmp_tspec(add_tspec_ns(ts, 50000000), ts_last) < 0) {
202                 lamport_violated = 1;
203                 sys_lamport++;
204           }
205         ts_last = ts;
206 
207           /*
208            * After default_get_precision() has set a nonzero sys_fuzz,
209            * ensure every reading of the OS clock advances by at least
210            * sys_fuzz over the prior reading, thereby assuring each
211            * fuzzed result is strictly later than the prior.  Limit the
212            * necessary fiction to 1 second.
213            */
214           if (!USING_SIGIO()) {
215                     ts_min = add_tspec_ns(ts_prev, sys_fuzz_nsec);
216                     if (cmp_tspec(ts, ts_min) < 0) {
217                               ts_lam = sub_tspec(ts_min, ts);
218                               if (ts_lam.tv_sec > 0 && !lamport_violated) {
219                                         msyslog(LOG_ERR,
220                                                   "get_systime Lamport advance exceeds one second (%.9f)",
221                                                   ts_lam.tv_sec +
222                                                       1e-9 * ts_lam.tv_nsec);
223                                         exit(1);
224                               }
225                               if (!lamport_violated)
226                                         ts = ts_min;
227                     }
228                     ts_prev = ts;
229           }
230 
231           /* convert from timespec to l_fp fixed-point */
232           result = tspec_stamp_to_lfp(ts);
233 
234           /*
235            * Add in the fuzz. 'ntp_random()' returns [0..2**31-1] so we
236            * must scale up the result by 2.0 to cover the full fractional
237            * range.
238            */
239           dfuzz = ntp_uurandom() * sys_fuzz;
240           DTOLFP(dfuzz, &lfpfuzz);
241           L_ADD(&result, &lfpfuzz);
242 
243           /*
244            * Ensure result is strictly greater than prior result (ignoring
245            * sys_residual's effect for now) once sys_fuzz has been
246            * determined.
247            *
248            * [Bug 3450] Rounding errors and time slew can lead to a
249            * violation of the expected postcondition. This is bound to
250            * happen from time to time (depending on state of the random
251            * generator, the current slew and the closeness of system time
252            * stamps drawn) and does not warrant a syslog entry. Instead it
253            * makes much more sense to ensure the postcondition and hop
254            * along silently.
255            */
256           if (!USING_SIGIO()) {
257                     if (   !L_ISZERO(&lfp_prev)
258                         && !lamport_violated
259                         && (sys_fuzz > 0.0)
260                        ) {
261                               lfpdelta = result;
262                               L_SUB(&lfpdelta, &lfp_prev);
263                               L_SUBUF(&lfpdelta, 1);
264                               if (lfpdelta.l_i < 0)
265                               {
266                                         L_NEG(&lfpdelta);
267                                         DPRINTF(1, ("get_systime: postcond failed by %s secs, fixed\n",
268                                                       lfptoa(&lfpdelta, 9)));
269                                         result = lfp_prev;
270                                         L_ADDUF(&result, 1);
271                                         sys_tsrounding++;
272                               }
273                     }
274                     lfp_prev = result;
275                     if (lamport_violated)
276                               lamport_violated = FALSE;
277           }
278           LEAVE_GET_SYSTIME_CRITSEC();
279           *now = result;
280 }
281 
282 
283 /*
284  * adj_systime - adjust system time by the argument.
285  */
286 #if !defined SYS_WINNT
287 int                                     /* 0 okay, 1 error */
adj_systime(double now)288 adj_systime(
289           double now                    /* adjustment (s) */
290           )
291 {
292           struct timeval adjtv;         /* new adjustment */
293           struct timeval oadjtv;        /* residual adjustment */
294           double    quant;              /* quantize to multiples of */
295           double    dtemp;
296           long      ticks;
297           int       isneg = 0;
298 
299           /*
300            * The Windows port adj_systime() depends on being called each
301            * second even when there's no additional correction, to allow
302            * emulation of adjtime() behavior on top of an API that simply
303            * sets the current rate.  This POSIX implementation needs to
304            * ignore invocations with zero correction, otherwise ongoing
305            * EVNT_NSET adjtime() can be aborted by a tiny adjtime()
306            * triggered by sys_residual.
307            */
308           if (0. == now) {
309                     if (enable_panic_check && allow_panic) {
310                               msyslog(LOG_ERR, "adj_systime: allow_panic is TRUE!");
311                               INSIST(!allow_panic);
312                     }
313                     return TRUE;
314           }
315 
316           /*
317            * Most Unix adjtime() implementations adjust the system clock
318            * in microsecond quanta, but some adjust in 10-ms quanta. We
319            * carefully round the adjustment to the nearest quantum, then
320            * adjust in quanta and keep the residue for later.
321            */
322           dtemp = now + sys_residual;
323           if (dtemp < 0) {
324                     isneg = 1;
325                     dtemp = -dtemp;
326           }
327           adjtv.tv_sec = (long)dtemp;
328           dtemp -= adjtv.tv_sec;
329           if (sys_tick > sys_fuzz)
330                     quant = sys_tick;
331           else
332                     quant = 1e-6;
333           ticks = (long)(dtemp / quant + .5);
334           adjtv.tv_usec = (long)(ticks * quant * 1.e6 + .5);
335           /* The rounding in the conversions could us push over the
336            * limits: make sure the result is properly normalised!
337            * note: sign comes later, all numbers non-negative here.
338            */
339           if (adjtv.tv_usec >= 1000000) {
340                     adjtv.tv_sec  += 1;
341                     adjtv.tv_usec -= 1000000;
342                     dtemp         -= 1.;
343           }
344           /* set the new residual with leftover from correction */
345           sys_residual = dtemp - adjtv.tv_usec * 1.e-6;
346 
347           /*
348            * Convert to signed seconds and microseconds for the Unix
349            * adjtime() system call. Note we purposely lose the adjtime()
350            * leftover.
351            */
352           if (isneg) {
353                     adjtv.tv_sec = -adjtv.tv_sec;
354                     adjtv.tv_usec = -adjtv.tv_usec;
355                     sys_residual = -sys_residual;
356           }
357           if (adjtv.tv_sec != 0 || adjtv.tv_usec != 0) {
358                     if (adjtime(&adjtv, &oadjtv) < 0) {
359                               msyslog(LOG_ERR, "adj_systime: %m");
360                               if (enable_panic_check && allow_panic) {
361                                         msyslog(LOG_ERR, "adj_systime: allow_panic is TRUE!");
362                               }
363                               return FALSE;
364                     }
365           }
366           if (enable_panic_check && allow_panic) {
367                     msyslog(LOG_ERR, "adj_systime: allow_panic is TRUE!");
368           }
369           return TRUE;
370 }
371 #endif
372 
373 /*
374  * helper to keep utmp/wtmp up to date
375  */
376 static void
update_uwtmp(struct timeval timetv,struct timeval tvlast)377 update_uwtmp(
378           struct timeval timetv,
379           struct timeval tvlast
380           )
381 {
382           struct timeval tvdiff;
383           /*
384            * FreeBSD, for example, has:
385            * struct utmp {
386            *           char    ut_line[UT_LINESIZE];
387            *           char    ut_name[UT_NAMESIZE];
388            *           char    ut_host[UT_HOSTSIZE];
389            *           long    ut_time;
390            * };
391            * and appends line="|", name="date", host="", time for the OLD
392            * and appends line="{", name="date", host="", time for the NEW // }
393            * to _PATH_WTMP .
394            *
395            * Some OSes have utmp, some have utmpx.
396            */
397 
398           /*
399            * Write old and new time entries in utmp and wtmp if step
400            * adjustment is greater than one second.
401            *
402            * This might become even Uglier...
403            */
404           tvdiff = abs_tval(sub_tval(timetv, tvlast));
405           if (tvdiff.tv_sec > 0) {
406 #ifdef HAVE_UTMP_H
407                     struct utmp ut;
408 #endif
409 #ifdef HAVE_UTMPX_H
410                     struct utmpx utx;
411 #endif
412 
413 #ifdef HAVE_UTMP_H
414                     ZERO(ut);
415 #endif
416 #ifdef HAVE_UTMPX_H
417                     ZERO(utx);
418 #endif
419 
420                     /* UTMP */
421 
422 #ifdef UPDATE_UTMP
423 # ifdef HAVE_PUTUTLINE
424 #  ifndef _PATH_UTMP
425 #   define _PATH_UTMP UTMP_FILE
426 #  endif
427                     utmpname(_PATH_UTMP);
428                     ut.ut_type = OLD_TIME;
429                     strlcpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line));
430                     ut.ut_time = tvlast.tv_sec;
431                     setutent();
432                     pututline(&ut);
433                     ut.ut_type = NEW_TIME;
434                     strlcpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line));
435                     ut.ut_time = timetv.tv_sec;
436                     setutent();
437                     pututline(&ut);
438                     endutent();
439 # else /* not HAVE_PUTUTLINE */
440 # endif /* not HAVE_PUTUTLINE */
441 #endif /* UPDATE_UTMP */
442 
443                     /* UTMPX */
444 
445 #ifdef UPDATE_UTMPX
446 # ifdef HAVE_PUTUTXLINE
447                     utx.ut_type = OLD_TIME;
448                     strlcpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line));
449                     utx.ut_tv = tvlast;
450                     setutxent();
451                     pututxline(&utx);
452                     utx.ut_type = NEW_TIME;
453                     strlcpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line));
454                     utx.ut_tv = timetv;
455                     setutxent();
456                     pututxline(&utx);
457                     endutxent();
458 # else /* not HAVE_PUTUTXLINE */
459 # endif /* not HAVE_PUTUTXLINE */
460 #endif /* UPDATE_UTMPX */
461 
462                     /* WTMP */
463 
464 #ifdef UPDATE_WTMP
465 # ifdef HAVE_PUTUTLINE
466 #  ifndef _PATH_WTMP
467 #   define _PATH_WTMP WTMP_FILE
468 #  endif
469                     utmpname(_PATH_WTMP);
470                     ut.ut_type = OLD_TIME;
471                     strlcpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line));
472                     ut.ut_time = tvlast.tv_sec;
473                     setutent();
474                     pututline(&ut);
475                     ut.ut_type = NEW_TIME;
476                     strlcpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line));
477                     ut.ut_time = timetv.tv_sec;
478                     setutent();
479                     pututline(&ut);
480                     endutent();
481 # else /* not HAVE_PUTUTLINE */
482 # endif /* not HAVE_PUTUTLINE */
483 #endif /* UPDATE_WTMP */
484 
485                     /* WTMPX */
486 
487 #ifdef UPDATE_WTMPX
488 # ifdef HAVE_PUTUTXLINE
489                     utx.ut_type = OLD_TIME;
490                     utx.ut_tv = tvlast;
491                     strlcpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line));
492 #  ifdef HAVE_UPDWTMPX
493                     updwtmpx(WTMPX_FILE, &utx);
494 #  else /* not HAVE_UPDWTMPX */
495 #  endif /* not HAVE_UPDWTMPX */
496 # else /* not HAVE_PUTUTXLINE */
497 # endif /* not HAVE_PUTUTXLINE */
498 # ifdef HAVE_PUTUTXLINE
499                     utx.ut_type = NEW_TIME;
500                     utx.ut_tv = timetv;
501                     strlcpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line));
502 #  ifdef HAVE_UPDWTMPX
503                     updwtmpx(WTMPX_FILE, &utx);
504 #  else /* not HAVE_UPDWTMPX */
505 #  endif /* not HAVE_UPDWTMPX */
506 # else /* not HAVE_PUTUTXLINE */
507 # endif /* not HAVE_PUTUTXLINE */
508 #endif /* UPDATE_WTMPX */
509 
510           }
511 }
512 
513 /*
514  * step_systime - step the system clock.
515  */
516 
517 int
step_systime(double step)518 step_systime(
519           double step
520           )
521 {
522           time_t pivot; /* for ntp era unfolding */
523           struct timeval timetv, tvlast;
524           struct timespec timets;
525           l_fp fp_ofs, fp_sys; /* offset and target system time in FP */
526 
527           /*
528            * Get pivot time for NTP era unfolding. Since we don't step
529            * very often, we can afford to do the whole calculation from
530            * scratch. And we're not in the time-critical path yet.
531            */
532 #if SIZEOF_TIME_T > 4
533           pivot = basedate_get_eracenter();
534 #else
535           /* This makes sure the resulting time stamp is on or after
536            * 1969-12-31/23:59:59 UTC and gives us additional two years,
537            * from the change of NTP era in 2036 to the UNIX rollover in
538            * 2038. (Minus one second, but that won't hurt.) We *really*
539            * need a longer 'time_t' after that!  Or a different baseline,
540            * but that would cause other serious trouble, too.
541            */
542           pivot = 0x7FFFFFFF;
543 #endif
544 
545           /* get the complete jump distance as l_fp */
546           DTOLFP(sys_residual, &fp_sys);
547           DTOLFP(step,         &fp_ofs);
548           L_ADD(&fp_ofs, &fp_sys);
549 
550           /* ---> time-critical path starts ---> */
551 
552           /* get the current time as l_fp (without fuzz) and as struct timeval */
553           get_ostime(&timets);
554           fp_sys = tspec_stamp_to_lfp(timets);
555           tvlast.tv_sec = timets.tv_sec;
556           tvlast.tv_usec = (timets.tv_nsec + 500) / 1000;
557 
558           /* get the target time as l_fp */
559           L_ADD(&fp_sys, &fp_ofs);
560 
561           /* unfold the new system time */
562           timetv = lfp_stamp_to_tval(fp_sys, &pivot);
563 
564           /* now set new system time */
565           if (ntp_set_tod(&timetv, NULL) != 0) {
566                     msyslog(LOG_ERR, "step-systime: %m");
567                     if (enable_panic_check && allow_panic) {
568                               msyslog(LOG_ERR, "step_systime: allow_panic is TRUE!");
569                     }
570                     return FALSE;
571           }
572 
573           /* <--- time-critical path ended with 'ntp_set_tod()' <--- */
574 
575           sys_residual = 0;
576           lamport_violated = (step < 0);
577           if (step_callback)
578                     (*step_callback)();
579 
580 #ifdef NEED_HPUX_ADJTIME
581           /*
582            * CHECKME: is this correct when called by ntpdate?????
583            */
584           _clear_adjtime();
585 #endif
586 
587           update_uwtmp(timetv, tvlast);
588           if (enable_panic_check && allow_panic) {
589                     msyslog(LOG_ERR, "step_systime: allow_panic is TRUE!");
590                     INSIST(!allow_panic);
591           }
592           return TRUE;
593 }
594 
595 
596 #if SIZEOF_TIME_T > 4
597 static const char *
tv_fmt_libbuf(const struct timeval * ptv)598 tv_fmt_libbuf(
599           const struct timeval * ptv
600           )
601 {
602           char *              retv;
603           vint64              secs;
604           ntpcal_split        dds;
605           struct calendar     jd;
606 
607           secs = time_to_vint64(&ptv->tv_sec);
608           dds  = ntpcal_daysplit(&secs);
609           ntpcal_daysplit_to_date(&jd, &dds, DAY_UNIX_STARTS);
610           LIB_GETBUF(retv);
611           snprintf(retv, LIB_BUFLENGTH,
612                      "%04hu-%02hu-%02hu/%02hu:%02hu:%02hu.%06u",
613                      jd.year, (u_short)jd.month, (u_short)jd.monthday,
614                      (u_short)jd.hour, (u_short)jd.minute, (u_short)jd.second,
615                      (u_int)ptv->tv_usec);
616           return retv;
617 }
618 #endif    /* SIZEOF_TIME_T > 4 */
619 
620 
621 int /*BOOL*/
clamp_systime(void)622 clamp_systime(void)
623 {
624 #if SIZEOF_TIME_T > 4
625 
626           struct timeval  tvbase, tvlast;
627           struct timespec timets;
628 
629           tvbase.tv_sec  = basedate_get_erabase();
630           tvbase.tv_usec = 0;
631 
632           /* ---> time-critical path starts ---> */
633 
634           /* get the current time as l_fp (without fuzz) and as struct timeval */
635           get_ostime(&timets);
636           tvlast.tv_sec = timets.tv_sec;
637           tvlast.tv_usec = (timets.tv_nsec + 500) / 1000;
638           if (tvlast.tv_usec >= 1000000) {
639                     tvlast.tv_usec -= 1000000;
640                     tvlast.tv_sec  += 1;
641           }
642 
643           if (tvbase.tv_sec > tvlast.tv_sec) {
644                     /* now set new system time */
645                     if (ntp_set_tod(&tvbase, NULL) != 0) {
646                               msyslog(LOG_ERR, "clamp-systime: %m");
647                               return FALSE;
648                     }
649           } else {
650                     msyslog(LOG_INFO,
651                               "clamp-systime: clock (%s) in allowed range",
652                               tv_fmt_libbuf(&tvlast));
653                     return FALSE;
654           }
655 
656           /* <--- time-critical path ended with 'ntp_set_tod()' <--- */
657 
658           sys_residual = 0;
659           lamport_violated = (tvbase.tv_sec < tvlast.tv_sec);
660           if (step_callback)
661                     (*step_callback)();
662 
663 #   ifdef NEED_HPUX_ADJTIME
664           /*
665            * CHECKME: is this correct when called by ntpdate?????
666            */
667           _clear_adjtime();
668 #   endif
669 
670           update_uwtmp(tvbase, tvlast);
671           msyslog(LOG_WARNING,
672                     "clamp-systime: clock stepped from %s to %s!",
673                     tv_fmt_libbuf(&tvlast), tv_fmt_libbuf(&tvbase));
674           return TRUE;
675 
676 #else
677 
678           return FALSE;
679 
680 #endif
681 }
682 
683 #endif    /* !SIM */
684