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