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> 82b15cb3dSCy Schubert 92b15cb3dSCy Schubert #include "ntp.h" 10224ba2bdSOllivier Robert #include "ntp_syslog.h" 11224ba2bdSOllivier Robert #include "ntp_stdlib.h" 12ea906c41SOllivier Robert #include "ntp_random.h" 132b15cb3dSCy Schubert #include "iosignal.h" 142b15cb3dSCy Schubert #include "timevalops.h" 152b15cb3dSCy Schubert #include "timespecops.h" 162b15cb3dSCy Schubert #include "ntp_calendar.h" 179c2daa00SOllivier Robert 18c0b746e5SOllivier Robert #ifdef HAVE_SYS_PARAM_H 19c0b746e5SOllivier Robert # include <sys/param.h> 20c0b746e5SOllivier Robert #endif 21c0b746e5SOllivier Robert #ifdef HAVE_UTMP_H 22c0b746e5SOllivier Robert # include <utmp.h> 23c0b746e5SOllivier Robert #endif /* HAVE_UTMP_H */ 24c0b746e5SOllivier Robert #ifdef HAVE_UTMPX_H 25c0b746e5SOllivier Robert # include <utmpx.h> 26c0b746e5SOllivier Robert #endif /* HAVE_UTMPX_H */ 27c0b746e5SOllivier Robert 28*3311ff84SXin LI int allow_panic = FALSE; /* allow panic correction (-g) */ 29*3311ff84SXin LI int enable_panic_check = TRUE; /* Can we check allow_panic's state? */ 302b15cb3dSCy Schubert 312b15cb3dSCy Schubert #ifndef USE_COMPILETIME_PIVOT 322b15cb3dSCy Schubert # define USE_COMPILETIME_PIVOT 1 332b15cb3dSCy Schubert #endif 342b15cb3dSCy Schubert 35c0b746e5SOllivier Robert /* 369c2daa00SOllivier Robert * These routines (get_systime, step_systime, adj_systime) implement an 379c2daa00SOllivier Robert * interface between the system independent NTP clock and the Unix 382b15cb3dSCy Schubert * system clock in various architectures and operating systems. Time is 392b15cb3dSCy Schubert * a precious quantity in these routines and every effort is made to 402b15cb3dSCy Schubert * minimize errors by unbiased rounding and amortizing adjustment 412b15cb3dSCy Schubert * residues. 429c2daa00SOllivier Robert * 432b15cb3dSCy Schubert * In order to improve the apparent resolution, provide unbiased 442b15cb3dSCy Schubert * rounding and most importantly ensure that the readings cannot be 452b15cb3dSCy Schubert * predicted, the low-order unused portion of the time below the minimum 462b15cb3dSCy Schubert * time to read the clock is filled with an unbiased random fuzz. 472b15cb3dSCy Schubert * 482b15cb3dSCy Schubert * The sys_tick variable specifies the system clock tick interval in 492b15cb3dSCy Schubert * seconds, for stepping clocks, defined as those which return times 502b15cb3dSCy Schubert * less than MINSTEP greater than the previous reading. For systems that 512b15cb3dSCy Schubert * use a high-resolution counter such that each clock reading is always 522b15cb3dSCy Schubert * at least MINSTEP greater than the prior, sys_tick is the time to read 532b15cb3dSCy Schubert * the system clock. 542b15cb3dSCy Schubert * 552b15cb3dSCy Schubert * The sys_fuzz variable measures the minimum time to read the system 562b15cb3dSCy Schubert * clock, regardless of its precision. When reading the system clock 572b15cb3dSCy Schubert * using get_systime() after sys_tick and sys_fuzz have been determined, 582b15cb3dSCy Schubert * ntpd ensures each unprocessed clock reading is no less than sys_fuzz 592b15cb3dSCy Schubert * later than the prior unprocessed reading, and then fuzzes the bits 602b15cb3dSCy Schubert * below sys_fuzz in the timestamp returned, ensuring each of its 612b15cb3dSCy Schubert * resulting readings is strictly later than the previous. 622b15cb3dSCy Schubert * 632b15cb3dSCy Schubert * When slewing the system clock using adj_systime() (with the kernel 642b15cb3dSCy Schubert * loop discipline unavailable or disabled), adjtime() offsets are 652b15cb3dSCy Schubert * quantized to sys_tick, if sys_tick is greater than sys_fuzz, which 662b15cb3dSCy Schubert * is to say if the OS presents a stepping clock. Otherwise, offsets 672b15cb3dSCy Schubert * are quantized to the microsecond resolution of adjtime()'s timeval 682b15cb3dSCy Schubert * input. The remaining correction sys_residual is carried into the 692b15cb3dSCy Schubert * next adjtime() and meanwhile is also factored into get_systime() 702b15cb3dSCy Schubert * readings. 71c0b746e5SOllivier Robert */ 722b15cb3dSCy Schubert double sys_tick = 0; /* tick size or time to read (s) */ 732b15cb3dSCy Schubert double sys_fuzz = 0; /* min. time to read the clock (s) */ 742b15cb3dSCy Schubert long sys_fuzz_nsec = 0; /* min. time to read the clock (ns) */ 752b15cb3dSCy Schubert double measured_tick; /* non-overridable sys_tick (s) */ 769c2daa00SOllivier Robert double sys_residual = 0; /* adjustment residue (s) */ 772b15cb3dSCy Schubert int trunc_os_clock; /* sys_tick > measured_tick */ 782b15cb3dSCy Schubert time_stepped_callback step_callback; 79c0b746e5SOllivier Robert 809c2daa00SOllivier Robert #ifndef SIM 812b15cb3dSCy Schubert /* perlinger@ntp.org: As 'get_sysime()' does it's own check for clock 822b15cb3dSCy Schubert * backstepping, this could probably become a local variable in 832b15cb3dSCy Schubert * 'get_systime()' and the cruft associated with communicating via a 842b15cb3dSCy Schubert * static value could be removed after the v4.2.8 release. 852b15cb3dSCy Schubert */ 862b15cb3dSCy Schubert static int lamport_violated; /* clock was stepped back */ 872b15cb3dSCy Schubert #endif /* !SIM */ 882b15cb3dSCy Schubert 892b15cb3dSCy Schubert #ifdef DEBUG 902b15cb3dSCy Schubert static int systime_init_done; 912b15cb3dSCy Schubert # define DONE_SYSTIME_INIT() systime_init_done = TRUE 922b15cb3dSCy Schubert #else 932b15cb3dSCy Schubert # define DONE_SYSTIME_INIT() do {} while (FALSE) 942b15cb3dSCy Schubert #endif 952b15cb3dSCy Schubert 962b15cb3dSCy Schubert #ifdef HAVE_SIGNALED_IO 972b15cb3dSCy Schubert int using_sigio; 982b15cb3dSCy Schubert #endif 992b15cb3dSCy Schubert 1002b15cb3dSCy Schubert #ifdef SYS_WINNT 1012b15cb3dSCy Schubert CRITICAL_SECTION get_systime_cs; 1022b15cb3dSCy Schubert #endif 1032b15cb3dSCy Schubert 1042b15cb3dSCy Schubert 1052b15cb3dSCy Schubert void 1062b15cb3dSCy Schubert set_sys_fuzz( 1072b15cb3dSCy Schubert double fuzz_val 1082b15cb3dSCy Schubert ) 1092b15cb3dSCy Schubert { 1102b15cb3dSCy Schubert sys_fuzz = fuzz_val; 1112b15cb3dSCy Schubert INSIST(sys_fuzz >= 0); 1122b15cb3dSCy Schubert INSIST(sys_fuzz <= 1.0); 1132b15cb3dSCy Schubert sys_fuzz_nsec = (long)(sys_fuzz * 1e9 + 0.5); 1142b15cb3dSCy Schubert } 1152b15cb3dSCy Schubert 1162b15cb3dSCy Schubert 1172b15cb3dSCy Schubert void 1182b15cb3dSCy Schubert init_systime(void) 1192b15cb3dSCy Schubert { 1202b15cb3dSCy Schubert INIT_GET_SYSTIME_CRITSEC(); 1212b15cb3dSCy Schubert INIT_WIN_PRECISE_TIME(); 1222b15cb3dSCy Schubert DONE_SYSTIME_INIT(); 1232b15cb3dSCy Schubert } 1242b15cb3dSCy Schubert 1252b15cb3dSCy Schubert 1262b15cb3dSCy Schubert #ifndef SIM /* ntpsim.c has get_systime() and friends for sim */ 1272b15cb3dSCy Schubert 1282b15cb3dSCy Schubert static inline void 1292b15cb3dSCy Schubert get_ostime( 1302b15cb3dSCy Schubert struct timespec * tsp 1312b15cb3dSCy Schubert ) 1322b15cb3dSCy Schubert { 1332b15cb3dSCy Schubert int rc; 1342b15cb3dSCy Schubert long ticks; 1352b15cb3dSCy Schubert 1362b15cb3dSCy Schubert #if defined(HAVE_CLOCK_GETTIME) 1372b15cb3dSCy Schubert rc = clock_gettime(CLOCK_REALTIME, tsp); 1382b15cb3dSCy Schubert #elif defined(HAVE_GETCLOCK) 1392b15cb3dSCy Schubert rc = getclock(TIMEOFDAY, tsp); 1402b15cb3dSCy Schubert #else 1412b15cb3dSCy Schubert struct timeval tv; 1422b15cb3dSCy Schubert 1432b15cb3dSCy Schubert rc = GETTIMEOFDAY(&tv, NULL); 1442b15cb3dSCy Schubert tsp->tv_sec = tv.tv_sec; 1452b15cb3dSCy Schubert tsp->tv_nsec = tv.tv_usec * 1000; 1462b15cb3dSCy Schubert #endif 1472b15cb3dSCy Schubert if (rc < 0) { 1482b15cb3dSCy Schubert msyslog(LOG_ERR, "read system clock failed: %m (%d)", 1492b15cb3dSCy Schubert errno); 1502b15cb3dSCy Schubert exit(1); 1512b15cb3dSCy Schubert } 1522b15cb3dSCy Schubert 1532b15cb3dSCy Schubert if (trunc_os_clock) { 1542b15cb3dSCy Schubert ticks = (long)((tsp->tv_nsec * 1e-9) / sys_tick); 1552b15cb3dSCy Schubert tsp->tv_nsec = (long)(ticks * 1e9 * sys_tick); 1562b15cb3dSCy Schubert } 1572b15cb3dSCy Schubert } 1582b15cb3dSCy Schubert 159c0b746e5SOllivier Robert 160c0b746e5SOllivier Robert /* 1619c2daa00SOllivier Robert * get_systime - return system time in NTP timestamp format. 162c0b746e5SOllivier Robert */ 163c0b746e5SOllivier Robert void 164c0b746e5SOllivier Robert get_systime( 1659c2daa00SOllivier Robert l_fp *now /* system time */ 166c0b746e5SOllivier Robert ) 167c0b746e5SOllivier Robert { 1682b15cb3dSCy Schubert static struct timespec ts_last; /* last sampled os time */ 1692b15cb3dSCy Schubert static struct timespec ts_prev; /* prior os time */ 1702b15cb3dSCy Schubert static l_fp lfp_prev; /* prior result */ 1712b15cb3dSCy Schubert static double dfuzz_prev; /* prior fuzz */ 1729c2daa00SOllivier Robert struct timespec ts; /* seconds and nanoseconds */ 1732b15cb3dSCy Schubert struct timespec ts_min; /* earliest permissible */ 1742b15cb3dSCy Schubert struct timespec ts_lam; /* lamport fictional increment */ 1752b15cb3dSCy Schubert struct timespec ts_prev_log; /* for msyslog only */ 1762b15cb3dSCy Schubert double dfuzz; 1772b15cb3dSCy Schubert double ddelta; 1782b15cb3dSCy Schubert l_fp result; 1792b15cb3dSCy Schubert l_fp lfpfuzz; 1802b15cb3dSCy Schubert l_fp lfpdelta; 1819c2daa00SOllivier Robert 1822b15cb3dSCy Schubert get_ostime(&ts); 1832b15cb3dSCy Schubert DEBUG_REQUIRE(systime_init_done); 1842b15cb3dSCy Schubert ENTER_GET_SYSTIME_CRITSEC(); 1852b15cb3dSCy Schubert 1862b15cb3dSCy Schubert /* First check if here was a Lamport violation, that is, two 1872b15cb3dSCy Schubert * successive calls to 'get_ostime()' resulted in negative 1882b15cb3dSCy Schubert * time difference. Use a few milliseconds of permissible 1892b15cb3dSCy Schubert * tolerance -- being too sharp can hurt here. (This is intented 1902b15cb3dSCy Schubert * for the Win32 target, where the HPC interpolation might 1912b15cb3dSCy Schubert * introduce small steps backward. It should not be an issue on 1922b15cb3dSCy Schubert * systems where get_ostime() results in a true syscall.) 1939c2daa00SOllivier Robert */ 1942b15cb3dSCy Schubert if (cmp_tspec(add_tspec_ns(ts, 50000000), ts_last) < 0) 1952b15cb3dSCy Schubert lamport_violated = 1; 1962b15cb3dSCy Schubert ts_last = ts; 1979c2daa00SOllivier Robert 1989c2daa00SOllivier Robert /* 1992b15cb3dSCy Schubert * After default_get_precision() has set a nonzero sys_fuzz, 2002b15cb3dSCy Schubert * ensure every reading of the OS clock advances by at least 2012b15cb3dSCy Schubert * sys_fuzz over the prior reading, thereby assuring each 2022b15cb3dSCy Schubert * fuzzed result is strictly later than the prior. Limit the 2032b15cb3dSCy Schubert * necessary fiction to 1 second. 2049c2daa00SOllivier Robert */ 2052b15cb3dSCy Schubert if (!USING_SIGIO()) { 2062b15cb3dSCy Schubert ts_min = add_tspec_ns(ts_prev, sys_fuzz_nsec); 2072b15cb3dSCy Schubert if (cmp_tspec(ts, ts_min) < 0) { 2082b15cb3dSCy Schubert ts_lam = sub_tspec(ts_min, ts); 2092b15cb3dSCy Schubert if (ts_lam.tv_sec > 0 && !lamport_violated) { 2102b15cb3dSCy Schubert msyslog(LOG_ERR, 2112b15cb3dSCy Schubert "get_systime Lamport advance exceeds one second (%.9f)", 2122b15cb3dSCy Schubert ts_lam.tv_sec + 2132b15cb3dSCy Schubert 1e-9 * ts_lam.tv_nsec); 2142b15cb3dSCy Schubert exit(1); 2152b15cb3dSCy Schubert } 2162b15cb3dSCy Schubert if (!lamport_violated) 2172b15cb3dSCy Schubert ts = ts_min; 2182b15cb3dSCy Schubert } 2192b15cb3dSCy Schubert ts_prev_log = ts_prev; 2202b15cb3dSCy Schubert ts_prev = ts; 2212b15cb3dSCy Schubert } else { 2222b15cb3dSCy Schubert /* 2232b15cb3dSCy Schubert * Quiet "ts_prev_log.tv_sec may be used uninitialized" 2242b15cb3dSCy Schubert * warning from x86 gcc 4.5.2. 2252b15cb3dSCy Schubert */ 2262b15cb3dSCy Schubert ZERO(ts_prev_log); 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 /* 2332b15cb3dSCy Schubert * Add in the fuzz. 2342b15cb3dSCy Schubert */ 2352b15cb3dSCy Schubert dfuzz = ntp_random() * 2. / FRAC * sys_fuzz; 2362b15cb3dSCy Schubert DTOLFP(dfuzz, &lfpfuzz); 2372b15cb3dSCy Schubert L_ADD(&result, &lfpfuzz); 2382b15cb3dSCy Schubert 2392b15cb3dSCy Schubert /* 2402b15cb3dSCy Schubert * Ensure result is strictly greater than prior result (ignoring 2412b15cb3dSCy Schubert * sys_residual's effect for now) once sys_fuzz has been 242ea906c41SOllivier Robert * determined. 243ea906c41SOllivier Robert */ 2442b15cb3dSCy Schubert if (!USING_SIGIO()) { 2452b15cb3dSCy Schubert if (!L_ISZERO(&lfp_prev) && !lamport_violated) { 2462b15cb3dSCy Schubert if (!L_ISGTU(&result, &lfp_prev) && 2472b15cb3dSCy Schubert sys_fuzz > 0.) { 2482b15cb3dSCy Schubert msyslog(LOG_ERR, "ts_prev %s ts_min %s", 2492b15cb3dSCy Schubert tspectoa(ts_prev_log), 2502b15cb3dSCy Schubert tspectoa(ts_min)); 2512b15cb3dSCy Schubert msyslog(LOG_ERR, "ts %s", tspectoa(ts)); 2522b15cb3dSCy Schubert msyslog(LOG_ERR, "sys_fuzz %ld nsec, prior fuzz %.9f", 2532b15cb3dSCy Schubert sys_fuzz_nsec, dfuzz_prev); 2542b15cb3dSCy Schubert msyslog(LOG_ERR, "this fuzz %.9f", 2552b15cb3dSCy Schubert dfuzz); 2562b15cb3dSCy Schubert lfpdelta = lfp_prev; 2572b15cb3dSCy Schubert L_SUB(&lfpdelta, &result); 2582b15cb3dSCy Schubert LFPTOD(&lfpdelta, ddelta); 2592b15cb3dSCy Schubert msyslog(LOG_ERR, 2602b15cb3dSCy Schubert "prev get_systime 0x%x.%08x is %.9f later than 0x%x.%08x", 2612b15cb3dSCy Schubert lfp_prev.l_ui, lfp_prev.l_uf, 2622b15cb3dSCy Schubert ddelta, result.l_ui, result.l_uf); 263c0b746e5SOllivier Robert } 2642b15cb3dSCy Schubert } 2652b15cb3dSCy Schubert lfp_prev = result; 2662b15cb3dSCy Schubert dfuzz_prev = dfuzz; 2672b15cb3dSCy Schubert if (lamport_violated) 2682b15cb3dSCy Schubert lamport_violated = FALSE; 2692b15cb3dSCy Schubert } 2702b15cb3dSCy Schubert LEAVE_GET_SYSTIME_CRITSEC(); 2712b15cb3dSCy Schubert *now = result; 272c0b746e5SOllivier Robert } 273c0b746e5SOllivier Robert 274c0b746e5SOllivier Robert 275c0b746e5SOllivier Robert /* 2769c2daa00SOllivier Robert * adj_systime - adjust system time by the argument. 277c0b746e5SOllivier Robert */ 278a151a66cSOllivier Robert #if !defined SYS_WINNT 2799c2daa00SOllivier Robert int /* 0 okay, 1 error */ 280c0b746e5SOllivier Robert adj_systime( 2819c2daa00SOllivier Robert double now /* adjustment (s) */ 282c0b746e5SOllivier Robert ) 283c0b746e5SOllivier Robert { 2849c2daa00SOllivier Robert struct timeval adjtv; /* new adjustment */ 2859c2daa00SOllivier Robert struct timeval oadjtv; /* residual adjustment */ 2862b15cb3dSCy Schubert double quant; /* quantize to multiples of */ 287c0b746e5SOllivier Robert double dtemp; 2889c2daa00SOllivier Robert long ticks; 2899c2daa00SOllivier Robert int isneg = 0; 290c0b746e5SOllivier Robert 291c0b746e5SOllivier Robert /* 2922b15cb3dSCy Schubert * The Windows port adj_systime() depends on being called each 2932b15cb3dSCy Schubert * second even when there's no additional correction, to allow 2942b15cb3dSCy Schubert * emulation of adjtime() behavior on top of an API that simply 2952b15cb3dSCy Schubert * sets the current rate. This POSIX implementation needs to 2962b15cb3dSCy Schubert * ignore invocations with zero correction, otherwise ongoing 2972b15cb3dSCy Schubert * EVNT_NSET adjtime() can be aborted by a tiny adjtime() 2982b15cb3dSCy Schubert * triggered by sys_residual. 2992b15cb3dSCy Schubert */ 300*3311ff84SXin LI if (0. == now) { 301*3311ff84SXin LI if (enable_panic_check && allow_panic) { 302*3311ff84SXin LI msyslog(LOG_ERR, "adj_systime: allow_panic is TRUE!"); 303*3311ff84SXin LI INSIST(!allow_panic); 304*3311ff84SXin LI } 3052b15cb3dSCy Schubert return TRUE; 306*3311ff84SXin LI } 3072b15cb3dSCy Schubert 3082b15cb3dSCy Schubert /* 3099c2daa00SOllivier Robert * Most Unix adjtime() implementations adjust the system clock 3109c2daa00SOllivier Robert * in microsecond quanta, but some adjust in 10-ms quanta. We 3119c2daa00SOllivier Robert * carefully round the adjustment to the nearest quantum, then 3129c2daa00SOllivier Robert * adjust in quanta and keep the residue for later. 313c0b746e5SOllivier Robert */ 3149c2daa00SOllivier Robert dtemp = now + sys_residual; 315c0b746e5SOllivier Robert if (dtemp < 0) { 316c0b746e5SOllivier Robert isneg = 1; 317c0b746e5SOllivier Robert dtemp = -dtemp; 318c0b746e5SOllivier Robert } 3199c2daa00SOllivier Robert adjtv.tv_sec = (long)dtemp; 3209c2daa00SOllivier Robert dtemp -= adjtv.tv_sec; 3212b15cb3dSCy Schubert if (sys_tick > sys_fuzz) 3222b15cb3dSCy Schubert quant = sys_tick; 3232b15cb3dSCy Schubert else 3242b15cb3dSCy Schubert quant = 1e-6; 3252b15cb3dSCy Schubert ticks = (long)(dtemp / quant + .5); 3262b15cb3dSCy Schubert adjtv.tv_usec = (long)(ticks * quant * 1e6); 3279c2daa00SOllivier Robert dtemp -= adjtv.tv_usec / 1e6; 3289c2daa00SOllivier Robert sys_residual = dtemp; 329c0b746e5SOllivier Robert 330c0b746e5SOllivier Robert /* 3319c2daa00SOllivier Robert * Convert to signed seconds and microseconds for the Unix 3329c2daa00SOllivier Robert * adjtime() system call. Note we purposely lose the adjtime() 3339c2daa00SOllivier Robert * leftover. 334c0b746e5SOllivier Robert */ 3359c2daa00SOllivier Robert if (isneg) { 3369c2daa00SOllivier Robert adjtv.tv_sec = -adjtv.tv_sec; 3379c2daa00SOllivier Robert adjtv.tv_usec = -adjtv.tv_usec; 338ea906c41SOllivier Robert sys_residual = -sys_residual; 339c0b746e5SOllivier Robert } 340ea906c41SOllivier Robert if (adjtv.tv_sec != 0 || adjtv.tv_usec != 0) { 3419c2daa00SOllivier Robert if (adjtime(&adjtv, &oadjtv) < 0) { 3429c2daa00SOllivier Robert msyslog(LOG_ERR, "adj_systime: %m"); 343*3311ff84SXin LI if (enable_panic_check && allow_panic) { 344*3311ff84SXin LI msyslog(LOG_ERR, "adj_systime: allow_panic is TRUE!"); 345*3311ff84SXin LI } 3462b15cb3dSCy Schubert return FALSE; 347c0b746e5SOllivier Robert } 348ea906c41SOllivier Robert } 349*3311ff84SXin LI if (enable_panic_check && allow_panic) { 350*3311ff84SXin LI msyslog(LOG_ERR, "adj_systime: allow_panic is TRUE!"); 351*3311ff84SXin LI } 3522b15cb3dSCy Schubert return TRUE; 353c0b746e5SOllivier Robert } 354a151a66cSOllivier Robert #endif 355c0b746e5SOllivier Robert 356c0b746e5SOllivier Robert 357c0b746e5SOllivier Robert /* 358c0b746e5SOllivier Robert * step_systime - step the system clock. 359c0b746e5SOllivier Robert */ 3602b15cb3dSCy Schubert 361c0b746e5SOllivier Robert int 362c0b746e5SOllivier Robert step_systime( 3632b15cb3dSCy Schubert double step 364c0b746e5SOllivier Robert ) 365c0b746e5SOllivier Robert { 3662b15cb3dSCy Schubert time_t pivot; /* for ntp era unfolding */ 3672b15cb3dSCy Schubert struct timeval timetv, tvlast, tvdiff; 3682b15cb3dSCy Schubert struct timespec timets; 3692b15cb3dSCy Schubert struct calendar jd; 3702b15cb3dSCy Schubert l_fp fp_ofs, fp_sys; /* offset and target system time in FP */ 371c0b746e5SOllivier Robert 3722b15cb3dSCy Schubert /* 3732b15cb3dSCy Schubert * Get pivot time for NTP era unfolding. Since we don't step 3742b15cb3dSCy Schubert * very often, we can afford to do the whole calculation from 3752b15cb3dSCy Schubert * scratch. And we're not in the time-critical path yet. 3762b15cb3dSCy Schubert */ 3772b15cb3dSCy Schubert #if SIZEOF_TIME_T > 4 3782b15cb3dSCy Schubert /* 3792b15cb3dSCy Schubert * This code makes sure the resulting time stamp for the new 3802b15cb3dSCy Schubert * system time is in the 2^32 seconds starting at 1970-01-01, 3812b15cb3dSCy Schubert * 00:00:00 UTC. 3822b15cb3dSCy Schubert */ 3832b15cb3dSCy Schubert pivot = 0x80000000; 3842b15cb3dSCy Schubert #if USE_COMPILETIME_PIVOT 3852b15cb3dSCy Schubert /* 3862b15cb3dSCy Schubert * Add the compile time minus 10 years to get a possible target 3872b15cb3dSCy Schubert * area of (compile time - 10 years) to (compile time + 126 3882b15cb3dSCy Schubert * years). This should be sufficient for a given binary of 3892b15cb3dSCy Schubert * NTPD. 3902b15cb3dSCy Schubert */ 3912b15cb3dSCy Schubert if (ntpcal_get_build_date(&jd)) { 3922b15cb3dSCy Schubert jd.year -= 10; 3932b15cb3dSCy Schubert pivot += ntpcal_date_to_time(&jd); 394c0b746e5SOllivier Robert } else { 3952b15cb3dSCy Schubert msyslog(LOG_ERR, 3962b15cb3dSCy Schubert "step-systime: assume 1970-01-01 as build date"); 397c0b746e5SOllivier Robert } 398c0b746e5SOllivier Robert #else 3992b15cb3dSCy Schubert UNUSED_LOCAL(jd); 4002b15cb3dSCy Schubert #endif /* USE_COMPILETIME_PIVOT */ 4012b15cb3dSCy Schubert #else 4022b15cb3dSCy Schubert UNUSED_LOCAL(jd); 4032b15cb3dSCy Schubert /* This makes sure the resulting time stamp is on or after 4042b15cb3dSCy Schubert * 1969-12-31/23:59:59 UTC and gives us additional two years, 4052b15cb3dSCy Schubert * from the change of NTP era in 2036 to the UNIX rollover in 4062b15cb3dSCy Schubert * 2038. (Minus one second, but that won't hurt.) We *really* 4072b15cb3dSCy Schubert * need a longer 'time_t' after that! Or a different baseline, 4082b15cb3dSCy Schubert * but that would cause other serious trouble, too. 4092b15cb3dSCy Schubert */ 4102b15cb3dSCy Schubert pivot = 0x7FFFFFFF; 411c0b746e5SOllivier Robert #endif 412c0b746e5SOllivier Robert 4132b15cb3dSCy Schubert /* get the complete jump distance as l_fp */ 4142b15cb3dSCy Schubert DTOLFP(sys_residual, &fp_sys); 4152b15cb3dSCy Schubert DTOLFP(step, &fp_ofs); 4162b15cb3dSCy Schubert L_ADD(&fp_ofs, &fp_sys); 417c0b746e5SOllivier Robert 4182b15cb3dSCy Schubert /* ---> time-critical path starts ---> */ 4192b15cb3dSCy Schubert 4202b15cb3dSCy Schubert /* get the current time as l_fp (without fuzz) and as struct timeval */ 4212b15cb3dSCy Schubert get_ostime(&timets); 4222b15cb3dSCy Schubert fp_sys = tspec_stamp_to_lfp(timets); 4232b15cb3dSCy Schubert tvlast.tv_sec = timets.tv_sec; 4242b15cb3dSCy Schubert tvlast.tv_usec = (timets.tv_nsec + 500) / 1000; 4252b15cb3dSCy Schubert 4262b15cb3dSCy Schubert /* get the target time as l_fp */ 4272b15cb3dSCy Schubert L_ADD(&fp_sys, &fp_ofs); 4282b15cb3dSCy Schubert 4292b15cb3dSCy Schubert /* unfold the new system time */ 4302b15cb3dSCy Schubert timetv = lfp_stamp_to_tval(fp_sys, &pivot); 4312b15cb3dSCy Schubert 4322b15cb3dSCy Schubert /* now set new system time */ 4339c2daa00SOllivier Robert if (ntp_set_tod(&timetv, NULL) != 0) { 4349c2daa00SOllivier Robert msyslog(LOG_ERR, "step-systime: %m"); 435*3311ff84SXin LI if (enable_panic_check && allow_panic) { 436*3311ff84SXin LI msyslog(LOG_ERR, "step_systime: allow_panic is TRUE!"); 437*3311ff84SXin LI } 4382b15cb3dSCy Schubert return FALSE; 439c0b746e5SOllivier Robert } 4402b15cb3dSCy Schubert 4412b15cb3dSCy Schubert /* <--- time-critical path ended with 'ntp_set_tod()' <--- */ 4422b15cb3dSCy Schubert 443c0b746e5SOllivier Robert sys_residual = 0; 4442b15cb3dSCy Schubert lamport_violated = (step < 0); 4452b15cb3dSCy Schubert if (step_callback) 4462b15cb3dSCy Schubert (*step_callback)(); 447c0b746e5SOllivier Robert 448c0b746e5SOllivier Robert #ifdef NEED_HPUX_ADJTIME 449c0b746e5SOllivier Robert /* 450c0b746e5SOllivier Robert * CHECKME: is this correct when called by ntpdate????? 451c0b746e5SOllivier Robert */ 452c0b746e5SOllivier Robert _clear_adjtime(); 453c0b746e5SOllivier Robert #endif 454c0b746e5SOllivier Robert 455c0b746e5SOllivier Robert /* 456c0b746e5SOllivier Robert * FreeBSD, for example, has: 457c0b746e5SOllivier Robert * struct utmp { 458c0b746e5SOllivier Robert * char ut_line[UT_LINESIZE]; 459c0b746e5SOllivier Robert * char ut_name[UT_NAMESIZE]; 460c0b746e5SOllivier Robert * char ut_host[UT_HOSTSIZE]; 461c0b746e5SOllivier Robert * long ut_time; 462c0b746e5SOllivier Robert * }; 463c0b746e5SOllivier Robert * and appends line="|", name="date", host="", time for the OLD 464*3311ff84SXin LI * and appends line="{", name="date", host="", time for the NEW // } 465c0b746e5SOllivier Robert * to _PATH_WTMP . 466c0b746e5SOllivier Robert * 467c0b746e5SOllivier Robert * Some OSes have utmp, some have utmpx. 468c0b746e5SOllivier Robert */ 469c0b746e5SOllivier Robert 470c0b746e5SOllivier Robert /* 4719c2daa00SOllivier Robert * Write old and new time entries in utmp and wtmp if step 4729c2daa00SOllivier Robert * adjustment is greater than one second. 473c0b746e5SOllivier Robert * 474c0b746e5SOllivier Robert * This might become even Uglier... 475c0b746e5SOllivier Robert */ 4762b15cb3dSCy Schubert tvdiff = abs_tval(sub_tval(timetv, tvlast)); 4772b15cb3dSCy Schubert if (tvdiff.tv_sec > 0) { 478c0b746e5SOllivier Robert #ifdef HAVE_UTMP_H 479c0b746e5SOllivier Robert struct utmp ut; 480c0b746e5SOllivier Robert #endif 481c0b746e5SOllivier Robert #ifdef HAVE_UTMPX_H 482c0b746e5SOllivier Robert struct utmpx utx; 483c0b746e5SOllivier Robert #endif 484c0b746e5SOllivier Robert 485c0b746e5SOllivier Robert #ifdef HAVE_UTMP_H 4862b15cb3dSCy Schubert ZERO(ut); 487c0b746e5SOllivier Robert #endif 488c0b746e5SOllivier Robert #ifdef HAVE_UTMPX_H 4892b15cb3dSCy Schubert ZERO(utx); 490c0b746e5SOllivier Robert #endif 491c0b746e5SOllivier Robert 492c0b746e5SOllivier Robert /* UTMP */ 493c0b746e5SOllivier Robert 494c0b746e5SOllivier Robert #ifdef UPDATE_UTMP 495c0b746e5SOllivier Robert # ifdef HAVE_PUTUTLINE 4962b15cb3dSCy Schubert # ifndef _PATH_UTMP 4972b15cb3dSCy Schubert # define _PATH_UTMP UTMP_FILE 4982b15cb3dSCy Schubert # endif 4992b15cb3dSCy Schubert utmpname(_PATH_UTMP); 500c0b746e5SOllivier Robert ut.ut_type = OLD_TIME; 5012b15cb3dSCy Schubert strlcpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line)); 5022b15cb3dSCy Schubert ut.ut_time = tvlast.tv_sec; 503c0b746e5SOllivier Robert setutent(); 5042b15cb3dSCy Schubert pututline(&ut); 505c0b746e5SOllivier Robert ut.ut_type = NEW_TIME; 5062b15cb3dSCy Schubert strlcpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line)); 507c0b746e5SOllivier Robert ut.ut_time = timetv.tv_sec; 5082b15cb3dSCy Schubert setutent(); 509c0b746e5SOllivier Robert pututline(&ut); 510c0b746e5SOllivier Robert endutent(); 511c0b746e5SOllivier Robert # else /* not HAVE_PUTUTLINE */ 512c0b746e5SOllivier Robert # endif /* not HAVE_PUTUTLINE */ 513c0b746e5SOllivier Robert #endif /* UPDATE_UTMP */ 514c0b746e5SOllivier Robert 515c0b746e5SOllivier Robert /* UTMPX */ 516c0b746e5SOllivier Robert 517c0b746e5SOllivier Robert #ifdef UPDATE_UTMPX 518c0b746e5SOllivier Robert # ifdef HAVE_PUTUTXLINE 519c0b746e5SOllivier Robert utx.ut_type = OLD_TIME; 5202b15cb3dSCy Schubert strlcpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line)); 5212b15cb3dSCy Schubert utx.ut_tv = tvlast; 522c0b746e5SOllivier Robert setutxent(); 5232b15cb3dSCy Schubert pututxline(&utx); 524c0b746e5SOllivier Robert utx.ut_type = NEW_TIME; 5252b15cb3dSCy Schubert strlcpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line)); 526c0b746e5SOllivier Robert utx.ut_tv = timetv; 5272b15cb3dSCy Schubert setutxent(); 528c0b746e5SOllivier Robert pututxline(&utx); 529c0b746e5SOllivier Robert endutxent(); 530c0b746e5SOllivier Robert # else /* not HAVE_PUTUTXLINE */ 531c0b746e5SOllivier Robert # endif /* not HAVE_PUTUTXLINE */ 532c0b746e5SOllivier Robert #endif /* UPDATE_UTMPX */ 533c0b746e5SOllivier Robert 534c0b746e5SOllivier Robert /* WTMP */ 535c0b746e5SOllivier Robert 536c0b746e5SOllivier Robert #ifdef UPDATE_WTMP 537c0b746e5SOllivier Robert # ifdef HAVE_PUTUTLINE 5382b15cb3dSCy Schubert # ifndef _PATH_WTMP 5392b15cb3dSCy Schubert # define _PATH_WTMP WTMP_FILE 5402b15cb3dSCy Schubert # endif 5412b15cb3dSCy Schubert utmpname(_PATH_WTMP); 542c0b746e5SOllivier Robert ut.ut_type = OLD_TIME; 5432b15cb3dSCy Schubert strlcpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line)); 5442b15cb3dSCy Schubert ut.ut_time = tvlast.tv_sec; 5452b15cb3dSCy Schubert setutent(); 546c0b746e5SOllivier Robert pututline(&ut); 547c0b746e5SOllivier Robert ut.ut_type = NEW_TIME; 5482b15cb3dSCy Schubert strlcpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line)); 549c0b746e5SOllivier Robert ut.ut_time = timetv.tv_sec; 5502b15cb3dSCy Schubert setutent(); 551c0b746e5SOllivier Robert pututline(&ut); 552c0b746e5SOllivier Robert endutent(); 553c0b746e5SOllivier Robert # else /* not HAVE_PUTUTLINE */ 554c0b746e5SOllivier Robert # endif /* not HAVE_PUTUTLINE */ 555c0b746e5SOllivier Robert #endif /* UPDATE_WTMP */ 556c0b746e5SOllivier Robert 557c0b746e5SOllivier Robert /* WTMPX */ 558c0b746e5SOllivier Robert 559c0b746e5SOllivier Robert #ifdef UPDATE_WTMPX 560c0b746e5SOllivier Robert # ifdef HAVE_PUTUTXLINE 561c0b746e5SOllivier Robert utx.ut_type = OLD_TIME; 5622b15cb3dSCy Schubert utx.ut_tv = tvlast; 5632b15cb3dSCy Schubert strlcpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line)); 564c0b746e5SOllivier Robert # ifdef HAVE_UPDWTMPX 565c0b746e5SOllivier Robert updwtmpx(WTMPX_FILE, &utx); 566c0b746e5SOllivier Robert # else /* not HAVE_UPDWTMPX */ 567c0b746e5SOllivier Robert # endif /* not HAVE_UPDWTMPX */ 568c0b746e5SOllivier Robert # else /* not HAVE_PUTUTXLINE */ 569c0b746e5SOllivier Robert # endif /* not HAVE_PUTUTXLINE */ 570c0b746e5SOllivier Robert # ifdef HAVE_PUTUTXLINE 571c0b746e5SOllivier Robert utx.ut_type = NEW_TIME; 572c0b746e5SOllivier Robert utx.ut_tv = timetv; 5732b15cb3dSCy Schubert strlcpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line)); 574c0b746e5SOllivier Robert # ifdef HAVE_UPDWTMPX 575c0b746e5SOllivier Robert updwtmpx(WTMPX_FILE, &utx); 576c0b746e5SOllivier Robert # else /* not HAVE_UPDWTMPX */ 577c0b746e5SOllivier Robert # endif /* not HAVE_UPDWTMPX */ 578c0b746e5SOllivier Robert # else /* not HAVE_PUTUTXLINE */ 579c0b746e5SOllivier Robert # endif /* not HAVE_PUTUTXLINE */ 580c0b746e5SOllivier Robert #endif /* UPDATE_WTMPX */ 581c0b746e5SOllivier Robert 582c0b746e5SOllivier Robert } 583*3311ff84SXin LI if (enable_panic_check && allow_panic) { 584*3311ff84SXin LI msyslog(LOG_ERR, "step_systime: allow_panic is TRUE!"); 585*3311ff84SXin LI INSIST(!allow_panic); 586*3311ff84SXin LI } 5872b15cb3dSCy Schubert return TRUE; 588c0b746e5SOllivier Robert } 5899c2daa00SOllivier Robert 5902b15cb3dSCy Schubert #endif /* !SIM */ 591