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