2 * Copyright 2000, International Business Machines Corporation and others.
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
13 * Revision 1.2 1993/04/11 17:35:40
14 * define NOSWAP option on sgi
16 * Revision 1.1 1992/09/21 16:35:59
18 * Revision 2.6 91/08/13 12:28:10
19 * Expect HP-UX to need large BOGUS drift comp value.
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.
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!
29 * Revision 2.3 90/09/27 16:57:07
30 * Bring afs.dev in sync with afs.test
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.
41 * Revision 2.1 90/08/07 19:23:11
42 * Start with clean version to sync test and dev trees.
44 * Revision 1.22 90/06/13 20:09:36
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.
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.
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
60 * Revision 1.18 89/12/11 14:25:51
61 * Added code to support AIX 2.2.1.
63 * Revision 1.17 89/05/24 12:26:23
64 * Latest May 18, Version 4.3 release from UMD.
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
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.
75 * Revision 3.4.1.7 89/04/10 15:58:45
76 * Add -l option to enable logging of clock adjust messages.
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
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.
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.
90 * Revision 3.4.1.3 89/03/22 18:29:41
91 * patch3: Use new RCS headers.
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
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.
103 * Revision 3.4 89/03/17 18:37:11
104 * Latest test release.
106 * Revision 3.3.1.1 89/03/17 18:26:32
109 * Revision 3.3 89/03/15 14:19:56
110 * New baseline for next release.
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
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.
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.
130 * Revision 3.1.1.1 89/02/15 08:58:46
131 * Bugfixes to released version.
134 * Revision 3.1 89/01/30 14:43:14
135 * Second UNIX NTP test release.
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.
143 #include <afs/param.h>
144 #if defined(AFS_SGI_ENV)
154 #include <sys/types.h>
155 #include <sys/param.h>
157 #include <sys/socket.h>
158 #include <sys/time.h>
162 #include <sys/ioctl.h>
163 #include <sys/resource.h>
167 #include <sys/file.h>
169 #include <sys/lock.h>
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>
184 #define LOG_NTP LOG_DAEMON
192 #include <sys/select.h>
193 #include <sys/signal.h>
201 #include "patchlevel.h"
206 struct sockaddr_in dst_sock = {AF_INET};
208 struct servent *servp;
209 struct list peer_list;
212 struct itimerval *itp = ⁢
216 char *conf = NTPINITFILE;
217 char *driftcomp_file = NTPDRIFTCOMP;
218 static int drift_fd = -1;
238 double WayTooBig = WAYTOOBIG;
239 afs_uint32 clock_watchdog;
241 struct ntpdata ntpframe;
245 extern char *malloc(), *ntoa();
246 extern double s_fixed_to_double(), ul_fixed_to_double();
248 void finish(), timeout(), tock(), make_new_peer(), init_ntp(), initialize(),
250 extern void transmit(), process_packet(), clock_update(),
251 clear(), clock_filter(), select_clock();
253 extern void init_logical_clock();
255 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)
259 #if !defined(AFS_SUN5_ENV)
260 #define INIT_KERN_VARS
263 #if defined(INIT_KERN_VARS)
264 void init_kern_vars();
265 #endif /* INIT_KERN_VARS */
267 #include "AFS_component_version_number.c"
273 struct sockaddr_in *dst = &dst_sock;
274 struct ntpdata *pkt = &ntpframe;
275 fd_set readfds, tmpmask;
276 int dstlen = sizeof(struct sockaddr_in);
283 #if defined(DEBUG) && defined(SIGUSR1) && defined(SIGUSR2)
284 void incdebug(), decdebug();
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.
294 struct sigaction nsa;
296 sigemptyset(&nsa.sa_mask);
297 nsa.sa_handler = SIG_DFL;
298 nsa.sa_flags = SA_FULLDUMP;
299 sigaction(SIGSEGV, &nsa, NULL);
301 initialize(); /* call NTP protocol initialization first,
302 then allow others to override default
305 while ((cc = getopt(argc, argv, "a:c:dD:lstrnf")) != EOF) {
308 if (strcmp(optarg, "any") == 0)
311 WayTooBig = atof(optarg);
318 fprintf(stderr, "%s: not compiled with DEBUG\n",
325 debug = atoi(optarg);
327 fprintf(stderr, "%s: not compiled with DEBUG\n",
340 fprintf(stderr, "%s: not compiled to set tickadj\n",
349 fprintf(stderr, "%s: not compiled to set kernel variables\n",
358 fprintf(stderr, "%s: not compiled for noswap\n",
376 fprintf(stderr, "ntpd: -%c: unknown option\n", cc);
382 if (!debug && !dontFork)
392 for (s = getdtablesize(); s >= 0; s--)
397 (void) setpgrp(0, getpid());
398 s = open("/dev/tty", 2);
401 (void) ioctl(s, (afs_uint32) TIOCNOTTY, (char *) 0);
408 openlog("ntpd", LOG_PID | LOG_NDELAY, LOG_NTP);
411 setlogmask(LOG_UPTO(LOG_DEBUG));
414 setlogmask(LOG_UPTO(LOG_INFO));
416 syslog(LOG_NOTICE, "%s version $Revision$", prog_name);
417 syslog(LOG_NOTICE, "patchlevel %d", PATCHLEVEL);
421 printf("%s version $Revision$ patchlevel %d\n",
422 prog_name, PATCHLEVEL);
424 #if defined(AFS_AIX_ENV)
427 #if defined(AFS_HPUX_ENV)
428 (void) rtprio (0, 90);
430 (void) setpriority(PRIO_PROCESS, 0, -10);
436 if (plock(PROCLOCK) != 0) {
437 syslog(LOG_ERR, "plock() failed: %m");
440 perror("plock() failed");
445 servp = getservbyname("ntp", "udp");
447 syslog(LOG_CRIT, "udp/ntp: service unknown, using default %d",
449 (void) create_sockets(htons(NTP_PORT));
451 (void) create_sockets(servp->s_port);
454 peer_list.head = peer_list.tail = NULL;
455 peer_list.members = 0;
458 #if defined(INIT_KERN_VARS)
460 #endif /* INIT_KERN_VARS */
461 init_logical_clock();
464 * Attempt to open for writing the file for storing the drift comp
465 * register. File must already exist for snapshots to be taken.
467 if ((i = open(driftcomp_file, O_WRONLY|O_CREAT, 0644)) >= 0) {
470 (void) gettimeofday(&tv, (struct timezone *) 0);
474 for (i = 0; i < nintf; i++) {
475 FD_SET(addrs[i].fd, &tmpmask);
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));
484 printf("Addr %d: %s fd %d %s\n", i,
485 addrs[i].name, addrs[i].fd,
486 ntoa(addrs[i].sin.sin_addr));
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);
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;
504 * Find highest fd in use. This might save a few microseconds in
505 * the select system call.
507 for (selfds = FD_SETSIZE - 1; selfds; selfds--)
508 if (FD_ISSET(selfds, &tmpmask))
512 printf("Highest fd in use is %d\n", selfds);
513 if (!selfds) abort();
517 (void) setitimer(ITIMER_REAL, itp, (struct itimerval *) 0);
519 for (;;) { /* go into a finite but hopefully very long
524 nfds = select(selfds, &readfds, (fd_set *) 0, (fd_set *) 0,
525 (struct timeval *) 0);
526 (void) gettimeofday(&tv, (struct timezone *) 0);
528 for(i = 0; i < nintf && nfds; i++) {
529 if (!FD_ISSET(addrs[i].fd, &readfds))
532 dstlen = sizeof(struct sockaddr_in);
534 recvfrom(addrs[i].fd, (char *) pkt,
536 (struct sockaddr *) dst, &dstlen)) < 0) {
538 if (errno != EWOULDBLOCK) {
539 syslog(LOG_ERR, "recvfrom: %m");
548 /* hpux seems to generate these zero's randomly */
549 if (cc == 0) continue;
551 if (cc < sizeof(*pkt)) {
554 printf("Runt packet from %s, got %d bytes, should be %d\n",
559 } else if (cc > sizeof(*pkt)) {
562 printf("too many chars returned by recvfrom. Host %s, got %d bytes, should be %d\n",
569 if (pkt->stratum == INFO_QUERY ||
570 pkt->stratum == INFO_REPLY) {
571 query_mode(dst, pkt, i);
577 dump_pkt(dst, pkt, NULL);
580 if ((pkt->status & VERSIONMASK) != NTPVERSION_1)
583 receive(dst, pkt, &tv, i);
589 } /* end of forever loop */
593 check_peer(dst, sock)
594 struct sockaddr_in *dst;
597 register struct ntp_peer *peer = peer_list.head;
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)))
606 return ((struct ntp_peer *) NULL);
610 dump_pkt(dst, pkt, peer)
611 struct sockaddr_in *dst;
613 struct ntp_peer *peer;
615 struct in_addr clock_host;
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,
623 switch (pkt->stratum) {
626 printf(" (%.4s)\n", (char *)&pkt->refid);
629 clock_host.s_addr = (afs_uint32) pkt->refid;
630 printf(" [%s]\n", inet_ntoa(clock_host));
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));
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));
665 struct ntp_peer *peer;
670 * initialize peer data fields
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 */
677 peer->timer = 1 << NTP_MINPOLL;
679 peer->hpoll = NTP_MINPOLL;
680 double_to_s_fixed(&peer->dispersion, PEER_MAXDISP);
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;
693 peer->pkt_dropped = 0;
697 * This procedure is called to delete a peer from our list of peers.
702 struct ntp_peer *peer;
704 extern struct ntp_peer dummy_peer;
706 if (peer == &dummy_peer)
714 if ((peer->next == NULL && peer->prev == NULL) ||
715 l->tail == NULL || l->head == NULL)
719 /* delete only peer in list? */
720 if (l->head == l->tail) {
722 if (l->head != peer) abort();
724 l->head = l->tail = NULL;
728 /* delete first peer? */
729 if (l->head == peer) {
730 l->head = peer->next;
731 l->head->prev = NULL;
735 /* delete last peer? */
736 if (l->tail == peer) {
737 l->tail = peer->prev;
738 l->tail->next = NULL;
742 /* drop peer in middle */
743 peer->prev->next = peer->next;
744 peer->next->prev = peer->prev;
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)");
755 peer->next = peer->prev = NULL;
764 register struct list *l;
765 struct ntp_peer *peer;
768 if (l->tail == NULL) {
769 /* insertion into empty list */
770 l->tail = l->head = peer;
771 peer->next = peer->prev = NULL;
775 /* insert at end of list */
776 l->tail->next = peer;
778 peer->prev = l->tail;
784 * Trivial signal handler.
790 /* re-enable self (we're not BSD any more) */
791 (void) signal(SIGALRM, tock);
797 static int periodic = 0;
798 register struct ntp_peer *peer = peer_list.head, *next;
800 extern void adj_host_clock();
805 * Count down sys.hold if necessary.
808 if (sys.hold <= (1<<CLOCK_ADJ))
811 sys.hold -= (1<<CLOCK_ADJ);
814 * If interval has expired blast off an NTP to that host.
816 while (peer != NULL) {
818 if (peer->next == NULL && peer != peer_list.tail) {
819 printf("Broken peer list\n");
820 syslog(LOG_ERR, "Broken peer list");
825 if (peer->reach != 0 || peer->hmode != MODE_SERVER) {
826 peer->stopwatch +=(1<<CLOCK_ADJ);
827 if (peer->timer <= peer->stopwatch) {
835 periodic += (1<<CLOCK_ADJ);
836 if (periodic >= 60*60) {
841 clock_watchdog += (1 << CLOCK_ADJ);
842 if (clock_watchdog >= NTP_MAXAGE) {
843 /* woof, woof - barking dogs bite! */
845 if (clock_watchdog < NTP_MAXAGE + (1 << CLOCK_ADJ)) {
847 "logical clock adjust timeout (%d seconds)",
851 printf("logical clock adjust timeout (%d seconds)\n",
859 (void) fflush(stdout);
865 * init_ntp() reads NTP daemon configuration information from disk file.
871 struct sockaddr_in sin;
875 int error = FALSE, c;
876 struct ntp_peer *peer;
883 extern double drift_comp;
885 bzero((char *) &sin, sizeof(sin));
886 fp = fopen(config, "r");
888 fprintf(stderr,"Problem opening NTP initialization file %s\n",
890 syslog(LOG_ERR,"Problem opening NTP initialization file %s",
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)
900 } else if (strcmp(name, "trusting") == 0) {
901 if (fscanf(fp, "%s", name) != 1)
904 if (*name == 'Y' || *name == 'y') {
906 } else if (*name == 'N' || *name == 'n') {
909 trusting = atoi(name);
911 } else if (strcmp(name, "logclock") == 0) {
912 if (fscanf(fp, "%s", name) != 1)
915 if (*name == 'Y' || *name == 'y') {
917 } else if (*name == 'N' || *name == 'n') {
920 logstats = atoi(name);
922 } else if (strcmp(name, "driftfile") == 0) {
923 if (fscanf(fp, "%s", name) != 1)
926 if (driftcomp_file = malloc(strlen(name)+1))
927 strcpy(driftcomp_file, name);
929 } else if (strcmp(name, "waytoobig") == 0 ||
930 strcmp(name, "setthreshold") == 0) {
931 if (fscanf(fp, "%s", name) != 1)
934 if (strcmp(name, "any") == 0)
937 WayTooBig = atof(name);
939 } else if (strncmp(name, "debuglevel", 5) == 0) {
940 if (fscanf(fp, "%d", &debuglevel) != 1)
943 else debug += debuglevel;
945 } else if (strcmp(name, "stratum") == 0) {
946 fprintf(stderr, "Obsolete command 'stratum'\n");
948 } else if (strcmp(name, "precision") == 0) {
949 if (fscanf(fp, "%d", &precision) != 1)
951 else sys.precision = (char) precision;
953 } else if (strcmp(name, "tickadj") == 0) {
954 if (fscanf(fp, "%d", &i) != 1)
957 } else if (strcmp(name, "settickadj") == 0) {
958 if (fscanf(fp, "%s", name) != 1)
961 if (*name == 'Y' || *name == 'y') {
963 } else if (*name == 'N' || *name == 'n') {
966 dotickadj = atoi(name);
968 } else if (strcmp(name, "setdosynctodr") == 0) {
969 if (fscanf(fp, "%s", name) != 1)
972 if (*name == 'Y' || *name == 'y') {
974 } else if (*name == 'N' || *name == 'n') {
977 dosynctodr = atoi(name);
981 } else if (strcmp(name, "noswap") == 0) {
985 } else if (strcmp(name, "broadcast") == 0) {
986 if (fscanf(fp, "%s", name) != 1) {
990 for (i = 0; i < nintf; i++)
991 if (strcmp(addrs[i].name, name) == 0)
994 syslog(LOG_ERR, "config file: %s not a known interface");
998 if ((addrs[i].if_flags & IFF_BROADCAST) == 0) {
999 syslog(LOG_ERR, "config file: %s doesn't support broadcast", name);
1003 if (peer = check_peer(&addrs[i].bcast, -1)) {
1004 syslog(LOG_ERR, "config file: duplicate broadcast for %s",
1009 peer = (struct ntp_peer *) malloc(sizeof(struct ntp_peer));
1012 syslog(LOG_ERR, "No memory");
1015 make_new_peer(peer);
1016 peer->flags = PEER_FL_BCAST;
1017 peer->hmode = MODE_BROADCAST;
1018 peer->src = addrs[i].bcast;
1020 #endif /* BROADCAST_NTP */
1021 } else if ((strcmp(name, "peer") == 0) ||
1022 (strcmp(name, "passive") == 0) ||
1023 (strcmp(name, "server") == 0)) {
1026 if (strcmp(name, "peer") == 0) {
1027 mode = MODE_SYM_ACT;
1028 } else if (strcmp(name, "server") == 0) {
1030 } else if (strcmp(name, "passive") == 0) {
1031 mode = MODE_SYM_PAS;
1033 printf("can't happen\n");
1036 if (fscanf(fp, "%s", name) != 1)
1039 else if (name[0] == '/') {
1040 int stratum, precision;
1043 if (fscanf(fp, "%4s", ref_clock) != 1) {
1045 syslog(LOG_ERR, "reference id missing");
1048 if (fscanf(fp, "%4d", &stratum) != 1) {
1050 syslog(LOG_ERR, "reference stratum missing");
1053 if (fscanf(fp, "%4d", &precision) != 1) {
1055 syslog(LOG_ERR, "reference precision missing");
1058 if (fscanf(fp, "%19s", clk_type) != 1) {
1060 syslog(LOG_ERR, "reference type missing");
1064 if((i = init_clock(name, clk_type)) < 0) {
1065 /* If we could not initialize clock line */
1068 printf("Could not init reference source %s (type %s)\n",
1072 syslog(LOG_ERR, "Could not init reference source %s (type %s)",
1077 peer = (struct ntp_peer *)
1078 malloc(sizeof(struct ntp_peer));
1084 make_new_peer(peer);
1086 (void) strncpy((char *) &peer->refid,
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;
1094 peer->stratum = stratum;
1095 peer->precision = precision;
1097 enqueue(&peer_list, peer);
1100 printf("Peer %s mode %d refid %.4s stratum %d precision %d\n",
1103 (char *)&peer->refid,
1104 stratum, precision);
1106 transmit(peer); /* head start for REFCLOCK */
1108 #endif /* REFCLOCK */
1109 else if (GetHostName(name, &sin) == 0)
1110 syslog(LOG_ERR, "%s: unknown host", name);
1112 for (i=0; i<nintf; i++)
1113 if (addrs[i].sin.sin_addr.s_addr ==
1114 sin.sin_addr.s_addr)
1118 sin.sin_port = servp->s_port;
1120 sin.sin_port = htons(NTP_PORT);
1122 peer = check_peer(&sin, -1);
1124 peer = (struct ntp_peer *)
1125 malloc(sizeof(struct ntp_peer));
1129 make_new_peer(peer);
1130 peer->flags = PEER_FL_CONFIG;
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;
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;
1144 case MODE_SYM_PAS: /* "passive" */
1145 peer->hmode = MODE_SYM_PAS;
1146 peer->flags |= PEER_FL_SYNC;
1149 printf("can't happen\n");
1155 enqueue(&peer_list, peer);
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,
1167 "Duplicate peer %s in in config file",
1168 inet_ntoa(sin.sin_addr));
1171 printf("Duplicate peer %s in in config file\n",
1172 inet_ntoa(sin.sin_addr));
1177 } else if( *name != '#' ) {
1178 syslog(LOG_ERR, "config file: %s not recognized", name);
1181 printf("unrecognized option in config file: %s\n", name);
1186 while (c != '\n' && c != EOF); /* next line */
1189 fprintf(stderr, "init_ntp: %s: initialization error\n", config);
1190 syslog(LOG_ERR, "init_ntp: %s: initialization error", config);
1195 * Read saved drift compensation register value.
1197 #if defined(AFS_SUN_ENV) || defined(AFS_HPUX_ENV)
1198 #define BOGUS_DRIFT_COMPENSATION 10.0
1200 #define BOGUS_DRIFT_COMPENSATION 1.0
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) {
1208 "Drift compensation value initialized to %f", j);
1211 "init_ntp: bad drift compensation value\n");
1213 "init_ntp: bad drift compensation value\n");
1219 int kern_tickadj, kern_hz, kern_tick, kern_dosynctodr;
1222 int SetKernel (kmem, nl, newValue)
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");
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");
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);
1243 #if defined(INIT_KERN_VARS)
1248 static char *memory = "/dev/kmem";
1249 static struct nlist nl[] = {
1265 static int *kern_vars[] =
1266 {&kern_tickadj, &kern_hz, &kern_tick, &kern_dosynctodr};
1268 kmem = open(memory, O_RDONLY);
1270 syslog(LOG_ERR, "Can't open %s for reading: %m", memory);
1278 nlist("/vmunix", nl);
1280 for (i = 0; i < (sizeof(kern_vars)/sizeof(kern_vars[0])); i++) {
1283 if ((where = nl[i].n_value) == 0) {
1284 syslog(LOG_ERR, "Unknown kernal var %s",
1293 if (lseek(kmem, where, L_SET) == -1) {
1294 syslog(LOG_ERR, "lseek for %s fails: %m",
1303 if (read(kmem, kern_vars[i], sizeof(int)) != sizeof(int)) {
1304 syslog(LOG_ERR, "read for %s fails: %m",
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.
1321 * TODO: the 500 needs to be parameterized.
1323 if (tickadj == 0 && kern_hz)
1324 tickadj = 500/kern_hz;
1328 printf("kernel vars: tickadj = %d, hz = %d, tick = %d\n",
1329 kern_tickadj, kern_hz, kern_tick);
1331 if (kern_dosynctodr) printf ("dosynctodr is on\n");
1333 printf("desired tickadj = %d, dotickadj = %d\n", tickadj,
1340 { int set_tickadj, set_dosynctodr;
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) {
1349 code = SetKernel (kmem, &nl[0], tickadj);
1350 if (code == 0) kern_tickadj = tickadj;
1352 if (set_dosynctodr) {
1353 code = SetKernel (kmem, &nl[3], 0);
1354 if (code == 0) kern_dosynctodr = 0;
1358 syslog(LOG_ERR, "Can't open %s: %m", memory);
1359 printf("Can't open %s\n", memory);
1363 #endif /* SETTICKADJ */
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)
1370 if (sys.precision == 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);
1380 else if (kern_hz <= 128)
1382 else if (kern_hz <= 256)
1384 else if (kern_hz <= 512)
1386 else if (kern_hz <= 1024)
1387 sys.precision = -10;
1388 else sys.precision = -11;
1390 "sys.precision set to %d from sys clock of %d HZ",
1391 sys.precision, kern_hz);
1393 syslog(LOG_INFO, msg);
1394 printf ("%s\n", msg);
1397 #endif /* INIT_KERN_VARS */
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.
1405 * We now try to interpret the name as in address before we go off and bother
1406 * the domain name servers.
1408 * Unfortunately the library routine inet_addr() does not detect mal formed
1409 * addresses that have characters or byte values > 255.
1412 GetHostName(name, sin)
1414 struct sockaddr_in *sin;
1419 if ((HostAddr = inet_addr(name)) != -1) {
1420 sin->sin_addr.s_addr = (afs_uint32) HostAddr;
1421 sin->sin_family = AF_INET;
1425 if (hp = gethostbyname(name)) {
1426 if (hp->h_addrtype != AF_INET)
1428 bcopy((char *) hp->h_addr, (char *) &sin->sin_addr,
1430 sin->sin_family = hp->h_addrtype;
1436 #define PKTBUF_SIZE 536
1438 /* number of clocks per packet */
1439 #define N_NTP_PKTS \
1440 ((PKTBUF_SIZE - sizeof(struct ntpinfo))/(sizeof(struct clockinfo)))
1442 query_mode(dst, ntp, sock)
1443 struct sockaddr_in *dst;
1444 struct ntpdata *ntp;
1445 int sock; /* which socket packet arrived on */
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;
1454 if (ntp->stratum != INFO_QUERY)
1456 nip->version = NTPDC_VERSION;
1457 nip->type = INFO_REPLY;
1459 nip->npkts = peer_list.members/N_NTP_PKTS;
1460 if (peer_list.members % N_NTP_PKTS)
1462 nip->peers = peer_list.members;
1464 cip = (struct clockinfo *)&nip[1];
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);
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);
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));
1501 if (nip->count++ >= N_NTP_PKTS - 1) {
1503 if ((sendto(addrs[sock].fd, (char *) packet,
1505 (struct sockaddr *) dst,
1506 sizeof(struct sockaddr_in))) < 0) {
1507 syslog(LOG_ERR, "sendto: %s %m",
1508 inet_ntoa(dst->sin_addr));
1510 nip->type = INFO_REPLY;
1512 cip = (struct clockinfo *)&nip[1];
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));
1526 /* every hour, dump some useful information to the log */
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;
1536 (void) sprintf(buf, "stats: dc %f comp %f peersw %d inh %d",
1537 drift_comp, compliance, peer_switches,
1540 if (sys.peer == NULL) {
1541 strcat(buf, " UNSYNC");
1543 } else if (sys.peer->flags & PEER_FL_REFCLOCK) {
1545 (void) sprintf(buf + p, " off %f SYNC %.4s %d",
1546 sys.peer->estoffset,
1547 (char *)&sys.peer->refid,
1552 (void) sprintf(buf + p, " off %f SYNC %s %d",
1553 sys.peer->estoffset,
1554 ntoa(sys.peer->src.sin_addr),
1557 syslog(LOG_INFO, buf);
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.
1568 if (drift_fd >= 0) {
1569 drifts[drift_count % 5] = drift_comp;
1570 /* works out to be 70 bytes */
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],
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");
1588 #if defined(DEBUG) && defined(SIGUSR1) && defined(SIGUSR2)
1592 /* re-enable self (we're not BSD any more) */
1593 (void) signal(SIGUSR1, incdebug);
1598 printf("DEBUG LEVEL %d\n", debug);
1600 (void) setlogmask(LOG_UPTO(LOG_DEBUG));
1602 syslog(LOG_DEBUG, "DEBUG LEVEL %d", debug);
1608 /* re-enable self (we're not BSD any more) */
1609 (void) signal(SIGUSR2, decdebug);
1614 printf("DEBUG LEVEL %d\n", debug);
1615 syslog(LOG_DEBUG, "DEBUG LEVEL %d", debug);
1618 (void) setlogmask(LOG_UPTO(LOG_INFO));
1627 syslog(LOG_NOTICE, "terminated: (sig %d)", sig);
1630 printf("ntpd terminated (sig %d)\n", sig);
1639 struct refclock *next;
1640 } *refclocks = NULL;
1642 int init_clock_local(), read_clock_local();
1644 int init_clock_psti(), read_clock_psti();
1647 init_clock(name, type)
1654 if (strcmp(type, "local") == 0) {
1655 reader = read_clock_local;
1656 cfd = init_clock_local(name);
1659 else if (strcmp(type, "psti") == 0) {
1660 reader = read_clock_psti;
1661 cfd = init_clock_psti(name);
1666 if (debug) printf("Unknown reference type\n"); else
1668 syslog(LOG_ERR, "Unknown reference clock type (%s)\n", type);
1672 r = (struct refclock *)malloc(sizeof(struct refclock));
1675 r->next = refclocks;
1681 read_clock(cfd, tvpp, otvpp)
1683 struct timeval **tvpp, **otvpp;
1687 for (r = refclocks; r; r = r->next)
1689 return((r->reader)(cfd, tvpp, otvpp));
1690 return(1); /* Can't happen */