System: ntp version 3.4 Patch #: 13 Priority: medium From: louie@trantor.umd.edu Description: A few cosmetic changes in ntp.c for the case when udp/ntp is not in the /etc/services file. A few extra diddles in ntp.h for the reference clock feature. A couple of changes to debug NeXT support in ntp_adjust.c Changes for reference clock feature in ntp_proto.c In ntp_sock.c, change the order that the bind() call is done for each socket. It turns out that if you have the Multicast code installed, incoming packets will be delived to the *first* socket that matches. It also turns out that when binding sockets, the first one bound is the last on checked, so we want to bind the wildcard socket first. Changes in ntpd.c for reference clock support. Also, a few diddles to accomodate the NeXT computer system that has a slightly different nlist.h A few cosmetic changes for ntpd.c Added support few a new type of unsigned long to double compiler brokenness, called GENERIC_UNS_BUG. If this is defined, then the unsigned long is shifted right one bit, the high-order bit of the result is cleared, then converted to a double. The double is multiplied by 2.0, and the a 1.0 is optionall added to it if the low order bit of the original unsigned long was set. Whew! Add test for GENERIC_UNS_BUG to test.c Repeat-By: Fix: From rn, say "| patch -p -N -d DIR", where DIR is your ntp source directory. Outside of rn, say "cd DIR; patch -p -N #define PATCHLEVEL 13 Index: Makefile *** Makefile.old Thu May 18 18:37:56 1989 --- Makefile Thu May 18 18:37:59 1989 *************** *** 1,6 **** ! # $Source: /usr/users/louie/ntp/RCS/Makefile,v $ $Revision: 3.4.1.6 $ $Date: 89/05/03 15:08:06 $ # # $Log: Makefile,v $ # Revision 3.4.1.6 89/05/03 15:08:06 louie # In the Makefile, remove references to the readclock.c module. # --- 1,10 ---- ! # $Source: /usr/users/louie/ntp/RCS/Makefile,v $ $Revision: 3.4.1.7 $ $Date: 89/05/18 12:43:32 $ # # $Log: Makefile,v $ + # Revision 3.4.1.7 89/05/18 12:43:32 louie + # Add preliminary support of NeXT machine, new floating point bug work-around + # and reference clock support. + # # Revision 3.4.1.6 89/05/03 15:08:06 louie # In the Makefile, remove references to the readclock.c module. # *************** *** 76,81 **** --- 80,87 ---- # SETTICKADJ - attempt to modify kernel's `tickadj' variable at run time. # REFCLOCK - define if you have a reference clock attached to your # machine. (untested by UMD) + # PSTI - define along with REFCLOCK if you have a PSTI clock attached + # that you'd like to use a a reference clock. # XTAL=0 - for line freq clock, or # XTAL=1 for crystal controlled clock (default) # LOG_NTP=foo - to change the syslog facility. You could specify *************** *** 84,91 **** # NOSWAP - allow use of plock() to prevent swapping # ! # FEATURES= ! FEATURES= -DBROADCAST_NTP -DSETTICKADJ -DDEBUG # for 4.3 BSD DEFINES= --- 90,98 ---- # NOSWAP - allow use of plock() to prevent swapping # ! #FEATURES= -DBROADCAST_NTP -DSETTICKADJ -DDEBUG ! #FEATURES= -DSETTICKADJ -DDEBUG -DREFCLOCK -DPSTI ! FEATURES= -DSETTICKADJ -DDEBUG -DREFCLOCK # for 4.3 BSD DEFINES= *************** *** 93,105 **** # for Sun #DEFINES= -DSUN_FLT_BUG ! # for Ultrix 2.0/2.2/3.0 # don't forget to fix the broken definition of inet_addr in netdb.h # it should be declared as a u_long not a in_addr (the doc is wrong also) ! # (Note 3.0 has it fixed). VAX_COMPILER_FLT_BUG is defined for pcc which ! # doesn't know how to convert an unsigned long into a float/double #DEFINES= -DVAX_COMPILER_FLT_BUG -DNOSWAP CFLAGS= -O ${DEFINES} ${FEATURES} ${INCPATH} # # Header files --- 100,116 ---- # for Sun #DEFINES= -DSUN_FLT_BUG ! # for Ultrix 2.0/2.2 # don't forget to fix the broken definition of inet_addr in netdb.h # it should be declared as a u_long not a in_addr (the doc is wrong also) ! # VAX_COMPILER_FLT_BUG is defined for pcc which doesn't know how to ! # convert an unsigned long into a float/double #DEFINES= -DVAX_COMPILER_FLT_BUG -DNOSWAP + # + # for a NeXT system, define these pre-processor symbols. + #DEFINES=-DSUN_FLT_BUG -DGENERIC_UNS_BUG + CFLAGS= -O ${DEFINES} ${FEATURES} ${INCPATH} # # Header files *************** *** 108,121 **** # Source files # ! SRCS= ntp.c ntpd.c ntpdc.c ntpsubs.c ntp_proto.c ntp_sock.c ntp_adjust.c ! NTPDSRC= ntpd.c ntpsubs.c ntp_proto.c ntp_sock.c ntp_adjust.c # Object files # ! OBJS= ntp.o ntpd.o ntpdc.o ntpsubs.o ntp_proto.o ntp_sock.o ntp_adjust.o ! NTPDOBJ= ntpd.o ntpsubs.o ntp_proto.o ntp_sock.o ntp_adjust.o DIST= README Makefile man ${SRCS} ${HDRS} ntp.conf test.c extract.pl stat.pl PROGS= ntp ntpd ntpdc ntest --- 119,135 ---- # Source files # ! NTPDSRC= ntpd.c ntpsubs.c ntp_proto.c ntp_sock.c ntp_adjust.c read_local.c \ ! read_psti.c ! SRCS= ntp.c ntpdc.c ${NTPDSRC} # Object files # ! NTPDOBJ= ntpd.o ntpsubs.o ntp_proto.o ntp_sock.o ntp_adjust.o read_local.o \ ! read_psti.o ! OBJS= ntp.o ntpdc.o ${NTPDOBJ} + DIST= README Makefile man ${SRCS} ${HDRS} ntp.conf test.c extract.pl stat.pl PROGS= ntp ntpd ntpdc ntest *************** *** 126,133 **** ${CC} ${LDFLAGS} -o ntp ntp.o ntpsubs.o ${LIBS} ntpd: ${NTPDOBJ} ! ${CC} ${LDFLAGS} -o ntpd ntpd.o ntpsubs.o ntp_adjust.o ntp_proto.o \ ! ntp_sock.o ${LIBS} ntpdc: ntpdc.o ${CC} ${LDFLAGS} -o ntpdc ntpdc.o ${LIBS} --- 140,146 ---- ${CC} ${LDFLAGS} -o ntp ntp.o ntpsubs.o ${LIBS} ntpd: ${NTPDOBJ} ! ${CC} ${LDFLAGS} -o ntpd ${NTPDOBJ} ${LIBS} ntpdc: ntpdc.o ${CC} ${LDFLAGS} -o ntpdc ntpdc.o ${LIBS} Index: README *** README.old Thu May 18 18:38:20 1989 --- README Thu May 18 18:38:28 1989 *************** *** 1,4 **** ! README for UNIX NTP release $Date: 89/05/03 15:08:58 $ $Revision: 3.4.1.5 $ --- 1,4 ---- ! README for UNIX NTP release $Date: 89/05/18 12:43:58 $ $Revision: 3.4.1.6 $ *************** *** 36,41 **** --- 36,42 ---- VAX: 5 Sun3: 10 Sun4: 5 + NeXT: 7 This step is optional; new algorithms will allow you to get by (with reduced accuracy) with the system supplied *************** *** 48,53 **** --- 49,76 ---- 7) Fire up ntpd in /etc/rc.local History: + 5/17/89 + Yet another preprocessor define for broken unsigned long to double + conversions. Define GENERIC_UNS_BUG, and the unsigned long is shifted + right one bit and cast to an int before conversion to a double. This + seems to work much better. + + Preliminary support for NeXT systems. Be sure to define both + GENERIC_UNS_BUG and SUN_FLT_BUG. The default value of tickadj in the + kernel is too large so you'll have to adjust it by using the + -t option and compiling with SETTICKADJ. I don't think you can use + gdb on the running /dev/mem image. NOTE: don't even think of trying + to run this on the 0.8 release of the system software. You will + utterly and absolutely hang you system. Current testing is being + done on the 0.9 release. So far, there seems to be some weirdness in + the kernel which is attempting to sync to the clock to the internal + clock chip every so ofter. So while it compiles and runs, it really + doesn't work very well on the NeXT machine. + + Integration of the reference clock code from Doug Kingston and Jeff + Schiller has been done. To configure a reference clock, check the + ntpd manual page. + 5/3/89 The changes to the ntp_proto.c module for clockhopper suppression have been tweaked once more, ever so slightly to conform with the 21 April Index: ntp.c *** ntp.c.old Thu May 18 18:38:44 1989 --- ntp.c Thu May 18 18:38:50 1989 *************** *** 1,9 **** #ifndef lint ! static char *rcsid = "$Source: /usr/users/louie/ntp/RCS/ntp.c,v $ $Revision: 3.4.1.5 $ $Date: 89/05/03 15:09:53 $"; #endif lint /* * $Log: ntp.c,v $ * Revision 3.4.1.5 89/05/03 15:09:53 louie * Fix minor problem in ntp.c to get sin_family set in the proper place. * --- 1,13 ---- #ifndef lint ! static char *rcsid = "$Source: /usr/users/louie/ntp/RCS/ntp.c,v $ $Revision: 3.4.1.6 $ $Date: 89/05/18 18:21:29 $"; #endif lint /* * $Log: ntp.c,v $ + * Revision 3.4.1.6 89/05/18 18:21:29 louie + * A few cosmetic changes in ntp.c for the case when udp/ntp is not in the + * /etc/services file. + * * Revision 3.4.1.5 89/05/03 15:09:53 louie * Fix minor problem in ntp.c to get sin_family set in the proper place. * *************** *** 79,84 **** --- 83,89 ---- */ #include + #include #include #include #include *************** *** 136,142 **** double t1, t2, t3, t4, offset, delay; char ref_clock[5]; time_t net_time; ! ref_clock[4] = NULL; timeout.tv_sec = TIME_OUT; timeout.tv_usec = 0; --- 141,147 ---- double t1, t2, t3, t4, offset, delay; char ref_clock[5]; time_t net_time; ! ref_clock[4] = '\0'; timeout.tv_sec = TIME_OUT; timeout.tv_usec = 0; *************** *** 144,150 **** sp = getservbyname("ntp", "udp"); if (sp == NULL) { ! fprintf(stderr, "udp/ntp: service unknown\nUsing default %d\n", NTP_PORT); dst.sin_port = htons(NTP_PORT); } else --- 149,155 ---- sp = getservbyname("ntp", "udp"); if (sp == NULL) { ! fprintf(stderr, "udp/ntp: service unknown; using default %d\n", NTP_PORT); dst.sin_port = htons(NTP_PORT); } else Index: ntp.h *** ntp.h.old Thu May 18 18:39:13 1989 --- ntp.h Thu May 18 18:39:19 1989 *************** *** 1,7 **** ! /* $Source: /usr/users/louie/ntp/RCS/ntp.h,v $ $Revision: 3.4.1.6 $ $Date: 89/05/03 15:11:06 $ */ /* * $Log: ntp.h,v $ * Revision 3.4.1.6 89/05/03 15:11:06 louie * Specify default file for drift value and more peer flag definitions to * reflect various stages of clock selection critera. --- 1,10 ---- ! /* $Source: /usr/users/louie/ntp/RCS/ntp.h,v $ $Revision: 3.4.1.7 $ $Date: 89/05/18 18:22:14 $ */ /* * $Log: ntp.h,v $ + * Revision 3.4.1.7 89/05/18 18:22:14 louie + * A few extra diddles in ntp.h for the reference clock feature. + * * Revision 3.4.1.6 89/05/03 15:11:06 louie * Specify default file for drift value and more peer flag definitions to * reflect various stages of clock selection critera. *************** *** 136,141 **** --- 139,148 ---- #define NTP_MAXAGE 86400 #define NTP_MAXSKW 0.01 /* seconds */ #define NTP_MINDIST 0.02 /* seconds */ + #ifdef REFCLOCK + #define NTP_REFMAXSKW 0.001 /* seconds (for REFCLOCKs) */ + #define NTP_REFMINDIST 0.001 /* seconds (for REFCLOCKs) */ + #endif #define NTP_MINPOLL 6 /* (64) seconds between messages */ #define NTP_MAXPOLL 10 /* (1024) secs to poll */ #define NTP_WINDOW 8 /* size of shift register */ *************** *** 297,302 **** --- 304,310 ---- #define PEER_FL_CANDIDATE 0x0200 /* candidate peer */ #define PEER_FL_SYNC 0x1000 /* peer can bet sync'd to */ #define PEER_FL_BCAST 0x2000 /* broadcast peer */ + #define PEER_FL_REFCLOCK 0x4000 /* peer is a local reference clock */ #define PEER_FL_SELECTED 0x8000 /* actually used by query routine */ int sock; /* index into sockets to derive Index: ntp_adjust.c *** ntp_adjust.c.old Thu May 18 18:39:29 1989 --- ntp_adjust.c Thu May 18 18:39:32 1989 *************** *** 1,5 **** #ifndef lint ! static char *RCSid = "$Source: /usr/users/louie/ntp/RCS/ntp_adjust.c,v $ $Revision: 3.4.1.3 $ $Date: 89/04/07 18:05:17 $"; #endif /* --- 1,5 ---- #ifndef lint ! static char *RCSid = "$Source: /usr/users/louie/ntp/RCS/ntp_adjust.c,v $ $Revision: 3.4.1.4 $ $Date: 89/05/18 18:23:36 $"; #endif /* *************** *** 7,12 **** --- 7,15 ---- * 5. of the NTP specification. * * $Log: ntp_adjust.c,v $ + * Revision 3.4.1.4 89/05/18 18:23:36 louie + * A couple of changes to debug NeXT support in ntp_adjust.c + * * Revision 3.4.1.3 89/04/07 18:05:17 louie * Removed unused variable from ntp_adjust.c module. * *************** *** 58,63 **** --- 61,67 ---- */ #include + #include #include #include #include *************** *** 132,138 **** adj_logical(offset) double offset; { ! struct timeval tv2; #ifdef XADJTIME2 struct timeval delta, olddelta; #endif --- 136,142 ---- adj_logical(offset) double offset; { ! struct timeval tv1, tv2; #ifdef XADJTIME2 struct timeval delta, olddelta; #endif *************** *** 150,158 **** (void) gettimeofday(&tv2, (struct timezone *) 0); steptime += tv2.tv_sec; steptime += tv2.tv_usec / 1000000.0; ! tv2.tv_sec = steptime; ! tv2.tv_usec = (steptime - tv2.tv_sec) * 1000000; ! if (settimeofday(&tv2, (struct timezone *) 0) < 0) { syslog(LOG_ERR, "Can't set time: %m"); return(-1); } --- 154,169 ---- (void) gettimeofday(&tv2, (struct timezone *) 0); steptime += tv2.tv_sec; steptime += tv2.tv_usec / 1000000.0; ! tv1.tv_sec = steptime; ! tv1.tv_usec = (steptime - tv1.tv_sec) * 1000000; ! #ifdef DEBUG ! if (debug > 2) { ! steptime = (tv1.tv_sec + tv1.tv_usec/1000000.0) - ! (tv2.tv_sec + tv2.tv_usec/1000000.0); ! printf("adj_logical: %f %f\n", offset, steptime); ! } ! #endif ! if (settimeofday(&tv1, (struct timezone *) 0) < 0) { syslog(LOG_ERR, "Can't set time: %m"); return(-1); } Index: ntp_proto.c *** ntp_proto.c.old Thu May 18 18:40:21 1989 --- ntp_proto.c Thu May 18 18:40:45 1989 *************** *** 1,5 **** #ifndef lint ! static char *rcsid = "$Source: /usr/users/louie/ntp/RCS/ntp_proto.c,v $ $Revision: 3.4.1.11 $ $Date: 89/05/03 23:51:30 $"; #endif /* --- 1,5 ---- #ifndef lint ! static char *rcsid = "$Source: /usr/users/louie/ntp/RCS/ntp_proto.c,v $ $Revision: 3.4.1.12 $ $Date: 89/05/18 18:25:04 $"; #endif /* *************** *** 11,16 **** --- 11,19 ---- /* * $Log: ntp_proto.c,v $ + * Revision 3.4.1.12 89/05/18 18:25:04 louie + * Changes for reference clock feature in ntp_proto.c + * * Revision 3.4.1.11 89/05/03 23:51:30 louie * Had my head on backwards with a reversed test in the clockhopper avoidance * code. Need to switch to the first selected clock when its stratum is lower *************** *** 108,113 **** --- 111,117 ---- */ #include + #include #include #include #include *************** *** 150,157 **** extern void make_new_peer(), double_to_s_fixed(), tstamp(), demobilize(); void process_packet(), clock_update(), clear(), clock_filter(), ! select_clock(), poll_update(); /* 3.4. Event Processing */ --- 154,165 ---- extern void make_new_peer(), double_to_s_fixed(), tstamp(), demobilize(); + #ifdef REFCLOCK + void refclock_input(); + #endif + void process_packet(), clock_update(), clear(), clock_filter(), ! receive(), select_clock(), poll_update(); /* 3.4. Event Processing */ *************** *** 194,200 **** peer->xmt = pkt->xmt; ! if ((peer->flags & PEER_FL_BCAST) == 0) { /* select correct socket to send reply on */ if (sendto(addrs[(peer->sock < 0 ? 0 : peer->sock)].fd, (char *) pkt, sizeof(ntpframe), --- 202,208 ---- peer->xmt = pkt->xmt; ! if ((peer->flags & (PEER_FL_BCAST|PEER_FL_REFCLOCK)) == 0) { /* select correct socket to send reply on */ if (sendto(addrs[(peer->sock < 0 ? 0 : peer->sock)].fd, (char *) pkt, sizeof(ntpframe), *************** *** 203,208 **** --- 211,251 ---- ntoa(peer->src.sin_addr)); return; } + #ifdef REFCLOCK + } else if (peer->flags & PEER_FL_REFCLOCK) { + /* Special version of code below, adjusted for refclocks */ + + + peer->pkt_sent++; + i = peer->reach; /* save a copy */ + + peer->reach = (peer->reach << 1) & NTP_WINDOW_SHIFT_MASK; + + if (i && peer->reach == 0) { + syslog(LOG_INFO, "Lost reachability with %.4s", + (char *)&peer->refid); + #ifdef DEBUG + if (debug) + printf("Lost reachability with %.4s\n", + (char *)&peer->refid); + #endif + } + + if (peer->reach == 0) + clear(peer); + + if (peer->valid < 2) + peer->valid++; + else { + clock_filter(peer, 0.0, 0.0); /* call with invalid values */ + select_clock(); /* and try to reselect clock */ + } + + peer->timer = 1<sock].fd, *************** *** 270,275 **** --- 313,353 ---- poll_update(peer, peer->hpoll + 1); } + #ifdef REFCLOCK + void + refclock_input(peer, pkt) + struct ntpdata *pkt; + struct ntp_peer *peer; + { + struct timeval *tvp; + struct timeval *otvp; + + if (read_clock(peer->sock, &tvp, &otvp)) + return; + + tstamp(&pkt->rec, tvp); + pkt->xmt = pkt->rec; + pkt->reftime = pkt->rec; + tstamp(&pkt->org, otvp); + peer->xmt = pkt->org; + pkt->refid = peer->refid; + pkt->status &= ~ALARM; + pkt->stratum = peer->stratum; + pkt->ppoll = 0xff; + pkt->precision = peer->precision; + double_to_s_fixed(&pkt->distance, 0.0); + double_to_s_fixed(&pkt->dispersion, 0.0); + #ifdef DEBUG + if (debug > 5) { + printf("\nFaking packet "); + dump_pkt(&peer->src, pkt, (struct ntp_peer *)NULL); + } + #endif + receive((struct sockaddr_in *)peer, pkt, otvp, -1); + return; + } + #endif REFCLOCK + /* 3.4.2. Receive Procedure */ void receive(dst, pkt, tvp, sock) *************** *** 300,306 **** /* if we're only going to support NTP Version 2 then this stuff isn't necessary, right? */ ! if ((peer_mode = pkt->status & MODEMASK) == 0) { /* packet from an older NTP implementation. Synthesize the correct mode. The mapping goes like this: --- 378,384 ---- /* if we're only going to support NTP Version 2 then this stuff isn't necessary, right? */ ! if ((peer_mode = pkt->status & MODEMASK) == 0 && dst) { /* packet from an older NTP implementation. Synthesize the correct mode. The mapping goes like this: *************** *** 337,342 **** --- 415,425 ---- peer->hmode = MODE_SYM_PAS; peer->reach = 0; clear(peer); + #ifdef REFCLOCK + } else if (sock == -1) { + /* we're begin called by refclock_input(), get peer ptr */ + peer = (struct ntp_peer *)dst; + #endif } else peer = check_peer(dst, sock); *************** *** 515,521 **** delay = (t2 - t1) - (t3 - t4); offset = ((t2 - t1) + (t3 - t4)) / 2.0; ! delay += NTP_MAXSKW + 1.0/(unsigned long)(1L << -sys.precision); if (peer->precision < 0 && -peer->precision < sizeof(long)*NBBY) delay += 1.0/(unsigned long)(1L << -peer->precision); --- 598,609 ---- delay = (t2 - t1) - (t3 - t4); offset = ((t2 - t1) + (t3 - t4)) / 2.0; ! delay += 1.0/(unsigned long)(1L << -sys.precision) ! #ifndef REFCLOCK ! + NTP_MAXSKW; ! #else ! + (peer->flags&PEER_FL_REFCLOCK) ? NTP_REFMAXSKW : NTP_MAXSKW; ! #endif if (peer->precision < 0 && -peer->precision < sizeof(long)*NBBY) delay += 1.0/(unsigned long)(1L << -peer->precision); *************** *** 524,530 **** --- 612,623 ---- return; } + #ifndef REFCLOCK delay = MAX(delay, NTP_MINDIST); + #else + delay = MAX(delay, (peer->flags & PEER_FL_REFCLOCK) ? + NTP_REFMINDIST : NTP_MINDIST); + #endif peer->valid = 0; clock_filter(peer, delay, offset); /* invoke clock filter procedure */ *************** *** 531,537 **** #ifdef DEBUG if (debug) { printf("host: %s : %f : %f : %f : %f : %f : %o\n", ! ntoa(dst->sin_addr), delay, offset, peer->estdelay, peer->estoffset, peer->estdisp, peer->reach); } --- 624,631 ---- #ifdef DEBUG if (debug) { printf("host: %s : %f : %f : %f : %f : %f : %o\n", ! dst ? ntoa(dst->sin_addr) : "refclock", ! delay, offset, peer->estdelay, peer->estoffset, peer->estdisp, peer->reach); } *************** *** 576,582 **** --- 670,690 ---- * Update the local system variables */ sys.leap = peer->leap; + #ifndef REFCLOCK sys.stratum = peer->stratum + 1; + sys.refid = peer->src.sin_addr.s_addr; + #else + if (peer->flags & PEER_FL_REFCLOCK) { + /* once we re-map the stratums so that stratum 0 is + better than stratum 1, some of this foolishness + can go away */ + sys.stratum = peer->stratum; + sys.refid = peer->refid; + } else { + sys.stratum = peer->stratum + 1; + sys.refid = peer->src.sin_addr.s_addr; + } + #endif temp = s_fixed_to_double(&peer->distance) + peer->estdelay; double_to_s_fixed(&sys.distance, temp); *************** *** 584,590 **** temp = s_fixed_to_double(&peer->dispersion) + peer->estdisp; double_to_s_fixed(&sys.dispersion, temp); - sys.refid = peer->src.sin_addr.s_addr; sys.reftime = peer->rec; #ifdef DEBUG --- 692,697 ---- *************** *** 714,719 **** --- 821,830 ---- interval = 1 << (MAX(MIN(peer->ppoll, MIN(peer->hpoll, NTP_MAXPOLL)), NTP_MINPOLL)); + #ifdef REFCLOCK + if (peer->flags & PEER_FL_REFCLOCK) + interval = 1 << NTP_MINPOLL; + #endif if (interval == peer->timer) return; Index: ntp_sock.c *** ntp_sock.c.old Thu May 18 18:41:07 1989 --- ntp_sock.c Thu May 18 18:41:09 1989 *************** *** 1,9 **** #ifndef lint ! static char *RCSid = "$Source: /usr/users/louie/ntp/RCS/ntp_sock.c,v $ $Revision: 3.4.1.2 $ $Date: 89/04/07 19:07:46 $"; #endif /* * $Log: ntp_sock.c,v $ * Revision 3.4.1.2 89/04/07 19:07:46 louie * Deleted unused variables in ntp_sock.c * --- 1,16 ---- #ifndef lint ! static char *RCSid = "$Source: /usr/users/louie/ntp/RCS/ntp_sock.c,v $ $Revision: 3.4.1.3 $ $Date: 89/05/18 18:28:20 $"; #endif /* * $Log: ntp_sock.c,v $ + * Revision 3.4.1.3 89/05/18 18:28:20 louie + * In ntp_sock.c, change the order that the bind() call is done for each socket. + * It turns out that if you have the Multicast code installed, incoming packets + * will be delived to the *first* socket that matches. It also turns out that + * when binding sockets, the first one bound is the last on checked, so we want + * to bind the wildcard socket first. + * * Revision 3.4.1.2 89/04/07 19:07:46 louie * Deleted unused variables in ntp_sock.c * *************** *** 38,43 **** --- 45,51 ---- * */ + #include #include #include #include *************** *** 261,267 **** } close(vs); ! for (i = nintf - 1; i >= 0; i--) { /* create a datagram (UDP) socket */ if ((addrs[i].fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { syslog(LOG_ERR, "socket() failed: %m"); --- 269,275 ---- } close(vs); ! for (i = 0; i < nintf; i++) { /* create a datagram (UDP) socket */ if ((addrs[i].fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { syslog(LOG_ERR, "socket() failed: %m"); *************** *** 315,321 **** * is being bound anyway.. */ if (setsockopt(addrs[i].fd, SOL_SOCKET, SO_REUSEADDR, - (char *)&off, sizeof(off))) { syslog(LOG_ERR, "setsockopt SO_REUSEADDR off fails: %m"); #ifdef TEST --- 323,328 ---- Index: ntpd.c *** ntpd.c.old Thu May 18 18:41:45 1989 --- ntpd.c Thu May 18 18:42:02 1989 *************** *** 1,9 **** #ifndef lint ! static char *rcsid = "$Source: /usr/users/louie/ntp/RCS/ntpd.c,v $ $Revision: 3.4.1.8 $ $Date: 89/05/03 15:16:17 $"; #endif lint /* * $Log: ntpd.c,v $ * Revision 3.4.1.8 89/05/03 15:16:17 louie * Add code to save the value of the drift compensation register to a file every * hour. Add additional configuration file directives which can specify the same --- 1,13 ---- #ifndef lint ! static char *rcsid = "$Source: /usr/users/louie/ntp/RCS/ntpd.c,v $ $Revision: 3.4.1.9 $ $Date: 89/05/18 18:30:17 $"; #endif lint /* * $Log: ntpd.c,v $ + * Revision 3.4.1.9 89/05/18 18:30:17 louie + * Changes in ntpd.c for reference clock support. Also, a few diddles to + * accomodate the NeXT computer system that has a slightly different nlist.h + * * Revision 3.4.1.8 89/05/03 15:16:17 louie * Add code to save the value of the drift compensation register to a file every * hour. Add additional configuration file directives which can specify the same *************** *** 78,83 **** --- 82,88 ---- */ #include + #include #include #include #include *************** *** 282,293 **** setlogmask(LOG_UPTO(LOG_INFO)); #endif /* LOG_DAEMON */ ! syslog(LOG_NOTICE, "%s version $Revision: 3.4.1.8 $", prog_name); syslog(LOG_NOTICE, "patchlevel %d", PATCHLEVEL); #ifdef DEBUG if (debug) ! printf("%s version $Revision: 3.4.1.8 $ patchlevel %d\n", prog_name, PATCHLEVEL); #endif (void) setpriority(PRIO_PROCESS, 0, -10); --- 287,298 ---- setlogmask(LOG_UPTO(LOG_INFO)); #endif /* LOG_DAEMON */ ! syslog(LOG_NOTICE, "%s version $Revision: 3.4.1.9 $", prog_name); syslog(LOG_NOTICE, "patchlevel %d", PATCHLEVEL); #ifdef DEBUG if (debug) ! printf("%s version $Revision: 3.4.1.9 $ patchlevel %d\n", prog_name, PATCHLEVEL); #endif (void) setpriority(PRIO_PROCESS, 0, -10); *************** *** 459,465 **** struct ntpdata *pkt; struct ntp_peer *peer; { - char ref_clock[5]; struct in_addr clock_host; printf("Packet: [%s](%d)\n", inet_ntoa(dst->sin_addr), --- 464,469 ---- *************** *** 471,479 **** switch (pkt->stratum) { case 0: case 1: ! (void) strncpy(ref_clock, (char *) &pkt->refid, 4); ! ref_clock[4] = '\0'; ! printf(" (%s)\n", ref_clock); break; default: clock_host.s_addr = (u_long) pkt->refid; --- 475,481 ---- switch (pkt->stratum) { case 0: case 1: ! printf(" (%.4s)\n", (char *)&pkt->refid); break; default: clock_host.s_addr = (u_long) pkt->refid; *************** *** 867,872 **** --- 869,943 ---- } if (fscanf(fp, "%s", name) != 1) error = TRUE; + #ifdef REFCLOCK + else if (name[0] == '/') { + int stratum, precision; + char clk_type[20]; + + if (fscanf(fp, "%4s", ref_clock) != 1) { + error = TRUE; + syslog(LOG_ERR, "reference id missing"); + goto skipit; + } + if (fscanf(fp, "%4d", &stratum) != 1) { + error = TRUE; + syslog(LOG_ERR, "reference stratum missing"); + goto skipit; + } + if (fscanf(fp, "%4d", &precision) != 1) { + error = TRUE; + syslog(LOG_ERR, "reference precision missing"); + goto skipit; + } + if (fscanf(fp, "%19s", clk_type) != 1) { + error = TRUE; + syslog(LOG_ERR, "reference type missing"); + goto skipit; + } + + if((i = init_clock(name, clk_type)) < 0) { + /* If we could not initialize clock line */ + #ifdef DEBUG + if (debug) + printf("Could not init reference source %s (type %s)\n", + name, clk_type); + else + #endif DEBUG + syslog(LOG_ERR, "Could not init reference source %s (type %s)", + name, clk_type); + error = TRUE; + goto skipit; + } + peer = (struct ntp_peer *) + malloc(sizeof(struct ntp_peer)); + if (peer == NULL) { + close(i); + error = TRUE; + goto skipit; + } + make_new_peer(peer); + ref_clock[4] = 0; + (void) strncpy((char *) &peer->refid, + ref_clock, 4); + peer->flags = PEER_FL_CONFIG|PEER_FL_REFCLOCK; + peer->hmode = MODE_SYM_ACT; + peer->stopwatch = stagger; + stagger += (1<flags |= PEER_FL_SYNC; + peer->sock = i; + peer->stratum = stratum; + peer->precision = precision; + clear(peer); + enqueue(&peer_list, peer); + if (debug > 1) + printf("Peer %s mode %d refid %.4s stratum %d precision %d\n", + name, + peer->hmode, + (char *)&peer->refid, + stratum, precision); + transmit(peer); /* head start for REFCLOCK */ + } + #endif REFCLOCK else if (GetHostName(name, &sin) == 0) syslog(LOG_ERR, "%s: unknown host", name); else { *************** *** 875,881 **** sin.sin_addr.s_addr) goto skipit; ! sin.sin_port = servp->s_port; peer = check_peer(&sin, -1); if (peer == NULL) { peer = (struct ntp_peer *) --- 946,956 ---- sin.sin_addr.s_addr) goto skipit; ! if (servp) ! sin.sin_port = servp->s_port; ! else ! sin.sin_port = htons(NTP_PORT); ! peer = check_peer(&sin, -1); if (peer == NULL) { peer = (struct ntp_peer *) *************** *** 952,958 **** * Read saved drift compensation register value. */ if ((fp = fopen(driftcomp_file, "r")) != NULL) { ! if (fscanf(fp, "%f", &j) == 1 && j > -1.0 && j < 1.0) { drift_comp = j; syslog(LOG_INFO, "Drift compensation value initialized to %f", j); --- 1027,1033 ---- * Read saved drift compensation register value. */ if ((fp = fopen(driftcomp_file, "r")) != NULL) { ! if (fscanf(fp, "%lf", &j) == 1 && j > -1.0 && j < 1.0) { drift_comp = j; syslog(LOG_INFO, "Drift compensation value initialized to %f", j); *************** *** 972,982 **** init_kern_vars() { int kmem; static char *memory = "/dev/kmem"; ! static struct nlist nl[] = ! { {"_tickadj"}, {"_hz"}, {"_tick"}, {""}, }; static int *kern_vars[] = {&kern_tickadj, &kern_hz, &kern_tick}; int i; --- 1047,1064 ---- init_kern_vars() { int kmem; static char *memory = "/dev/kmem"; ! static struct nlist nl[] = { ! #ifndef NeXT ! {"_tickadj"}, {"_hz"}, {"_tick"}, {""}, + #else + {{"_tickadj"}}, + {{"_hz"}}, + {{"_tick"}}, + {{""}}, + #endif }; static int *kern_vars[] = {&kern_tickadj, &kern_hz, &kern_tick}; int i; *************** *** 997,1013 **** if ((where = nl[i].n_value) == 0) { syslog(LOG_ERR, "Unknown kernal var %s", ! nl[i].n_name); continue; } if (lseek(kmem, where, L_SET) == -1) { syslog(LOG_ERR, "lseek for %s fails: %m", ! nl[i].n_name); continue; } if (read(kmem, kern_vars[i], sizeof(int)) != sizeof(int)) { syslog(LOG_ERR, "read for %s fails: %m", ! nl[i].n_name); *kern_vars[i] = 0; } } --- 1079,1111 ---- if ((where = nl[i].n_value) == 0) { syslog(LOG_ERR, "Unknown kernal var %s", ! #ifdef NeXT ! nl[i].n_un.n_name ! #else ! nl[i].n_name ! #endif ! ); continue; } if (lseek(kmem, where, L_SET) == -1) { syslog(LOG_ERR, "lseek for %s fails: %m", ! #ifdef NeXT ! nl[i].n_un.n_name ! #else ! nl[i].n_name ! #endif ! ); continue; } if (read(kmem, kern_vars[i], sizeof(int)) != sizeof(int)) { syslog(LOG_ERR, "read for %s fails: %m", ! #ifdef NeXT ! nl[i].n_un.n_name ! #else ! nl[i].n_name ! #endif ! ); ! *kern_vars[i] = 0; } } *************** *** 1226,1235 **** drift_comp, compliance, peer_switches, peer_sw_inhibited); ! if (sys.peer == NULL) strcat(buf, " UNSYNC"); ! else { p = strlen(buf); (void) sprintf(buf + p, " off %f SYNC %s %d", sys.peer->estoffset, ntoa(sys.peer->src.sin_addr), --- 1324,1341 ---- drift_comp, compliance, peer_switches, peer_sw_inhibited); ! if (sys.peer == NULL) { strcat(buf, " UNSYNC"); ! #ifdef REFCLOCK ! } else if (sys.peer->flags & PEER_FL_REFCLOCK) { p = strlen(buf); + (void) sprintf(buf + p, " off %f SYNC %.4s %d", + sys.peer->estoffset, + (char *)&sys.peer->refid, + sys.peer->stratum); + #endif + } else { + p = strlen(buf); (void) sprintf(buf + p, " off %f SYNC %s %d", sys.peer->estoffset, ntoa(sys.peer->src.sin_addr), *************** *** 1306,1309 **** --- 1412,1471 ---- #endif exit(1); } + + #ifdef REFCLOCK + struct refclock { + int fd; + int (*reader)(); + struct refclock *next; + } *refclocks = NULL; + int init_clock_local(), read_clock_local(); + #ifdef PSTI + int init_clock_psti(), read_clock_psti(); + #endif PSTI + + init_clock(name, type) + char *name, *type; + { + struct refclock *r; + int (*reader)(); + int cfd; + + if (strcmp(type, "local") == 0) { + reader = read_clock_local; + cfd = init_clock_local(name); + } + #ifdef PSTI + else if (strcmp(type, "psti") == 0) { + reader = read_clock_psti; + cfd = init_clock_psti(name); + } + #endif PSTI + else { + if (debug) printf("Unknown reference type\n"); else + syslog(LOG_ERR, "Unknown reference clock type (%s)\n", type); + return(-1); + } + if (cfd >= 0) { + r = (struct refclock *)malloc(sizeof(struct refclock)); + r->fd = cfd; + r->reader = reader; + r->next = refclocks; + refclocks = r; + } + return(cfd); + } + + read_clock(cfd, tvpp, otvpp) + int cfd; + struct timeval **tvpp, **otvpp; + { + struct refclock *r; + + for (r = refclocks; r; r = r->next) + if(r->fd == cfd) + return((r->reader)(cfd, tvpp, otvpp)); + return(1); /* Can't happen */ + } + #endif Index: ntpdc.c *** ntpdc.c.old Thu May 18 18:42:37 1989 --- ntpdc.c Thu May 18 18:42:42 1989 *************** *** 1,9 **** #ifndef lint ! static char *RCSid = "$Source: /usr/users/louie/ntp/RCS/ntpdc.c,v $ $Revision: 3.4.1.6 $ $Date: 89/05/03 15:17:27 $"; #endif /* * $Log: ntpdc.c,v $ * Revision 3.4.1.6 89/05/03 15:17:27 louie * ntpdc now will display addional peer flags which indicate how far through * the clock selection process a peer was considered. --- 1,12 ---- #ifndef lint ! static char *RCSid = "$Source: /usr/users/louie/ntp/RCS/ntpdc.c,v $ $Revision: 3.4.1.7 $ $Date: 89/05/18 18:31:26 $"; #endif /* * $Log: ntpdc.c,v $ + * Revision 3.4.1.7 89/05/18 18:31:26 louie + * A few cosmetic changes for ntpd.c + * * Revision 3.4.1.6 89/05/03 15:17:27 louie * ntpdc now will display addional peer flags which indicate how far through * the clock selection process a peer was considered. *************** *** 70,75 **** --- 73,79 ---- * */ + #include #include #include #include *************** *** 262,268 **** } sp = getservbyname("ntp", "udp"); if (sp == 0) { ! fprintf(stderr,"udp/ntp: service unknown\nUsing default\n"); watcher.sin_port = htons(NTP_PORT); } else watcher.sin_port = sp->s_port; --- 266,273 ---- } sp = getservbyname("ntp", "udp"); if (sp == 0) { ! fprintf(stderr,"udp/ntp: service unknown, using default %d\n", ! NTP_PORT); watcher.sin_port = htons(NTP_PORT); } else watcher.sin_port = sp->s_port; *************** *** 324,330 **** struct clockinfo *n; { int i; - char ref_clock[5]; struct in_addr clock_host; double offset[PEER_SHIFT], delay[PEER_SHIFT], dsp,del,off; char *cvthname(); --- 329,334 ---- *************** *** 348,356 **** ntohs(n->flags), n->leap); if (n->stratum == 1 || n->stratum == 0) { ! (void) strncpy(ref_clock, (char *) &n->refid, 4); ! ref_clock[4] = '\0'; ! printf("Reference clock ID: %s", ref_clock); } else { clock_host.s_addr = (u_long) n->refid; printf("Reference clock ID: [%s]", inet_ntoa(clock_host)); --- 352,358 ---- ntohs(n->flags), n->leap); if (n->stratum == 1 || n->stratum == 0) { ! printf("Reference clock ID: %.4s", (char *)&n->refid); } else { clock_host.s_addr = (u_long) n->refid; printf("Reference clock ID: [%s]", inet_ntoa(clock_host)); Index: ntpsubs.c *** ntpsubs.c.old Thu May 18 18:42:53 1989 --- ntpsubs.c Thu May 18 18:42:55 1989 *************** *** 1,9 **** #ifndef lint ! static char *RCSid = "$Source: /usr/users/louie/ntp/RCS/ntpsubs.c,v $ $Revision: 3.4.1.2 $ $Date: 89/03/29 12:46:02 $"; #endif lint /* * $Log: ntpsubs.c,v $ * Revision 3.4.1.2 89/03/29 12:46:02 louie * Check for success sending query before trying to listen for answers. Will * catch case of no server running and an ICMP port unreachable being returned. --- 1,17 ---- #ifndef lint ! static char *RCSid = "$Source: /usr/users/louie/ntp/RCS/ntpsubs.c,v $ $Revision: 3.4.1.3 $ $Date: 89/05/18 18:33:50 $"; #endif lint /* * $Log: ntpsubs.c,v $ + * Revision 3.4.1.3 89/05/18 18:33:50 louie + * Added support few a new type of unsigned long to double compiler brokenness, + * called GENERIC_UNS_BUG. If this is defined, then the unsigned long is + * shifted right one bit, the high-order bit of the result is cleared, then + * converted to a double. The double is multiplied by 2.0, and the a 1.0 is + * optionall added to it if the low order bit of the original unsigned long + * was set. Whew! + * * Revision 3.4.1.2 89/03/29 12:46:02 louie * Check for success sending query before trying to listen for answers. Will * catch case of no server running and an ICMP port unreachable being returned. *************** *** 35,40 **** --- 43,49 ---- */ #include + #include #include #include #include *************** *** 59,65 **** --- 68,88 ---- struct l_fixedpt *t; { double a, b; + #ifdef GENERIC_UNS_BUG + register int i; + i = ntohl(t->fraction); + a = (long)((i >> 1) & 0x7fffffff); + a *= 2.0; + if (i & 1) + a += 1.0; + a = a / (4.294967296e9); /* shift dec point over by 32 bits */ + i = ntohl(t->int_part); + b = (long)((i >> 1) & 0x7fffffff); + b *= 2.0; + if (i & 1) + b += 1.0; + #else /* GENERIC_UNS_BUG */ a = (unsigned long) ntohl(t->fraction); #ifdef VAX_COMPILER_FLT_BUG if (a < 0.0) a += 4.294967296e9; *************** *** 69,81 **** #ifdef VAX_COMPILER_FLT_BUG if (b < 0.0) b += 4.294967296e9; #endif ! a += b; /* add rest of integer part */ ! return (a); } /* * Here we have to worry about the high order bit being signed */ double l_fixed_to_double(t) struct l_fixedpt *t; --- 92,106 ---- #ifdef VAX_COMPILER_FLT_BUG if (b < 0.0) b += 4.294967296e9; #endif ! #endif /* GENERIC_UNS_BUG */ ! return (a + b); } /* * Here we have to worry about the high order bit being signed */ + + #if 0 double l_fixed_to_double(t) struct l_fixedpt *t; *************** *** 108,113 **** --- 133,139 ---- } return (a); } + #endif /* * Here we have to worry about the high order bit being signed Index: read_local.c *** read_local.c.old Thu May 18 18:43:01 1989 --- read_local.c Thu May 18 18:43:02 1989 *************** *** 0 **** --- 1,30 ---- + #ifdef REFCLOCK + /* + * A dummy clock reading routine that reads the current system time. + * from the local host. Its possible that this could be actually used + * if the system was in fact a very accurate time keeper (a true real-time + * system with good crystal clock or better). + */ + + #include + #include + + init_clock_local(file) + char *file; + { + return getdtablesize(); /* invalid if we ever use it */ + } + + read_clock_local(cfd, tvp, mtvp) + int cfd; + struct timeval **tvp, **mtvp; + { + static struct timeval realtime, mytime; + + gettimeofday(&realtime, 0); + mytime = realtime; + *tvp = &realtime; + *mtvp = &mytime; + return(0); + } + #endif Index: read_psti.c *** read_psti.c.old Thu May 18 18:43:07 1989 --- read_psti.c Thu May 18 18:43:09 1989 *************** *** 0 **** --- 1,369 ---- + #if defined(REFCLOCK) && defined(PSTI) + #ifndef lint + static char *rcsid = "$Header: /usr/users/louie/ntp/RCS/read_psti.c,v 3.4.1.1 89/05/18 18:36:45 louie Exp Locker: louie $"; + static char *sccsid = "@(#)read_psti.c 1.1 MS/ACF 89/02/17"; + #endif lint + + #define ERR_RATE 60 /* Repeat errors once an hour */ + + /* + * read_psti.c + * January 1988 -- orignal by Jeffrey I. Schiller + * January 1989 -- QU version by Doug Kingston + * + * This module facilitates reading a Precision Time Standard, Inc. + * WWV radio clock. We assume that clock is configured for 9600 baud, + * no parity. Output is accepted in either 24 or 12 hour format. + * Time is requested and processed in GMT. + * + * This version is designed to make use of the QU command due to + * additional information it provides (like date and flags). + * Select is used to prevent hanging in a read when there are + * no characters to read. The line is run in cooked mode to + * reduce overhead. + * + * This requires a PSTI ROM revision later 4.01.000 or later. + * + * Routines defined: + * init_clock_psti(): Open the tty associated with the clock and + * set its tty mode bits. Returns fd on success + * and -1 on failure. + * read_clock_psti(): Reads the clock and returns either 0 on success + * or non-zero on error. On success, pointers are + * provided to the reference and local time. + */ + #include + #include + #include + #include + #include + #if defined(sun) + #include + #endif + + #ifdef DEBUG + extern int debug; + #endif DEBUG + + static int nerrors = 0; + static char clockdata[32]; + #define MIN_READ 13 /* for Rev 4.01.001 */ + + static double reltime(); + + #ifdef STANDALONE + + #ifndef CLOCKDEV + #define CLOCKDEV "/dev/radioclock" + #endif + + #define DEBUG 1 + int debug = 1; + + main(argc, argv) + int argc; + char **argv; + { + struct timeval *tvp, *otvp; + + debug = argc; + if (openclock(CLOCKDEV)) + do { + (void)readclock(&tvp, &otvp); + sleep(1); + } while (debug>1); + exit(0); + } + #endif STANDALONE + + + init_clock_psti(timesource) + char *timesource; + { + int cfd; + #ifdef TCSETA + struct termio tty; + #else + struct sgttyb tty; + #endif + + if ((cfd = open(timesource, 2)) < 0) { + #ifdef DEBUG + if (debug) perror(timesource); else + #endif DEBUG + syslog(LOG_ERR, "can't open %s: %m", timesource); + return(-1); + } + + if (ioctl(cfd, TIOCEXCL, 0) < 0) { + #ifdef DEBUG + if (debug) perror("TIOCEXCL on radioclock failed"); else + #endif DEBUG + syslog(LOG_ERR, "TIOCEXCL on %s failed: %m", timesource); + return(-1); + } + + #ifdef TCSETA + if (ioctl(cfd, TCGETA, &tty) < 0) { + #ifdef DEBUG + if (debug) perror("ioctl on radioclock failed"); else + #endif DEBUG + syslog(LOG_ERR, "ioctl on %s failed: %m", timesource); + return(-1); + } + tty.c_cflag = (B9600<<16)|B9600|CS8|CLOCAL|CREAD; + tty.c_iflag = ICRNL; + tty.c_oflag = 0; + tty.c_lflag = 0; + bzero((char *)tty.c_cc, sizeof tty.c_cc); + tty.c_cc[VMIN] = MIN_READ; + tty.c_cc[VTIME] = 0; + if (ioctl(cfd, TCSETA, &tty) < 0) { + #else TCSETA /* Use older Berkeley style IOCTL's */ + bzero((char *)&tty, sizeof tty); + tty.sg_ispeed = tty.sg_ospeed = B9600; + tty.sg_flags = ANYP|CRMOD; + tty.sg_erase = tty.sg_kill = '\0'; + if (ioctl(cfd, TIOCSETP, &tty) < 0) { + #endif TCSETA + #ifdef DEBUG + if (debug) perror("ioctl on radioclock failed"); else + #endif DEBUG + syslog(LOG_ERR, "ioctl on %s failed: %m", timesource); + return(-1); + } + if (write(cfd, "xxxxxxsn\r", 9) != 9) { + #ifdef DEBUG + if (debug) perror("init write to radioclock failed"); else + #endif DEBUG + syslog(LOG_ERR, "init write to %s failed: %m", timesource); + return(-1); + } + return(cfd); /* Succeeded in opening the clock */ + } + + /* + * read_clock_psti() -- Read the PSTI Radio Clock. + */ + read_clock_psti(cfd, tvpp, otvpp) + int cfd; + struct timeval **tvpp, **otvpp; + { + static struct timeval radiotime; + static struct timeval mytime; + struct timeval timeout; + struct tm *mtm; + struct tm radio_tm, *rtm = &radio_tm; + register int i; + register int millis; + register double diff; + int stat1, stat2; + fd_set readfds; + char message[256]; + #ifndef TCSETA + register char *cp; + int need; + #endif TCSETA + + FD_ZERO(&readfds); + FD_SET(cfd, &readfds); + timeout.tv_sec = 2; + timeout.tv_usec = 0; + + (void) ioctl(cfd, TIOCFLUSH, 0); /* scrap the I/O queues */ + + /* BEGIN TIME CRITICAL CODE SECTION!!!!!! */ + /* EVERY CYCLE FROM THIS POINT OUT ADDS TO THE INACCURACY OF + THE READ CLOCK VALUE!!!!! */ + if (write(cfd, "\003qu0000", 7) != 7) { + #ifdef DEBUG + if (debug) printf("radioclock write failed\n"); else + #endif DEBUG + if ((nerrors++%ERR_RATE) == 0) + syslog(LOG_ERR, "write to radioclock failed: %m"); + return(1); + } + if(select(cfd+1, &readfds, 0, 0, &timeout) != 1) { + #ifdef DEBUG + if (debug) printf("radioclock poll timed out\n"); else + #endif DEBUG + if ((nerrors++%ERR_RATE) == 0) + syslog(LOG_ERR, "poll of radioclock failed: %m"); + return(1); + } + if ((i = read(cfd, clockdata, sizeof clockdata)) < MIN_READ) { + #ifdef DEBUG + if (debug) printf("radioclock read error (%d)\n", i); else + #endif DEBUG + if ((nerrors++%ERR_RATE) == 0) + syslog(LOG_ERR, "radioclock read error (%d!=13): %m", i); + return(1); + } + + (void) gettimeofday(&mytime, (struct timezone *)0); + /* END OF TIME CRITICAL CODE SECTION!!!! */ + + if (clockdata[i-1] != '\n') { + #ifdef DEBUG + if (debug) printf("radioclock format error1 (%.12s)(0x%x)\n", + clockdata, clockdata[12]); else + #endif DEBUG + if ((nerrors++%ERR_RATE) == 0) + syslog(LOG_ERR, "radioclock format error1 (%.12s)(0x%x)", + clockdata, clockdata[12]); + return(1); + } + for (i = 0; i < 12; i++) { + if (clockdata[i] < '0' || clockdata[i] > 'o') { + #ifdef DEBUG + if (debug) printf("radioclock format error2\n"); else + #endif DEBUG + if ((nerrors++%ERR_RATE) == 0) + syslog(LOG_ERR, "radioclock format error2\n"); + return(1); + } + } + stat1 = clockdata[0]-'0'; + stat2 = clockdata[1]-'0'; + millis = ((clockdata[2]-'0')*64)+(clockdata[3]-'0'); + rtm->tm_sec = (clockdata[4]-'0'); + rtm->tm_min = (clockdata[5]-'0'); + rtm->tm_hour = (clockdata[6]-'0'); + rtm->tm_yday = ((clockdata[7]-'0')*64)+(clockdata[8]-'0')-1; + rtm->tm_year = 86+(clockdata[9]-'0'); + /* byte 10 and 11 reserved */ + + /* + * Correct "hours" based on whether or not AM/PM mode is enabled. + * If clock is in 24 hour (military) mode then no correction is + * needed. + */ + if(stat2&0x10) { /* Map AM/PM time to Military */ + if (stat2&0x8) { + if (rtm->tm_hour != 12) rtm->tm_hour += 12; + } else { + if (rtm->tm_hour == 12) rtm->tm_hour = 0; + } + } + + if (stat1 != 0x4 && (nerrors++%ERR_RATE)==0) { + #ifdef DEBUG + if (debug) printf("radioclock fault #%d 0x%x:%s%s%s%s%s%s\n", + nerrors, stat1, + stat1&0x20?" Out of Spec,":"", + stat1&0x10?" Hardware Fault,":"", + stat1&0x8?" Signal Fault,":"", + stat1&0x4?" Time Avail,":"", + stat1&0x2?" Year Mismatch,":"", + stat1&0x1?" Clock Reset,":""); + else { + #endif DEBUG + sprintf(message, "radioclock fault #%d 0x%x:%s%s%s%s%s%s\n", + nerrors, stat1, + stat1&0x20?" Out of Spec,":"", + stat1&0x10?" Hardware Fault,":"", + stat1&0x8?" Signal Fault,":"", + stat1&0x4?" Time Avail,":"", + stat1&0x2?" Year Mismatch,":"", + stat1&0x1?" Clock Reset,":""); + syslog(LOG_ERR, message); + } + } + if (stat1&0x38) /* Out of Spec, Hardware Fault, Signal Fault */ + return(1); + if ((millis > 999 || rtm->tm_sec > 60 || rtm->tm_min > 60 || + rtm->tm_hour > 23 || rtm->tm_yday > 365) && (nerrors++%ERR_RATE)==0) { + #ifdef DEBUG + if (debug) printf("radioclock bogon #%d: %dd %dh %dm %ds %dms\n", + nerrors, rtm->tm_yday, rtm->tm_hour, + rtm->tm_min, rtm->tm_sec, millis); + else + #endif DEBUG + sprintf(message, "radioclock bogon #%d: %dd %dh %dm %ds %dms\n", + nerrors, rtm->tm_yday, rtm->tm_hour, + rtm->tm_min, rtm->tm_sec, millis); + syslog(LOG_ERR, message); + return(1); + } + + mtm = gmtime(&mytime.tv_sec); + diff = reltime(rtm, millis*1000) - reltime(mtm, mytime.tv_usec); + #ifdef DEBUG + if (debug > 1) + printf("Clock time: 19%d day %03d %02d:%02d:%02d.%03d diff %.3f\n", + rtm->tm_year, rtm->tm_yday, rtm->tm_hour, + rtm->tm_min, rtm->tm_sec, millis, diff); + #endif DEBUG + + if (diff > (90*24*60*60.0) && (nerrors++%ERR_RATE)==0) { + #ifdef DEBUG + if (debug) + printf("offset excessive (system 19%d/%d, clock 19%d/%d)\n", + mtm->tm_year, mtm->tm_yday, + rtm->tm_year, mtm->tm_yday); + else + #endif DEBUG + syslog(LOG_ERR, "offset excessive (system 19%d/%d, clock 19%d/%d)\n", + mtm->tm_year, mtm->tm_yday, + rtm->tm_year, mtm->tm_yday); + return(1); + } + + diff += (double)mytime.tv_sec + ((double)mytime.tv_usec/1000000.0); + radiotime.tv_sec = diff; + radiotime.tv_usec = (diff - (double)radiotime.tv_sec) * 1000000; + #ifdef DEBUG + if (debug > 1) { + printf("System time: 19%d day %03d %02d:%02d:%02d.%03d\n", + mtm->tm_year, mtm->tm_yday, mtm->tm_hour, + mtm->tm_min, mtm->tm_sec, mytime.tv_usec/1000); + printf("stat1 0%o, stat2 0%o: ", stat1, stat2); + if (stat1 || stat2) + printf("%s%s%s%s%s%s%s%s%s%s%s%s", + stat1&0x20?" Out of Spec,":"", + stat1&0x10?" Hardware Fault,":"", + stat1&0x8?" Signal Fault,":"", + stat1&0x4?" Time Avail,":"", + stat1&0x2?" Year Mismatch,":"", + stat1&0x1?" Clock Reset,":"", + stat2&0x20?" DST on,":"", + stat2&0x10?" 12hr mode,":"", + stat2&0x8?" PM,":"", + stat2&0x4?" Spare?,":"", + stat2&0x2?" DST??? +1,":"", + stat2&0x1?" DST??? -1,":""); + printf("\n"); + } + #endif DEBUG + /* If necessary, acknowledge "Clock Reset" flag bit */ + if (stat1 & 0x1) { + if (write(cfd, "si0", 3) != 3) { + #ifdef DEBUG + if (debug) printf("radioclock reset write failed\n"); else + #endif DEBUG + syslog(LOG_ERR, "reset write to radioclock failed: %m"); + return(1); + } + } + if (nerrors && stat1==0x4) { + syslog(LOG_ERR, "radioclock OK (after %d errors)", nerrors); + nerrors = 0; + } + *tvpp = &radiotime; + *otvpp = &mytime; + return(0); + } + + static double + reltime(tm, usec) + register struct tm *tm; + register int usec; + { + return(tm->tm_year*(366.0*24.0*60.0*60.0) + + tm->tm_yday*(24.0*60.0*60.0) + + tm->tm_hour*(60.0*60.0) + + tm->tm_min*(60.0) + + tm->tm_sec + + usec/1000000.0); + } + #endif Index: test.c *** test.c.old Thu May 18 18:43:20 1989 --- test.c Thu May 18 18:43:22 1989 *************** *** 1,9 **** #ifndef lint ! static char *RCSid = "$Source: /usr/users/louie/ntp/RCS/test.c,v $ $Revision: 3.4.1.3 $ $Date: 89/04/07 19:10:41 $"; #endif /* * $Log: test.c,v $ * Revision 3.4.1.3 89/04/07 19:10:41 louie * Add check for SUN_FLT_BUG problem in test.c * --- 1,12 ---- #ifndef lint ! static char *RCSid = "$Source: /usr/users/louie/ntp/RCS/test.c,v $ $Revision: 3.4.1.4 $ $Date: 89/05/18 18:37:39 $"; #endif /* * $Log: test.c,v $ + * Revision 3.4.1.4 89/05/18 18:37:39 louie + * Add test for GENERIC_UNS_BUG to test.c + * * Revision 3.4.1.3 89/04/07 19:10:41 louie * Add check for SUN_FLT_BUG problem in test.c * *************** *** 95,101 **** --- 98,106 ---- printf(" %4.2f ", value[i]); double_to_l_fixed(&sample, value[i]); printf(" x%#8X.%#8X ", sample.int_part, sample.fraction); + #if 0 printf(" %4.2f", l_fixed_to_double(&sample)); + #endif printf("\t"); double_to_s_fixed(&s_sample, value[i]); printf(" x%#4X.%#4X ", s_sample.int_part, s_sample.fraction); *************** *** 126,139 **** unsigned long ul = 0x80000001; double dbl; dbl = ul; #ifdef VAX_COMPILER_FLT_BUG if (dbl < 0.0) dbl += 4.294967296e9; #endif if (dbl != 2147483649.0) { printf("test3 fails: can't convert from unsigned long to float\n"); printf(" (%lu != %15g)\n", ul, dbl); ! printf("Try defining VAX_COMPILER_FLT_BUG in the Makefile.\n"); return 1; } else { if (v) --- 131,156 ---- unsigned long ul = 0x80000001; double dbl; + #ifdef GENERIC_UNS_BUG + /* + * Hopefully, we can avoid the unsigned issue altogether. Make sure + * that the high-order (sign) bit is zero, and fiddle from there + */ + dbl = (long)((ul >> 1) & 0x7fffffff); + dbl *= 2.0; + if (ul & 1) + dbl += 1.0; + #else dbl = ul; #ifdef VAX_COMPILER_FLT_BUG if (dbl < 0.0) dbl += 4.294967296e9; #endif + #endif if (dbl != 2147483649.0) { printf("test3 fails: can't convert from unsigned long to float\n"); printf(" (%lu != %15g)\n", ul, dbl); ! printf( ! "Try defining VAX_COMPILER_FLT_BUG or GENERIC_UNS_BUG in the Makefile.\n"); return 1; } else { if (v)