1 #include <u.h> 2 #include <libc.h> 3 #include <auth.h> 4 #include <ip.h> 5 #include <mp.h> 6 7 /* nanosecond times */ 8 #define SEC 1000000000LL 9 #define MIN (60LL*SEC) 10 #define HOUR (60LL*MIN) 11 #define DAY (24LL*HOUR) 12 13 enum { 14 Fs, 15 Rtc, 16 Ntp, 17 Utc, 18 19 HZAvgSecs= 3*60, /* target averaging period for the frequency in seconds */ 20 MinSampleSecs= 60, /* minimum sampling time in seconds */ 21 }; 22 23 24 char *dir = "/tmp"; // directory sample files live in 25 char *logfile = "timesync"; 26 char *timeserver; 27 char *Rootid; 28 int utcfil; 29 int debug; 30 int impotent; 31 int logging; 32 int type; 33 int gmtdelta; // rtc+gmtdelta = gmt 34 uvlong avgerr; 35 36 // ntp server info 37 int stratum = 14; 38 vlong mydisp, rootdisp; 39 vlong mydelay, rootdelay; 40 vlong avgdelay; 41 vlong lastutc; 42 uchar rootid[4]; 43 char *sysid; 44 int myprec; 45 46 // list of time samples 47 typedef struct Sample Sample; 48 struct Sample 49 { 50 Sample *next; 51 uvlong ticks; 52 vlong ltime; 53 vlong stime; 54 }; 55 56 // ntp packet 57 typedef struct NTPpkt NTPpkt; 58 struct NTPpkt 59 { 60 uchar mode; 61 uchar stratum; 62 uchar poll; 63 uchar precision; 64 uchar rootdelay[4]; 65 uchar rootdisp[4]; 66 uchar rootid[4]; 67 uchar refts[8]; 68 uchar origts[8]; // departed client 69 uchar recvts[8]; // arrived at server 70 uchar xmitts[8]; // departed server 71 uchar keyid[4]; 72 uchar digest[16]; 73 }; 74 75 // ntp server 76 typedef struct NTPserver NTPserver; 77 struct NTPserver 78 { 79 NTPserver *next; 80 char *name; 81 uchar stratum; 82 uchar precision; 83 vlong rootdelay; 84 vlong rootdisp; 85 vlong rtt; 86 vlong dt; 87 }; 88 89 NTPserver *ntpservers; 90 91 enum 92 { 93 NTPSIZE= 48, // basic ntp packet 94 NTPDIGESTSIZE= 20, // key and digest 95 }; 96 97 static void addntpserver(char *name); 98 static int adjustperiod(vlong diff, vlong accuracy, int secs); 99 static void background(void); 100 static int caperror(vlong dhz, int tsecs, vlong taccuracy); 101 static long fstime(void); 102 static int gettime(vlong *nsec, uvlong *ticks, uvlong *hz); // returns time, ticks, hz 103 static int getclockprecision(vlong); 104 static void hnputts(void *p, vlong nsec); 105 static void hnputts(void *p, vlong nsec); 106 static void inittime(void); 107 static vlong nhgetts(void *p); 108 static vlong nhgetts(void *p); 109 static void ntpserver(char*); 110 static vlong ntpsample(void); 111 static int ntptimediff(NTPserver *ns); 112 static int openfreqfile(void); 113 static vlong readfreqfile(int fd, vlong ohz, vlong minhz, vlong maxhz); 114 static long rtctime(void); 115 static vlong sample(long (*get)(void)); 116 static void setpriority(void); 117 static void setrootid(char *d); 118 static void settime(vlong now, uvlong hz, vlong delta, int n); // set time, hz, delta, period 119 static vlong utcsample(void); 120 static uvlong vabs(vlong); 121 static uvlong whatisthefrequencykenneth(uvlong hz, uvlong minhz, uvlong maxhz, vlong dt, vlong ticks, vlong period); 122 static void writefreqfile(int fd, vlong hz, int secs, vlong diff); 123 124 // ((1970-1900)*365 + 17/*leap days*/)*24*60*60 125 #define EPOCHDIFF 2208988800UL 126 127 void 128 main(int argc, char **argv) 129 { 130 int i; 131 int secs; // sampling period 132 int tsecs; // temporary sampling period 133 int t, fd; 134 Sample *s, *x, *first, **l; 135 vlong diff, accuracy, taccuracy; 136 uvlong hz, minhz, maxhz, period, nhz; 137 char *servenet[4]; 138 int nservenet; 139 char *a; 140 Tm tl, tg; 141 142 type = Fs; // by default, sync with the file system 143 debug = 0; 144 accuracy = 1000000LL; // default accuracy is 1 millisecond 145 nservenet = 0; 146 tsecs = secs = MinSampleSecs; 147 timeserver = ""; 148 149 ARGBEGIN{ 150 case 'a': 151 a = ARGF(); 152 if(a == nil) 153 sysfatal("bad accuracy specified"); 154 accuracy = strtoll(a, 0, 0); // accuracy specified in ns 155 if(accuracy <= 1LL) 156 sysfatal("bad accuracy specified"); 157 break; 158 case 'f': 159 type = Fs; 160 stratum = 2; 161 break; 162 case 'r': 163 type = Rtc; 164 stratum = 0; 165 break; 166 case 'U': 167 type = Utc; 168 stratum = 1; 169 timeserver = ARGF(); 170 if (timeserver == nil) 171 sysfatal("bad time source"); 172 break; 173 case 'n': 174 type = Ntp; 175 break; 176 case 'D': 177 debug = 1; 178 break; 179 case 'd': 180 dir = ARGF(); 181 break; 182 case 'L': 183 // 184 // Assume time source in local time rather than GMT. 185 // Calculate difference so that rtctime can return GMT. 186 // This is useful with the rtc on PC's that run Windows 187 // since Windows keeps the local time in the rtc. 188 // 189 t = time(0); 190 tl = *localtime(t); 191 tg = *gmtime(t); 192 193 // if the years are different, we're at most a day off, so just rewrite 194 if(tl.year < tg.year){ 195 tg.year--; 196 tg.yday = tl.yday + 1; 197 }else if(tl.year > tg.year){ 198 tl.year--; 199 tl.yday = tg.yday+1; 200 } 201 assert(tl.year == tg.year); 202 203 tg.sec -= tl.sec; 204 tg.min -= tl.min; 205 tg.hour -= tl.hour; 206 tg.yday -= tl.yday; 207 gmtdelta = tg.sec+60*(tg.min+60*(tg.hour+tg.yday*24)); 208 209 assert(abs(gmtdelta) <= 24*60*60); 210 break; 211 case 'i': 212 impotent = 1; 213 break; 214 case 'I': 215 Rootid = ARGF(); 216 break; 217 case 's': 218 if(nservenet >= nelem(servenet)) 219 sysfatal("too many networks to serve on"); 220 a = ARGF(); 221 if(a == nil) 222 sysfatal("must specify network to serve on"); 223 servenet[nservenet++] = a; 224 break; 225 case 'l': 226 logging = 1; 227 break; 228 case 'S': 229 a = ARGF(); 230 if(a == nil) 231 sysfatal("bad stratum specified"); 232 stratum = strtoll(a, 0, 0); 233 break; 234 }ARGEND; 235 236 fmtinstall('E', eipfmt); 237 fmtinstall('I', eipfmt); 238 fmtinstall('V', eipfmt); 239 sysid = getenv("sysname"); 240 241 // detach from the current namespace 242 if(debug) 243 rfork(RFNAMEG); 244 245 switch(type){ 246 case Fs: 247 if(argc > 0) 248 timeserver = argv[0]; 249 else 250 timeserver = "/srv/boot"; 251 break; 252 case Ntp: 253 if(argc > 0){ 254 for(i = 0; i <argc; i++) 255 addntpserver(argv[i]); 256 } else { 257 addntpserver("$ntp"); 258 } 259 break; 260 } 261 262 setpriority(); 263 264 // figure out our time interface and initial frequency 265 inittime(); 266 gettime(0, 0, &hz); 267 minhz = hz - (hz>>2); 268 maxhz = hz + (hz>>2); 269 myprec = getclockprecision(hz); 270 271 // convert the accuracy from nanoseconds to ticks 272 taccuracy = hz*accuracy/SEC; 273 274 // 275 // bind in clocks 276 // 277 switch(type){ 278 case Fs: 279 fd = open(timeserver, ORDWR); 280 if(fd < 0) 281 sysfatal("opening %s: %r\n", timeserver); 282 if(amount(fd, "/n/boot", MREPL, "") < 0) 283 sysfatal("mounting %s: %r\n", timeserver); 284 close(fd); 285 break; 286 case Rtc: 287 bind("#r", "/dev", MAFTER); 288 if(access("/dev/rtc", AREAD) < 0) 289 sysfatal("accessing /dev/rtc: %r\n"); 290 break; 291 case Utc: 292 fd = open(timeserver, OREAD); 293 if(fd < 0) 294 sysfatal("opening %s: %r\n", timeserver); 295 utcfil = fd; 296 break; 297 } 298 299 // 300 // start a local ntp server(s) 301 // 302 for(i = 0; i < nservenet; i++){ 303 switch(rfork(RFPROC|RFFDG|RFMEM|RFNOWAIT)){ 304 case -1: 305 sysfatal("forking: %r"); 306 break; 307 case 0: 308 ntpserver(servenet[i]); 309 _exits(0); 310 break; 311 default: 312 break; 313 } 314 } 315 316 // get the last known frequency from the file 317 fd = openfreqfile(); 318 hz = readfreqfile(fd, hz, minhz, maxhz); 319 320 // this is the main loop. it gets a sample, adjusts the 321 // clock and computes a sleep period until the next loop. 322 // we balance frequency drift against the length of the 323 // period to avoid blowing the accuracy limit. 324 first = nil; 325 l = &first; 326 avgerr = accuracy>>1; 327 for(;; background(),sleep(tsecs*(1000))){ 328 s = mallocz(sizeof(*s), 1); 329 diff = 0; 330 331 // get times for this sample 332 switch(type){ 333 case Fs: 334 s->stime = sample(fstime); 335 break; 336 case Rtc: 337 s->stime = sample(rtctime); 338 break; 339 case Utc: 340 s->stime = utcsample(); 341 if(s->stime == 0LL){ 342 if(logging) 343 syslog(0, logfile, "no sample"); 344 free(s); 345 if (secs > 60 * 15) 346 tsecs = 60*15; 347 continue; 348 } 349 break; 350 case Ntp: 351 diff = ntpsample(); 352 if(diff == 0LL){ 353 if(logging) 354 syslog(0, logfile, "no sample"); 355 free(s); 356 if(secs > 60*15) 357 tsecs = 60*15; 358 continue; 359 } 360 break; 361 } 362 363 // use fastest method to read local clock and ticks 364 gettime(&s->ltime, &s->ticks, 0); 365 if(type == Ntp) 366 s->stime = s->ltime + diff; 367 368 // if the sample was bad, ignore it 369 if(s->stime < 0){ 370 free(s); 371 continue; 372 } 373 374 // reset local time 375 diff = s->stime - s->ltime; 376 if(diff > 10*SEC || diff < -10*SEC){ 377 // we're way off, just set the time 378 secs = MinSampleSecs; 379 settime(s->stime, 0, 0, 0); 380 } else { 381 // keep a running average of the error. 382 avgerr = (avgerr>>1) + (vabs(diff)>>1); 383 384 // the time to next sample depends on how good or 385 // bad we're doing. 386 tsecs = secs = adjustperiod(diff, accuracy, secs); 387 388 // work off the fixed difference. This is done 389 // by adding a ramp to the clock. Each 100th of a 390 // second (or so) the kernel will add diff/(4*secs*100) 391 // to the clock. we only do 1/4 of the difference per 392 // period to dampen any measurement noise. 393 settime(-1, 0, diff, 4*secs); 394 395 } 396 if(debug) 397 fprint(2, "δ %lld avgδ %lld f %lld\n", diff, avgerr, hz); 398 399 // dump old samples (keep at least one) 400 while(first != nil){ 401 if(first->next == nil) 402 break; 403 if(s->stime - first->next->stime < DAY) 404 break; 405 x = first; 406 first = first->next; 407 free(x); 408 } 409 410 // The sampling error is limited by the total error. If 411 // we make sure the sampling period is at least 16 million 412 // times the average error, we should calculate a frequency 413 // with on average a 1e-7 error. 414 // 415 // So that big hz changes don't blow our accuracy requirement, 416 // we shorten the period to make sure that δhz*secs will be 417 // greater than the accuracy limit. 418 period = avgerr<<24; 419 for(x = first; x != nil; x = x->next){ 420 if(s->stime - x->stime < period) 421 break; 422 if(x->next == nil || s->stime - x->next->stime < period) 423 break; 424 } 425 if(x != nil){ 426 nhz = whatisthefrequencykenneth( 427 hz, minhz, maxhz, 428 s->stime - x->stime, 429 s->ticks - x->ticks, 430 period); 431 tsecs = caperror(vabs(nhz-hz), tsecs, taccuracy); 432 hz = nhz; 433 writefreqfile(fd, hz, (s->stime - x->stime)/SEC, diff); 434 } 435 436 // add current sample to list. 437 *l = s; 438 l = &s->next; 439 440 if(logging) 441 syslog(0, logfile, "δ %lld avgδ %lld hz %lld", 442 diff, avgerr, hz); 443 } 444 } 445 446 // 447 // adjust the sampling period with some histeresis 448 // 449 static int 450 adjustperiod(vlong diff, vlong accuracy, int secs) 451 { 452 uvlong absdiff; 453 454 absdiff = vabs(diff); 455 456 if(absdiff < (accuracy>>1)) 457 secs += 60; 458 else if(absdiff > accuracy) 459 secs >>= 1; 460 else 461 secs -= 60; 462 if(secs < MinSampleSecs) 463 secs = MinSampleSecs; 464 return secs; 465 } 466 467 // 468 // adjust the frequency 469 // 470 static uvlong 471 whatisthefrequencykenneth(uvlong hz, uvlong minhz, uvlong maxhz, vlong dt, vlong ticks, vlong period) 472 { 473 static mpint *mpdt; 474 static mpint *mpticks; 475 static mpint *mphz; 476 static mpint *mpbillion; 477 uvlong ohz = hz; 478 479 // sanity check 480 if(dt <= 0 || ticks <= 0) 481 return hz; 482 483 if(mphz == nil){ 484 mphz = mpnew(0); 485 mpbillion = uvtomp(SEC, nil); 486 } 487 488 // hz = (ticks*SEC)/dt 489 mpdt = vtomp(dt, mpdt); 490 mpticks = vtomp(ticks, mpticks); 491 mpmul(mpticks, mpbillion, mpticks); 492 mpdiv(mpticks, mpdt, mphz, nil); 493 hz = mptoui(mphz); 494 495 // sanity 496 if(hz < minhz || hz > maxhz) 497 return ohz; 498 499 // damp the change if we're shorter than the target period 500 if(period > dt) 501 hz = (12ULL*ohz + 4ULL*hz)/16ULL; 502 503 settime(-1, hz, 0, 0); 504 return hz; 505 } 506 507 // We may be changing the frequency to match a bad measurement 508 // or to match a condition no longer in effet. To make sure 509 // that this doesn't blow our error budget over the next measurement 510 // period, shorten the period to make sure that δhz*secs will be 511 // less than the accuracy limit. Here taccuracy is accuracy converted 512 // from nanoseconds to ticks. 513 static int 514 caperror(vlong dhz, int tsecs, vlong taccuracy) 515 { 516 if(dhz*tsecs <= taccuracy) 517 return tsecs; 518 519 if(debug) 520 fprint(2, "δhz %lld tsecs %d tacc %lld\n", dhz, tsecs, taccuracy); 521 522 tsecs = taccuracy/dhz; 523 if(tsecs < MinSampleSecs) 524 tsecs = MinSampleSecs; 525 return tsecs; 526 } 527 528 // 529 // kernel interface 530 // 531 enum 532 { 533 Ibintime, 534 Insec, 535 Itiming, 536 }; 537 int ifc; 538 int bintimefd = -1; 539 int timingfd = -1; 540 int nsecfd = -1; 541 int fastclockfd = -1; 542 543 static void 544 inittime(void) 545 { 546 int mode; 547 548 if(impotent) 549 mode = OREAD; 550 else 551 mode = ORDWR; 552 553 // bind in clocks 554 if(access("/dev/time", 0) < 0) 555 bind("#c", "/dev", MAFTER); 556 if(access("/dev/rtc", 0) < 0) 557 bind("#r", "/dev", MAFTER); 558 559 // figure out what interface we have 560 ifc = Ibintime; 561 bintimefd = open("/dev/bintime", mode); 562 if(bintimefd >= 0) 563 return; 564 ifc = Insec; 565 nsecfd = open("/dev/nsec", mode); 566 if(nsecfd < 0) 567 sysfatal("opening /dev/nsec"); 568 fastclockfd = open("/dev/fastclock", mode); 569 if(fastclockfd < 0) 570 sysfatal("opening /dev/fastclock"); 571 timingfd = open("/dev/timing", OREAD); 572 if(timingfd < 0) 573 return; 574 ifc = Itiming; 575 } 576 577 // 578 // convert binary numbers from/to kernel 579 // 580 static uvlong uvorder = 0x0001020304050607ULL; 581 582 static uchar* 583 be2vlong(vlong *to, uchar *f) 584 { 585 uchar *t, *o; 586 int i; 587 588 t = (uchar*)to; 589 o = (uchar*)&uvorder; 590 for(i = 0; i < sizeof(vlong); i++) 591 t[o[i]] = f[i]; 592 return f+sizeof(vlong); 593 } 594 595 static uchar* 596 vlong2be(uchar *t, vlong from) 597 { 598 uchar *f, *o; 599 int i; 600 601 f = (uchar*)&from; 602 o = (uchar*)&uvorder; 603 for(i = 0; i < sizeof(vlong); i++) 604 t[i] = f[o[i]]; 605 return t+sizeof(vlong); 606 } 607 608 static long order = 0x00010203; 609 610 static uchar* 611 be2long(long *to, uchar *f) 612 { 613 uchar *t, *o; 614 int i; 615 616 t = (uchar*)to; 617 o = (uchar*)ℴ 618 for(i = 0; i < sizeof(long); i++) 619 t[o[i]] = f[i]; 620 return f+sizeof(long); 621 } 622 623 static uchar* 624 long2be(uchar *t, long from) 625 { 626 uchar *f, *o; 627 int i; 628 629 f = (uchar*)&from; 630 o = (uchar*)ℴ 631 for(i = 0; i < sizeof(long); i++) 632 t[i] = f[o[i]]; 633 return t+sizeof(long); 634 } 635 636 // 637 // read ticks and local time in nanoseconds 638 // 639 static int 640 gettime(vlong *nsec, uvlong *ticks, uvlong *hz) 641 { 642 int i, n; 643 uchar ub[3*8], *p; 644 char b[2*24+1]; 645 646 switch(ifc){ 647 case Ibintime: 648 n = sizeof(vlong); 649 if(hz != nil) 650 n = 3*sizeof(vlong); 651 if(ticks != nil) 652 n = 2*sizeof(vlong); 653 i = read(bintimefd, ub, n); 654 if(i != n) 655 break; 656 p = ub; 657 if(nsec != nil) 658 be2vlong(nsec, ub); 659 p += sizeof(vlong); 660 if(ticks != nil) 661 be2vlong((vlong*)ticks, p); 662 p += sizeof(vlong); 663 if(hz != nil) 664 be2vlong((vlong*)hz, p); 665 return 0; 666 case Itiming: 667 n = sizeof(vlong); 668 if(ticks != nil) 669 n = 2*sizeof(vlong); 670 i = read(timingfd, ub, n); 671 if(i != n) 672 break; 673 p = ub; 674 if(nsec != nil) 675 be2vlong(nsec, ub); 676 p += sizeof(vlong); 677 if(ticks != nil) 678 be2vlong((vlong*)ticks, p); 679 if(hz != nil){ 680 seek(fastclockfd, 0, 0); 681 n = read(fastclockfd, b, sizeof(b)-1); 682 if(n <= 0) 683 break; 684 b[n] = 0; 685 *hz = strtoll(b+24, 0, 0); 686 } 687 return 0; 688 case Insec: 689 if(nsec != nil){ 690 seek(nsecfd, 0, 0); 691 n = read(nsecfd, b, sizeof(b)-1); 692 if(n <= 0) 693 break; 694 b[n] = 0; 695 *nsec = strtoll(b, 0, 0); 696 } 697 if(ticks != nil){ 698 seek(fastclockfd, 0, 0); 699 n = read(fastclockfd, b, sizeof(b)-1); 700 if(n <= 0) 701 break; 702 b[n] = 0; 703 *ticks = strtoll(b, 0, 0); 704 } 705 if(hz != nil){ 706 seek(fastclockfd, 0, 0); 707 n = read(fastclockfd, b, sizeof(b)-1); 708 if(n <= 24) 709 break; 710 b[n] = 0; 711 *hz = strtoll(b+24, 0, 0); 712 } 713 return 0; 714 } 715 return -1; 716 } 717 718 static void 719 settime(vlong now, uvlong hz, vlong delta, int n) 720 { 721 uchar b[1+sizeof(vlong)+sizeof(long)], *p; 722 723 if(debug) 724 fprint(2, "settime(now=%lld, hz=%llud, delta=%lld, period=%d)\n", now, hz, delta, n); 725 if(impotent) 726 return; 727 switch(ifc){ 728 case Ibintime: 729 if(now >= 0){ 730 p = b; 731 *p++ = 'n'; 732 p = vlong2be(p, now); 733 if(write(bintimefd, b, p-b) < 0) 734 sysfatal("writing /dev/bintime: %r"); 735 } 736 if(delta != 0){ 737 p = b; 738 *p++ = 'd'; 739 p = vlong2be(p, delta); 740 p = long2be(p, n); 741 if(write(bintimefd, b, p-b) < 0) 742 sysfatal("writing /dev/bintime: %r"); 743 } 744 if(hz != 0){ 745 p = b; 746 *p++ = 'f'; 747 p = vlong2be(p, hz); 748 if(write(bintimefd, b, p-b) < 0) 749 sysfatal("writing /dev/bintime: %r"); 750 } 751 break; 752 case Itiming: 753 case Insec: 754 seek(nsecfd, 0, 0); 755 if(now >= 0 || delta != 0){ 756 if(fprint(nsecfd, "%lld %lld %d", now, delta, n) < 0) 757 sysfatal("writing /dev/nsec: %r"); 758 } 759 if(hz > 0){ 760 seek(fastclockfd, 0, 0); 761 if(fprint(fastclockfd, "%lld", hz) < 0) 762 sysfatal("writing /dev/fastclock: %r"); 763 } 764 } 765 } 766 767 // 768 // set priority high and wire process to a processor 769 // 770 static void 771 setpriority(void) 772 { 773 int fd; 774 char buf[32]; 775 776 sprint(buf, "/proc/%d/ctl", getpid()); 777 fd = open(buf, ORDWR); 778 if(fd < 0){ 779 fprint(2, "can't set priority\n"); 780 return; 781 } 782 if(fprint(fd, "pri 100") < 0) 783 fprint(2, "can't set priority\n"); 784 if(fprint(fd, "wired 2") < 0) 785 fprint(2, "can't wire process\n"); 786 close(fd); 787 } 788 789 // convert to ntp timestamps 790 static void 791 hnputts(void *p, vlong nsec) 792 { 793 uchar *a; 794 ulong tsh; 795 ulong tsl; 796 797 a = p; 798 799 // zero is a special case 800 if(nsec == 0) 801 return; 802 803 tsh = (nsec/SEC); 804 nsec -= tsh*SEC; 805 tsl = (nsec<<32)/SEC; 806 hnputl(a, tsh+EPOCHDIFF); 807 hnputl(a+4, tsl); 808 } 809 810 // convert from ntp timestamps 811 static vlong 812 nhgetts(void *p) 813 { 814 uchar *a; 815 ulong tsh, tsl; 816 vlong nsec; 817 818 a = p; 819 tsh = nhgetl(a); 820 tsl = nhgetl(a+4); 821 nsec = tsl*SEC; 822 nsec >>= 32; 823 nsec += (tsh - EPOCHDIFF)*SEC; 824 return nsec; 825 } 826 827 // convert to ntp 32 bit fixed point 828 static void 829 hnputfp(void *p, vlong nsec) 830 { 831 uchar *a; 832 ulong fp; 833 834 a = p; 835 836 fp = nsec/(SEC/((vlong)(1<<16))); 837 hnputl(a, fp); 838 } 839 840 // convert from ntp fixed point to nanosecs 841 static vlong 842 nhgetfp(void *p) 843 { 844 uchar *a; 845 ulong fp; 846 vlong nsec; 847 848 a = p; 849 fp = nhgetl(a); 850 nsec = ((vlong)fp)*(SEC/((vlong)(1<<16))); 851 return nsec; 852 } 853 854 // get network address of the server 855 static void 856 setrootid(char *d) 857 { 858 char buf[128]; 859 int fd, n; 860 char *p; 861 862 snprint(buf, sizeof(buf), "%s/remote", d); 863 fd = open(buf, OREAD); 864 if(fd < 0) 865 return; 866 n = read(fd, buf, sizeof buf); 867 close(fd); 868 if(n <= 0) 869 return; 870 p = strchr(buf, '!'); 871 if(p != nil) 872 *p = 0; 873 v4parseip(rootid, buf); 874 } 875 876 static void 877 ding(void*, char *s) 878 { 879 if(strstr(s, "alarm") != nil) 880 noted(NCONT); 881 noted(NDFLT); 882 } 883 884 static void 885 addntpserver(char *name) 886 { 887 NTPserver *ns, **l; 888 889 ns = mallocz(sizeof(NTPserver), 1); 890 if(ns == nil) 891 sysfatal("addntpserver: %r"); 892 timeserver = strdup(name); 893 ns->name = name; 894 for(l = &ntpservers; *l != nil; l = &(*l)->next) 895 ; 896 *l = ns; 897 } 898 899 // 900 // sntp client, we keep calling if the delay seems 901 // unusually high, i.e., 30% longer than avg. 902 // 903 static int 904 ntptimediff(NTPserver *ns) 905 { 906 int fd, tries, n; 907 NTPpkt ntpin, ntpout; 908 vlong dt, recvts, origts, xmitts, destts, x; 909 char dir[64]; 910 911 fd = dial(netmkaddr(ns->name, "udp", "ntp"), 0, dir, 0); 912 if(fd < 0){ 913 syslog(0, logfile, "can't reach %s: %r", ns->name); 914 return -1; 915 } 916 setrootid(dir); 917 notify(ding); 918 919 memset(&ntpout, 0, sizeof(ntpout)); 920 ntpout.mode = 3 | (3 << 3); 921 922 for(tries = 0; tries < 3; tries++){ 923 alarm(2*1000); 924 925 gettime(&x, 0, 0); 926 hnputts(ntpout.xmitts, x); 927 if(write(fd, &ntpout, NTPSIZE) < 0){ 928 alarm(0); 929 continue; 930 } 931 932 n = read(fd, &ntpin, sizeof(ntpin)); 933 alarm(0); 934 gettime(&destts, 0, 0); 935 if(n >= NTPSIZE){ 936 close(fd); 937 938 // we got one, use it 939 recvts = nhgetts(ntpin.recvts); 940 origts = nhgetts(ntpin.origts); 941 xmitts = nhgetts(ntpin.xmitts); 942 dt = ((recvts - origts) + (xmitts - destts))/2; 943 944 // save results 945 ns->rtt = ((destts - origts) - (xmitts - recvts))/2; 946 ns->dt = dt; 947 ns->stratum = ntpin.stratum; 948 ns->precision = ntpin.precision; 949 ns->rootdelay = nhgetfp(ntpin.rootdelay); 950 ns->rootdisp = nhgetfp(ntpin.rootdisp); 951 952 if(debug) 953 fprint(2, "ntp %s stratum %d ntpdelay(%lld)\n", 954 ns->name, ntpin.stratum, ns->rtt); 955 return 0; 956 } 957 958 // try again 959 sleep(250); 960 } 961 close(fd); 962 return -1; 963 } 964 965 static vlong 966 ntpsample(void) 967 { 968 NTPserver *tns, *ns; 969 vlong metric, x; 970 971 metric = 1000LL*SEC; 972 ns = nil; 973 for(tns = ntpservers; tns != nil; tns = tns->next){ 974 if(ntptimediff(tns) < 0) 975 continue; 976 x = vabs(tns->rootdisp) + (vabs(tns->rtt+tns->rootdelay)>>1); 977 if(debug) 978 fprint(2, "ntp %s rootdelay %lld rootdisp %lld metric %lld\n", 979 tns->name, tns->rootdelay, tns->rootdisp, x); 980 if(x < metric){ 981 metric = x; 982 ns = tns; 983 } 984 } 985 986 if(ns == nil) 987 return 0LL; 988 989 // save data for our server 990 rootdisp = ns->rootdisp; 991 rootdelay = ns->rootdelay; 992 mydelay = ns->rtt; 993 mydisp = avgerr; 994 if(ns->stratum == 0) 995 stratum = 0; 996 else 997 stratum = ns->stratum + 1; 998 999 return ns->dt; 1000 } 1001 1002 // 1003 // sample the utc file 1004 // 1005 static vlong 1006 utcsample(void) 1007 { 1008 vlong s; 1009 int n; 1010 char *v[2], buf[128]; 1011 1012 s = 0; 1013 seek(utcfil, 0, 0); 1014 n = read(utcfil, buf, sizeof buf - 1); 1015 if (n <= 0) 1016 return(0LL); 1017 buf[n] = 0; 1018 n = tokenize(buf, v, nelem(v)); 1019 if (strcmp(v[0], "0") == 0) 1020 return(0LL); 1021 if (n == 2) { 1022 gettime(&s, nil, nil); 1023 s -= atoll(v[1]); 1024 } 1025 lastutc = atoll(v[0]) + s; 1026 return(lastutc); 1027 } 1028 1029 // 1030 // sntp server 1031 // 1032 static int 1033 openlisten(char *net) 1034 { 1035 int fd, cfd; 1036 char data[128]; 1037 char devdir[40]; 1038 1039 sprint(data, "%s/udp!*!ntp", net); 1040 cfd = announce(data, devdir); 1041 if(cfd < 0) 1042 sysfatal("can't announce"); 1043 if(fprint(cfd, "headers") < 0) 1044 sysfatal("can't set header mode"); 1045 fprint(cfd, "oldheaders"); 1046 1047 sprint(data, "%s/data", devdir); 1048 1049 fd = open(data, ORDWR); 1050 if(fd < 0) 1051 sysfatal("open udp data"); 1052 return fd; 1053 } 1054 static void 1055 ntpserver(char *servenet) 1056 { 1057 int fd, n; 1058 NTPpkt *ntp; 1059 char buf[512]; 1060 int vers, mode; 1061 vlong recvts, x; 1062 1063 fd = openlisten(servenet); 1064 1065 if (Rootid == nil) 1066 switch(type){ 1067 case Fs: 1068 Rootid = "WWV"; 1069 break; 1070 case Rtc: 1071 Rootid = "LOCL"; 1072 break; 1073 case Utc: 1074 Rootid = "UTC"; 1075 break; 1076 case Ntp: 1077 /* set by the ntp client */ 1078 break; 1079 } 1080 if (Rootid != nil) 1081 memmove(rootid, Rootid, strlen(Rootid) > 4 ? 4 : strlen(Rootid)); 1082 1083 for(;;){ 1084 n = read(fd, buf, sizeof(buf)); 1085 gettime(&recvts, 0, 0); 1086 if(n < 0) 1087 return; 1088 if(n < OUdphdrsize + NTPSIZE) 1089 continue; 1090 1091 ntp = (NTPpkt*)(buf+OUdphdrsize); 1092 mode = ntp->mode & 7; 1093 vers = (ntp->mode>>3) & 7; 1094 if(mode != 3) 1095 continue; 1096 1097 ntp->mode = (vers<<3)|4; 1098 ntp->stratum = stratum; 1099 ntp->precision = myprec; 1100 hnputfp(ntp->rootdelay, rootdelay + mydelay); 1101 hnputfp(ntp->rootdisp, rootdisp + mydisp); 1102 hnputts(ntp->refts, lastutc); 1103 memmove(ntp->origts, ntp->xmitts, sizeof(ntp->origts)); 1104 hnputts(ntp->recvts, recvts); 1105 memmove(ntp->rootid, rootid, sizeof(ntp->rootid)); 1106 gettime(&x, 0, 0); 1107 hnputts(ntp->xmitts, x); 1108 write(fd, buf, NTPSIZE+OUdphdrsize); 1109 } 1110 } 1111 1112 // 1113 // get the current time from the file system 1114 // 1115 static long 1116 fstime(void) 1117 { 1118 Dir *d; 1119 ulong t; 1120 1121 d = dirstat("/n/boot"); 1122 if(d != nil){ 1123 t = d->atime; 1124 free(d); 1125 } else 1126 t = 0; 1127 return t; 1128 } 1129 1130 // 1131 // get the current time from the real time clock 1132 // 1133 static long 1134 rtctime(void) 1135 { 1136 char b[20]; 1137 static int f = -1; 1138 int i, retries; 1139 1140 memset(b, 0, sizeof(b)); 1141 for(retries = 0; retries < 100; retries++){ 1142 if(f < 0) 1143 f = open("/dev/rtc", OREAD|OCEXEC); 1144 if(f < 0) 1145 break; 1146 if(seek(f, 0, 0) < 0 || (i = read(f, b, sizeof(b))) < 0){ 1147 close(f); 1148 f = -1; 1149 } else { 1150 if(i != 0) 1151 break; 1152 } 1153 } 1154 return strtoul(b, 0, 10)+gmtdelta; 1155 } 1156 1157 1158 // 1159 // Sample a clock. We wait for the clock to always 1160 // be at the leading edge of a clock period. 1161 // 1162 static vlong 1163 sample(long (*get)(void)) 1164 { 1165 long this, last; 1166 vlong start, end; 1167 1168 /* 1169 * wait for the second to change 1170 */ 1171 last = (*get)(); 1172 for(;;){ 1173 gettime(&start, 0, 0); 1174 this = (*get)(); 1175 gettime(&end, 0, 0); 1176 if(this != last) 1177 break; 1178 last = this; 1179 } 1180 return SEC*this - (end-start)/2; 1181 } 1182 1183 // 1184 // the name of the frequency file has the method and possibly the 1185 // server name encoded in it. 1186 // 1187 static int 1188 openfreqfile(void) 1189 { 1190 char buf[29]; 1191 int fd; 1192 1193 if(sysid == nil) 1194 return -1; 1195 1196 switch(type){ 1197 case Ntp: 1198 snprint(buf, sizeof buf, "%s/ts.%s.%d.%s", dir, sysid, type, timeserver); 1199 break; 1200 default: 1201 snprint(buf, sizeof buf, "%s/ts.%s.%d", dir, sysid, type); 1202 break; 1203 } 1204 fd = open(buf, ORDWR); 1205 if(fd < 0) 1206 fd = create(buf, ORDWR, 0666); 1207 if(fd < 0) 1208 return -1; 1209 return fd; 1210 } 1211 1212 // 1213 // the file contains the last known frequency and the 1214 // number of seconds it was sampled over 1215 // 1216 static vlong 1217 readfreqfile(int fd, vlong ohz, vlong minhz, vlong maxhz) 1218 { 1219 int n; 1220 char buf[128]; 1221 vlong hz; 1222 1223 n = read(fd, buf, sizeof(buf)-1); 1224 if(n <= 0) 1225 return ohz; 1226 buf[n] = 0; 1227 hz = strtoll(buf, nil, 0); 1228 1229 if(hz > maxhz || hz < minhz) 1230 return ohz; 1231 1232 settime(-1, hz, 0, 0); 1233 return hz; 1234 } 1235 1236 // 1237 // remember hz and averaging period 1238 // 1239 static void 1240 writefreqfile(int fd, vlong hz, int secs, vlong diff) 1241 { 1242 long now; 1243 static long last; 1244 1245 if(fd < 0) 1246 return; 1247 now = time(0); 1248 if(now - last < 10*60) 1249 return; 1250 last = now; 1251 if(seek(fd, 0, 0) < 0) 1252 return; 1253 fprint(fd, "%lld %d %d %lld\n", hz, secs, type, diff); 1254 } 1255 1256 static uvlong 1257 vabs(vlong x) 1258 { 1259 if(x < 0LL) 1260 return (uvlong)-x; 1261 else 1262 return (uvlong)x; 1263 } 1264 1265 static void 1266 background(void) 1267 { 1268 static int inbackground; 1269 1270 if(inbackground) 1271 return; 1272 1273 if(!debug) { 1274 switch(rfork(RFPROC|RFFDG|RFNAMEG|RFNOTEG|RFNOWAIT)){ 1275 case -1: 1276 sysfatal("forking: %r"); 1277 break; 1278 case 0: 1279 break; 1280 default: 1281 exits(0); 1282 } 1283 } 1284 inbackground = 1; 1285 } 1286 1287 static int 1288 getclockprecision(vlong hz) 1289 { 1290 int i; 1291 1292 i = 8; 1293 while(hz > 0){ 1294 i--; 1295 hz >>= 1; 1296 } 1297 return i; 1298 } 1299