1c0b746e5SOllivier Robert /* 2c0b746e5SOllivier Robert * systime -- routines to fiddle a UNIX clock. 39c2daa00SOllivier Robert * 49c2daa00SOllivier Robert * ATTENTION: Get approval from Dave Mills on all changes to this file! 59c2daa00SOllivier Robert * 6c0b746e5SOllivier Robert */ 72b15cb3dSCy Schubert #include <config.h> 809100258SXin LI #include <math.h> 92b15cb3dSCy Schubert 102b15cb3dSCy Schubert #include "ntp.h" 1109100258SXin LI #include "ntpd.h" 12224ba2bdSOllivier Robert #include "ntp_syslog.h" 13224ba2bdSOllivier Robert #include "ntp_stdlib.h" 14ea906c41SOllivier Robert #include "ntp_random.h" 152b15cb3dSCy Schubert #include "iosignal.h" 162b15cb3dSCy Schubert #include "timevalops.h" 172b15cb3dSCy Schubert #include "timespecops.h" 182b15cb3dSCy Schubert #include "ntp_calendar.h" 199c2daa00SOllivier Robert 20c0b746e5SOllivier Robert #ifdef HAVE_SYS_PARAM_H 21c0b746e5SOllivier Robert # include <sys/param.h> 22c0b746e5SOllivier Robert #endif 23c0b746e5SOllivier Robert #ifdef HAVE_UTMP_H 24c0b746e5SOllivier Robert # include <utmp.h> 25c0b746e5SOllivier Robert #endif /* HAVE_UTMP_H */ 26c0b746e5SOllivier Robert #ifdef HAVE_UTMPX_H 27c0b746e5SOllivier Robert # include <utmpx.h> 28c0b746e5SOllivier Robert #endif /* HAVE_UTMPX_H */ 29c0b746e5SOllivier Robert 303311ff84SXin LI int allow_panic = FALSE; /* allow panic correction (-g) */ 313311ff84SXin LI int enable_panic_check = TRUE; /* Can we check allow_panic's state? */ 322b15cb3dSCy Schubert 3309100258SXin LI u_long sys_lamport; /* Lamport violation */ 3409100258SXin LI u_long sys_tsrounding; /* timestamp rounding errors */ 3509100258SXin LI 362b15cb3dSCy Schubert #ifndef USE_COMPILETIME_PIVOT 372b15cb3dSCy Schubert # define USE_COMPILETIME_PIVOT 1 382b15cb3dSCy Schubert #endif 392b15cb3dSCy Schubert 40c0b746e5SOllivier Robert /* 419c2daa00SOllivier Robert * These routines (get_systime, step_systime, adj_systime) implement an 429c2daa00SOllivier Robert * interface between the system independent NTP clock and the Unix 432b15cb3dSCy Schubert * system clock in various architectures and operating systems. Time is 442b15cb3dSCy Schubert * a precious quantity in these routines and every effort is made to 452b15cb3dSCy Schubert * minimize errors by unbiased rounding and amortizing adjustment 462b15cb3dSCy Schubert * residues. 479c2daa00SOllivier Robert * 482b15cb3dSCy Schubert * In order to improve the apparent resolution, provide unbiased 492b15cb3dSCy Schubert * rounding and most importantly ensure that the readings cannot be 502b15cb3dSCy Schubert * predicted, the low-order unused portion of the time below the minimum 512b15cb3dSCy Schubert * time to read the clock is filled with an unbiased random fuzz. 522b15cb3dSCy Schubert * 532b15cb3dSCy Schubert * The sys_tick variable specifies the system clock tick interval in 542b15cb3dSCy Schubert * seconds, for stepping clocks, defined as those which return times 552b15cb3dSCy Schubert * less than MINSTEP greater than the previous reading. For systems that 562b15cb3dSCy Schubert * use a high-resolution counter such that each clock reading is always 572b15cb3dSCy Schubert * at least MINSTEP greater than the prior, sys_tick is the time to read 582b15cb3dSCy Schubert * the system clock. 592b15cb3dSCy Schubert * 602b15cb3dSCy Schubert * The sys_fuzz variable measures the minimum time to read the system 612b15cb3dSCy Schubert * clock, regardless of its precision. When reading the system clock 622b15cb3dSCy Schubert * using get_systime() after sys_tick and sys_fuzz have been determined, 632b15cb3dSCy Schubert * ntpd ensures each unprocessed clock reading is no less than sys_fuzz 642b15cb3dSCy Schubert * later than the prior unprocessed reading, and then fuzzes the bits 652b15cb3dSCy Schubert * below sys_fuzz in the timestamp returned, ensuring each of its 662b15cb3dSCy Schubert * resulting readings is strictly later than the previous. 672b15cb3dSCy Schubert * 682b15cb3dSCy Schubert * When slewing the system clock using adj_systime() (with the kernel 692b15cb3dSCy Schubert * loop discipline unavailable or disabled), adjtime() offsets are 702b15cb3dSCy Schubert * quantized to sys_tick, if sys_tick is greater than sys_fuzz, which 712b15cb3dSCy Schubert * is to say if the OS presents a stepping clock. Otherwise, offsets 722b15cb3dSCy Schubert * are quantized to the microsecond resolution of adjtime()'s timeval 732b15cb3dSCy Schubert * input. The remaining correction sys_residual is carried into the 742b15cb3dSCy Schubert * next adjtime() and meanwhile is also factored into get_systime() 752b15cb3dSCy Schubert * readings. 76c0b746e5SOllivier Robert */ 772b15cb3dSCy Schubert double sys_tick = 0; /* tick size or time to read (s) */ 782b15cb3dSCy Schubert double sys_fuzz = 0; /* min. time to read the clock (s) */ 792b15cb3dSCy Schubert long sys_fuzz_nsec = 0; /* min. time to read the clock (ns) */ 802b15cb3dSCy Schubert double measured_tick; /* non-overridable sys_tick (s) */ 819c2daa00SOllivier Robert double sys_residual = 0; /* adjustment residue (s) */ 822b15cb3dSCy Schubert int trunc_os_clock; /* sys_tick > measured_tick */ 832b15cb3dSCy Schubert time_stepped_callback step_callback; 84c0b746e5SOllivier Robert 859c2daa00SOllivier Robert #ifndef SIM 862b15cb3dSCy Schubert /* perlinger@ntp.org: As 'get_sysime()' does it's own check for clock 872b15cb3dSCy Schubert * backstepping, this could probably become a local variable in 882b15cb3dSCy Schubert * 'get_systime()' and the cruft associated with communicating via a 892b15cb3dSCy Schubert * static value could be removed after the v4.2.8 release. 902b15cb3dSCy Schubert */ 912b15cb3dSCy Schubert static int lamport_violated; /* clock was stepped back */ 922b15cb3dSCy Schubert #endif /* !SIM */ 932b15cb3dSCy Schubert 942b15cb3dSCy Schubert #ifdef DEBUG 952b15cb3dSCy Schubert static int systime_init_done; 962b15cb3dSCy Schubert # define DONE_SYSTIME_INIT() systime_init_done = TRUE 972b15cb3dSCy Schubert #else 982b15cb3dSCy Schubert # define DONE_SYSTIME_INIT() do {} while (FALSE) 992b15cb3dSCy Schubert #endif 1002b15cb3dSCy Schubert 1012b15cb3dSCy Schubert #ifdef HAVE_SIGNALED_IO 1022b15cb3dSCy Schubert int using_sigio; 1032b15cb3dSCy Schubert #endif 1042b15cb3dSCy Schubert 1052b15cb3dSCy Schubert #ifdef SYS_WINNT 1062b15cb3dSCy Schubert CRITICAL_SECTION get_systime_cs; 1072b15cb3dSCy Schubert #endif 1082b15cb3dSCy Schubert 1092b15cb3dSCy Schubert 1102b15cb3dSCy Schubert void 1112b15cb3dSCy Schubert set_sys_fuzz( 1122b15cb3dSCy Schubert double fuzz_val 1132b15cb3dSCy Schubert ) 1142b15cb3dSCy Schubert { 1152b15cb3dSCy Schubert sys_fuzz = fuzz_val; 1162b15cb3dSCy Schubert INSIST(sys_fuzz >= 0); 1172b15cb3dSCy Schubert INSIST(sys_fuzz <= 1.0); 11809100258SXin LI /* [Bug 3450] ensure nsec fuzz >= sys_fuzz to reduce chance of 11909100258SXin LI * short-falling fuzz advance 12009100258SXin LI */ 12109100258SXin LI sys_fuzz_nsec = (long)ceil(sys_fuzz * 1e9); 1222b15cb3dSCy Schubert } 1232b15cb3dSCy Schubert 1242b15cb3dSCy Schubert 1252b15cb3dSCy Schubert void 1262b15cb3dSCy Schubert init_systime(void) 1272b15cb3dSCy Schubert { 1282b15cb3dSCy Schubert INIT_GET_SYSTIME_CRITSEC(); 1292b15cb3dSCy Schubert INIT_WIN_PRECISE_TIME(); 1302b15cb3dSCy Schubert DONE_SYSTIME_INIT(); 1312b15cb3dSCy Schubert } 1322b15cb3dSCy Schubert 1332b15cb3dSCy Schubert 1342b15cb3dSCy Schubert #ifndef SIM /* ntpsim.c has get_systime() and friends for sim */ 1352b15cb3dSCy Schubert 1362b15cb3dSCy Schubert static inline void 1372b15cb3dSCy Schubert get_ostime( 1382b15cb3dSCy Schubert struct timespec * tsp 1392b15cb3dSCy Schubert ) 1402b15cb3dSCy Schubert { 1412b15cb3dSCy Schubert int rc; 1422b15cb3dSCy Schubert long ticks; 1432b15cb3dSCy Schubert 1442b15cb3dSCy Schubert #if defined(HAVE_CLOCK_GETTIME) 1452b15cb3dSCy Schubert rc = clock_gettime(CLOCK_REALTIME, tsp); 1462b15cb3dSCy Schubert #elif defined(HAVE_GETCLOCK) 1472b15cb3dSCy Schubert rc = getclock(TIMEOFDAY, tsp); 1482b15cb3dSCy Schubert #else 1492b15cb3dSCy Schubert struct timeval tv; 1502b15cb3dSCy Schubert 1512b15cb3dSCy Schubert rc = GETTIMEOFDAY(&tv, NULL); 1522b15cb3dSCy Schubert tsp->tv_sec = tv.tv_sec; 1532b15cb3dSCy Schubert tsp->tv_nsec = tv.tv_usec * 1000; 1542b15cb3dSCy Schubert #endif 1552b15cb3dSCy Schubert if (rc < 0) { 1562b15cb3dSCy Schubert msyslog(LOG_ERR, "read system clock failed: %m (%d)", 1572b15cb3dSCy Schubert errno); 1582b15cb3dSCy Schubert exit(1); 1592b15cb3dSCy Schubert } 1602b15cb3dSCy Schubert 1612b15cb3dSCy Schubert if (trunc_os_clock) { 1622b15cb3dSCy Schubert ticks = (long)((tsp->tv_nsec * 1e-9) / sys_tick); 1632b15cb3dSCy Schubert tsp->tv_nsec = (long)(ticks * 1e9 * sys_tick); 1642b15cb3dSCy Schubert } 1652b15cb3dSCy Schubert } 1662b15cb3dSCy Schubert 167c0b746e5SOllivier Robert 168c0b746e5SOllivier Robert /* 1699c2daa00SOllivier Robert * get_systime - return system time in NTP timestamp format. 170c0b746e5SOllivier Robert */ 171c0b746e5SOllivier Robert void 172c0b746e5SOllivier Robert get_systime( 1739c2daa00SOllivier Robert l_fp *now /* system time */ 174c0b746e5SOllivier Robert ) 175c0b746e5SOllivier Robert { 1762b15cb3dSCy Schubert static struct timespec ts_last; /* last sampled os time */ 1772b15cb3dSCy Schubert static struct timespec ts_prev; /* prior os time */ 1782b15cb3dSCy Schubert static l_fp lfp_prev; /* prior result */ 1799c2daa00SOllivier Robert struct timespec ts; /* seconds and nanoseconds */ 1802b15cb3dSCy Schubert struct timespec ts_min; /* earliest permissible */ 1812b15cb3dSCy Schubert struct timespec ts_lam; /* lamport fictional increment */ 1822b15cb3dSCy Schubert double dfuzz; 1832b15cb3dSCy Schubert l_fp result; 1842b15cb3dSCy Schubert l_fp lfpfuzz; 1852b15cb3dSCy Schubert l_fp lfpdelta; 1869c2daa00SOllivier Robert 1872b15cb3dSCy Schubert get_ostime(&ts); 1882b15cb3dSCy Schubert DEBUG_REQUIRE(systime_init_done); 1892b15cb3dSCy Schubert ENTER_GET_SYSTIME_CRITSEC(); 1902b15cb3dSCy Schubert 1912b15cb3dSCy Schubert /* First check if here was a Lamport violation, that is, two 1922b15cb3dSCy Schubert * successive calls to 'get_ostime()' resulted in negative 1932b15cb3dSCy Schubert * time difference. Use a few milliseconds of permissible 1942b15cb3dSCy Schubert * tolerance -- being too sharp can hurt here. (This is intented 1952b15cb3dSCy Schubert * for the Win32 target, where the HPC interpolation might 1962b15cb3dSCy Schubert * introduce small steps backward. It should not be an issue on 1972b15cb3dSCy Schubert * systems where get_ostime() results in a true syscall.) 1989c2daa00SOllivier Robert */ 19909100258SXin LI if (cmp_tspec(add_tspec_ns(ts, 50000000), ts_last) < 0) { 2002b15cb3dSCy Schubert lamport_violated = 1; 20109100258SXin LI sys_lamport++; 20209100258SXin LI } 2032b15cb3dSCy Schubert ts_last = ts; 2049c2daa00SOllivier Robert 2059c2daa00SOllivier Robert /* 2062b15cb3dSCy Schubert * After default_get_precision() has set a nonzero sys_fuzz, 2072b15cb3dSCy Schubert * ensure every reading of the OS clock advances by at least 2082b15cb3dSCy Schubert * sys_fuzz over the prior reading, thereby assuring each 2092b15cb3dSCy Schubert * fuzzed result is strictly later than the prior. Limit the 2102b15cb3dSCy Schubert * necessary fiction to 1 second. 2119c2daa00SOllivier Robert */ 2122b15cb3dSCy Schubert if (!USING_SIGIO()) { 2132b15cb3dSCy Schubert ts_min = add_tspec_ns(ts_prev, sys_fuzz_nsec); 2142b15cb3dSCy Schubert if (cmp_tspec(ts, ts_min) < 0) { 2152b15cb3dSCy Schubert ts_lam = sub_tspec(ts_min, ts); 2162b15cb3dSCy Schubert if (ts_lam.tv_sec > 0 && !lamport_violated) { 2172b15cb3dSCy Schubert msyslog(LOG_ERR, 2182b15cb3dSCy Schubert "get_systime Lamport advance exceeds one second (%.9f)", 2192b15cb3dSCy Schubert ts_lam.tv_sec + 2202b15cb3dSCy Schubert 1e-9 * ts_lam.tv_nsec); 2212b15cb3dSCy Schubert exit(1); 2222b15cb3dSCy Schubert } 2232b15cb3dSCy Schubert if (!lamport_violated) 2242b15cb3dSCy Schubert ts = ts_min; 2252b15cb3dSCy Schubert } 2262b15cb3dSCy Schubert ts_prev = ts; 2272b15cb3dSCy Schubert } 2289c2daa00SOllivier Robert 2292b15cb3dSCy Schubert /* convert from timespec to l_fp fixed-point */ 2302b15cb3dSCy Schubert result = tspec_stamp_to_lfp(ts); 2319c2daa00SOllivier Robert 2329c2daa00SOllivier Robert /* 23309100258SXin LI * Add in the fuzz. 'ntp_random()' returns [0..2**31-1] so we 23409100258SXin LI * must scale up the result by 2.0 to cover the full fractional 23509100258SXin LI * range. 2362b15cb3dSCy Schubert */ 237*a466cc55SCy Schubert dfuzz = ntp_uurandom() * sys_fuzz; 2382b15cb3dSCy Schubert DTOLFP(dfuzz, &lfpfuzz); 2392b15cb3dSCy Schubert L_ADD(&result, &lfpfuzz); 2402b15cb3dSCy Schubert 2412b15cb3dSCy Schubert /* 2422b15cb3dSCy Schubert * Ensure result is strictly greater than prior result (ignoring 2432b15cb3dSCy Schubert * sys_residual's effect for now) once sys_fuzz has been 244ea906c41SOllivier Robert * determined. 24509100258SXin LI * 24609100258SXin LI * [Bug 3450] Rounding errors and time slew can lead to a 24709100258SXin LI * violation of the expected postcondition. This is bound to 24809100258SXin LI * happen from time to time (depending on state of the random 24909100258SXin LI * generator, the current slew and the closeness of system time 25009100258SXin LI * stamps drawn) and does not warrant a syslog entry. Instead it 25109100258SXin LI * makes much more sense to ensure the postcondition and hop 25209100258SXin LI * along silently. 253ea906c41SOllivier Robert */ 2542b15cb3dSCy Schubert if (!USING_SIGIO()) { 25509100258SXin LI if ( !L_ISZERO(&lfp_prev) 25609100258SXin LI && !lamport_violated 25709100258SXin LI && (sys_fuzz > 0.0) 25809100258SXin LI ) { 25909100258SXin LI lfpdelta = result; 26009100258SXin LI L_SUB(&lfpdelta, &lfp_prev); 26109100258SXin LI L_SUBUF(&lfpdelta, 1); 26209100258SXin LI if (lfpdelta.l_i < 0) 26309100258SXin LI { 26409100258SXin LI L_NEG(&lfpdelta); 26509100258SXin LI DPRINTF(1, ("get_systime: postcond failed by %s secs, fixed\n", 26609100258SXin LI lfptoa(&lfpdelta, 9))); 26709100258SXin LI result = lfp_prev; 26809100258SXin LI L_ADDUF(&result, 1); 26909100258SXin LI sys_tsrounding++; 270c0b746e5SOllivier Robert } 2712b15cb3dSCy Schubert } 2722b15cb3dSCy Schubert lfp_prev = result; 2732b15cb3dSCy Schubert if (lamport_violated) 2742b15cb3dSCy Schubert lamport_violated = FALSE; 2752b15cb3dSCy Schubert } 2762b15cb3dSCy Schubert LEAVE_GET_SYSTIME_CRITSEC(); 2772b15cb3dSCy Schubert *now = result; 278c0b746e5SOllivier Robert } 279c0b746e5SOllivier Robert 280c0b746e5SOllivier Robert 281c0b746e5SOllivier Robert /* 2829c2daa00SOllivier Robert * adj_systime - adjust system time by the argument. 283c0b746e5SOllivier Robert */ 284a151a66cSOllivier Robert #if !defined SYS_WINNT 2859c2daa00SOllivier Robert int /* 0 okay, 1 error */ 286c0b746e5SOllivier Robert adj_systime( 2879c2daa00SOllivier Robert double now /* adjustment (s) */ 288c0b746e5SOllivier Robert ) 289c0b746e5SOllivier Robert { 2909c2daa00SOllivier Robert struct timeval adjtv; /* new adjustment */ 2919c2daa00SOllivier Robert struct timeval oadjtv; /* residual adjustment */ 2922b15cb3dSCy Schubert double quant; /* quantize to multiples of */ 293c0b746e5SOllivier Robert double dtemp; 2949c2daa00SOllivier Robert long ticks; 2959c2daa00SOllivier Robert int isneg = 0; 296c0b746e5SOllivier Robert 297c0b746e5SOllivier Robert /* 2982b15cb3dSCy Schubert * The Windows port adj_systime() depends on being called each 2992b15cb3dSCy Schubert * second even when there's no additional correction, to allow 3002b15cb3dSCy Schubert * emulation of adjtime() behavior on top of an API that simply 3012b15cb3dSCy Schubert * sets the current rate. This POSIX implementation needs to 3022b15cb3dSCy Schubert * ignore invocations with zero correction, otherwise ongoing 3032b15cb3dSCy Schubert * EVNT_NSET adjtime() can be aborted by a tiny adjtime() 3042b15cb3dSCy Schubert * triggered by sys_residual. 3052b15cb3dSCy Schubert */ 3063311ff84SXin LI if (0. == now) { 3073311ff84SXin LI if (enable_panic_check && allow_panic) { 3083311ff84SXin LI msyslog(LOG_ERR, "adj_systime: allow_panic is TRUE!"); 3093311ff84SXin LI INSIST(!allow_panic); 3103311ff84SXin LI } 3112b15cb3dSCy Schubert return TRUE; 3123311ff84SXin LI } 3132b15cb3dSCy Schubert 3142b15cb3dSCy Schubert /* 3159c2daa00SOllivier Robert * Most Unix adjtime() implementations adjust the system clock 3169c2daa00SOllivier Robert * in microsecond quanta, but some adjust in 10-ms quanta. We 3179c2daa00SOllivier Robert * carefully round the adjustment to the nearest quantum, then 3189c2daa00SOllivier Robert * adjust in quanta and keep the residue for later. 319c0b746e5SOllivier Robert */ 3209c2daa00SOllivier Robert dtemp = now + sys_residual; 321c0b746e5SOllivier Robert if (dtemp < 0) { 322c0b746e5SOllivier Robert isneg = 1; 323c0b746e5SOllivier Robert dtemp = -dtemp; 324c0b746e5SOllivier Robert } 3259c2daa00SOllivier Robert adjtv.tv_sec = (long)dtemp; 3269c2daa00SOllivier Robert dtemp -= adjtv.tv_sec; 3272b15cb3dSCy Schubert if (sys_tick > sys_fuzz) 3282b15cb3dSCy Schubert quant = sys_tick; 3292b15cb3dSCy Schubert else 3302b15cb3dSCy Schubert quant = 1e-6; 3312b15cb3dSCy Schubert ticks = (long)(dtemp / quant + .5); 33268ba7e87SXin LI adjtv.tv_usec = (long)(ticks * quant * 1.e6 + .5); 33368ba7e87SXin LI /* The rounding in the conversions could us push over the 33468ba7e87SXin LI * limits: make sure the result is properly normalised! 33568ba7e87SXin LI * note: sign comes later, all numbers non-negative here. 33668ba7e87SXin LI */ 33768ba7e87SXin LI if (adjtv.tv_usec >= 1000000) { 33868ba7e87SXin LI adjtv.tv_sec += 1; 33968ba7e87SXin LI adjtv.tv_usec -= 1000000; 34068ba7e87SXin LI dtemp -= 1.; 34168ba7e87SXin LI } 34268ba7e87SXin LI /* set the new residual with leftover from correction */ 34368ba7e87SXin LI sys_residual = dtemp - adjtv.tv_usec * 1.e-6; 344c0b746e5SOllivier Robert 345c0b746e5SOllivier Robert /* 3469c2daa00SOllivier Robert * Convert to signed seconds and microseconds for the Unix 3479c2daa00SOllivier Robert * adjtime() system call. Note we purposely lose the adjtime() 3489c2daa00SOllivier Robert * leftover. 349c0b746e5SOllivier Robert */ 3509c2daa00SOllivier Robert if (isneg) { 3519c2daa00SOllivier Robert adjtv.tv_sec = -adjtv.tv_sec; 3529c2daa00SOllivier Robert adjtv.tv_usec = -adjtv.tv_usec; 353ea906c41SOllivier Robert sys_residual = -sys_residual; 354c0b746e5SOllivier Robert } 355ea906c41SOllivier Robert if (adjtv.tv_sec != 0 || adjtv.tv_usec != 0) { 3569c2daa00SOllivier Robert if (adjtime(&adjtv, &oadjtv) < 0) { 3579c2daa00SOllivier Robert msyslog(LOG_ERR, "adj_systime: %m"); 3583311ff84SXin LI if (enable_panic_check && allow_panic) { 3593311ff84SXin LI msyslog(LOG_ERR, "adj_systime: allow_panic is TRUE!"); 3603311ff84SXin LI } 3612b15cb3dSCy Schubert return FALSE; 362c0b746e5SOllivier Robert } 363ea906c41SOllivier Robert } 3643311ff84SXin LI if (enable_panic_check && allow_panic) { 3653311ff84SXin LI msyslog(LOG_ERR, "adj_systime: allow_panic is TRUE!"); 3663311ff84SXin LI } 3672b15cb3dSCy Schubert return TRUE; 368c0b746e5SOllivier Robert } 369a151a66cSOllivier Robert #endif 370c0b746e5SOllivier Robert 371c0b746e5SOllivier Robert /* 37209100258SXin LI * helper to keep utmp/wtmp up to date 373c0b746e5SOllivier Robert */ 37409100258SXin LI static void 37509100258SXin LI update_uwtmp( 37609100258SXin LI struct timeval timetv, 37709100258SXin LI struct timeval tvlast 378c0b746e5SOllivier Robert ) 379c0b746e5SOllivier Robert { 38009100258SXin LI struct timeval tvdiff; 381c0b746e5SOllivier Robert /* 382c0b746e5SOllivier Robert * FreeBSD, for example, has: 383c0b746e5SOllivier Robert * struct utmp { 384c0b746e5SOllivier Robert * char ut_line[UT_LINESIZE]; 385c0b746e5SOllivier Robert * char ut_name[UT_NAMESIZE]; 386c0b746e5SOllivier Robert * char ut_host[UT_HOSTSIZE]; 387c0b746e5SOllivier Robert * long ut_time; 388c0b746e5SOllivier Robert * }; 389c0b746e5SOllivier Robert * and appends line="|", name="date", host="", time for the OLD 3903311ff84SXin LI * and appends line="{", name="date", host="", time for the NEW // } 391c0b746e5SOllivier Robert * to _PATH_WTMP . 392c0b746e5SOllivier Robert * 393c0b746e5SOllivier Robert * Some OSes have utmp, some have utmpx. 394c0b746e5SOllivier Robert */ 395c0b746e5SOllivier Robert 396c0b746e5SOllivier Robert /* 3979c2daa00SOllivier Robert * Write old and new time entries in utmp and wtmp if step 3989c2daa00SOllivier Robert * adjustment is greater than one second. 399c0b746e5SOllivier Robert * 400c0b746e5SOllivier Robert * This might become even Uglier... 401c0b746e5SOllivier Robert */ 4022b15cb3dSCy Schubert tvdiff = abs_tval(sub_tval(timetv, tvlast)); 4032b15cb3dSCy Schubert if (tvdiff.tv_sec > 0) { 404c0b746e5SOllivier Robert #ifdef HAVE_UTMP_H 405c0b746e5SOllivier Robert struct utmp ut; 406c0b746e5SOllivier Robert #endif 407c0b746e5SOllivier Robert #ifdef HAVE_UTMPX_H 408c0b746e5SOllivier Robert struct utmpx utx; 409c0b746e5SOllivier Robert #endif 410c0b746e5SOllivier Robert 411c0b746e5SOllivier Robert #ifdef HAVE_UTMP_H 4122b15cb3dSCy Schubert ZERO(ut); 413c0b746e5SOllivier Robert #endif 414c0b746e5SOllivier Robert #ifdef HAVE_UTMPX_H 4152b15cb3dSCy Schubert ZERO(utx); 416c0b746e5SOllivier Robert #endif 417c0b746e5SOllivier Robert 418c0b746e5SOllivier Robert /* UTMP */ 419c0b746e5SOllivier Robert 420c0b746e5SOllivier Robert #ifdef UPDATE_UTMP 421c0b746e5SOllivier Robert # ifdef HAVE_PUTUTLINE 4222b15cb3dSCy Schubert # ifndef _PATH_UTMP 4232b15cb3dSCy Schubert # define _PATH_UTMP UTMP_FILE 4242b15cb3dSCy Schubert # endif 4252b15cb3dSCy Schubert utmpname(_PATH_UTMP); 426c0b746e5SOllivier Robert ut.ut_type = OLD_TIME; 4272b15cb3dSCy Schubert strlcpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line)); 4282b15cb3dSCy Schubert ut.ut_time = tvlast.tv_sec; 429c0b746e5SOllivier Robert setutent(); 4302b15cb3dSCy Schubert pututline(&ut); 431c0b746e5SOllivier Robert ut.ut_type = NEW_TIME; 4322b15cb3dSCy Schubert strlcpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line)); 433c0b746e5SOllivier Robert ut.ut_time = timetv.tv_sec; 4342b15cb3dSCy Schubert setutent(); 435c0b746e5SOllivier Robert pututline(&ut); 436c0b746e5SOllivier Robert endutent(); 437c0b746e5SOllivier Robert # else /* not HAVE_PUTUTLINE */ 438c0b746e5SOllivier Robert # endif /* not HAVE_PUTUTLINE */ 439c0b746e5SOllivier Robert #endif /* UPDATE_UTMP */ 440c0b746e5SOllivier Robert 441c0b746e5SOllivier Robert /* UTMPX */ 442c0b746e5SOllivier Robert 443c0b746e5SOllivier Robert #ifdef UPDATE_UTMPX 444c0b746e5SOllivier Robert # ifdef HAVE_PUTUTXLINE 445c0b746e5SOllivier Robert utx.ut_type = OLD_TIME; 4462b15cb3dSCy Schubert strlcpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line)); 4472b15cb3dSCy Schubert utx.ut_tv = tvlast; 448c0b746e5SOllivier Robert setutxent(); 4492b15cb3dSCy Schubert pututxline(&utx); 450c0b746e5SOllivier Robert utx.ut_type = NEW_TIME; 4512b15cb3dSCy Schubert strlcpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line)); 452c0b746e5SOllivier Robert utx.ut_tv = timetv; 4532b15cb3dSCy Schubert setutxent(); 454c0b746e5SOllivier Robert pututxline(&utx); 455c0b746e5SOllivier Robert endutxent(); 456c0b746e5SOllivier Robert # else /* not HAVE_PUTUTXLINE */ 457c0b746e5SOllivier Robert # endif /* not HAVE_PUTUTXLINE */ 458c0b746e5SOllivier Robert #endif /* UPDATE_UTMPX */ 459c0b746e5SOllivier Robert 460c0b746e5SOllivier Robert /* WTMP */ 461c0b746e5SOllivier Robert 462c0b746e5SOllivier Robert #ifdef UPDATE_WTMP 463c0b746e5SOllivier Robert # ifdef HAVE_PUTUTLINE 4642b15cb3dSCy Schubert # ifndef _PATH_WTMP 4652b15cb3dSCy Schubert # define _PATH_WTMP WTMP_FILE 4662b15cb3dSCy Schubert # endif 4672b15cb3dSCy Schubert utmpname(_PATH_WTMP); 468c0b746e5SOllivier Robert ut.ut_type = OLD_TIME; 4692b15cb3dSCy Schubert strlcpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line)); 4702b15cb3dSCy Schubert ut.ut_time = tvlast.tv_sec; 4712b15cb3dSCy Schubert setutent(); 472c0b746e5SOllivier Robert pututline(&ut); 473c0b746e5SOllivier Robert ut.ut_type = NEW_TIME; 4742b15cb3dSCy Schubert strlcpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line)); 475c0b746e5SOllivier Robert ut.ut_time = timetv.tv_sec; 4762b15cb3dSCy Schubert setutent(); 477c0b746e5SOllivier Robert pututline(&ut); 478c0b746e5SOllivier Robert endutent(); 479c0b746e5SOllivier Robert # else /* not HAVE_PUTUTLINE */ 480c0b746e5SOllivier Robert # endif /* not HAVE_PUTUTLINE */ 481c0b746e5SOllivier Robert #endif /* UPDATE_WTMP */ 482c0b746e5SOllivier Robert 483c0b746e5SOllivier Robert /* WTMPX */ 484c0b746e5SOllivier Robert 485c0b746e5SOllivier Robert #ifdef UPDATE_WTMPX 486c0b746e5SOllivier Robert # ifdef HAVE_PUTUTXLINE 487c0b746e5SOllivier Robert utx.ut_type = OLD_TIME; 4882b15cb3dSCy Schubert utx.ut_tv = tvlast; 4892b15cb3dSCy Schubert strlcpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line)); 490c0b746e5SOllivier Robert # ifdef HAVE_UPDWTMPX 491c0b746e5SOllivier Robert updwtmpx(WTMPX_FILE, &utx); 492c0b746e5SOllivier Robert # else /* not HAVE_UPDWTMPX */ 493c0b746e5SOllivier Robert # endif /* not HAVE_UPDWTMPX */ 494c0b746e5SOllivier Robert # else /* not HAVE_PUTUTXLINE */ 495c0b746e5SOllivier Robert # endif /* not HAVE_PUTUTXLINE */ 496c0b746e5SOllivier Robert # ifdef HAVE_PUTUTXLINE 497c0b746e5SOllivier Robert utx.ut_type = NEW_TIME; 498c0b746e5SOllivier Robert utx.ut_tv = timetv; 4992b15cb3dSCy Schubert strlcpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line)); 500c0b746e5SOllivier Robert # ifdef HAVE_UPDWTMPX 501c0b746e5SOllivier Robert updwtmpx(WTMPX_FILE, &utx); 502c0b746e5SOllivier Robert # else /* not HAVE_UPDWTMPX */ 503c0b746e5SOllivier Robert # endif /* not HAVE_UPDWTMPX */ 504c0b746e5SOllivier Robert # else /* not HAVE_PUTUTXLINE */ 505c0b746e5SOllivier Robert # endif /* not HAVE_PUTUTXLINE */ 506c0b746e5SOllivier Robert #endif /* UPDATE_WTMPX */ 507c0b746e5SOllivier Robert 508c0b746e5SOllivier Robert } 50909100258SXin LI } 51009100258SXin LI 51109100258SXin LI /* 51209100258SXin LI * step_systime - step the system clock. 51309100258SXin LI */ 51409100258SXin LI 51509100258SXin LI int 51609100258SXin LI step_systime( 51709100258SXin LI double step 51809100258SXin LI ) 51909100258SXin LI { 52009100258SXin LI time_t pivot; /* for ntp era unfolding */ 52109100258SXin LI struct timeval timetv, tvlast; 52209100258SXin LI struct timespec timets; 52309100258SXin LI l_fp fp_ofs, fp_sys; /* offset and target system time in FP */ 52409100258SXin LI 52509100258SXin LI /* 52609100258SXin LI * Get pivot time for NTP era unfolding. Since we don't step 52709100258SXin LI * very often, we can afford to do the whole calculation from 52809100258SXin LI * scratch. And we're not in the time-critical path yet. 52909100258SXin LI */ 53009100258SXin LI #if SIZEOF_TIME_T > 4 53109100258SXin LI pivot = basedate_get_eracenter(); 53209100258SXin LI #else 53309100258SXin LI /* This makes sure the resulting time stamp is on or after 53409100258SXin LI * 1969-12-31/23:59:59 UTC and gives us additional two years, 53509100258SXin LI * from the change of NTP era in 2036 to the UNIX rollover in 53609100258SXin LI * 2038. (Minus one second, but that won't hurt.) We *really* 53709100258SXin LI * need a longer 'time_t' after that! Or a different baseline, 53809100258SXin LI * but that would cause other serious trouble, too. 53909100258SXin LI */ 54009100258SXin LI pivot = 0x7FFFFFFF; 54109100258SXin LI #endif 54209100258SXin LI 54309100258SXin LI /* get the complete jump distance as l_fp */ 54409100258SXin LI DTOLFP(sys_residual, &fp_sys); 54509100258SXin LI DTOLFP(step, &fp_ofs); 54609100258SXin LI L_ADD(&fp_ofs, &fp_sys); 54709100258SXin LI 54809100258SXin LI /* ---> time-critical path starts ---> */ 54909100258SXin LI 55009100258SXin LI /* get the current time as l_fp (without fuzz) and as struct timeval */ 55109100258SXin LI get_ostime(&timets); 55209100258SXin LI fp_sys = tspec_stamp_to_lfp(timets); 55309100258SXin LI tvlast.tv_sec = timets.tv_sec; 55409100258SXin LI tvlast.tv_usec = (timets.tv_nsec + 500) / 1000; 55509100258SXin LI 55609100258SXin LI /* get the target time as l_fp */ 55709100258SXin LI L_ADD(&fp_sys, &fp_ofs); 55809100258SXin LI 55909100258SXin LI /* unfold the new system time */ 56009100258SXin LI timetv = lfp_stamp_to_tval(fp_sys, &pivot); 56109100258SXin LI 56209100258SXin LI /* now set new system time */ 56309100258SXin LI if (ntp_set_tod(&timetv, NULL) != 0) { 56409100258SXin LI msyslog(LOG_ERR, "step-systime: %m"); 56509100258SXin LI if (enable_panic_check && allow_panic) { 56609100258SXin LI msyslog(LOG_ERR, "step_systime: allow_panic is TRUE!"); 56709100258SXin LI } 56809100258SXin LI return FALSE; 56909100258SXin LI } 57009100258SXin LI 57109100258SXin LI /* <--- time-critical path ended with 'ntp_set_tod()' <--- */ 57209100258SXin LI 57309100258SXin LI sys_residual = 0; 57409100258SXin LI lamport_violated = (step < 0); 57509100258SXin LI if (step_callback) 57609100258SXin LI (*step_callback)(); 57709100258SXin LI 57809100258SXin LI #ifdef NEED_HPUX_ADJTIME 57909100258SXin LI /* 58009100258SXin LI * CHECKME: is this correct when called by ntpdate????? 58109100258SXin LI */ 58209100258SXin LI _clear_adjtime(); 58309100258SXin LI #endif 58409100258SXin LI 58509100258SXin LI update_uwtmp(timetv, tvlast); 5863311ff84SXin LI if (enable_panic_check && allow_panic) { 5873311ff84SXin LI msyslog(LOG_ERR, "step_systime: allow_panic is TRUE!"); 5883311ff84SXin LI INSIST(!allow_panic); 5893311ff84SXin LI } 5902b15cb3dSCy Schubert return TRUE; 591c0b746e5SOllivier Robert } 5929c2daa00SOllivier Robert 593*a466cc55SCy Schubert 594*a466cc55SCy Schubert #if SIZEOF_TIME_T > 4 59509100258SXin LI static const char * 59609100258SXin LI tv_fmt_libbuf( 59709100258SXin LI const struct timeval * ptv 59809100258SXin LI ) 59909100258SXin LI { 60009100258SXin LI char * retv; 60109100258SXin LI vint64 secs; 60209100258SXin LI ntpcal_split dds; 60309100258SXin LI struct calendar jd; 60409100258SXin LI 60509100258SXin LI secs = time_to_vint64(&ptv->tv_sec); 60609100258SXin LI dds = ntpcal_daysplit(&secs); 60709100258SXin LI ntpcal_daysplit_to_date(&jd, &dds, DAY_UNIX_STARTS); 60809100258SXin LI LIB_GETBUF(retv); 60909100258SXin LI snprintf(retv, LIB_BUFLENGTH, 61009100258SXin LI "%04hu-%02hu-%02hu/%02hu:%02hu:%02hu.%06u", 61109100258SXin LI jd.year, (u_short)jd.month, (u_short)jd.monthday, 61209100258SXin LI (u_short)jd.hour, (u_short)jd.minute, (u_short)jd.second, 61309100258SXin LI (u_int)ptv->tv_usec); 61409100258SXin LI return retv; 61509100258SXin LI } 616*a466cc55SCy Schubert #endif /* SIZEOF_TIME_T > 4 */ 61709100258SXin LI 61809100258SXin LI 61909100258SXin LI int /*BOOL*/ 62009100258SXin LI clamp_systime(void) 62109100258SXin LI { 62209100258SXin LI #if SIZEOF_TIME_T > 4 62309100258SXin LI 6242d4e511cSCy Schubert struct timeval tvbase, tvlast; 62509100258SXin LI struct timespec timets; 62609100258SXin LI 6272d4e511cSCy Schubert tvbase.tv_sec = basedate_get_erabase(); 6282d4e511cSCy Schubert tvbase.tv_usec = 0; 62909100258SXin LI 63009100258SXin LI /* ---> time-critical path starts ---> */ 63109100258SXin LI 63209100258SXin LI /* get the current time as l_fp (without fuzz) and as struct timeval */ 63309100258SXin LI get_ostime(&timets); 63409100258SXin LI tvlast.tv_sec = timets.tv_sec; 63509100258SXin LI tvlast.tv_usec = (timets.tv_nsec + 500) / 1000; 63609100258SXin LI if (tvlast.tv_usec >= 1000000) { 63709100258SXin LI tvlast.tv_usec -= 1000000; 63809100258SXin LI tvlast.tv_sec += 1; 63909100258SXin LI } 64009100258SXin LI 6412d4e511cSCy Schubert if (tvbase.tv_sec > tvlast.tv_sec) { 64209100258SXin LI /* now set new system time */ 6432d4e511cSCy Schubert if (ntp_set_tod(&tvbase, NULL) != 0) { 64409100258SXin LI msyslog(LOG_ERR, "clamp-systime: %m"); 64509100258SXin LI return FALSE; 64609100258SXin LI } 64709100258SXin LI } else { 64809100258SXin LI msyslog(LOG_INFO, 64909100258SXin LI "clamp-systime: clock (%s) in allowed range", 6502d4e511cSCy Schubert tv_fmt_libbuf(&tvlast)); 65109100258SXin LI return FALSE; 65209100258SXin LI } 65309100258SXin LI 65409100258SXin LI /* <--- time-critical path ended with 'ntp_set_tod()' <--- */ 65509100258SXin LI 65609100258SXin LI sys_residual = 0; 6572d4e511cSCy Schubert lamport_violated = (tvbase.tv_sec < tvlast.tv_sec); 65809100258SXin LI if (step_callback) 65909100258SXin LI (*step_callback)(); 66009100258SXin LI 66109100258SXin LI # ifdef NEED_HPUX_ADJTIME 66209100258SXin LI /* 66309100258SXin LI * CHECKME: is this correct when called by ntpdate????? 66409100258SXin LI */ 66509100258SXin LI _clear_adjtime(); 66609100258SXin LI # endif 66709100258SXin LI 6682d4e511cSCy Schubert update_uwtmp(tvbase, tvlast); 66909100258SXin LI msyslog(LOG_WARNING, 67009100258SXin LI "clamp-systime: clock stepped from %s to %s!", 6712d4e511cSCy Schubert tv_fmt_libbuf(&tvlast), tv_fmt_libbuf(&tvbase)); 67209100258SXin LI return TRUE; 67309100258SXin LI 67409100258SXin LI #else 67509100258SXin LI 6762d4e511cSCy Schubert return FALSE; 6772d4e511cSCy Schubert 67809100258SXin LI #endif 67909100258SXin LI } 68009100258SXin LI 6812b15cb3dSCy Schubert #endif /* !SIM */ 682