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