1 /* 2 * systime -- routines to fiddle a UNIX clock. 3 * 4 * ATTENTION: Get approval from Dave Mills on all changes to this file! 5 * 6 */ 7 #include "ntp_machine.h" 8 #include "ntp_fp.h" 9 #include "ntp_syslog.h" 10 #include "ntp_unixtime.h" 11 #include "ntp_stdlib.h" 12 #include "ntp_random.h" 13 #include "ntpd.h" /* for sys_precision */ 14 15 #ifdef SIM 16 # include "ntpsim.h" 17 #endif /*SIM */ 18 19 #ifdef HAVE_SYS_PARAM_H 20 # include <sys/param.h> 21 #endif 22 #ifdef HAVE_UTMP_H 23 # include <utmp.h> 24 #endif /* HAVE_UTMP_H */ 25 #ifdef HAVE_UTMPX_H 26 # include <utmpx.h> 27 #endif /* HAVE_UTMPX_H */ 28 29 /* 30 * These routines (get_systime, step_systime, adj_systime) implement an 31 * interface between the system independent NTP clock and the Unix 32 * system clock in various architectures and operating systems. 33 * 34 * Time is a precious quantity in these routines and every effort is 35 * made to minimize errors by always rounding toward zero and amortizing 36 * adjustment residues. By default the adjustment quantum is 1 us for 37 * the usual Unix tickadj() system call, but this can be increased if 38 * necessary by the tick configuration command. For instance, when the 39 * adjtime() quantum is a clock tick for a 100-Hz clock, the quantum 40 * should be 10 ms. 41 */ 42 #if defined RELIANTUNIX_CLOCK || defined SCO5_CLOCK 43 double sys_tick = 10e-3; /* 10 ms tickadj() */ 44 #else 45 double sys_tick = 1e-6; /* 1 us tickadj() */ 46 #endif 47 double sys_residual = 0; /* adjustment residue (s) */ 48 49 #ifndef SIM 50 51 /* 52 * get_systime - return system time in NTP timestamp format. 53 */ 54 void 55 get_systime( 56 l_fp *now /* system time */ 57 ) 58 { 59 double dtemp; 60 61 #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK) 62 struct timespec ts; /* seconds and nanoseconds */ 63 64 /* 65 * Convert Unix clock from seconds and nanoseconds to seconds. 66 * The bottom is only two bits down, so no need for fuzz. 67 * Some systems don't have that level of precision, however... 68 */ 69 # ifdef HAVE_CLOCK_GETTIME 70 clock_gettime(CLOCK_REALTIME, &ts); 71 # else 72 getclock(TIMEOFDAY, &ts); 73 # endif 74 now->l_i = ts.tv_sec + JAN_1970; 75 dtemp = ts.tv_nsec / 1e9; 76 77 #else /* HAVE_CLOCK_GETTIME || HAVE_GETCLOCK */ 78 struct timeval tv; /* seconds and microseconds */ 79 80 /* 81 * Convert Unix clock from seconds and microseconds to seconds. 82 * Add in unbiased random fuzz beneath the microsecond. 83 */ 84 GETTIMEOFDAY(&tv, NULL); 85 now->l_i = tv.tv_sec + JAN_1970; 86 dtemp = tv.tv_usec / 1e6; 87 88 #endif /* HAVE_CLOCK_GETTIME || HAVE_GETCLOCK */ 89 90 /* 91 * ntp_random() produces 31 bits (always nonnegative). 92 * This bit is done only after the precision has been 93 * determined. 94 */ 95 if (sys_precision != 0) 96 dtemp += (ntp_random() / FRAC - .5) / (1 << 97 -sys_precision); 98 99 /* 100 * Renormalize to seconds past 1900 and fraction. 101 */ 102 dtemp += sys_residual; 103 if (dtemp >= 1) { 104 dtemp -= 1; 105 now->l_i++; 106 } else if (dtemp < 0) { 107 dtemp += 1; 108 now->l_i--; 109 } 110 dtemp *= FRAC; 111 now->l_uf = (u_int32)dtemp; 112 } 113 114 115 /* 116 * adj_systime - adjust system time by the argument. 117 */ 118 #if !defined SYS_WINNT 119 int /* 0 okay, 1 error */ 120 adj_systime( 121 double now /* adjustment (s) */ 122 ) 123 { 124 struct timeval adjtv; /* new adjustment */ 125 struct timeval oadjtv; /* residual adjustment */ 126 double dtemp; 127 long ticks; 128 int isneg = 0; 129 130 /* 131 * Most Unix adjtime() implementations adjust the system clock 132 * in microsecond quanta, but some adjust in 10-ms quanta. We 133 * carefully round the adjustment to the nearest quantum, then 134 * adjust in quanta and keep the residue for later. 135 */ 136 dtemp = now + sys_residual; 137 if (dtemp < 0) { 138 isneg = 1; 139 dtemp = -dtemp; 140 } 141 adjtv.tv_sec = (long)dtemp; 142 dtemp -= adjtv.tv_sec; 143 ticks = (long)(dtemp / sys_tick + .5); 144 adjtv.tv_usec = (long)(ticks * sys_tick * 1e6); 145 dtemp -= adjtv.tv_usec / 1e6; 146 sys_residual = dtemp; 147 148 /* 149 * Convert to signed seconds and microseconds for the Unix 150 * adjtime() system call. Note we purposely lose the adjtime() 151 * leftover. 152 */ 153 if (isneg) { 154 adjtv.tv_sec = -adjtv.tv_sec; 155 adjtv.tv_usec = -adjtv.tv_usec; 156 sys_residual = -sys_residual; 157 } 158 if (adjtv.tv_sec != 0 || adjtv.tv_usec != 0) { 159 if (adjtime(&adjtv, &oadjtv) < 0) { 160 msyslog(LOG_ERR, "adj_systime: %m"); 161 return (0); 162 } 163 } 164 return (1); 165 } 166 #endif 167 168 169 /* 170 * step_systime - step the system clock. 171 */ 172 int 173 step_systime( 174 double now 175 ) 176 { 177 struct timeval timetv, adjtv, oldtimetv; 178 int isneg = 0; 179 double dtemp; 180 #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK) 181 struct timespec ts; 182 #endif 183 184 dtemp = sys_residual + now; 185 if (dtemp < 0) { 186 isneg = 1; 187 dtemp = - dtemp; 188 adjtv.tv_sec = (int32)dtemp; 189 adjtv.tv_usec = (u_int32)((dtemp - 190 (double)adjtv.tv_sec) * 1e6 + .5); 191 } else { 192 adjtv.tv_sec = (int32)dtemp; 193 adjtv.tv_usec = (u_int32)((dtemp - 194 (double)adjtv.tv_sec) * 1e6 + .5); 195 } 196 #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK) 197 # ifdef HAVE_CLOCK_GETTIME 198 (void) clock_gettime(CLOCK_REALTIME, &ts); 199 # else 200 (void) getclock(TIMEOFDAY, &ts); 201 # endif 202 timetv.tv_sec = ts.tv_sec; 203 timetv.tv_usec = ts.tv_nsec / 1000; 204 #else /* not HAVE_GETCLOCK */ 205 (void) GETTIMEOFDAY(&timetv, (struct timezone *)0); 206 #endif /* not HAVE_GETCLOCK */ 207 208 oldtimetv = timetv; 209 210 #ifdef DEBUG 211 if (debug) 212 printf("step_systime: step %.6f residual %.6f\n", now, sys_residual); 213 #endif 214 if (isneg) { 215 timetv.tv_sec -= adjtv.tv_sec; 216 timetv.tv_usec -= adjtv.tv_usec; 217 if (timetv.tv_usec < 0) { 218 timetv.tv_sec--; 219 timetv.tv_usec += 1000000; 220 } 221 } else { 222 timetv.tv_sec += adjtv.tv_sec; 223 timetv.tv_usec += adjtv.tv_usec; 224 if (timetv.tv_usec >= 1000000) { 225 timetv.tv_sec++; 226 timetv.tv_usec -= 1000000; 227 } 228 } 229 if (ntp_set_tod(&timetv, NULL) != 0) { 230 msyslog(LOG_ERR, "step-systime: %m"); 231 return (0); 232 } 233 sys_residual = 0; 234 235 #ifdef NEED_HPUX_ADJTIME 236 /* 237 * CHECKME: is this correct when called by ntpdate????? 238 */ 239 _clear_adjtime(); 240 #endif 241 242 /* 243 * FreeBSD, for example, has: 244 * struct utmp { 245 * char ut_line[UT_LINESIZE]; 246 * char ut_name[UT_NAMESIZE]; 247 * char ut_host[UT_HOSTSIZE]; 248 * long ut_time; 249 * }; 250 * and appends line="|", name="date", host="", time for the OLD 251 * and appends line="{", name="date", host="", time for the NEW 252 * to _PATH_WTMP . 253 * 254 * Some OSes have utmp, some have utmpx. 255 */ 256 257 /* 258 * Write old and new time entries in utmp and wtmp if step 259 * adjustment is greater than one second. 260 * 261 * This might become even Uglier... 262 */ 263 if (oldtimetv.tv_sec != timetv.tv_sec) 264 { 265 #ifdef HAVE_UTMP_H 266 struct utmp ut; 267 #endif 268 #ifdef HAVE_UTMPX_H 269 struct utmpx utx; 270 #endif 271 272 #ifdef HAVE_UTMP_H 273 memset((char *)&ut, 0, sizeof(ut)); 274 #endif 275 #ifdef HAVE_UTMPX_H 276 memset((char *)&utx, 0, sizeof(utx)); 277 #endif 278 279 /* UTMP */ 280 281 #ifdef UPDATE_UTMP 282 # ifdef HAVE_PUTUTLINE 283 ut.ut_type = OLD_TIME; 284 (void)strcpy(ut.ut_line, OTIME_MSG); 285 ut.ut_time = oldtimetv.tv_sec; 286 pututline(&ut); 287 setutent(); 288 ut.ut_type = NEW_TIME; 289 (void)strcpy(ut.ut_line, NTIME_MSG); 290 ut.ut_time = timetv.tv_sec; 291 pututline(&ut); 292 endutent(); 293 # else /* not HAVE_PUTUTLINE */ 294 # endif /* not HAVE_PUTUTLINE */ 295 #endif /* UPDATE_UTMP */ 296 297 /* UTMPX */ 298 299 #ifdef UPDATE_UTMPX 300 # ifdef HAVE_PUTUTXLINE 301 utx.ut_type = OLD_TIME; 302 (void)strcpy(utx.ut_line, OTIME_MSG); 303 utx.ut_tv = oldtimetv; 304 pututxline(&utx); 305 setutxent(); 306 utx.ut_type = NEW_TIME; 307 (void)strcpy(utx.ut_line, NTIME_MSG); 308 utx.ut_tv = timetv; 309 pututxline(&utx); 310 endutxent(); 311 # else /* not HAVE_PUTUTXLINE */ 312 # endif /* not HAVE_PUTUTXLINE */ 313 #endif /* UPDATE_UTMPX */ 314 315 /* WTMP */ 316 317 #ifdef UPDATE_WTMP 318 # ifdef HAVE_PUTUTLINE 319 utmpname(WTMP_FILE); 320 ut.ut_type = OLD_TIME; 321 (void)strcpy(ut.ut_line, OTIME_MSG); 322 ut.ut_time = oldtimetv.tv_sec; 323 pututline(&ut); 324 ut.ut_type = NEW_TIME; 325 (void)strcpy(ut.ut_line, NTIME_MSG); 326 ut.ut_time = timetv.tv_sec; 327 pututline(&ut); 328 endutent(); 329 # else /* not HAVE_PUTUTLINE */ 330 # endif /* not HAVE_PUTUTLINE */ 331 #endif /* UPDATE_WTMP */ 332 333 /* WTMPX */ 334 335 #ifdef UPDATE_WTMPX 336 # ifdef HAVE_PUTUTXLINE 337 utx.ut_type = OLD_TIME; 338 utx.ut_tv = oldtimetv; 339 (void)strcpy(utx.ut_line, OTIME_MSG); 340 # ifdef HAVE_UPDWTMPX 341 updwtmpx(WTMPX_FILE, &utx); 342 # else /* not HAVE_UPDWTMPX */ 343 # endif /* not HAVE_UPDWTMPX */ 344 # else /* not HAVE_PUTUTXLINE */ 345 # endif /* not HAVE_PUTUTXLINE */ 346 # ifdef HAVE_PUTUTXLINE 347 utx.ut_type = NEW_TIME; 348 utx.ut_tv = timetv; 349 (void)strcpy(utx.ut_line, NTIME_MSG); 350 # ifdef HAVE_UPDWTMPX 351 updwtmpx(WTMPX_FILE, &utx); 352 # else /* not HAVE_UPDWTMPX */ 353 # endif /* not HAVE_UPDWTMPX */ 354 # else /* not HAVE_PUTUTXLINE */ 355 # endif /* not HAVE_PUTUTXLINE */ 356 #endif /* UPDATE_WTMPX */ 357 358 } 359 return (1); 360 } 361 362 #else /* SIM */ 363 /* 364 * Clock routines for the simulator - Harish Nair, with help 365 */ 366 /* 367 * get_systime - return the system time in NTP timestamp format 368 */ 369 void 370 get_systime( 371 l_fp *now /* current system time in l_fp */ ) 372 { 373 /* 374 * To fool the code that determines the local clock precision, 375 * we advance the clock a minimum of 200 nanoseconds on every 376 * clock read. This is appropriate for a typical modern machine 377 * with nanosecond clocks. Note we make no attempt here to 378 * simulate reading error, since the error is so small. This may 379 * change when the need comes to implement picosecond clocks. 380 */ 381 if (ntp_node.ntp_time == ntp_node.last_time) 382 ntp_node.ntp_time += 200e-9; 383 ntp_node.last_time = ntp_node.ntp_time; 384 DTOLFP(ntp_node.ntp_time, now); 385 } 386 387 388 /* 389 * adj_systime - advance or retard the system clock exactly like the 390 * real thng. 391 */ 392 int /* always succeeds */ 393 adj_systime( 394 double now /* time adjustment (s) */ 395 ) 396 { 397 struct timeval adjtv; /* new adjustment */ 398 double dtemp; 399 long ticks; 400 int isneg = 0; 401 402 /* 403 * Most Unix adjtime() implementations adjust the system clock 404 * in microsecond quanta, but some adjust in 10-ms quanta. We 405 * carefully round the adjustment to the nearest quantum, then 406 * adjust in quanta and keep the residue for later. 407 */ 408 dtemp = now + sys_residual; 409 if (dtemp < 0) { 410 isneg = 1; 411 dtemp = -dtemp; 412 } 413 adjtv.tv_sec = (long)dtemp; 414 dtemp -= adjtv.tv_sec; 415 ticks = (long)(dtemp / sys_tick + .5); 416 adjtv.tv_usec = (long)(ticks * sys_tick * 1e6); 417 dtemp -= adjtv.tv_usec / 1e6; 418 sys_residual = dtemp; 419 420 /* 421 * Convert to signed seconds and microseconds for the Unix 422 * adjtime() system call. Note we purposely lose the adjtime() 423 * leftover. 424 */ 425 if (isneg) { 426 adjtv.tv_sec = -adjtv.tv_sec; 427 adjtv.tv_usec = -adjtv.tv_usec; 428 sys_residual = -sys_residual; 429 } 430 ntp_node.adj = now; 431 return (1); 432 } 433 434 435 /* 436 * step_systime - step the system clock. We are religious here. 437 */ 438 int /* always succeeds */ 439 step_systime( 440 double now /* step adjustment (s) */ 441 ) 442 { 443 #ifdef DEBUG 444 if (debug) 445 printf("step_systime: time %.6f adj %.6f\n", 446 ntp_node.ntp_time, now); 447 #endif 448 ntp_node.ntp_time += now; 449 return (1); 450 } 451 452 /* 453 * node_clock - update the clocks 454 */ 455 int /* always succeeds */ 456 node_clock( 457 Node *n, /* global node pointer */ 458 double t /* node time */ 459 ) 460 { 461 double dtemp; 462 463 /* 464 * Advance client clock (ntp_time). Advance server clock 465 * (clk_time) adjusted for systematic and random frequency 466 * errors. The random error is a random walk computed as the 467 * integral of samples from a Gaussian distribution. 468 */ 469 dtemp = t - n->ntp_time; 470 n->time = t; 471 n->ntp_time += dtemp; 472 n->ferr += gauss(0, dtemp * n->fnse); 473 n->clk_time += dtemp * (1 + n->ferr); 474 475 /* 476 * Perform the adjtime() function. If the adjustment completed 477 * in the previous interval, amortize the entire amount; if not, 478 * carry the leftover to the next interval. 479 */ 480 dtemp *= n->slew; 481 if (dtemp < fabs(n->adj)) { 482 if (n->adj < 0) { 483 n->adj += dtemp; 484 n->ntp_time -= dtemp; 485 } else { 486 n->adj -= dtemp; 487 n->ntp_time += dtemp; 488 } 489 } else { 490 n->ntp_time += n->adj; 491 n->adj = 0; 492 } 493 return (0); 494 } 495 496 497 /* 498 * gauss() - returns samples from a gaussion distribution 499 */ 500 double /* Gaussian sample */ 501 gauss( 502 double m, /* sample mean */ 503 double s /* sample standard deviation (sigma) */ 504 ) 505 { 506 double q1, q2; 507 508 /* 509 * Roll a sample from a Gaussian distribution with mean m and 510 * standard deviation s. For m = 0, s = 1, mean(y) = 0, 511 * std(y) = 1. 512 */ 513 if (s == 0) 514 return (m); 515 while ((q1 = drand48()) == 0); 516 q2 = drand48(); 517 return (m + s * sqrt(-2. * log(q1)) * cos(2. * PI * q2)); 518 } 519 520 521 /* 522 * poisson() - returns samples from a network delay distribution 523 */ 524 double /* delay sample (s) */ 525 poisson( 526 double m, /* fixed propagation delay (s) */ 527 double s /* exponential parameter (mu) */ 528 ) 529 { 530 double q1; 531 532 /* 533 * Roll a sample from a composite distribution with propagation 534 * delay m and exponential distribution time with parameter s. 535 * For m = 0, s = 1, mean(y) = std(y) = 1. 536 */ 537 if (s == 0) 538 return (m); 539 while ((q1 = drand48()) == 0); 540 return (m - s * log(q1 * s)); 541 } 542 #endif /* SIM */ 543