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
10 #include <afsconfig.h>
11 #include <afs/param.h>
15 #if defined(AFS_SGI_ENV)
25 #include <sys/types.h>
26 #include <sys/param.h>
28 #include <sys/socket.h>
33 #include <sys/ioctl.h>
34 #include <sys/resource.h>
45 #include <netinet/in.h>
46 #include <netinet/in_systm.h>
47 #include <netinet/ip.h>
48 #include <netinet/udp.h>
49 #include <arpa/inet.h>
55 #define LOG_NTP LOG_DAEMON
63 #include <sys/select.h>
64 #include <sys/signal.h>
72 #include "patchlevel.h"
77 struct sockaddr_in dst_sock = {AF_INET};
79 struct servent *servp;
80 struct list peer_list;
83 struct itimerval *itp = ⁢
87 char *conf = NTPINITFILE;
88 char *driftcomp_file = NTPDRIFTCOMP;
89 static int drift_fd = -1;
109 double WayTooBig = WAYTOOBIG;
110 afs_uint32 clock_watchdog;
112 struct ntpdata ntpframe;
116 extern char *malloc(), *ntoa();
117 extern double s_fixed_to_double(), ul_fixed_to_double();
119 void finish(), timeout(), tock(), make_new_peer(), init_ntp(), initialize(),
121 extern void transmit(), process_packet(), clock_update(),
122 clear(), clock_filter(), select_clock();
124 extern void init_logical_clock();
126 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)
130 #if !defined(AFS_SUN5_ENV)
131 #define INIT_KERN_VARS
134 #if defined(INIT_KERN_VARS)
135 void init_kern_vars();
136 #endif /* INIT_KERN_VARS */
138 #include "AFS_component_version_number.c"
144 struct sockaddr_in *dst = &dst_sock;
145 struct ntpdata *pkt = &ntpframe;
146 fd_set readfds, tmpmask;
147 int dstlen = sizeof(struct sockaddr_in);
154 #if defined(DEBUG) && defined(SIGUSR1) && defined(SIGUSR2)
155 void incdebug(), decdebug();
160 * The following signal action for AIX is necessary so that in case of a
161 * crash (i.e. core is generated) we can include the user's data section
162 * in the core dump. Unfortunately, by default, only a partial core is
163 * generated which, in many cases, isn't too useful.
165 struct sigaction nsa;
167 sigemptyset(&nsa.sa_mask);
168 nsa.sa_handler = SIG_DFL;
169 nsa.sa_flags = SA_FULLDUMP;
170 sigaction(SIGSEGV, &nsa, NULL);
172 initialize(); /* call NTP protocol initialization first,
173 then allow others to override default
176 while ((cc = getopt(argc, argv, "a:c:dD:lstrnf")) != EOF) {
179 if (strcmp(optarg, "any") == 0)
182 WayTooBig = atof(optarg);
189 fprintf(stderr, "%s: not compiled with DEBUG\n",
196 debug = atoi(optarg);
198 fprintf(stderr, "%s: not compiled with DEBUG\n",
211 fprintf(stderr, "%s: not compiled to set tickadj\n",
220 fprintf(stderr, "%s: not compiled to set kernel variables\n",
229 fprintf(stderr, "%s: not compiled for noswap\n",
247 fprintf(stderr, "ntpd: -%c: unknown option\n", cc);
253 if (!debug && !dontFork)
263 for (s = getdtablesize(); s >= 0; s--)
268 (void) setpgrp(0, getpid());
269 s = open("/dev/tty", 2);
272 (void) ioctl(s, (afs_uint32) TIOCNOTTY, (char *) 0);
279 openlog("ntpd", LOG_PID | LOG_NDELAY, LOG_NTP);
282 setlogmask(LOG_UPTO(LOG_DEBUG));
285 setlogmask(LOG_UPTO(LOG_INFO));
287 syslog(LOG_NOTICE, "%s version $Revision$", prog_name);
288 syslog(LOG_NOTICE, "patchlevel %d", PATCHLEVEL);
292 printf("%s version $Revision$ patchlevel %d\n",
293 prog_name, PATCHLEVEL);
295 #if defined(AFS_AIX_ENV)
298 #if defined(AFS_HPUX_ENV)
299 (void) rtprio (0, 90);
301 (void) setpriority(PRIO_PROCESS, 0, -10);
307 if (plock(PROCLOCK) != 0) {
308 syslog(LOG_ERR, "plock() failed: %m");
311 perror("plock() failed");
316 servp = getservbyname("ntp", "udp");
318 syslog(LOG_CRIT, "udp/ntp: service unknown, using default %d",
320 (void) create_sockets(htons(NTP_PORT));
322 (void) create_sockets(servp->s_port);
325 peer_list.head = peer_list.tail = NULL;
326 peer_list.members = 0;
329 #if defined(INIT_KERN_VARS)
331 #endif /* INIT_KERN_VARS */
332 init_logical_clock();
335 * Attempt to open for writing the file for storing the drift comp
336 * register. File must already exist for snapshots to be taken.
338 if ((i = open(driftcomp_file, O_WRONLY|O_CREAT, 0644)) >= 0) {
341 (void) gettimeofday(&tv, (struct timezone *) 0);
345 for (i = 0; i < nintf; i++) {
346 FD_SET(addrs[i].fd, &tmpmask);
349 if (addrs[i].if_flags & IFF_BROADCAST)
350 printf("Addr %d: %s fd %d %s broadcast %s\n",
351 i, addrs[i].name, addrs[i].fd,
352 ntoa(addrs[i].sin.sin_addr),
353 ntoa(addrs[i].bcast.sin_addr));
355 printf("Addr %d: %s fd %d %s\n", i,
356 addrs[i].name, addrs[i].fd,
357 ntoa(addrs[i].sin.sin_addr));
362 (void) signal(SIGINT, finish);
363 (void) signal(SIGTERM, finish);
364 (void) signal(SIGALRM, tock);
365 #if defined(DEBUG) && defined(SIGUSR1) && defined(SIGUSR2)
366 (void) signal(SIGUSR1, incdebug);
367 (void) signal(SIGUSR2, decdebug);
369 itp->it_interval.tv_sec = (1<<CLOCK_ADJ);
370 itp->it_interval.tv_usec = 0;
371 itp->it_value.tv_sec = 1;
372 itp->it_value.tv_usec = 0;
375 * Find highest fd in use. This might save a few microseconds in
376 * the select system call.
378 for (selfds = FD_SETSIZE - 1; selfds; selfds--)
379 if (FD_ISSET(selfds, &tmpmask))
383 printf("Highest fd in use is %d\n", selfds);
384 if (!selfds) abort();
388 (void) setitimer(ITIMER_REAL, itp, (struct itimerval *) 0);
390 for (;;) { /* go into a finite but hopefully very long
395 nfds = select(selfds, &readfds, (fd_set *) 0, (fd_set *) 0,
396 (struct timeval *) 0);
397 (void) gettimeofday(&tv, (struct timezone *) 0);
399 for(i = 0; i < nintf && nfds; i++) {
400 if (!FD_ISSET(addrs[i].fd, &readfds))
403 dstlen = sizeof(struct sockaddr_in);
405 recvfrom(addrs[i].fd, (char *) pkt,
407 (struct sockaddr *) dst, &dstlen)) < 0) {
409 if (errno != EWOULDBLOCK) {
410 syslog(LOG_ERR, "recvfrom: %m");
419 /* hpux seems to generate these zero's randomly */
420 if (cc == 0) continue;
422 if (cc < sizeof(*pkt)) {
425 printf("Runt packet from %s, got %d bytes, should be %d\n",
430 } else if (cc > sizeof(*pkt)) {
433 printf("too many chars returned by recvfrom. Host %s, got %d bytes, should be %d\n",
440 if (pkt->stratum == INFO_QUERY ||
441 pkt->stratum == INFO_REPLY) {
442 query_mode(dst, pkt, i);
448 dump_pkt(dst, pkt, NULL);
451 if ((pkt->status & VERSIONMASK) != NTPVERSION_1)
454 receive(dst, pkt, &tv, i);
460 } /* end of forever loop */
464 check_peer(dst, sock)
465 struct sockaddr_in *dst;
468 register struct ntp_peer *peer = peer_list.head;
470 while (peer != NULL) {
471 if ((peer->src.sin_addr.s_addr == dst->sin_addr.s_addr) &&
472 (peer->src.sin_port == dst->sin_port) &&
473 ((peer->sock == sock) || (peer->sock == -1)))
477 return ((struct ntp_peer *) NULL);
481 dump_pkt(dst, pkt, peer)
482 struct sockaddr_in *dst;
484 struct ntp_peer *peer;
486 struct in_addr clock_host;
488 printf("Packet: [%s](%d)\n", inet_ntoa(dst->sin_addr),
489 (int) htons(dst->sin_port));
490 printf("Leap %d, version %d, mode %d, poll %d, precision %d stratum %d",
491 (pkt->status & LEAPMASK) >> 6, (pkt->status & VERSIONMASK) >> 3,
492 pkt->status & MODEMASK, pkt->ppoll, pkt->precision,
494 switch (pkt->stratum) {
497 printf(" (%.4s)\n", (char *)&pkt->refid);
500 clock_host.s_addr = (afs_uint32) pkt->refid;
501 printf(" [%s]\n", inet_ntoa(clock_host));
504 printf("Synch Dist is %04X.%04X Synch Dispersion is %04X.%04X\n",
505 ntohs((u_short) pkt->distance.int_part),
506 ntohs((u_short) pkt->distance.fraction),
507 ntohs((u_short) pkt->dispersion.int_part),
508 ntohs((u_short) pkt->dispersion.fraction));
509 printf("Reference Timestamp is %08lx.%08lx %f\n",
510 ntohl(pkt->reftime.int_part),
511 ntohl(pkt->reftime.fraction),
512 ul_fixed_to_double(&pkt->reftime));
513 printf("Originate Timestamp is %08lx.%08lx %f\n",
514 ntohl(pkt->org.int_part),
515 ntohl(pkt->org.fraction),
516 ul_fixed_to_double(&pkt->org));
517 printf("Receive Timestamp is %08lx.%08lx %f\n",
518 ntohl(pkt->rec.int_part),
519 ntohl(pkt->rec.fraction),
520 ul_fixed_to_double(&pkt->rec));
521 printf("Transmit Timestamp is %08lx.%08lx %f\n",
522 ntohl(pkt->xmt.int_part),
523 ntohl(pkt->xmt.fraction),
524 ul_fixed_to_double(&pkt->xmt));
526 printf("Input Timestamp is %08lx.%08lx %f\n",
527 ntohl(peer->rec.int_part),
528 ntohl(peer->rec.fraction),
529 ul_fixed_to_double(&peer->rec));
536 struct ntp_peer *peer;
541 * initialize peer data fields
543 peer->src.sin_family = AF_INET;
544 peer->src.sin_port = 0;
545 peer->src.sin_addr.s_addr = 0;
546 peer->hmode = MODE_SYM_PAS; /* default: symmetric passive mode */
548 peer->timer = 1 << NTP_MINPOLL;
550 peer->hpoll = NTP_MINPOLL;
551 double_to_s_fixed(&peer->dispersion, PEER_MAXDISP);
553 peer->estoffset = 0.0;
554 peer->estdelay = 0.0;
555 peer->org.int_part = peer->org.fraction = 0;
556 peer->rec.int_part = peer->rec.fraction = 0;
557 peer->filter.samples = 0;
558 for (i = 0; i < NTP_WINDOW; i++) {
559 peer->filter.offset[i] = 0.0;
560 peer->filter.delay[i] = 0.0;
564 peer->pkt_dropped = 0;
568 * This procedure is called to delete a peer from our list of peers.
573 struct ntp_peer *peer;
575 extern struct ntp_peer dummy_peer;
577 if (peer == &dummy_peer)
585 if ((peer->next == NULL && peer->prev == NULL) ||
586 l->tail == NULL || l->head == NULL)
590 /* delete only peer in list? */
591 if (l->head == l->tail) {
593 if (l->head != peer) abort();
595 l->head = l->tail = NULL;
599 /* delete first peer? */
600 if (l->head == peer) {
601 l->head = peer->next;
602 l->head->prev = NULL;
606 /* delete last peer? */
607 if (l->tail == peer) {
608 l->tail = peer->prev;
609 l->tail->next = NULL;
613 /* drop peer in middle */
614 peer->prev->next = peer->next;
615 peer->next->prev = peer->prev;
619 /* just some sanity checking */
620 if ((l->members <= 0) ||
621 (l->members && l->tail == NULL) ||
622 (l->members == 0 && l->tail != NULL)) {
623 syslog(LOG_ERR, "List hosed (demobilize)");
626 peer->next = peer->prev = NULL;
635 register struct list *l;
636 struct ntp_peer *peer;
639 if (l->tail == NULL) {
640 /* insertion into empty list */
641 l->tail = l->head = peer;
642 peer->next = peer->prev = NULL;
646 /* insert at end of list */
647 l->tail->next = peer;
649 peer->prev = l->tail;
655 * Trivial signal handler.
661 /* re-enable self (we're not BSD any more) */
662 (void) signal(SIGALRM, tock);
668 static int periodic = 0;
669 register struct ntp_peer *peer = peer_list.head, *next;
671 extern void adj_host_clock();
676 * Count down sys.hold if necessary.
679 if (sys.hold <= (1<<CLOCK_ADJ))
682 sys.hold -= (1<<CLOCK_ADJ);
685 * If interval has expired blast off an NTP to that host.
687 while (peer != NULL) {
689 if (peer->next == NULL && peer != peer_list.tail) {
690 printf("Broken peer list\n");
691 syslog(LOG_ERR, "Broken peer list");
696 if (peer->reach != 0 || peer->hmode != MODE_SERVER) {
697 peer->stopwatch +=(1<<CLOCK_ADJ);
698 if (peer->timer <= peer->stopwatch) {
706 periodic += (1<<CLOCK_ADJ);
707 if (periodic >= 60*60) {
712 clock_watchdog += (1 << CLOCK_ADJ);
713 if (clock_watchdog >= NTP_MAXAGE) {
714 /* woof, woof - barking dogs bite! */
716 if (clock_watchdog < NTP_MAXAGE + (1 << CLOCK_ADJ)) {
718 "logical clock adjust timeout (%d seconds)",
722 printf("logical clock adjust timeout (%d seconds)\n",
730 (void) fflush(stdout);
736 * init_ntp() reads NTP daemon configuration information from disk file.
742 struct sockaddr_in sin;
746 int error = FALSE, c;
747 struct ntp_peer *peer;
754 extern double drift_comp;
756 memset((char *) &sin, 0, sizeof(sin));
757 fp = fopen(config, "r");
759 fprintf(stderr,"Problem opening NTP initialization file %s\n",
761 syslog(LOG_ERR,"Problem opening NTP initialization file %s",
766 while (fscanf(fp, "%s", name) != EOF) { /* read first word of line
767 * and compare to key words */
768 if (strcmp(name, "maxpeers") == 0) {
769 if (fscanf(fp, "%d", &sys.maxpeers) != 1)
771 } else if (strcmp(name, "trusting") == 0) {
772 if (fscanf(fp, "%s", name) != 1)
775 if (*name == 'Y' || *name == 'y') {
777 } else if (*name == 'N' || *name == 'n') {
780 trusting = atoi(name);
782 } else if (strcmp(name, "logclock") == 0) {
783 if (fscanf(fp, "%s", name) != 1)
786 if (*name == 'Y' || *name == 'y') {
788 } else if (*name == 'N' || *name == 'n') {
791 logstats = atoi(name);
793 } else if (strcmp(name, "driftfile") == 0) {
794 if (fscanf(fp, "%s", name) != 1)
797 if (driftcomp_file = malloc(strlen(name)+1))
798 strcpy(driftcomp_file, name);
800 } else if (strcmp(name, "waytoobig") == 0 ||
801 strcmp(name, "setthreshold") == 0) {
802 if (fscanf(fp, "%s", name) != 1)
805 if (strcmp(name, "any") == 0)
808 WayTooBig = atof(name);
810 } else if (strncmp(name, "debuglevel", 5) == 0) {
811 if (fscanf(fp, "%d", &debuglevel) != 1)
814 else debug += debuglevel;
816 } else if (strcmp(name, "stratum") == 0) {
817 fprintf(stderr, "Obsolete command 'stratum'\n");
819 } else if (strcmp(name, "precision") == 0) {
820 if (fscanf(fp, "%d", &precision) != 1)
822 else sys.precision = (char) precision;
824 } else if (strcmp(name, "tickadj") == 0) {
825 if (fscanf(fp, "%d", &i) != 1)
828 } else if (strcmp(name, "settickadj") == 0) {
829 if (fscanf(fp, "%s", name) != 1)
832 if (*name == 'Y' || *name == 'y') {
834 } else if (*name == 'N' || *name == 'n') {
837 dotickadj = atoi(name);
839 } else if (strcmp(name, "setdosynctodr") == 0) {
840 if (fscanf(fp, "%s", name) != 1)
843 if (*name == 'Y' || *name == 'y') {
845 } else if (*name == 'N' || *name == 'n') {
848 dosynctodr = atoi(name);
852 } else if (strcmp(name, "noswap") == 0) {
856 } else if (strcmp(name, "broadcast") == 0) {
857 if (fscanf(fp, "%s", name) != 1) {
861 for (i = 0; i < nintf; i++)
862 if (strcmp(addrs[i].name, name) == 0)
865 syslog(LOG_ERR, "config file: %s not a known interface");
869 if ((addrs[i].if_flags & IFF_BROADCAST) == 0) {
870 syslog(LOG_ERR, "config file: %s doesn't support broadcast", name);
874 if (peer = check_peer(&addrs[i].bcast, -1)) {
875 syslog(LOG_ERR, "config file: duplicate broadcast for %s",
880 peer = (struct ntp_peer *) malloc(sizeof(struct ntp_peer));
883 syslog(LOG_ERR, "No memory");
887 peer->flags = PEER_FL_BCAST;
888 peer->hmode = MODE_BROADCAST;
889 peer->src = addrs[i].bcast;
891 #endif /* BROADCAST_NTP */
892 } else if ((strcmp(name, "peer") == 0) ||
893 (strcmp(name, "passive") == 0) ||
894 (strcmp(name, "server") == 0)) {
897 if (strcmp(name, "peer") == 0) {
899 } else if (strcmp(name, "server") == 0) {
901 } else if (strcmp(name, "passive") == 0) {
904 printf("can't happen\n");
907 if (fscanf(fp, "%s", name) != 1)
910 else if (name[0] == '/') {
911 int stratum, precision;
914 if (fscanf(fp, "%4s", ref_clock) != 1) {
916 syslog(LOG_ERR, "reference id missing");
919 if (fscanf(fp, "%4d", &stratum) != 1) {
921 syslog(LOG_ERR, "reference stratum missing");
924 if (fscanf(fp, "%4d", &precision) != 1) {
926 syslog(LOG_ERR, "reference precision missing");
929 if (fscanf(fp, "%19s", clk_type) != 1) {
931 syslog(LOG_ERR, "reference type missing");
935 if((i = init_clock(name, clk_type)) < 0) {
936 /* If we could not initialize clock line */
939 printf("Could not init reference source %s (type %s)\n",
943 syslog(LOG_ERR, "Could not init reference source %s (type %s)",
948 peer = (struct ntp_peer *)
949 malloc(sizeof(struct ntp_peer));
957 (void) strncpy((char *) &peer->refid,
959 peer->flags = PEER_FL_CONFIG|PEER_FL_REFCLOCK;
960 peer->hmode = MODE_SYM_ACT;
961 peer->stopwatch = stagger;
962 stagger += (1<<CLOCK_ADJ);
963 peer->flags |= PEER_FL_SYNC;
965 peer->stratum = stratum;
966 peer->precision = precision;
968 enqueue(&peer_list, peer);
971 printf("Peer %s mode %d refid %.4s stratum %d precision %d\n",
974 (char *)&peer->refid,
977 transmit(peer); /* head start for REFCLOCK */
979 #endif /* REFCLOCK */
980 else if (GetHostName(name, &sin) == 0)
981 syslog(LOG_ERR, "%s: unknown host", name);
983 for (i=0; i<nintf; i++)
984 if (addrs[i].sin.sin_addr.s_addr ==
989 sin.sin_port = servp->s_port;
991 sin.sin_port = htons(NTP_PORT);
993 peer = check_peer(&sin, -1);
995 peer = (struct ntp_peer *)
996 malloc(sizeof(struct ntp_peer));
1000 make_new_peer(peer);
1001 peer->flags = PEER_FL_CONFIG;
1003 case MODE_SYM_ACT: /* "peer" */
1004 peer->hmode = MODE_SYM_ACT;
1005 peer->stopwatch = stagger;
1006 stagger += (1<<CLOCK_ADJ);
1007 peer->flags |= PEER_FL_SYNC;
1009 case MODE_CLIENT: /* "server" */
1010 peer->hmode = MODE_CLIENT;
1011 peer->stopwatch = stagger;
1012 stagger += (1<<CLOCK_ADJ);
1013 peer->flags |= PEER_FL_SYNC;
1015 case MODE_SYM_PAS: /* "passive" */
1016 peer->hmode = MODE_SYM_PAS;
1017 peer->flags |= PEER_FL_SYNC;
1020 printf("can't happen\n");
1026 enqueue(&peer_list, peer);
1029 printf("Peer %s/%d af %d mode %d\n",
1030 inet_ntoa(peer->src.sin_addr),
1031 ntohs(peer->src.sin_port),
1032 peer->src.sin_family,
1038 "Duplicate peer %s in in config file",
1039 inet_ntoa(sin.sin_addr));
1042 printf("Duplicate peer %s in in config file\n",
1043 inet_ntoa(sin.sin_addr));
1048 } else if( *name != '#' ) {
1049 syslog(LOG_ERR, "config file: %s not recognized", name);
1052 printf("unrecognized option in config file: %s\n", name);
1057 while (c != '\n' && c != EOF); /* next line */
1060 fprintf(stderr, "init_ntp: %s: initialization error\n", config);
1061 syslog(LOG_ERR, "init_ntp: %s: initialization error", config);
1066 * Read saved drift compensation register value.
1068 #if defined(AFS_SUN_ENV) || defined(AFS_HPUX_ENV)
1069 #define BOGUS_DRIFT_COMPENSATION 10.0
1071 #define BOGUS_DRIFT_COMPENSATION 1.0
1073 if ((fp = fopen(driftcomp_file, "r")) != NULL) {
1074 if (fscanf(fp, "%lf", &j) == 1 &&
1075 j > -BOGUS_DRIFT_COMPENSATION &&
1076 j < BOGUS_DRIFT_COMPENSATION) {
1079 "Drift compensation value initialized to %f", j);
1082 "init_ntp: bad drift compensation value\n");
1084 "init_ntp: bad drift compensation value\n");
1090 int kern_tickadj, kern_hz, kern_tick, kern_dosynctodr;
1093 int SetKernel (kmem, nl, newValue)
1097 static char *memory = "/dev/kmem";
1098 if (lseek(kmem, (long)nl->n_value, L_SET) == -1) {
1099 syslog(LOG_ERR, "%s: lseek fails: %m", memory);
1100 perror ("setting kernel variable");
1103 if (write(kmem, &newValue, sizeof(int)) != sizeof(int)) {
1104 syslog(LOG_ERR, "%s: kernel variable assignment fails: %m", memory);
1105 printf("SetKernel variable %s fails\n", nl->n_name);
1106 perror ("setting kernel variable");
1109 syslog(LOG_INFO, "System %s SET to %d", nl->n_name, newValue);
1110 printf("System %s SET to %d\n", nl->n_name, newValue);
1114 #if defined(INIT_KERN_VARS)
1119 static char *memory = "/dev/kmem";
1120 static struct nlist nl[] = {
1136 static int *kern_vars[] =
1137 {&kern_tickadj, &kern_hz, &kern_tick, &kern_dosynctodr};
1139 kmem = open(memory, O_RDONLY);
1141 syslog(LOG_ERR, "Can't open %s for reading: %m", memory);
1149 nlist("/vmunix", nl);
1151 for (i = 0; i < (sizeof(kern_vars)/sizeof(kern_vars[0])); i++) {
1154 if ((where = nl[i].n_value) == 0) {
1155 syslog(LOG_ERR, "Unknown kernal var %s",
1164 if (lseek(kmem, where, L_SET) == -1) {
1165 syslog(LOG_ERR, "lseek for %s fails: %m",
1174 if (read(kmem, kern_vars[i], sizeof(int)) != sizeof(int)) {
1175 syslog(LOG_ERR, "read for %s fails: %m",
1188 * If desired value of tickadj is not specified in the configuration
1189 * file, compute a "reasonable" value here, based on the assumption
1190 * that we don't have to slew more than 2ms every 4 seconds.
1192 * TODO: the 500 needs to be parameterized.
1194 if (tickadj == 0 && kern_hz)
1195 tickadj = 500/kern_hz;
1199 printf("kernel vars: tickadj = %d, hz = %d, tick = %d\n",
1200 kern_tickadj, kern_hz, kern_tick);
1202 if (kern_dosynctodr) printf ("dosynctodr is on\n");
1204 printf("desired tickadj = %d, dotickadj = %d\n", tickadj,
1211 { int set_tickadj, set_dosynctodr;
1213 set_tickadj = (dotickadj && tickadj && (tickadj != kern_tickadj)
1214 /* do some plausibility checks on the value... */
1215 && (kern_tickadj > 0) && (kern_tickadj < 20000));
1216 set_dosynctodr = (dosynctodr && (kern_dosynctodr == 1));
1217 if (set_tickadj || set_dosynctodr) {
1218 if ((kmem = open(memory, O_RDWR)) >= 0) {
1220 code = SetKernel (kmem, &nl[0], tickadj);
1221 if (code == 0) kern_tickadj = tickadj;
1223 if (set_dosynctodr) {
1224 code = SetKernel (kmem, &nl[3], 0);
1225 if (code == 0) kern_dosynctodr = 0;
1229 syslog(LOG_ERR, "Can't open %s: %m", memory);
1230 printf("Can't open %s\n", memory);
1234 #endif /* SETTICKADJ */
1237 * If we have successfully discovered `hz' from the kernel, then we
1238 * can set sys.precision, if it has not already been specified. If
1239 * no value of `hz' is available, then use default (-6)
1241 if (sys.precision == 0) {
1244 sys.precision = MeasurePrecision(&interval);
1245 if (sys.precision) {
1246 sprintf (msg, "sys.precision set to %d from measured minimum clock interval of %d usec",
1247 sys.precision, interval);
1251 else if (kern_hz <= 128)
1253 else if (kern_hz <= 256)
1255 else if (kern_hz <= 512)
1257 else if (kern_hz <= 1024)
1258 sys.precision = -10;
1259 else sys.precision = -11;
1261 "sys.precision set to %d from sys clock of %d HZ",
1262 sys.precision, kern_hz);
1264 syslog(LOG_INFO, msg);
1265 printf ("%s\n", msg);
1268 #endif /* INIT_KERN_VARS */
1272 * Given host or net name or internet address in dot notation assign the
1273 * internet address in byte format. source is ../routed/startup.c with minor
1274 * changes to detect syntax errors.
1276 * We now try to interpret the name as in address before we go off and bother
1277 * the domain name servers.
1279 * Unfortunately the library routine inet_addr() does not detect mal formed
1280 * addresses that have characters or byte values > 255.
1283 GetHostName(name, sin)
1285 struct sockaddr_in *sin;
1290 if ((HostAddr = inet_addr(name)) != -1) {
1291 sin->sin_addr.s_addr = (afs_uint32) HostAddr;
1292 sin->sin_family = AF_INET;
1296 if (hp = gethostbyname(name)) {
1297 if (hp->h_addrtype != AF_INET)
1299 memcpy((char *) &sin->sin_addr, (char *) hp->h_addr, hp->h_length);
1300 sin->sin_family = hp->h_addrtype;
1306 #define PKTBUF_SIZE 536
1308 /* number of clocks per packet */
1309 #define N_NTP_PKTS \
1310 ((PKTBUF_SIZE - sizeof(struct ntpinfo))/(sizeof(struct clockinfo)))
1312 query_mode(dst, ntp, sock)
1313 struct sockaddr_in *dst;
1314 struct ntpdata *ntp;
1315 int sock; /* which socket packet arrived on */
1317 char packet[PKTBUF_SIZE];
1318 register struct ntpinfo *nip = (struct ntpinfo *) packet;
1319 register struct ntp_peer *peer = peer_list.head;
1320 struct clockinfo *cip;
1324 if (ntp->stratum != INFO_QUERY)
1326 nip->version = NTPDC_VERSION;
1327 nip->type = INFO_REPLY;
1329 nip->npkts = peer_list.members/N_NTP_PKTS;
1330 if (peer_list.members % N_NTP_PKTS)
1332 nip->peers = peer_list.members;
1334 cip = (struct clockinfo *)&nip[1];
1336 while (peer != NULL) {
1337 cip->net_address = peer->src.sin_addr.s_addr;
1338 if ((peer->sock < 0) || (peer->sock >= nintf))
1339 cip->my_address = htonl(0);
1341 cip->my_address = addrs[peer->sock].sin.sin_addr.s_addr;
1342 cip->port = peer->src.sin_port; /* already in network order */
1343 cip->flags = htons(peer->flags);
1344 if (sys.peer == peer)
1345 cip->flags |= htons(PEER_FL_SELECTED);
1346 cip->pkt_sent = htonl(peer->pkt_sent);
1347 cip->pkt_rcvd = htonl(peer->pkt_rcvd);
1348 cip->pkt_dropped = htonl(peer->pkt_dropped);
1349 cip->timer = htonl(peer->timer);
1350 cip->leap = peer->leap;
1351 cip->stratum = peer->stratum;
1352 cip->ppoll = peer->ppoll;
1353 cip->precision = peer->precision;
1354 cip->hpoll = peer->hpoll;
1355 cip->reach = htons(peer->reach & NTP_WINDOW_SHIFT_MASK);
1356 cip->estdisp = htonl((afs_int32) (peer->estdisp * 1000.0));
1357 cip->estdelay = htonl((afs_int32) (peer->estdelay * 1000.0));
1358 cip->estoffset = htonl((afs_int32) (peer->estoffset * 1000.0));
1359 cip->refid = peer->refid;
1360 cip->reftime.int_part = htonl(peer->reftime.int_part);
1361 cip->reftime.fraction = htonl(peer->reftime.fraction);
1363 cip->info_filter.index = htons(peer->filter.samples);
1364 for (i = 0; i < PEER_SHIFT; i++) {
1365 cip->info_filter.offset[i] =
1366 htonl((afs_int32)(peer->filter.offset[i] * 1000.0));
1367 cip->info_filter.delay[i] =
1368 htonl((afs_int32)(peer->filter.delay[i] * 1000.0));
1371 if (nip->count++ >= N_NTP_PKTS - 1) {
1373 if ((sendto(addrs[sock].fd, (char *) packet,
1375 (struct sockaddr *) dst,
1376 sizeof(struct sockaddr_in))) < 0) {
1377 syslog(LOG_ERR, "sendto: %s %m",
1378 inet_ntoa(dst->sin_addr));
1380 nip->type = INFO_REPLY;
1382 cip = (struct clockinfo *)&nip[1];
1388 if ((sendto(addrs[sock].fd, (char *) packet, sizeof(packet), 0,
1389 (struct sockaddr *) dst,
1390 sizeof(struct sockaddr_in))) < 0) {
1391 syslog(LOG_ERR, "sendto: %s %m", ntoa(dst->sin_addr));
1396 /* every hour, dump some useful information to the log */
1401 static double drifts[5] = { 0.0, 0.0, 0.0, 0.0, 0.0 };
1402 static int drift_count = 0;
1403 extern double drift_comp, compliance;
1404 extern int peer_switches, peer_sw_inhibited;
1406 (void) sprintf(buf, "stats: dc %f comp %f peersw %d inh %d",
1407 drift_comp, compliance, peer_switches,
1410 if (sys.peer == NULL) {
1411 strcat(buf, " UNSYNC");
1413 } else if (sys.peer->flags & PEER_FL_REFCLOCK) {
1415 (void) sprintf(buf + p, " off %f SYNC %.4s %d",
1416 sys.peer->estoffset,
1417 (char *)&sys.peer->refid,
1422 (void) sprintf(buf + p, " off %f SYNC %s %d",
1423 sys.peer->estoffset,
1424 ntoa(sys.peer->src.sin_addr),
1427 syslog(LOG_INFO, buf);
1433 * If the drift compensation snapshot file is open, then write
1434 * the current value to it. Since there's only one block in the
1435 * file, and no one else is reading it, we'll just keep the file
1436 * open and write to it.
1438 if (drift_fd >= 0) {
1439 drifts[drift_count % 5] = drift_comp;
1440 /* works out to be 70 bytes */
1442 "%+12.10f %+12.10f %+12.10f %+12.10f %+12.10f %4d\n",
1443 drifts[drift_count % 5],
1444 drifts[(drift_count+4) % 5],
1445 drifts[(drift_count+3) % 5],
1446 drifts[(drift_count+2) % 5],
1447 drifts[(drift_count+1) % 5],
1450 (void) lseek(drift_fd, 0L, L_SET);
1451 if (write(drift_fd, buf, strlen(buf)) < 0) {
1452 syslog(LOG_ERR, "Error writing drift comp file: %m");
1458 #if defined(DEBUG) && defined(SIGUSR1) && defined(SIGUSR2)
1462 /* re-enable self (we're not BSD any more) */
1463 (void) signal(SIGUSR1, incdebug);
1468 printf("DEBUG LEVEL %d\n", debug);
1470 (void) setlogmask(LOG_UPTO(LOG_DEBUG));
1472 syslog(LOG_DEBUG, "DEBUG LEVEL %d", debug);
1478 /* re-enable self (we're not BSD any more) */
1479 (void) signal(SIGUSR2, decdebug);
1484 printf("DEBUG LEVEL %d\n", debug);
1485 syslog(LOG_DEBUG, "DEBUG LEVEL %d", debug);
1488 (void) setlogmask(LOG_UPTO(LOG_INFO));
1497 syslog(LOG_NOTICE, "terminated: (sig %d)", sig);
1500 printf("ntpd terminated (sig %d)\n", sig);
1509 struct refclock *next;
1510 } *refclocks = NULL;
1512 int init_clock_local(), read_clock_local();
1514 int init_clock_psti(), read_clock_psti();
1517 init_clock(name, type)
1524 if (strcmp(type, "local") == 0) {
1525 reader = read_clock_local;
1526 cfd = init_clock_local(name);
1529 else if (strcmp(type, "psti") == 0) {
1530 reader = read_clock_psti;
1531 cfd = init_clock_psti(name);
1536 if (debug) printf("Unknown reference type\n"); else
1538 syslog(LOG_ERR, "Unknown reference clock type (%s)\n", type);
1542 r = (struct refclock *)malloc(sizeof(struct refclock));
1545 r->next = refclocks;
1551 read_clock(cfd, tvpp, otvpp)
1553 struct timeval **tvpp, **otvpp;
1557 for (r = refclocks; r; r = r->next)
1559 return((r->reader)(cfd, tvpp, otvpp));
1560 return(1); /* Can't happen */