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