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