pull-prototypes-to-head-20020821
[openafs.git] / src / ntp / ntpd.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 RCSID("$Header$");
14
15 #if defined(AFS_SGI_ENV)
16 #define NOSWAP 1
17 #endif
18 #include <stdio.h>
19 #ifdef  AFS_AIX32_ENV
20 #include <signal.h>
21 #endif
22 #ifdef  AFS_SUN5_ENV
23 #include <signal.h>
24 #endif
25 #include <sys/types.h>
26 #include <sys/param.h>
27 #include <sys/uio.h>
28 #include <sys/socket.h>
29 #include <sys/time.h>
30 #ifdef  AFS_SUN5_ENV
31 #define BSD_COMP
32 #endif
33 #include <sys/ioctl.h>
34 #include <sys/resource.h>
35 #ifdef  AFS_SUN5_ENV
36 #include <fcntl.h>
37 #endif
38 #include <sys/file.h>
39 #ifdef NOSWAP
40 #include <sys/lock.h>
41 #endif
42
43 #include <net/if.h>
44
45 #include <netinet/in.h>
46 #include <netinet/in_systm.h>
47 #include <netinet/ip.h>
48 #include <netinet/udp.h>
49 #include <arpa/inet.h>
50 #include <netdb.h>
51 #include <strings.h>
52 #include <errno.h>
53 #include <syslog.h>
54 #ifndef LOG_NTP
55 #define LOG_NTP LOG_DAEMON
56 #endif
57 #ifdef  AFS_SUN5_ENV
58 #include <libelf.h>
59 #endif
60 #include <nlist.h>
61
62 #ifdef AFS_AIX32_ENV
63 #include <sys/select.h>
64 #include <sys/signal.h>
65 #endif
66
67 #ifdef  AFS_HPUX_ENV
68 #include <signal.h>
69 #endif
70
71 #include "ntp.h"
72 #include "patchlevel.h"
73
74 #define TRUE    1
75 #define FALSE   0
76
77 struct sockaddr_in dst_sock = {AF_INET};
78
79 struct servent *servp;
80 struct list peer_list;
81
82 struct itimerval it;
83 struct itimerval *itp = &it;
84 struct timeval tv;
85 char *prog_name;
86
87 char *conf = NTPINITFILE;
88 char *driftcomp_file = NTPDRIFTCOMP;
89 static int drift_fd = -1;
90
91 #ifdef  DEBUG
92 int debug = 0;
93 #endif
94
95 int     tickadj = 0;
96 int     dotickadj = 0;
97 int     dosynctodr = 0;
98
99 #ifdef  NOSWAP
100 int     noswap = 0;
101 #endif
102
103 int doset = 1;
104 int ticked;
105 int selfds;
106 int trusting = 1;
107 int logstats;
108
109 double WayTooBig = WAYTOOBIG;
110 afs_uint32 clock_watchdog;
111
112 struct ntpdata ntpframe;
113 struct sysdata sys;
114
115 extern int errno;
116 extern char *malloc(), *ntoa();
117 extern double s_fixed_to_double(), ul_fixed_to_double();
118
119 void finish(), timeout(), tock(), make_new_peer(), init_ntp(), initialize(),
120         hourly();
121 extern void transmit(), process_packet(), clock_update(),
122         clear(), clock_filter(), select_clock();
123
124 extern void init_logical_clock();
125
126 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)
127 #define SETTICKADJ
128 #endif
129
130 #if !defined(AFS_SUN5_ENV)
131 #define INIT_KERN_VARS
132 #endif
133
134 #if defined(INIT_KERN_VARS)
135 void init_kern_vars();
136 #endif  /* INIT_KERN_VARS */
137
138 #include "AFS_component_version_number.c"
139
140 main(argc, argv)
141         int argc;
142         char *argv[];
143 {
144         struct sockaddr_in *dst = &dst_sock;
145         struct ntpdata *pkt = &ntpframe;
146         fd_set readfds, tmpmask;
147         int dstlen = sizeof(struct sockaddr_in);
148         int cc;
149         int dontFork = 0;
150         register int i;
151         extern char *optarg;
152         extern int atoi();
153
154 #if     defined(DEBUG) && defined(SIGUSR1) && defined(SIGUSR2)
155         void incdebug(), decdebug();
156 #endif
157
158 #ifdef  AFS_AIX32_ENV
159         /*
160          * The following signal action for AIX is necessary so that in case of a 
161          * crash (i.e. core is generated) we can include the user's data section 
162          * in the core dump. Unfortunately, by default, only a partial core is
163          * generated which, in many cases, isn't too useful.
164          */
165         struct sigaction nsa;
166     
167         sigemptyset(&nsa.sa_mask);
168         nsa.sa_handler = SIG_DFL;
169         nsa.sa_flags = SA_FULLDUMP;
170         sigaction(SIGSEGV, &nsa, NULL);
171 #endif
172         initialize();           /* call NTP protocol initialization first,
173                                    then allow others to override default
174                                    values */
175         prog_name = argv[0];
176         while ((cc = getopt(argc, argv, "a:c:dD:lstrnf")) != EOF) {
177                 switch (cc) {
178                 case 'a':
179                         if (strcmp(optarg, "any") == 0)
180                                 WayTooBig = 10e15;
181                         else
182                                 WayTooBig = atof(optarg);
183                         break;
184
185                 case 'd':
186 #ifdef  DEBUG
187                         debug++;
188 #else
189                         fprintf(stderr, "%s: not compiled with DEBUG\n",
190                                 prog_name);
191 #endif
192                         break;
193
194                 case 'D':
195 #ifdef  DEBUG
196                         debug = atoi(optarg);
197 #else
198                         fprintf(stderr, "%s: not compiled with DEBUG\n",
199                                 prog_name);
200 #endif
201                         break;
202
203                 case 's':
204                         doset = 0;
205                         break;
206
207                 case 't':
208 #ifdef  SETTICKADJ
209                         dotickadj++;
210 #else
211                         fprintf(stderr, "%s: not compiled to set tickadj\n",
212                                 prog_name);
213 #endif
214                         break;
215
216                 case 'r':
217 #ifdef  SETTICKADJ
218                         dosynctodr++;
219 #else
220                         fprintf(stderr, "%s: not compiled to set kernel variables\n",
221                                 prog_name);
222 #endif
223                         break;
224
225                 case 'n':
226 #ifdef  NOSWAP
227                         noswap = 1;
228 #else
229                         fprintf(stderr, "%s: not compiled for noswap\n",
230                                 prog_name);
231 #endif
232                         break;
233
234                 case 'l':
235                         logstats = 1;
236                         break;
237
238                 case 'c':
239                         conf = optarg;
240                         break;
241
242                 case 'f':
243                         dontFork = 1;
244                         break;
245
246                 default:
247                         fprintf(stderr, "ntpd: -%c: unknown option\n", cc);
248                         break;
249                 }
250         }
251
252 #ifdef  DEBUG
253         if (!debug && !dontFork)
254 #else
255         if (!dontFork)
256 #endif
257             {
258                 if (fork())
259                         exit(0);
260
261                 {
262                         int s;
263                         for (s = getdtablesize(); s >= 0; s--)
264                                 (void) close(s);
265                         (void) open("/", 0);
266                         (void) dup2(0, 1);
267                         (void) dup2(0, 2);
268                         (void) setpgrp(0, getpid());
269                         s = open("/dev/tty", 2);
270                         if (s >= 0) {
271 #ifndef AFS_HPUX_ENV
272                                 (void) ioctl(s, (afs_uint32) TIOCNOTTY, NULL);
273 #endif
274                                 (void) close(s);
275                         }
276                 }
277         }
278
279         openlog("ntpd", LOG_PID | LOG_NDELAY, LOG_NTP);
280 #ifdef  DEBUG
281         if (debug)
282                 setlogmask(LOG_UPTO(LOG_DEBUG));
283         else
284 #endif  /* DEBUG */
285                 setlogmask(LOG_UPTO(LOG_INFO));
286
287         syslog(LOG_NOTICE, "%s version $Revision$", prog_name);
288         syslog(LOG_NOTICE, "patchlevel %d", PATCHLEVEL);
289
290 #ifdef  DEBUG
291         if (debug)
292                 printf("%s version $Revision$ patchlevel %d\n",
293                        prog_name, PATCHLEVEL);
294 #endif
295 #if defined(AFS_AIX_ENV)
296         (void) nice(-10);
297 #else
298 #if defined(AFS_HPUX_ENV)
299         (void) rtprio (0, 90);
300 #else
301         (void) setpriority(PRIO_PROCESS, 0, -10);
302 #endif
303 #endif
304
305 #ifdef  NOSWAP
306         if (noswap)
307                 if (plock(PROCLOCK) != 0)  {
308                         syslog(LOG_ERR, "plock() failed: %m");
309 #ifdef  DEBUG
310                         if (debug)
311                                 perror("plock() failed");
312 #endif
313                 }
314 #endif
315
316         servp = getservbyname("ntp", "udp");
317         if (servp == NULL) {
318                 syslog(LOG_CRIT, "udp/ntp: service unknown, using default %d",
319                        NTP_PORT);
320                 (void) create_sockets(htons(NTP_PORT));
321         } else
322                 (void) create_sockets(servp->s_port);
323
324
325         peer_list.head = peer_list.tail = NULL;
326         peer_list.members = 0;
327
328         init_ntp(conf);
329 #if defined(INIT_KERN_VARS)
330         init_kern_vars();
331 #endif  /* INIT_KERN_VARS */
332         init_logical_clock();
333
334         /*
335          * Attempt to open for writing the file for storing the drift comp
336          * register.  File must already exist for snapshots to be taken.
337          */
338         if ((i = open(driftcomp_file, O_WRONLY|O_CREAT, 0644)) >= 0) {
339                 drift_fd = i;
340         }
341         (void) gettimeofday(&tv, NULL);
342         srand(tv.tv_sec);
343
344         FD_ZERO(&tmpmask);
345         for (i = 0; i < nintf; i++) {
346                 FD_SET(addrs[i].fd, &tmpmask);
347 #ifdef  DEBUG
348                 if (debug>2) {
349                         if (addrs[i].if_flags & IFF_BROADCAST)
350                                 printf("Addr %d: %s fd %d %s broadcast %s\n",
351                                        i, addrs[i].name, addrs[i].fd,
352                                        ntoa(addrs[i].sin.sin_addr),
353                                        ntoa(addrs[i].bcast.sin_addr));
354                         else
355                                 printf("Addr %d: %s fd %d %s\n", i,
356                                        addrs[i].name, addrs[i].fd,
357                                        ntoa(addrs[i].sin.sin_addr));
358                 }
359 #endif
360         }
361
362         (void) signal(SIGINT, finish);
363         (void) signal(SIGTERM, finish);
364         (void) signal(SIGALRM, tock);
365 #if     defined(DEBUG) && defined(SIGUSR1) && defined(SIGUSR2)
366         (void) signal(SIGUSR1, incdebug);
367         (void) signal(SIGUSR2, decdebug);
368 #endif
369         itp->it_interval.tv_sec = (1<<CLOCK_ADJ);
370         itp->it_interval.tv_usec = 0;
371         itp->it_value.tv_sec = 1;
372         itp->it_value.tv_usec = 0;
373
374         /*
375          * Find highest fd in use.  This might save a few microseconds in
376          * the select system call.
377          */
378         for (selfds = FD_SETSIZE - 1; selfds; selfds--)
379                 if (FD_ISSET(selfds, &tmpmask))
380                         break;
381 #ifdef  DEBUG
382         if (debug > 2)
383                 printf("Highest fd in use is %d\n", selfds);
384         if (!selfds) abort();
385 #endif
386         selfds++;
387
388         (void) setitimer(ITIMER_REAL, itp, NULL);
389
390         for (;;) {              /* go into a finite but hopefully very long
391                                  * loop */
392                 int nfds;
393
394                 readfds = tmpmask;
395                 nfds = select(selfds, &readfds, (fd_set *) 0, (fd_set *) 0,
396                                                 NULL);
397                 (void) gettimeofday(&tv, NULL);
398
399                 for(i = 0; i < nintf && nfds; i++) {
400                         if (!FD_ISSET(addrs[i].fd, &readfds))
401                                 continue;
402                         addrs[i].uses++;
403                         dstlen = sizeof(struct sockaddr_in);
404                         if ((cc = 
405                              recvfrom(addrs[i].fd, (char *) pkt, 
406                                       sizeof(ntpframe), 0, 
407                                       (struct sockaddr *) dst, &dstlen)) < 0) {
408
409                                 if (errno != EWOULDBLOCK) {
410                                         syslog(LOG_ERR, "recvfrom: %m");
411 #ifdef  DEBUG
412                                         if(debug > 2)
413                                                 perror("recvfrom");
414 #endif
415                                 }
416                                 continue;
417                         }
418
419                         /* hpux seems to generate these zero's randomly */
420                         if (cc == 0) continue;
421
422                         if (cc < sizeof(*pkt)) {
423 #ifdef  DEBUG
424                                 if (debug)
425                                         printf("Runt packet from %s, got %d bytes, should be %d\n",
426                                                ntoa(dst->sin_addr),
427                                                cc, sizeof(*pkt));
428 #endif
429                                 continue;
430                         } else if (cc > sizeof(*pkt)) {
431 #ifdef  DEBUG
432                                 if (debug)
433                                         printf("too many chars returned by recvfrom.  Host %s, got %d bytes, should be %d\n",
434                                                ntoa(dst->sin_addr),
435                                                cc, sizeof(*pkt));
436 #endif
437                                 continue;
438                         }
439
440                         if (pkt->stratum == INFO_QUERY || 
441                             pkt->stratum == INFO_REPLY) {
442                                 query_mode(dst, pkt, i);
443                                 continue;
444                         }
445 #ifdef  DEBUG
446                         if (debug > 3) {
447                                 printf("\nInput ");
448                                 dump_pkt(dst, pkt, NULL);
449                         }
450 #endif
451                         if ((pkt->status & VERSIONMASK) != NTPVERSION_1)
452                                 continue;
453
454                         receive(dst, pkt, &tv, i);
455                 }
456                 if (ticked) {
457                         ticked = 0;
458                         timeout();
459                 }
460         }                       /* end of forever loop */
461 }
462
463 struct ntp_peer *
464 check_peer(dst, sock)
465         struct sockaddr_in *dst;
466         int sock;
467 {
468         register struct ntp_peer *peer = peer_list.head;
469
470         while (peer != NULL) {
471                 if ((peer->src.sin_addr.s_addr == dst->sin_addr.s_addr) &&
472                     (peer->src.sin_port == dst->sin_port) &&
473                     ((peer->sock == sock) || (peer->sock == -1)))
474                         return peer;
475                 peer = peer->next;
476         }
477         return ((struct ntp_peer *) NULL);
478 }
479
480 #ifdef  DEBUG
481 dump_pkt(dst, pkt, peer)
482         struct sockaddr_in *dst;
483         struct ntpdata *pkt;
484         struct ntp_peer *peer;
485 {
486         struct in_addr clock_host;
487
488         printf("Packet: [%s](%d)\n", inet_ntoa(dst->sin_addr),
489                (int) htons(dst->sin_port));
490         printf("Leap %d, version %d, mode %d, poll %d, precision %d stratum %d",
491                (pkt->status & LEAPMASK) >> 6, (pkt->status & VERSIONMASK) >> 3,
492                pkt->status & MODEMASK, pkt->ppoll, pkt->precision,
493                pkt->stratum);
494         switch (pkt->stratum) {
495         case 0:
496         case 1:
497                 printf(" (%.4s)\n", (char *)&pkt->refid);
498                 break;
499         default:
500                 clock_host.s_addr = (afs_uint32) pkt->refid;
501                 printf(" [%s]\n", inet_ntoa(clock_host));
502                 break;
503         }
504         printf("Synch Dist is %04X.%04X  Synch Dispersion is %04X.%04X\n",
505                ntohs((u_short) pkt->distance.int_part),
506                ntohs((u_short) pkt->distance.fraction),
507                ntohs((u_short) pkt->dispersion.int_part),
508                ntohs((u_short) pkt->dispersion.fraction));
509         printf("Reference Timestamp is %08lx.%08lx %f\n",
510                ntohl(pkt->reftime.int_part),
511                ntohl(pkt->reftime.fraction),
512                ul_fixed_to_double(&pkt->reftime));
513         printf("Originate Timestamp is %08lx.%08lx %f\n",
514                ntohl(pkt->org.int_part),
515                ntohl(pkt->org.fraction),
516                ul_fixed_to_double(&pkt->org));
517         printf("Receive Timestamp is   %08lx.%08lx %f\n",
518                ntohl(pkt->rec.int_part),
519                ntohl(pkt->rec.fraction),
520                ul_fixed_to_double(&pkt->rec));
521         printf("Transmit Timestamp is  %08lx.%08lx %f\n",
522                ntohl(pkt->xmt.int_part),
523                ntohl(pkt->xmt.fraction),
524                ul_fixed_to_double(&pkt->xmt));
525         if(peer != NULL)
526                 printf("Input Timestamp is     %08lx.%08lx %f\n",
527                        ntohl(peer->rec.int_part),
528                        ntohl(peer->rec.fraction),
529                        ul_fixed_to_double(&peer->rec));
530         putchar('\n');
531 }
532 #endif
533
534 void
535 make_new_peer(peer)
536         struct ntp_peer *peer;
537 {
538         int i;
539
540         /*
541          * initialize peer data fields 
542          */
543         peer->src.sin_family = AF_INET;
544         peer->src.sin_port = 0;
545         peer->src.sin_addr.s_addr = 0;
546         peer->hmode = MODE_SYM_PAS;     /* default: symmetric passive mode */
547         peer->flags = 0;
548         peer->timer = 1 << NTP_MINPOLL;
549         peer->stopwatch = 0;
550         peer->hpoll = NTP_MINPOLL;
551         double_to_s_fixed(&peer->dispersion, PEER_MAXDISP);
552         peer->reach = 0;
553         peer->estoffset = 0.0;
554         peer->estdelay = 0.0;
555         peer->org.int_part = peer->org.fraction = 0;
556         peer->rec.int_part = peer->rec.fraction = 0;
557         peer->filter.samples = 0;
558         for (i = 0; i < NTP_WINDOW; i++) {
559                 peer->filter.offset[i] = 0.0;
560                 peer->filter.delay[i] = 0.0;
561         }
562         peer->pkt_sent = 0;
563         peer->pkt_rcvd = 0;
564         peer->pkt_dropped = 0;
565 }
566
567 /*
568  *  This procedure is called to delete a peer from our list of peers.
569  */
570 void
571 demobilize(l, peer)
572         struct list *l;
573         struct ntp_peer *peer;
574 {
575         extern struct ntp_peer dummy_peer;
576
577         if (peer == &dummy_peer)
578 #ifdef  DEBUG
579                 abort();
580 #else
581                 return;
582 #endif
583
584 #ifdef  DEBUG
585         if ((peer->next == NULL && peer->prev == NULL) ||
586             l->tail == NULL || l->head == NULL)
587                 abort();
588 #endif
589
590         /* delete only peer in list? */
591         if (l->head == l->tail) {
592 #ifdef  DEBUG
593                 if (l->head != peer) abort();
594 #endif
595                 l->head = l->tail = NULL;
596                 goto dropit;
597         }
598
599         /* delete first peer? */
600         if (l->head == peer) {
601                 l->head = peer->next;
602                 l->head->prev = NULL;
603                 goto dropit;
604         }
605
606         /* delete last peer? */
607         if (l->tail == peer) {
608                 l->tail = peer->prev;
609                 l->tail->next = NULL;
610                 goto dropit;
611         }
612
613         /* drop peer in middle */
614         peer->prev->next = peer->next;
615         peer->next->prev = peer->prev;
616
617  dropit:
618 #ifdef  DEBUG
619         /* just some sanity checking */
620         if ((l->members <= 0) || 
621             (l->members && l->tail == NULL) ||
622             (l->members == 0 && l->tail != NULL)) {
623                 syslog(LOG_ERR, "List hosed (demobilize)");
624                 abort();
625         }
626         peer->next = peer->prev = NULL;
627 #endif
628         free((char *) peer);
629         l->members--;
630
631         return;
632 }
633
634 enqueue(l, peer)
635         register struct list *l;
636         struct ntp_peer *peer;
637 {
638         l->members++;
639         if (l->tail == NULL) {
640                 /* insertion into empty list */
641                 l->tail = l->head = peer;
642                 peer->next = peer->prev = NULL;
643                 return;
644         }
645
646         /* insert at end of list */
647         l->tail->next = peer;
648         peer->next = NULL;
649         peer->prev = l->tail;
650         l->tail = peer;
651 }
652 \f
653 /* XXX */
654 /*
655  *  Trivial signal handler.
656  */
657 void 
658 tock(x) {
659         ticked = 1;
660
661         /* re-enable self (we're not BSD any more) */
662         (void) signal(SIGALRM, tock);
663 }
664
665 void
666 timeout()
667 {
668         static int periodic = 0;
669         register struct ntp_peer *peer = peer_list.head, *next;
670 #ifndef XADJTIME2
671         extern void adj_host_clock();
672
673         adj_host_clock();
674 #endif
675         /*
676          * Count down sys.hold if necessary.
677          */
678         if (sys.hold) {
679                 if (sys.hold <= (1<<CLOCK_ADJ))
680                         sys.hold = 0;
681                 else
682                         sys.hold -= (1<<CLOCK_ADJ);
683         }
684         /*
685          * If interval has expired blast off an NTP to that host.
686          */
687         while (peer != NULL) {
688 #ifdef  DEBUG
689                 if (peer->next == NULL && peer != peer_list.tail) {
690                         printf("Broken peer list\n");
691                         syslog(LOG_ERR, "Broken peer list");
692                         abort();
693                 }
694 #endif
695                 next = peer->next;
696                 if (peer->reach != 0 || peer->hmode != MODE_SERVER) {
697                         peer->stopwatch +=(1<<CLOCK_ADJ);
698                         if (peer->timer <= peer->stopwatch) {
699                                 transmit(peer);
700                                 peer->stopwatch = 0;
701                         }
702                 }
703                 peer = next;
704         }
705
706         periodic += (1<<CLOCK_ADJ);
707         if (periodic >= 60*60) {
708                 periodic = 0;
709                 hourly();
710         }
711
712         clock_watchdog += (1 << CLOCK_ADJ);
713         if (clock_watchdog >= NTP_MAXAGE) {
714                 /* woof, woof - barking dogs bite! */
715                 sys.leap = ALARM;
716                 if (clock_watchdog < NTP_MAXAGE + (1 << CLOCK_ADJ)) {
717                         syslog(LOG_ERR,
718                                "logical clock adjust timeout (%d seconds)",
719                                NTP_MAXAGE);
720 #ifdef  DEBUG
721                         if (debug)
722                          printf("logical clock adjust timeout (%d seconds)\n",
723                                 NTP_MAXAGE);
724 #endif
725                 }
726         }
727
728 #ifdef  DEBUG
729         if (debug)
730                 (void) fflush(stdout);
731 #endif
732 }
733 \f
734
735 /*
736  * init_ntp() reads NTP daemon configuration information from disk file.
737  */
738 void
739 init_ntp(config)
740         char *config;
741 {
742         struct sockaddr_in sin;
743         char ref_clock[5];
744         char name[81];
745         FILE *fp;
746         int error = FALSE, c;
747         struct ntp_peer *peer;
748         int precision;
749         int stratum;
750         int i;
751         int debuglevel;
752         int stagger = 0;
753         double j;
754         extern double drift_comp;
755
756         memset((char *) &sin, 0, sizeof(sin));
757         fp = fopen(config, "r");
758         if (fp == NULL) {
759                 fprintf(stderr,"Problem opening NTP initialization file %s\n",
760                         config);
761                 syslog(LOG_ERR,"Problem opening NTP initialization file %s",
762                         config);
763                 exit(1);
764         }
765
766         while (fscanf(fp, "%s", name) != EOF) { /* read first word of line
767                                                  * and compare to key words */
768                 if (strcmp(name, "maxpeers") == 0) {
769                         if (fscanf(fp, "%d", &sys.maxpeers) != 1)
770                                 error = TRUE;
771                 } else if (strcmp(name, "trusting") == 0) {
772                         if (fscanf(fp, "%s", name) != 1)
773                                 error = TRUE;
774                         else {
775                                 if (*name == 'Y' || *name == 'y') {
776                                         trusting = 1;
777                                 } else if (*name == 'N' || *name == 'n') {
778                                         trusting = 0;
779                                 } else
780                                         trusting = atoi(name);
781                         }
782                 } else if (strcmp(name, "logclock") == 0) {
783                         if (fscanf(fp, "%s", name) != 1)
784                                 error = TRUE;
785                         else {
786                                 if (*name == 'Y' || *name == 'y') {
787                                         logstats = 1;
788                                 } else if (*name == 'N' || *name == 'n') {
789                                         logstats = 0;
790                                 } else
791                                         logstats = atoi(name);
792                         }
793                 } else if (strcmp(name, "driftfile") == 0) {
794                         if (fscanf(fp, "%s", name) != 1)
795                                 error = TRUE;
796                         else {
797                                 if (driftcomp_file = malloc(strlen(name)+1))
798                                         strcpy(driftcomp_file, name);
799                         }
800                 } else if (strcmp(name, "waytoobig") == 0 ||
801                            strcmp(name, "setthreshold") == 0) {
802                         if (fscanf(fp, "%s", name) != 1)
803                                 error = TRUE;
804                         else {
805                                 if (strcmp(name, "any") == 0)
806                                         WayTooBig = 10e15;
807                                 else
808                                         WayTooBig = atof(name);
809                         }
810                 } else if (strncmp(name, "debuglevel", 5) == 0) {
811                         if (fscanf(fp, "%d", &debuglevel) != 1)
812                                 error = TRUE;
813 #ifdef  DEBUG
814                         else debug += debuglevel;
815 #endif
816                 } else if (strcmp(name, "stratum") == 0) {
817                         fprintf(stderr, "Obsolete command 'stratum'\n");
818                         error = TRUE;
819                 } else if (strcmp(name, "precision") == 0) {
820                         if (fscanf(fp, "%d", &precision) != 1)
821                                 error = TRUE;
822                         else sys.precision = (char) precision;
823 #ifdef  SETTICKADJ
824                 } else if (strcmp(name, "tickadj") == 0) {
825                         if (fscanf(fp, "%d", &i) != 1)
826                                 error = TRUE;
827                         else tickadj = i;
828                 } else if (strcmp(name, "settickadj") == 0) {
829                         if (fscanf(fp, "%s", name) != 1)
830                                 error = TRUE;
831                         else {
832                                 if (*name == 'Y' || *name == 'y') {
833                                         dotickadj = 1;
834                                 } else if (*name == 'N' || *name == 'n') {
835                                         dotickadj = 0;
836                                 } else
837                                         dotickadj = atoi(name);
838                         }
839                 } else if (strcmp(name, "setdosynctodr") == 0) {
840                         if (fscanf(fp, "%s", name) != 1)
841                                 error = TRUE;
842                         else {
843                                 if (*name == 'Y' || *name == 'y') {
844                                         dosynctodr = 1;
845                                 } else if (*name == 'N' || *name == 'n') {
846                                         dosynctodr = 0;
847                                 } else
848                                         dosynctodr = atoi(name);
849                         }
850 #endif
851 #ifdef  NOSWAP
852                 } else if (strcmp(name, "noswap") == 0) {
853                         noswap = 1;
854 #endif
855 #ifdef  BROADCAST_NTP
856                 } else if (strcmp(name, "broadcast") == 0) {
857                         if (fscanf(fp, "%s", name) != 1) {
858                                 error = TRUE;
859                                 goto skipit;
860                         }
861                         for (i = 0; i < nintf; i++)
862                                 if (strcmp(addrs[i].name, name) == 0)
863                                         break;
864                         if (i == nintf) {
865                                 syslog(LOG_ERR, "config file: %s not a known interface");
866                                 error = TRUE;
867                                 goto skipit;
868                         }
869                         if ((addrs[i].if_flags & IFF_BROADCAST) == 0) {
870                                 syslog(LOG_ERR, "config file: %s doesn't support broadcast", name);
871                                 error = TRUE;
872                                 goto skipit;
873                         }
874                         if (peer = check_peer(&addrs[i].bcast, -1)) {
875                                 syslog(LOG_ERR, "config file: duplicate broadcast for %s",
876                                        name);
877                                 error = TRUE;
878                                 goto skipit;
879                         }
880                         peer = (struct ntp_peer *) malloc(sizeof(struct ntp_peer));
881                         if (peer == NULL) {
882                                 error = TRUE;
883                                 syslog(LOG_ERR, "No memory");
884                                 goto skipit;
885                         }
886                         make_new_peer(peer);
887                         peer->flags = PEER_FL_BCAST;
888                         peer->hmode = MODE_BROADCAST;
889                         peer->src = addrs[i].bcast;
890                         peer->sock = i;
891 #endif  /* BROADCAST_NTP */
892                 } else if ((strcmp(name, "peer") == 0) || 
893                            (strcmp(name, "passive") == 0) ||
894                            (strcmp(name, "server") == 0)) {
895                         int mode = 0;
896
897                         if (strcmp(name, "peer") == 0) {
898                                 mode = MODE_SYM_ACT;
899                         } else if (strcmp(name, "server") == 0) {
900                                 mode = MODE_CLIENT;
901                         } else if (strcmp(name, "passive") == 0) {
902                                 mode = MODE_SYM_PAS;
903                         } else {
904                                 printf("can't happen\n");
905                                 abort();
906                         }
907                         if (fscanf(fp, "%s", name) != 1)
908                                 error = TRUE;
909 #ifdef REFCLOCK
910                         else if (name[0] == '/') {
911                                 int stratum, precision;
912                                 char clk_type[20];
913
914                                 if (fscanf(fp, "%4s", ref_clock) != 1) {
915                                         error = TRUE;
916                                         syslog(LOG_ERR, "reference id missing");
917                                         goto skipit;
918                                 }
919                                 if (fscanf(fp, "%4d", &stratum) != 1) {
920                                         error = TRUE;
921                                         syslog(LOG_ERR, "reference stratum missing");
922                                         goto skipit;
923                                 }
924                                 if (fscanf(fp, "%4d", &precision) != 1) {
925                                         error = TRUE;
926                                         syslog(LOG_ERR, "reference precision missing");
927                                         goto skipit;
928                                 }
929                                 if (fscanf(fp, "%19s", clk_type) != 1) {
930                                         error = TRUE;
931                                         syslog(LOG_ERR, "reference type missing");
932                                         goto skipit;
933                                 }
934
935                                 if((i = init_clock(name, clk_type)) < 0) {
936                                         /* If we could not initialize clock line */
937 #ifdef DEBUG
938                                         if (debug)
939                                                 printf("Could not init reference source %s (type %s)\n",
940                                                         name, clk_type);
941                                         else
942 #endif /* DEBUG */
943                                                 syslog(LOG_ERR, "Could not init reference source %s (type %s)",
944                                                         name, clk_type);
945                                         error = TRUE;
946                                         goto skipit;
947                                 }
948                                 peer = (struct ntp_peer *)
949                                         malloc(sizeof(struct ntp_peer));
950                                 if (peer == NULL) {
951                                         close(i);
952                                         error = TRUE;
953                                         goto skipit;
954                                 }
955                                 make_new_peer(peer);
956                                 ref_clock[4] = 0;
957                                 (void) strncpy((char *) &peer->refid,
958                                                 ref_clock, 4);
959                                 peer->flags = PEER_FL_CONFIG|PEER_FL_REFCLOCK;
960                                 peer->hmode = MODE_SYM_ACT;
961                                 peer->stopwatch = stagger;
962                                 stagger += (1<<CLOCK_ADJ);
963                                 peer->flags |= PEER_FL_SYNC;
964                                 peer->sock = i;
965                                 peer->stratum = stratum;
966                                 peer->precision = precision;
967                                 clear(peer);
968                                 enqueue(&peer_list, peer);
969 #ifdef DEBUG
970                                 if (debug > 1)
971                                         printf("Peer %s mode %d refid %.4s stratum %d precision %d\n",
972                                                name,
973                                                peer->hmode,
974                                                (char *)&peer->refid,
975                                                stratum, precision);
976 #endif
977                                 transmit(peer); /* head start for REFCLOCK */
978                         }
979 #endif /* REFCLOCK */
980                         else if (GetHostName(name, &sin) == 0)
981                                 syslog(LOG_ERR, "%s: unknown host", name);
982                         else {
983                                 for (i=0; i<nintf; i++)
984                                         if (addrs[i].sin.sin_addr.s_addr ==
985                                             sin.sin_addr.s_addr)
986                                                 goto skipit;
987
988                                 if (servp)
989                                         sin.sin_port = servp->s_port;
990                                 else
991                                         sin.sin_port = htons(NTP_PORT);
992
993                                 peer = check_peer(&sin, -1);
994                                 if (peer == NULL) {
995                                         peer = (struct ntp_peer *)
996                                                 malloc(sizeof(struct ntp_peer));
997                                         if (peer == NULL)
998                                                 error = TRUE;
999                                         else {
1000                                                 make_new_peer(peer);
1001                                                 peer->flags = PEER_FL_CONFIG;
1002                                                 switch (mode) {
1003                                                 case MODE_SYM_ACT:      /* "peer" */
1004                                                         peer->hmode = MODE_SYM_ACT;
1005                                                         peer->stopwatch = stagger;
1006                                                         stagger += (1<<CLOCK_ADJ);
1007                                                         peer->flags |= PEER_FL_SYNC;
1008                                                         break;
1009                                                 case MODE_CLIENT:       /* "server" */
1010                                                         peer->hmode = MODE_CLIENT;
1011                                                         peer->stopwatch = stagger;
1012                                                         stagger += (1<<CLOCK_ADJ);
1013                                                         peer->flags |= PEER_FL_SYNC;
1014                                                         break;
1015                                                 case MODE_SYM_PAS:      /* "passive" */
1016                                                         peer->hmode = MODE_SYM_PAS;
1017                                                         peer->flags |= PEER_FL_SYNC;
1018                                                         break;
1019                                                 default:
1020                                                         printf("can't happen\n");
1021                                                         abort();
1022                                                 }
1023                                                 peer->src = sin;
1024                                                 peer->sock = -1;
1025                                                 clear(peer);
1026                                                 enqueue(&peer_list, peer);
1027 #ifdef  DEBUG
1028                                                 if (debug > 1)
1029                                                         printf("Peer %s/%d af %d mode %d\n",
1030                                                                inet_ntoa(peer->src.sin_addr),
1031                                                                ntohs(peer->src.sin_port),
1032                                                                peer->src.sin_family,
1033                                                                peer->hmode);
1034 #endif
1035                                         }
1036                                 } else {
1037                                         syslog(LOG_WARNING,
1038                                      "Duplicate peer %s in in config file",
1039                                                inet_ntoa(sin.sin_addr));
1040 #ifdef  DEBUG
1041                                         if(debug)
1042                                                 printf("Duplicate peer %s in in config file\n",
1043                                                        inet_ntoa(sin.sin_addr));
1044 #endif
1045                                 }
1046                         }
1047                         skipit:;
1048                 } else if( *name != '#' ) {
1049                         syslog(LOG_ERR, "config file: %s not recognized", name);
1050 #ifdef DEBUG
1051                         if(debug)
1052                                 printf("unrecognized option in config file: %s\n", name);
1053 #endif
1054                 }
1055                 do
1056                         c = fgetc(fp);
1057                 while (c != '\n' && c != EOF);  /* next line */
1058         }                       /* end while */
1059         if (error) {
1060                 fprintf(stderr, "init_ntp: %s: initialization error\n", config);
1061                 syslog(LOG_ERR, "init_ntp: %s: initialization error", config);
1062
1063                 exit(1);
1064         }
1065         /*
1066          *  Read saved drift compensation register value.
1067          */
1068 #if defined(AFS_SUN_ENV) || defined(AFS_HPUX_ENV)
1069 #define BOGUS_DRIFT_COMPENSATION 10.0
1070 #else
1071 #define BOGUS_DRIFT_COMPENSATION 1.0
1072 #endif
1073         if ((fp = fopen(driftcomp_file, "r")) != NULL) {
1074                 if (fscanf(fp, "%lf", &j) == 1 &&
1075                     j > -BOGUS_DRIFT_COMPENSATION &&
1076                     j < BOGUS_DRIFT_COMPENSATION) {
1077                         drift_comp = j;
1078                         syslog(LOG_INFO,
1079                                "Drift compensation value initialized to %f", j);
1080                 } else {
1081                         fprintf(stderr,
1082                                 "init_ntp: bad drift compensation value\n");
1083                         syslog(LOG_ERR,
1084                                "init_ntp: bad drift compensation value\n");
1085                 }
1086                 fclose(fp);
1087         }
1088 }
1089 \f
1090 int kern_tickadj, kern_hz, kern_tick, kern_dosynctodr;
1091
1092 #ifdef  SETTICKADJ
1093 int SetKernel (kmem, nl, newValue)
1094   int kmem;
1095   struct nlist *nl;
1096 {
1097     static char *memory = "/dev/kmem";
1098     if (lseek(kmem, (long)nl->n_value, L_SET) == -1) {
1099         syslog(LOG_ERR, "%s: lseek fails: %m", memory);
1100         perror ("setting kernel variable");
1101         return errno;
1102     }
1103     if (write(kmem, &newValue, sizeof(int)) != sizeof(int)) {
1104         syslog(LOG_ERR, "%s: kernel variable assignment fails: %m", memory);
1105         printf("SetKernel variable %s fails\n", nl->n_name);
1106         perror ("setting kernel variable");
1107         return errno;
1108     } 
1109     syslog(LOG_INFO, "System %s SET to %d", nl->n_name, newValue);
1110     printf("System %s SET to %d\n", nl->n_name, newValue);
1111 }
1112 #endif
1113
1114 #if defined(INIT_KERN_VARS)
1115 void
1116 init_kern_vars()
1117 {
1118         int kmem;
1119         static char     *memory = "/dev/kmem";
1120         static struct nlist nl[] = {
1121 #ifndef NeXT
1122                 {"_tickadj"},
1123                 {"_hz"},
1124                 {"_tick"},
1125 #ifdef AFS_SUN_ENV
1126                 {"_dosynctodr"},
1127 #endif
1128                 {""},
1129 #else
1130                 {{"_tickadj"}},
1131                 {{"_hz"}},
1132                 {{"_tick"}},
1133                 {{""}},
1134 #endif
1135         };
1136         static int *kern_vars[] =
1137             {&kern_tickadj, &kern_hz, &kern_tick, &kern_dosynctodr};
1138         int i;
1139         kmem = open(memory, O_RDONLY);
1140         if (kmem < 0) {
1141                 syslog(LOG_ERR, "Can't open %s for reading: %m", memory);
1142 #ifdef  DEBUG
1143                 if (debug)
1144                         perror(memory);
1145 #endif
1146                 return;
1147         }
1148
1149         nlist("/vmunix", nl);
1150
1151         for (i = 0; i < (sizeof(kern_vars)/sizeof(kern_vars[0])); i++) {
1152                 long where;
1153
1154                 if ((where = nl[i].n_value) == 0) {
1155                         syslog(LOG_ERR, "Unknown kernal var %s",
1156 #ifdef  NeXT
1157                                nl[i].n_un.n_name
1158 #else
1159                                nl[i].n_name
1160 #endif
1161                                );
1162                         continue;
1163                 }
1164                 if (lseek(kmem, where, L_SET) == -1) {
1165                         syslog(LOG_ERR, "lseek for %s fails: %m",
1166 #ifdef  NeXT
1167                                nl[i].n_un.n_name
1168 #else
1169                                nl[i].n_name
1170 #endif
1171                                );
1172                         continue;
1173                 }
1174                 if (read(kmem, kern_vars[i], sizeof(int)) != sizeof(int)) {
1175                         syslog(LOG_ERR, "read for %s fails: %m",
1176 #ifdef  NeXT
1177                                nl[i].n_un.n_name
1178 #else
1179                                nl[i].n_name
1180 #endif
1181                                );
1182
1183                         *kern_vars[i] = 0;
1184                 }
1185         }
1186
1187         /*
1188          *  If desired value of tickadj is not specified in the configuration
1189          *  file, compute a "reasonable" value here, based on the assumption 
1190          *  that we don't have to slew more than 2ms every 4 seconds.
1191          *
1192          *  TODO: the 500 needs to be parameterized.
1193          */
1194         if (tickadj == 0 && kern_hz)
1195                 tickadj = 500/kern_hz;
1196
1197 #ifdef  DEBUG
1198         if (debug) {
1199                 printf("kernel vars: tickadj = %d, hz = %d, tick = %d\n",
1200                        kern_tickadj, kern_hz, kern_tick);
1201 #ifdef AFS_SUN_ENV
1202                 if (kern_dosynctodr) printf ("dosynctodr is on\n");
1203 #endif
1204                 printf("desired tickadj = %d, dotickadj = %d\n", tickadj,
1205                        dotickadj);
1206         }
1207 #endif
1208         close(kmem);
1209
1210 #ifdef  SETTICKADJ
1211         {   int set_tickadj, set_dosynctodr;
1212             int code;
1213             set_tickadj = (dotickadj && tickadj && (tickadj != kern_tickadj)
1214                            /* do some plausibility checks on the value... */
1215                            && (kern_tickadj > 0) && (kern_tickadj < 20000));
1216             set_dosynctodr = (dosynctodr && (kern_dosynctodr == 1));
1217             if (set_tickadj || set_dosynctodr) {
1218                 if ((kmem = open(memory, O_RDWR)) >= 0) {
1219                     if (set_tickadj) {
1220                         code = SetKernel (kmem, &nl[0], tickadj);
1221                         if (code == 0) kern_tickadj = tickadj;
1222                     }
1223                     if (set_dosynctodr) {
1224                         code = SetKernel (kmem, &nl[3], 0);
1225                         if (code == 0) kern_dosynctodr = 0;
1226                     }
1227                     close (kmem);
1228                 } else {
1229                     syslog(LOG_ERR, "Can't open %s: %m", memory);
1230                     printf("Can't open %s\n", memory);
1231                 }
1232             }
1233         }
1234 #endif  /* SETTICKADJ */
1235
1236         /*
1237          *  If we have successfully discovered `hz' from the kernel, then we
1238          *  can set sys.precision, if it has not already been specified.  If
1239          *  no value of `hz' is available, then use default (-6)
1240          */
1241         if (sys.precision == 0) {
1242             char msg[128];
1243             int interval = 0;
1244             sys.precision = MeasurePrecision(&interval);
1245             if (sys.precision) {
1246                 sprintf (msg, "sys.precision set to %d from measured minimum clock interval of %d usec",
1247                          sys.precision, interval);
1248             } else {
1249                 if (kern_hz <= 64)
1250                     sys.precision = -6;
1251                 else if (kern_hz <= 128)
1252                     sys.precision = -7;
1253                 else if (kern_hz <= 256)
1254                     sys.precision = -8;
1255                 else if (kern_hz <= 512)
1256                     sys.precision = -9;
1257                 else if (kern_hz <= 1024)
1258                     sys.precision = -10;
1259                 else sys.precision = -11;
1260                 sprintf (msg,
1261                          "sys.precision set to %d from sys clock of %d HZ",
1262                          sys.precision, kern_hz);
1263             }
1264             syslog(LOG_INFO, msg);
1265             printf ("%s\n", msg);
1266         }
1267 }
1268 #endif  /* INIT_KERN_VARS */
1269
1270
1271 /*
1272  * Given host or net name or internet address in dot notation assign the
1273  * internet address in byte format. source is ../routed/startup.c with minor
1274  * changes to detect syntax errors. 
1275  *
1276  * We now try to interpret the name as in address before we go off and bother
1277  * the domain name servers.
1278  *
1279  * Unfortunately the library routine inet_addr() does not detect mal formed
1280  * addresses that have characters or byte values > 255. 
1281  */
1282
1283 GetHostName(name, sin)
1284         char *name;
1285         struct sockaddr_in *sin;
1286 {
1287         afs_int32 HostAddr;
1288         struct hostent *hp;
1289
1290         if ((HostAddr = inet_addr(name)) != -1) {
1291                 sin->sin_addr.s_addr = (afs_uint32) HostAddr;
1292                 sin->sin_family = AF_INET;
1293                 return (1);
1294         }
1295
1296         if (hp = gethostbyname(name)) {
1297                 if (hp->h_addrtype != AF_INET)
1298                         return (0);
1299                 memcpy((char *) &sin->sin_addr, (char *) hp->h_addr, hp->h_length);
1300                 sin->sin_family = hp->h_addrtype;
1301                 return (1);
1302         }
1303         return (0);
1304 }
1305
1306 #define PKTBUF_SIZE     536
1307
1308 /* number of clocks per packet */
1309 #define N_NTP_PKTS \
1310       ((PKTBUF_SIZE - sizeof(struct ntpinfo))/(sizeof(struct clockinfo)))
1311
1312 query_mode(dst, ntp, sock)
1313         struct sockaddr_in *dst;
1314         struct ntpdata *ntp;
1315         int sock;               /* which socket packet arrived on */
1316 {
1317         char packet[PKTBUF_SIZE];
1318         register struct ntpinfo *nip = (struct ntpinfo *) packet;
1319         register struct ntp_peer *peer = peer_list.head;
1320         struct clockinfo *cip;
1321         int seq = 0;
1322         int i;
1323
1324         if (ntp->stratum != INFO_QUERY)
1325                 return;
1326         nip->version = NTPDC_VERSION;
1327         nip->type = INFO_REPLY;
1328         nip->seq = 0;
1329         nip->npkts = peer_list.members/N_NTP_PKTS;
1330         if (peer_list.members % N_NTP_PKTS)
1331                 nip->npkts++;
1332         nip->peers = peer_list.members;
1333         nip->count = 0;
1334         cip = (struct clockinfo *)&nip[1];
1335
1336         while (peer != NULL) {
1337                 cip->net_address = peer->src.sin_addr.s_addr;
1338                 if ((peer->sock < 0) || (peer->sock >= nintf))
1339                         cip->my_address = htonl(0);
1340                 else
1341                         cip->my_address = addrs[peer->sock].sin.sin_addr.s_addr;
1342                 cip->port = peer->src.sin_port; /* already in network order */
1343                 cip->flags = htons(peer->flags);
1344                 if (sys.peer == peer)
1345                         cip->flags |= htons(PEER_FL_SELECTED);
1346                 cip->pkt_sent = htonl(peer->pkt_sent);
1347                 cip->pkt_rcvd = htonl(peer->pkt_rcvd);
1348                 cip->pkt_dropped = htonl(peer->pkt_dropped);
1349                 cip->timer = htonl(peer->timer);
1350                 cip->leap = peer->leap;
1351                 cip->stratum = peer->stratum;
1352                 cip->ppoll = peer->ppoll;
1353                 cip->precision = peer->precision;
1354                 cip->hpoll = peer->hpoll;
1355                 cip->reach = htons(peer->reach & NTP_WINDOW_SHIFT_MASK);
1356                 cip->estdisp = htonl((afs_int32) (peer->estdisp * 1000.0));
1357                 cip->estdelay = htonl((afs_int32) (peer->estdelay * 1000.0));
1358                 cip->estoffset = htonl((afs_int32) (peer->estoffset * 1000.0));
1359                 cip->refid = peer->refid;
1360                 cip->reftime.int_part = htonl(peer->reftime.int_part);
1361                 cip->reftime.fraction = htonl(peer->reftime.fraction);
1362
1363                 cip->info_filter.index = htons(peer->filter.samples);
1364                 for (i = 0; i < PEER_SHIFT; i++) {
1365                         cip->info_filter.offset[i] =
1366                                 htonl((afs_int32)(peer->filter.offset[i] * 1000.0));
1367                         cip->info_filter.delay[i] =
1368                                 htonl((afs_int32)(peer->filter.delay[i] * 1000.0));
1369                 }
1370                 cip++;
1371                 if (nip->count++ >= N_NTP_PKTS - 1) {
1372                         nip->seq =seq++;
1373                         if ((sendto(addrs[sock].fd, (char *) packet, 
1374                                     sizeof(packet), 0,
1375                                     (struct sockaddr *) dst,
1376                                     sizeof(struct sockaddr_in))) < 0) {
1377                                 syslog(LOG_ERR, "sendto: %s  %m",
1378                                        inet_ntoa(dst->sin_addr));
1379                         }
1380                         nip->type = INFO_REPLY;
1381                         nip->count = 0;
1382                         cip = (struct clockinfo *)&nip[1];
1383                 }
1384                 peer = peer->next;
1385         }
1386         if (nip->count) {
1387                 nip->seq = seq;
1388                 if ((sendto(addrs[sock].fd, (char *) packet, sizeof(packet), 0,
1389                             (struct sockaddr *) dst,
1390                             sizeof(struct sockaddr_in))) < 0) {
1391                         syslog(LOG_ERR, "sendto: %s  %m", ntoa(dst->sin_addr));
1392                 }
1393         }
1394 }
1395
1396 /* every hour, dump some useful information to the log */
1397 void
1398 hourly() {
1399         char buf[200];
1400         register int p = 0;
1401         static double drifts[5] = { 0.0, 0.0, 0.0, 0.0, 0.0 };
1402         static int drift_count = 0;
1403         extern double drift_comp, compliance;
1404         extern int peer_switches, peer_sw_inhibited;
1405
1406         (void) sprintf(buf, "stats: dc %f comp %f peersw %d inh %d",
1407                        drift_comp, compliance, peer_switches,
1408                        peer_sw_inhibited);
1409
1410         if (sys.peer == NULL) {
1411                 strcat(buf, " UNSYNC");
1412 #ifdef  REFCLOCK
1413         } else if (sys.peer->flags & PEER_FL_REFCLOCK) {
1414                 p = strlen(buf);
1415                 (void) sprintf(buf + p, " off %f SYNC %.4s %d",
1416                                sys.peer->estoffset,
1417                                (char *)&sys.peer->refid,
1418                                sys.peer->stratum);
1419 #endif
1420         } else {
1421                 p = strlen(buf);
1422                 (void) sprintf(buf + p, " off %f SYNC %s %d",
1423                                sys.peer->estoffset,
1424                                ntoa(sys.peer->src.sin_addr),
1425                                sys.peer->stratum);
1426         }
1427         syslog(LOG_INFO, buf);
1428 #ifdef  DEBUG
1429         if (debug)
1430                 puts(buf);
1431 #endif
1432         /*
1433          *  If the drift compensation snapshot file is open, then write
1434          *  the current value to it.  Since there's only one block in the
1435          *  file, and no one else is reading it, we'll just keep the file
1436          *  open and write to it.
1437          */
1438         if (drift_fd >= 0) {
1439                 drifts[drift_count % 5] = drift_comp;
1440                 /* works out to be 70 bytes */
1441                 (void) sprintf(buf,
1442                      "%+12.10f %+12.10f %+12.10f %+12.10f %+12.10f %4d\n",
1443                                drifts[drift_count % 5],
1444                                drifts[(drift_count+4) % 5],
1445                                drifts[(drift_count+3) % 5],
1446                                drifts[(drift_count+2) % 5],
1447                                drifts[(drift_count+1) % 5],
1448                                drift_count + 1);
1449
1450                 (void) lseek(drift_fd, 0L, L_SET);
1451                 if (write(drift_fd, buf, strlen(buf)) < 0) {
1452                         syslog(LOG_ERR, "Error writing drift comp file: %m");
1453                 }
1454                 drift_count++;
1455         }
1456 }
1457 \f
1458 #if     defined(DEBUG) && defined(SIGUSR1) && defined(SIGUSR2)
1459 void
1460 incdebug(x)
1461 {
1462         /* re-enable self (we're not BSD any more) */
1463         (void) signal(SIGUSR1, incdebug);
1464
1465         if (debug == 255)
1466                 return;
1467         debug++;
1468         printf("DEBUG LEVEL %d\n", debug);
1469 #ifdef  LOG_DAEMON
1470         (void) setlogmask(LOG_UPTO(LOG_DEBUG));
1471 #endif
1472         syslog(LOG_DEBUG, "DEBUG LEVEL %d", debug);
1473 }
1474
1475 void
1476 decdebug(x)
1477 {
1478         /* re-enable self (we're not BSD any more) */
1479         (void) signal(SIGUSR2, decdebug);
1480
1481         if (debug == 0)
1482                 return;
1483         debug--;
1484         printf("DEBUG LEVEL %d\n", debug);
1485         syslog(LOG_DEBUG, "DEBUG LEVEL %d", debug);
1486 #ifdef  LOG_DAEMON
1487         if (debug == 0)
1488                 (void) setlogmask(LOG_UPTO(LOG_INFO));
1489 #endif
1490 }
1491 #endif
1492
1493 void
1494 finish(sig)
1495         int sig;
1496 {
1497         syslog(LOG_NOTICE, "terminated: (sig %d)", sig);
1498 #ifdef  DEBUG
1499         if (debug)
1500                 printf("ntpd terminated (sig %d)\n", sig);
1501 #endif
1502         exit(1);
1503 }
1504 \f
1505 #ifdef  REFCLOCK
1506 struct refclock {
1507         int fd;
1508         int (*reader)();
1509         struct refclock *next;
1510 } *refclocks = NULL;
1511
1512 int init_clock_local(), read_clock_local();
1513 #ifdef PSTI
1514 int init_clock_psti(), read_clock_psti();
1515 #endif /* PSTI */
1516
1517 init_clock(name, type)
1518 char *name, *type;
1519 {
1520         struct refclock *r;
1521         int (*reader)();
1522         int cfd;
1523
1524         if (strcmp(type, "local") == 0) {
1525                 reader = read_clock_local;
1526                 cfd = init_clock_local(name);
1527         }
1528 #ifdef PSTI
1529         else if (strcmp(type, "psti") == 0) {
1530                 reader = read_clock_psti;
1531                 cfd = init_clock_psti(name);
1532         }
1533 #endif /* PSTI */
1534         else {
1535 #ifdef DEBUG
1536                 if (debug) printf("Unknown reference type\n"); else
1537 #endif
1538                 syslog(LOG_ERR, "Unknown reference clock type (%s)\n", type);
1539                 return(-1);
1540         }
1541         if (cfd >= 0) {
1542                 r = (struct refclock *)malloc(sizeof(struct refclock));
1543                 r->fd = cfd;
1544                 r->reader = reader;
1545                 r->next = refclocks;
1546                 refclocks = r;
1547         }
1548         return(cfd);
1549 }
1550
1551 read_clock(cfd, tvpp, otvpp)
1552 int cfd;
1553 struct timeval **tvpp, **otvpp;
1554 {
1555         struct refclock *r;
1556
1557         for (r = refclocks; r; r = r->next)
1558                 if(r->fd == cfd)
1559                         return((r->reader)(cfd, tvpp, otvpp));
1560         return(1); /* Can't happen */
1561 }
1562 #endif