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" 1909100258SXin LI #include "lib_strbuf.h" 209c2daa00SOllivier Robert 21c0b746e5SOllivier Robert #ifdef HAVE_SYS_PARAM_H 22c0b746e5SOllivier Robert # include <sys/param.h> 23c0b746e5SOllivier Robert #endif 24c0b746e5SOllivier Robert #ifdef HAVE_UTMP_H 25c0b746e5SOllivier Robert # include <utmp.h> 26c0b746e5SOllivier Robert #endif /* HAVE_UTMP_H */ 27c0b746e5SOllivier Robert #ifdef HAVE_UTMPX_H 28c0b746e5SOllivier Robert # include <utmpx.h> 29c0b746e5SOllivier Robert #endif /* HAVE_UTMPX_H */ 30c0b746e5SOllivier Robert 313311ff84SXin LI int allow_panic = FALSE; /* allow panic correction (-g) */ 323311ff84SXin LI int enable_panic_check = TRUE; /* Can we check allow_panic's state? */ 332b15cb3dSCy Schubert 3409100258SXin LI u_long sys_lamport; /* Lamport violation */ 3509100258SXin LI u_long sys_tsrounding; /* timestamp rounding errors */ 3609100258SXin LI 372b15cb3dSCy Schubert #ifndef USE_COMPILETIME_PIVOT 382b15cb3dSCy Schubert # define USE_COMPILETIME_PIVOT 1 392b15cb3dSCy Schubert #endif 402b15cb3dSCy Schubert 41c0b746e5SOllivier Robert /* 429c2daa00SOllivier Robert * These routines (get_systime, step_systime, adj_systime) implement an 439c2daa00SOllivier Robert * interface between the system independent NTP clock and the Unix 442b15cb3dSCy Schubert * system clock in various architectures and operating systems. Time is 452b15cb3dSCy Schubert * a precious quantity in these routines and every effort is made to 462b15cb3dSCy Schubert * minimize errors by unbiased rounding and amortizing adjustment 472b15cb3dSCy Schubert * residues. 489c2daa00SOllivier Robert * 492b15cb3dSCy Schubert * In order to improve the apparent resolution, provide unbiased 502b15cb3dSCy Schubert * rounding and most importantly ensure that the readings cannot be 512b15cb3dSCy Schubert * predicted, the low-order unused portion of the time below the minimum 522b15cb3dSCy Schubert * time to read the clock is filled with an unbiased random fuzz. 532b15cb3dSCy Schubert * 542b15cb3dSCy Schubert * The sys_tick variable specifies the system clock tick interval in 552b15cb3dSCy Schubert * seconds, for stepping clocks, defined as those which return times 562b15cb3dSCy Schubert * less than MINSTEP greater than the previous reading. For systems that 572b15cb3dSCy Schubert * use a high-resolution counter such that each clock reading is always 582b15cb3dSCy Schubert * at least MINSTEP greater than the prior, sys_tick is the time to read 592b15cb3dSCy Schubert * the system clock. 602b15cb3dSCy Schubert * 612b15cb3dSCy Schubert * The sys_fuzz variable measures the minimum time to read the system 622b15cb3dSCy Schubert * clock, regardless of its precision. When reading the system clock 632b15cb3dSCy Schubert * using get_systime() after sys_tick and sys_fuzz have been determined, 642b15cb3dSCy Schubert * ntpd ensures each unprocessed clock reading is no less than sys_fuzz 652b15cb3dSCy Schubert * later than the prior unprocessed reading, and then fuzzes the bits 662b15cb3dSCy Schubert * below sys_fuzz in the timestamp returned, ensuring each of its 672b15cb3dSCy Schubert * resulting readings is strictly later than the previous. 682b15cb3dSCy Schubert * 692b15cb3dSCy Schubert * When slewing the system clock using adj_systime() (with the kernel 702b15cb3dSCy Schubert * loop discipline unavailable or disabled), adjtime() offsets are 712b15cb3dSCy Schubert * quantized to sys_tick, if sys_tick is greater than sys_fuzz, which 722b15cb3dSCy Schubert * is to say if the OS presents a stepping clock. Otherwise, offsets 732b15cb3dSCy Schubert * are quantized to the microsecond resolution of adjtime()'s timeval 742b15cb3dSCy Schubert * input. The remaining correction sys_residual is carried into the 752b15cb3dSCy Schubert * next adjtime() and meanwhile is also factored into get_systime() 762b15cb3dSCy Schubert * readings. 77c0b746e5SOllivier Robert */ 782b15cb3dSCy Schubert double sys_tick = 0; /* tick size or time to read (s) */ 792b15cb3dSCy Schubert double sys_fuzz = 0; /* min. time to read the clock (s) */ 802b15cb3dSCy Schubert long sys_fuzz_nsec = 0; /* min. time to read the clock (ns) */ 812b15cb3dSCy Schubert double measured_tick; /* non-overridable sys_tick (s) */ 829c2daa00SOllivier Robert double sys_residual = 0; /* adjustment residue (s) */ 832b15cb3dSCy Schubert int trunc_os_clock; /* sys_tick > measured_tick */ 842b15cb3dSCy Schubert time_stepped_callback step_callback; 85c0b746e5SOllivier Robert 869c2daa00SOllivier Robert #ifndef SIM 872b15cb3dSCy Schubert /* perlinger@ntp.org: As 'get_sysime()' does it's own check for clock 882b15cb3dSCy Schubert * backstepping, this could probably become a local variable in 892b15cb3dSCy Schubert * 'get_systime()' and the cruft associated with communicating via a 902b15cb3dSCy Schubert * static value could be removed after the v4.2.8 release. 912b15cb3dSCy Schubert */ 922b15cb3dSCy Schubert static int lamport_violated; /* clock was stepped back */ 932b15cb3dSCy Schubert #endif /* !SIM */ 942b15cb3dSCy Schubert 952b15cb3dSCy Schubert #ifdef DEBUG 962b15cb3dSCy Schubert static int systime_init_done; 972b15cb3dSCy Schubert # define DONE_SYSTIME_INIT() systime_init_done = TRUE 982b15cb3dSCy Schubert #else 992b15cb3dSCy Schubert # define DONE_SYSTIME_INIT() do {} while (FALSE) 1002b15cb3dSCy Schubert #endif 1012b15cb3dSCy Schubert 1022b15cb3dSCy Schubert #ifdef HAVE_SIGNALED_IO 1032b15cb3dSCy Schubert int using_sigio; 1042b15cb3dSCy Schubert #endif 1052b15cb3dSCy Schubert 1062b15cb3dSCy Schubert #ifdef SYS_WINNT 1072b15cb3dSCy Schubert CRITICAL_SECTION get_systime_cs; 1082b15cb3dSCy Schubert #endif 1092b15cb3dSCy Schubert 1102b15cb3dSCy Schubert 1112b15cb3dSCy Schubert void 1122b15cb3dSCy Schubert set_sys_fuzz( 1132b15cb3dSCy Schubert double fuzz_val 1142b15cb3dSCy Schubert ) 1152b15cb3dSCy Schubert { 1162b15cb3dSCy Schubert sys_fuzz = fuzz_val; 1172b15cb3dSCy Schubert INSIST(sys_fuzz >= 0); 1182b15cb3dSCy Schubert INSIST(sys_fuzz <= 1.0); 11909100258SXin LI /* [Bug 3450] ensure nsec fuzz >= sys_fuzz to reduce chance of 12009100258SXin LI * short-falling fuzz advance 12109100258SXin LI */ 12209100258SXin LI sys_fuzz_nsec = (long)ceil(sys_fuzz * 1e9); 1232b15cb3dSCy Schubert } 1242b15cb3dSCy Schubert 1252b15cb3dSCy Schubert 1262b15cb3dSCy Schubert void 1272b15cb3dSCy Schubert init_systime(void) 1282b15cb3dSCy Schubert { 1292b15cb3dSCy Schubert INIT_GET_SYSTIME_CRITSEC(); 1302b15cb3dSCy Schubert INIT_WIN_PRECISE_TIME(); 1312b15cb3dSCy Schubert DONE_SYSTIME_INIT(); 1322b15cb3dSCy Schubert } 1332b15cb3dSCy Schubert 1342b15cb3dSCy Schubert 1352b15cb3dSCy Schubert #ifndef SIM /* ntpsim.c has get_systime() and friends for sim */ 1362b15cb3dSCy Schubert 1372b15cb3dSCy Schubert static inline void 1382b15cb3dSCy Schubert get_ostime( 1392b15cb3dSCy Schubert struct timespec * tsp 1402b15cb3dSCy Schubert ) 1412b15cb3dSCy Schubert { 1422b15cb3dSCy Schubert int rc; 1432b15cb3dSCy Schubert long ticks; 1442b15cb3dSCy Schubert 1452b15cb3dSCy Schubert #if defined(HAVE_CLOCK_GETTIME) 1462b15cb3dSCy Schubert rc = clock_gettime(CLOCK_REALTIME, tsp); 1472b15cb3dSCy Schubert #elif defined(HAVE_GETCLOCK) 1482b15cb3dSCy Schubert rc = getclock(TIMEOFDAY, tsp); 1492b15cb3dSCy Schubert #else 1502b15cb3dSCy Schubert struct timeval tv; 1512b15cb3dSCy Schubert 1522b15cb3dSCy Schubert rc = GETTIMEOFDAY(&tv, NULL); 1532b15cb3dSCy Schubert tsp->tv_sec = tv.tv_sec; 1542b15cb3dSCy Schubert tsp->tv_nsec = tv.tv_usec * 1000; 1552b15cb3dSCy Schubert #endif 1562b15cb3dSCy Schubert if (rc < 0) { 1572b15cb3dSCy Schubert msyslog(LOG_ERR, "read system clock failed: %m (%d)", 1582b15cb3dSCy Schubert errno); 1592b15cb3dSCy Schubert exit(1); 1602b15cb3dSCy Schubert } 1612b15cb3dSCy Schubert 1622b15cb3dSCy Schubert if (trunc_os_clock) { 1632b15cb3dSCy Schubert ticks = (long)((tsp->tv_nsec * 1e-9) / sys_tick); 1642b15cb3dSCy Schubert tsp->tv_nsec = (long)(ticks * 1e9 * sys_tick); 1652b15cb3dSCy Schubert } 1662b15cb3dSCy Schubert } 1672b15cb3dSCy Schubert 168c0b746e5SOllivier Robert 169c0b746e5SOllivier Robert /* 1709c2daa00SOllivier Robert * get_systime - return system time in NTP timestamp format. 171c0b746e5SOllivier Robert */ 172c0b746e5SOllivier Robert void 173c0b746e5SOllivier Robert get_systime( 1749c2daa00SOllivier Robert l_fp *now /* system time */ 175c0b746e5SOllivier Robert ) 176c0b746e5SOllivier Robert { 1772b15cb3dSCy Schubert static struct timespec ts_last; /* last sampled os time */ 1782b15cb3dSCy Schubert static struct timespec ts_prev; /* prior os time */ 1792b15cb3dSCy Schubert static l_fp lfp_prev; /* prior result */ 1809c2daa00SOllivier Robert struct timespec ts; /* seconds and nanoseconds */ 1812b15cb3dSCy Schubert struct timespec ts_min; /* earliest permissible */ 1822b15cb3dSCy Schubert struct timespec ts_lam; /* lamport fictional increment */ 1832b15cb3dSCy Schubert double dfuzz; 1842b15cb3dSCy Schubert l_fp result; 1852b15cb3dSCy Schubert l_fp lfpfuzz; 1862b15cb3dSCy Schubert l_fp lfpdelta; 1879c2daa00SOllivier Robert 1882b15cb3dSCy Schubert get_ostime(&ts); 1892b15cb3dSCy Schubert DEBUG_REQUIRE(systime_init_done); 1902b15cb3dSCy Schubert ENTER_GET_SYSTIME_CRITSEC(); 1912b15cb3dSCy Schubert 1922b15cb3dSCy Schubert /* First check if here was a Lamport violation, that is, two 1932b15cb3dSCy Schubert * successive calls to 'get_ostime()' resulted in negative 1942b15cb3dSCy Schubert * time difference. Use a few milliseconds of permissible 1952b15cb3dSCy Schubert * tolerance -- being too sharp can hurt here. (This is intented 1962b15cb3dSCy Schubert * for the Win32 target, where the HPC interpolation might 1972b15cb3dSCy Schubert * introduce small steps backward. It should not be an issue on 1982b15cb3dSCy Schubert * systems where get_ostime() results in a true syscall.) 1999c2daa00SOllivier Robert */ 20009100258SXin LI if (cmp_tspec(add_tspec_ns(ts, 50000000), ts_last) < 0) { 2012b15cb3dSCy Schubert lamport_violated = 1; 20209100258SXin LI sys_lamport++; 20309100258SXin LI } 2042b15cb3dSCy Schubert ts_last = ts; 2059c2daa00SOllivier Robert 2069c2daa00SOllivier Robert /* 2072b15cb3dSCy Schubert * After default_get_precision() has set a nonzero sys_fuzz, 2082b15cb3dSCy Schubert * ensure every reading of the OS clock advances by at least 2092b15cb3dSCy Schubert * sys_fuzz over the prior reading, thereby assuring each 2102b15cb3dSCy Schubert * fuzzed result is strictly later than the prior. Limit the 2112b15cb3dSCy Schubert * necessary fiction to 1 second. 2129c2daa00SOllivier Robert */ 2132b15cb3dSCy Schubert if (!USING_SIGIO()) { 2142b15cb3dSCy Schubert ts_min = add_tspec_ns(ts_prev, sys_fuzz_nsec); 2152b15cb3dSCy Schubert if (cmp_tspec(ts, ts_min) < 0) { 2162b15cb3dSCy Schubert ts_lam = sub_tspec(ts_min, ts); 2172b15cb3dSCy Schubert if (ts_lam.tv_sec > 0 && !lamport_violated) { 2182b15cb3dSCy Schubert msyslog(LOG_ERR, 2192b15cb3dSCy Schubert "get_systime Lamport advance exceeds one second (%.9f)", 2202b15cb3dSCy Schubert ts_lam.tv_sec + 2212b15cb3dSCy Schubert 1e-9 * ts_lam.tv_nsec); 2222b15cb3dSCy Schubert exit(1); 2232b15cb3dSCy Schubert } 2242b15cb3dSCy Schubert if (!lamport_violated) 2252b15cb3dSCy Schubert ts = ts_min; 2262b15cb3dSCy Schubert } 2272b15cb3dSCy Schubert ts_prev = ts; 2282b15cb3dSCy Schubert } 2299c2daa00SOllivier Robert 2302b15cb3dSCy Schubert /* convert from timespec to l_fp fixed-point */ 2312b15cb3dSCy Schubert result = tspec_stamp_to_lfp(ts); 2329c2daa00SOllivier Robert 2339c2daa00SOllivier Robert /* 23409100258SXin LI * Add in the fuzz. 'ntp_random()' returns [0..2**31-1] so we 23509100258SXin LI * must scale up the result by 2.0 to cover the full fractional 23609100258SXin LI * range. 2372b15cb3dSCy Schubert */ 238*a466cc55SCy Schubert dfuzz = ntp_uurandom() * sys_fuzz; 2392b15cb3dSCy Schubert DTOLFP(dfuzz, &lfpfuzz); 2402b15cb3dSCy Schubert L_ADD(&result, &lfpfuzz); 2412b15cb3dSCy Schubert 2422b15cb3dSCy Schubert /* 2432b15cb3dSCy Schubert * Ensure result is strictly greater than prior result (ignoring 2442b15cb3dSCy Schubert * sys_residual's effect for now) once sys_fuzz has been 245ea906c41SOllivier Robert * determined. 24609100258SXin LI * 24709100258SXin LI * [Bug 3450] Rounding errors and time slew can lead to a 24809100258SXin LI * violation of the expected postcondition. This is bound to 24909100258SXin LI * happen from time to time (depending on state of the random 25009100258SXin LI * generator, the current slew and the closeness of system time 25109100258SXin LI * stamps drawn) and does not warrant a syslog entry. Instead it 25209100258SXin LI * makes much more sense to ensure the postcondition and hop 25309100258SXin LI * along silently. 254ea906c41SOllivier Robert */ 2552b15cb3dSCy Schubert if (!USING_SIGIO()) { 25609100258SXin LI if ( !L_ISZERO(&lfp_prev) 25709100258SXin LI && !lamport_violated 25809100258SXin LI && (sys_fuzz > 0.0) 25909100258SXin LI ) { 26009100258SXin LI lfpdelta = result; 26109100258SXin LI L_SUB(&lfpdelta, &lfp_prev); 26209100258SXin LI L_SUBUF(&lfpdelta, 1); 26309100258SXin LI if (lfpdelta.l_i < 0) 26409100258SXin LI { 26509100258SXin LI L_NEG(&lfpdelta); 26609100258SXin LI DPRINTF(1, ("get_systime: postcond failed by %s secs, fixed\n", 26709100258SXin LI lfptoa(&lfpdelta, 9))); 26809100258SXin LI result = lfp_prev; 26909100258SXin LI L_ADDUF(&result, 1); 27009100258SXin LI sys_tsrounding++; 271c0b746e5SOllivier Robert } 2722b15cb3dSCy Schubert } 2732b15cb3dSCy Schubert lfp_prev = result; 2742b15cb3dSCy Schubert if (lamport_violated) 2752b15cb3dSCy Schubert lamport_violated = FALSE; 2762b15cb3dSCy Schubert } 2772b15cb3dSCy Schubert LEAVE_GET_SYSTIME_CRITSEC(); 2782b15cb3dSCy Schubert *now = result; 279c0b746e5SOllivier Robert } 280c0b746e5SOllivier Robert 281c0b746e5SOllivier Robert 282c0b746e5SOllivier Robert /* 2839c2daa00SOllivier Robert * adj_systime - adjust system time by the argument. 284c0b746e5SOllivier Robert */ 285a151a66cSOllivier Robert #if !defined SYS_WINNT 2869c2daa00SOllivier Robert int /* 0 okay, 1 error */ 287c0b746e5SOllivier Robert adj_systime( 2889c2daa00SOllivier Robert double now /* adjustment (s) */ 289c0b746e5SOllivier Robert ) 290c0b746e5SOllivier Robert { 2919c2daa00SOllivier Robert struct timeval adjtv; /* new adjustment */ 2929c2daa00SOllivier Robert struct timeval oadjtv; /* residual adjustment */ 2932b15cb3dSCy Schubert double quant; /* quantize to multiples of */ 294c0b746e5SOllivier Robert double dtemp; 2959c2daa00SOllivier Robert long ticks; 2969c2daa00SOllivier Robert int isneg = 0; 297c0b746e5SOllivier Robert 298c0b746e5SOllivier Robert /* 2992b15cb3dSCy Schubert * The Windows port adj_systime() depends on being called each 3002b15cb3dSCy Schubert * second even when there's no additional correction, to allow 3012b15cb3dSCy Schubert * emulation of adjtime() behavior on top of an API that simply 3022b15cb3dSCy Schubert * sets the current rate. This POSIX implementation needs to 3032b15cb3dSCy Schubert * ignore invocations with zero correction, otherwise ongoing 3042b15cb3dSCy Schubert * EVNT_NSET adjtime() can be aborted by a tiny adjtime() 3052b15cb3dSCy Schubert * triggered by sys_residual. 3062b15cb3dSCy Schubert */ 3073311ff84SXin LI if (0. == now) { 3083311ff84SXin LI if (enable_panic_check && allow_panic) { 3093311ff84SXin LI msyslog(LOG_ERR, "adj_systime: allow_panic is TRUE!"); 3103311ff84SXin LI INSIST(!allow_panic); 3113311ff84SXin LI } 3122b15cb3dSCy Schubert return TRUE; 3133311ff84SXin LI } 3142b15cb3dSCy Schubert 3152b15cb3dSCy Schubert /* 3169c2daa00SOllivier Robert * Most Unix adjtime() implementations adjust the system clock 3179c2daa00SOllivier Robert * in microsecond quanta, but some adjust in 10-ms quanta. We 3189c2daa00SOllivier Robert * carefully round the adjustment to the nearest quantum, then 3199c2daa00SOllivier Robert * adjust in quanta and keep the residue for later. 320c0b746e5SOllivier Robert */ 3219c2daa00SOllivier Robert dtemp = now + sys_residual; 322c0b746e5SOllivier Robert if (dtemp < 0) { 323c0b746e5SOllivier Robert isneg = 1; 324c0b746e5SOllivier Robert dtemp = -dtemp; 325c0b746e5SOllivier Robert } 3269c2daa00SOllivier Robert adjtv.tv_sec = (long)dtemp; 3279c2daa00SOllivier Robert dtemp -= adjtv.tv_sec; 3282b15cb3dSCy Schubert if (sys_tick > sys_fuzz) 3292b15cb3dSCy Schubert quant = sys_tick; 3302b15cb3dSCy Schubert else 3312b15cb3dSCy Schubert quant = 1e-6; 3322b15cb3dSCy Schubert ticks = (long)(dtemp / quant + .5); 33368ba7e87SXin LI adjtv.tv_usec = (long)(ticks * quant * 1.e6 + .5); 33468ba7e87SXin LI /* The rounding in the conversions could us push over the 33568ba7e87SXin LI * limits: make sure the result is properly normalised! 33668ba7e87SXin LI * note: sign comes later, all numbers non-negative here. 33768ba7e87SXin LI */ 33868ba7e87SXin LI if (adjtv.tv_usec >= 1000000) { 33968ba7e87SXin LI adjtv.tv_sec += 1; 34068ba7e87SXin LI adjtv.tv_usec -= 1000000; 34168ba7e87SXin LI dtemp -= 1.; 34268ba7e87SXin LI } 34368ba7e87SXin LI /* set the new residual with leftover from correction */ 34468ba7e87SXin LI sys_residual = dtemp - adjtv.tv_usec * 1.e-6; 345c0b746e5SOllivier Robert 346c0b746e5SOllivier Robert /* 3479c2daa00SOllivier Robert * Convert to signed seconds and microseconds for the Unix 3489c2daa00SOllivier Robert * adjtime() system call. Note we purposely lose the adjtime() 3499c2daa00SOllivier Robert * leftover. 350c0b746e5SOllivier Robert */ 3519c2daa00SOllivier Robert if (isneg) { 3529c2daa00SOllivier Robert adjtv.tv_sec = -adjtv.tv_sec; 3539c2daa00SOllivier Robert adjtv.tv_usec = -adjtv.tv_usec; 354ea906c41SOllivier Robert sys_residual = -sys_residual; 355c0b746e5SOllivier Robert } 356ea906c41SOllivier Robert if (adjtv.tv_sec != 0 || adjtv.tv_usec != 0) { 3579c2daa00SOllivier Robert if (adjtime(&adjtv, &oadjtv) < 0) { 3589c2daa00SOllivier Robert msyslog(LOG_ERR, "adj_systime: %m"); 3593311ff84SXin LI if (enable_panic_check && allow_panic) { 3603311ff84SXin LI msyslog(LOG_ERR, "adj_systime: allow_panic is TRUE!"); 3613311ff84SXin LI } 3622b15cb3dSCy Schubert return FALSE; 363c0b746e5SOllivier Robert } 364ea906c41SOllivier Robert } 3653311ff84SXin LI if (enable_panic_check && allow_panic) { 3663311ff84SXin LI msyslog(LOG_ERR, "adj_systime: allow_panic is TRUE!"); 3673311ff84SXin LI } 3682b15cb3dSCy Schubert return TRUE; 369c0b746e5SOllivier Robert } 370a151a66cSOllivier Robert #endif 371c0b746e5SOllivier Robert 372c0b746e5SOllivier Robert /* 37309100258SXin LI * helper to keep utmp/wtmp up to date 374c0b746e5SOllivier Robert */ 37509100258SXin LI static void 37609100258SXin LI update_uwtmp( 37709100258SXin LI struct timeval timetv, 37809100258SXin LI struct timeval tvlast 379c0b746e5SOllivier Robert ) 380c0b746e5SOllivier Robert { 38109100258SXin LI struct timeval tvdiff; 382c0b746e5SOllivier Robert /* 383c0b746e5SOllivier Robert * FreeBSD, for example, has: 384c0b746e5SOllivier Robert * struct utmp { 385c0b746e5SOllivier Robert * char ut_line[UT_LINESIZE]; 386c0b746e5SOllivier Robert * char ut_name[UT_NAMESIZE]; 387c0b746e5SOllivier Robert * char ut_host[UT_HOSTSIZE]; 388c0b746e5SOllivier Robert * long ut_time; 389c0b746e5SOllivier Robert * }; 390c0b746e5SOllivier Robert * and appends line="|", name="date", host="", time for the OLD 3913311ff84SXin LI * and appends line="{", name="date", host="", time for the NEW // } 392c0b746e5SOllivier Robert * to _PATH_WTMP . 393c0b746e5SOllivier Robert * 394c0b746e5SOllivier Robert * Some OSes have utmp, some have utmpx. 395c0b746e5SOllivier Robert */ 396c0b746e5SOllivier Robert 397c0b746e5SOllivier Robert /* 3989c2daa00SOllivier Robert * Write old and new time entries in utmp and wtmp if step 3999c2daa00SOllivier Robert * adjustment is greater than one second. 400c0b746e5SOllivier Robert * 401c0b746e5SOllivier Robert * This might become even Uglier... 402c0b746e5SOllivier Robert */ 4032b15cb3dSCy Schubert tvdiff = abs_tval(sub_tval(timetv, tvlast)); 4042b15cb3dSCy Schubert if (tvdiff.tv_sec > 0) { 405c0b746e5SOllivier Robert #ifdef HAVE_UTMP_H 406c0b746e5SOllivier Robert struct utmp ut; 407c0b746e5SOllivier Robert #endif 408c0b746e5SOllivier Robert #ifdef HAVE_UTMPX_H 409c0b746e5SOllivier Robert struct utmpx utx; 410c0b746e5SOllivier Robert #endif 411c0b746e5SOllivier Robert 412c0b746e5SOllivier Robert #ifdef HAVE_UTMP_H 4132b15cb3dSCy Schubert ZERO(ut); 414c0b746e5SOllivier Robert #endif 415c0b746e5SOllivier Robert #ifdef HAVE_UTMPX_H 4162b15cb3dSCy Schubert ZERO(utx); 417c0b746e5SOllivier Robert #endif 418c0b746e5SOllivier Robert 419c0b746e5SOllivier Robert /* UTMP */ 420c0b746e5SOllivier Robert 421c0b746e5SOllivier Robert #ifdef UPDATE_UTMP 422c0b746e5SOllivier Robert # ifdef HAVE_PUTUTLINE 4232b15cb3dSCy Schubert # ifndef _PATH_UTMP 4242b15cb3dSCy Schubert # define _PATH_UTMP UTMP_FILE 4252b15cb3dSCy Schubert # endif 4262b15cb3dSCy Schubert utmpname(_PATH_UTMP); 427c0b746e5SOllivier Robert ut.ut_type = OLD_TIME; 4282b15cb3dSCy Schubert strlcpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line)); 4292b15cb3dSCy Schubert ut.ut_time = tvlast.tv_sec; 430c0b746e5SOllivier Robert setutent(); 4312b15cb3dSCy Schubert pututline(&ut); 432c0b746e5SOllivier Robert ut.ut_type = NEW_TIME; 4332b15cb3dSCy Schubert strlcpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line)); 434c0b746e5SOllivier Robert ut.ut_time = timetv.tv_sec; 4352b15cb3dSCy Schubert setutent(); 436c0b746e5SOllivier Robert pututline(&ut); 437c0b746e5SOllivier Robert endutent(); 438c0b746e5SOllivier Robert # else /* not HAVE_PUTUTLINE */ 439c0b746e5SOllivier Robert # endif /* not HAVE_PUTUTLINE */ 440c0b746e5SOllivier Robert #endif /* UPDATE_UTMP */ 441c0b746e5SOllivier Robert 442c0b746e5SOllivier Robert /* UTMPX */ 443c0b746e5SOllivier Robert 444c0b746e5SOllivier Robert #ifdef UPDATE_UTMPX 445c0b746e5SOllivier Robert # ifdef HAVE_PUTUTXLINE 446c0b746e5SOllivier Robert utx.ut_type = OLD_TIME; 4472b15cb3dSCy Schubert strlcpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line)); 4482b15cb3dSCy Schubert utx.ut_tv = tvlast; 449c0b746e5SOllivier Robert setutxent(); 4502b15cb3dSCy Schubert pututxline(&utx); 451c0b746e5SOllivier Robert utx.ut_type = NEW_TIME; 4522b15cb3dSCy Schubert strlcpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line)); 453c0b746e5SOllivier Robert utx.ut_tv = timetv; 4542b15cb3dSCy Schubert setutxent(); 455c0b746e5SOllivier Robert pututxline(&utx); 456c0b746e5SOllivier Robert endutxent(); 457c0b746e5SOllivier Robert # else /* not HAVE_PUTUTXLINE */ 458c0b746e5SOllivier Robert # endif /* not HAVE_PUTUTXLINE */ 459c0b746e5SOllivier Robert #endif /* UPDATE_UTMPX */ 460c0b746e5SOllivier Robert 461c0b746e5SOllivier Robert /* WTMP */ 462c0b746e5SOllivier Robert 463c0b746e5SOllivier Robert #ifdef UPDATE_WTMP 464c0b746e5SOllivier Robert # ifdef HAVE_PUTUTLINE 4652b15cb3dSCy Schubert # ifndef _PATH_WTMP 4662b15cb3dSCy Schubert # define _PATH_WTMP WTMP_FILE 4672b15cb3dSCy Schubert # endif 4682b15cb3dSCy Schubert utmpname(_PATH_WTMP); 469c0b746e5SOllivier Robert ut.ut_type = OLD_TIME; 4702b15cb3dSCy Schubert strlcpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line)); 4712b15cb3dSCy Schubert ut.ut_time = tvlast.tv_sec; 4722b15cb3dSCy Schubert setutent(); 473c0b746e5SOllivier Robert pututline(&ut); 474c0b746e5SOllivier Robert ut.ut_type = NEW_TIME; 4752b15cb3dSCy Schubert strlcpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line)); 476c0b746e5SOllivier Robert ut.ut_time = timetv.tv_sec; 4772b15cb3dSCy Schubert setutent(); 478c0b746e5SOllivier Robert pututline(&ut); 479c0b746e5SOllivier Robert endutent(); 480c0b746e5SOllivier Robert # else /* not HAVE_PUTUTLINE */ 481c0b746e5SOllivier Robert # endif /* not HAVE_PUTUTLINE */ 482c0b746e5SOllivier Robert #endif /* UPDATE_WTMP */ 483c0b746e5SOllivier Robert 484c0b746e5SOllivier Robert /* WTMPX */ 485c0b746e5SOllivier Robert 486c0b746e5SOllivier Robert #ifdef UPDATE_WTMPX 487c0b746e5SOllivier Robert # ifdef HAVE_PUTUTXLINE 488c0b746e5SOllivier Robert utx.ut_type = OLD_TIME; 4892b15cb3dSCy Schubert utx.ut_tv = tvlast; 4902b15cb3dSCy Schubert strlcpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line)); 491c0b746e5SOllivier Robert # ifdef HAVE_UPDWTMPX 492c0b746e5SOllivier Robert updwtmpx(WTMPX_FILE, &utx); 493c0b746e5SOllivier Robert # else /* not HAVE_UPDWTMPX */ 494c0b746e5SOllivier Robert # endif /* not HAVE_UPDWTMPX */ 495c0b746e5SOllivier Robert # else /* not HAVE_PUTUTXLINE */ 496c0b746e5SOllivier Robert # endif /* not HAVE_PUTUTXLINE */ 497c0b746e5SOllivier Robert # ifdef HAVE_PUTUTXLINE 498c0b746e5SOllivier Robert utx.ut_type = NEW_TIME; 499c0b746e5SOllivier Robert utx.ut_tv = timetv; 5002b15cb3dSCy Schubert strlcpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line)); 501c0b746e5SOllivier Robert # ifdef HAVE_UPDWTMPX 502c0b746e5SOllivier Robert updwtmpx(WTMPX_FILE, &utx); 503c0b746e5SOllivier Robert # else /* not HAVE_UPDWTMPX */ 504c0b746e5SOllivier Robert # endif /* not HAVE_UPDWTMPX */ 505c0b746e5SOllivier Robert # else /* not HAVE_PUTUTXLINE */ 506c0b746e5SOllivier Robert # endif /* not HAVE_PUTUTXLINE */ 507c0b746e5SOllivier Robert #endif /* UPDATE_WTMPX */ 508c0b746e5SOllivier Robert 509c0b746e5SOllivier Robert } 51009100258SXin LI } 51109100258SXin LI 51209100258SXin LI /* 51309100258SXin LI * step_systime - step the system clock. 51409100258SXin LI */ 51509100258SXin LI 51609100258SXin LI int 51709100258SXin LI step_systime( 51809100258SXin LI double step 51909100258SXin LI ) 52009100258SXin LI { 52109100258SXin LI time_t pivot; /* for ntp era unfolding */ 52209100258SXin LI struct timeval timetv, tvlast; 52309100258SXin LI struct timespec timets; 52409100258SXin LI l_fp fp_ofs, fp_sys; /* offset and target system time in FP */ 52509100258SXin LI 52609100258SXin LI /* 52709100258SXin LI * Get pivot time for NTP era unfolding. Since we don't step 52809100258SXin LI * very often, we can afford to do the whole calculation from 52909100258SXin LI * scratch. And we're not in the time-critical path yet. 53009100258SXin LI */ 53109100258SXin LI #if SIZEOF_TIME_T > 4 53209100258SXin LI pivot = basedate_get_eracenter(); 53309100258SXin LI #else 53409100258SXin LI /* This makes sure the resulting time stamp is on or after 53509100258SXin LI * 1969-12-31/23:59:59 UTC and gives us additional two years, 53609100258SXin LI * from the change of NTP era in 2036 to the UNIX rollover in 53709100258SXin LI * 2038. (Minus one second, but that won't hurt.) We *really* 53809100258SXin LI * need a longer 'time_t' after that! Or a different baseline, 53909100258SXin LI * but that would cause other serious trouble, too. 54009100258SXin LI */ 54109100258SXin LI pivot = 0x7FFFFFFF; 54209100258SXin LI #endif 54309100258SXin LI 54409100258SXin LI /* get the complete jump distance as l_fp */ 54509100258SXin LI DTOLFP(sys_residual, &fp_sys); 54609100258SXin LI DTOLFP(step, &fp_ofs); 54709100258SXin LI L_ADD(&fp_ofs, &fp_sys); 54809100258SXin LI 54909100258SXin LI /* ---> time-critical path starts ---> */ 55009100258SXin LI 55109100258SXin LI /* get the current time as l_fp (without fuzz) and as struct timeval */ 55209100258SXin LI get_ostime(&timets); 55309100258SXin LI fp_sys = tspec_stamp_to_lfp(timets); 55409100258SXin LI tvlast.tv_sec = timets.tv_sec; 55509100258SXin LI tvlast.tv_usec = (timets.tv_nsec + 500) / 1000; 55609100258SXin LI 55709100258SXin LI /* get the target time as l_fp */ 55809100258SXin LI L_ADD(&fp_sys, &fp_ofs); 55909100258SXin LI 56009100258SXin LI /* unfold the new system time */ 56109100258SXin LI timetv = lfp_stamp_to_tval(fp_sys, &pivot); 56209100258SXin LI 56309100258SXin LI /* now set new system time */ 56409100258SXin LI if (ntp_set_tod(&timetv, NULL) != 0) { 56509100258SXin LI msyslog(LOG_ERR, "step-systime: %m"); 56609100258SXin LI if (enable_panic_check && allow_panic) { 56709100258SXin LI msyslog(LOG_ERR, "step_systime: allow_panic is TRUE!"); 56809100258SXin LI } 56909100258SXin LI return FALSE; 57009100258SXin LI } 57109100258SXin LI 57209100258SXin LI /* <--- time-critical path ended with 'ntp_set_tod()' <--- */ 57309100258SXin LI 57409100258SXin LI sys_residual = 0; 57509100258SXin LI lamport_violated = (step < 0); 57609100258SXin LI if (step_callback) 57709100258SXin LI (*step_callback)(); 57809100258SXin LI 57909100258SXin LI #ifdef NEED_HPUX_ADJTIME 58009100258SXin LI /* 58109100258SXin LI * CHECKME: is this correct when called by ntpdate????? 58209100258SXin LI */ 58309100258SXin LI _clear_adjtime(); 58409100258SXin LI #endif 58509100258SXin LI 58609100258SXin LI update_uwtmp(timetv, tvlast); 5873311ff84SXin LI if (enable_panic_check && allow_panic) { 5883311ff84SXin LI msyslog(LOG_ERR, "step_systime: allow_panic is TRUE!"); 5893311ff84SXin LI INSIST(!allow_panic); 5903311ff84SXin LI } 5912b15cb3dSCy Schubert return TRUE; 592c0b746e5SOllivier Robert } 5939c2daa00SOllivier Robert 594*a466cc55SCy Schubert 595*a466cc55SCy Schubert #if SIZEOF_TIME_T > 4 59609100258SXin LI static const char * 59709100258SXin LI tv_fmt_libbuf( 59809100258SXin LI const struct timeval * ptv 59909100258SXin LI ) 60009100258SXin LI { 60109100258SXin LI char * retv; 60209100258SXin LI vint64 secs; 60309100258SXin LI ntpcal_split dds; 60409100258SXin LI struct calendar jd; 60509100258SXin LI 60609100258SXin LI secs = time_to_vint64(&ptv->tv_sec); 60709100258SXin LI dds = ntpcal_daysplit(&secs); 60809100258SXin LI ntpcal_daysplit_to_date(&jd, &dds, DAY_UNIX_STARTS); 60909100258SXin LI LIB_GETBUF(retv); 61009100258SXin LI snprintf(retv, LIB_BUFLENGTH, 61109100258SXin LI "%04hu-%02hu-%02hu/%02hu:%02hu:%02hu.%06u", 61209100258SXin LI jd.year, (u_short)jd.month, (u_short)jd.monthday, 61309100258SXin LI (u_short)jd.hour, (u_short)jd.minute, (u_short)jd.second, 61409100258SXin LI (u_int)ptv->tv_usec); 61509100258SXin LI return retv; 61609100258SXin LI } 617*a466cc55SCy Schubert #endif /* SIZEOF_TIME_T > 4 */ 61809100258SXin LI 61909100258SXin LI 62009100258SXin LI int /*BOOL*/ 62109100258SXin LI clamp_systime(void) 62209100258SXin LI { 62309100258SXin LI #if SIZEOF_TIME_T > 4 62409100258SXin LI 6252d4e511cSCy Schubert struct timeval tvbase, tvlast; 62609100258SXin LI struct timespec timets; 62709100258SXin LI 6282d4e511cSCy Schubert tvbase.tv_sec = basedate_get_erabase(); 6292d4e511cSCy Schubert tvbase.tv_usec = 0; 63009100258SXin LI 63109100258SXin LI /* ---> time-critical path starts ---> */ 63209100258SXin LI 63309100258SXin LI /* get the current time as l_fp (without fuzz) and as struct timeval */ 63409100258SXin LI get_ostime(&timets); 63509100258SXin LI tvlast.tv_sec = timets.tv_sec; 63609100258SXin LI tvlast.tv_usec = (timets.tv_nsec + 500) / 1000; 63709100258SXin LI if (tvlast.tv_usec >= 1000000) { 63809100258SXin LI tvlast.tv_usec -= 1000000; 63909100258SXin LI tvlast.tv_sec += 1; 64009100258SXin LI } 64109100258SXin LI 6422d4e511cSCy Schubert if (tvbase.tv_sec > tvlast.tv_sec) { 64309100258SXin LI /* now set new system time */ 6442d4e511cSCy Schubert if (ntp_set_tod(&tvbase, NULL) != 0) { 64509100258SXin LI msyslog(LOG_ERR, "clamp-systime: %m"); 64609100258SXin LI return FALSE; 64709100258SXin LI } 64809100258SXin LI } else { 64909100258SXin LI msyslog(LOG_INFO, 65009100258SXin LI "clamp-systime: clock (%s) in allowed range", 6512d4e511cSCy Schubert tv_fmt_libbuf(&tvlast)); 65209100258SXin LI return FALSE; 65309100258SXin LI } 65409100258SXin LI 65509100258SXin LI /* <--- time-critical path ended with 'ntp_set_tod()' <--- */ 65609100258SXin LI 65709100258SXin LI sys_residual = 0; 6582d4e511cSCy Schubert lamport_violated = (tvbase.tv_sec < tvlast.tv_sec); 65909100258SXin LI if (step_callback) 66009100258SXin LI (*step_callback)(); 66109100258SXin LI 66209100258SXin LI # ifdef NEED_HPUX_ADJTIME 66309100258SXin LI /* 66409100258SXin LI * CHECKME: is this correct when called by ntpdate????? 66509100258SXin LI */ 66609100258SXin LI _clear_adjtime(); 66709100258SXin LI # endif 66809100258SXin LI 6692d4e511cSCy Schubert update_uwtmp(tvbase, tvlast); 67009100258SXin LI msyslog(LOG_WARNING, 67109100258SXin LI "clamp-systime: clock stepped from %s to %s!", 6722d4e511cSCy Schubert tv_fmt_libbuf(&tvlast), tv_fmt_libbuf(&tvbase)); 67309100258SXin LI return TRUE; 67409100258SXin LI 67509100258SXin LI #else 67609100258SXin LI 6772d4e511cSCy Schubert return FALSE; 6782d4e511cSCy Schubert 67909100258SXin LI #endif 68009100258SXin LI } 68109100258SXin LI 6822b15cb3dSCy Schubert #endif /* !SIM */ 683