440 lines
14 KiB
Plaintext
440 lines
14 KiB
Plaintext
--- Makefile
|
|
+++ Makefile
|
|
@@ -1,13 +1,20 @@
|
|
CC=gcc
|
|
|
|
+WARNINGS=-Wall -W -Wpointer-arith -Wbad-function-cast -Wcast-qual \
|
|
+ -Wstrict-prototypes -Wmissing-prototypes \
|
|
+ -Wmissing-declarations -Wnested-externs -Winline -Wcast-align
|
|
+
|
|
+CFLAGS = $(RPM_OPT_FLAGS) -D_GNU_SOURCE $(WARNINGS)
|
|
+
|
|
all: netdate
|
|
|
|
netdate: netdate.o
|
|
|
|
install: netdate
|
|
- install -s -m 0755 netdate /usr/local/sbin/netdate
|
|
- install -m 0644 netdate.8 /usr/local/man/man8
|
|
+ install -m 0755 netdate ${DESTDIR}/usr/sbin/netdate
|
|
+ install -m 0644 netdate.8 ${DESTDIR}/usr/share/man/man8
|
|
|
|
clean:
|
|
- rm -f netdate *.o core
|
|
+ rm -f netdate *~ *.o core
|
|
+
|
|
|
|
--- netdate.8
|
|
+++ netdate.8
|
|
@@ -53,40 +53,40 @@
|
|
if that host supplies it.
|
|
.SH EXAMPLE
|
|
The most accurate hosts are named first in each example.
|
|
-Some such call on \fInetdate\fP should be put at the end of \fB/etc/rc.local\fP,
|
|
+Some such call on \fInetdate\fP should be put at the end of \fB/etc/init.d/boot.local\fP,
|
|
so that the time will be set properly on system startup.
|
|
-It is also useful to have a shell script, e.g., \fB/etc/timehosts\fP,
|
|
+It is also useful to have a shell script, e.g., \fB/sbin/timehosts\fP,
|
|
which contains a call on \fInetdate\fP with arguments appropriate
|
|
to the local system, so that it is easy to set the time manually.
|
|
-.SH "netdate -l 30 udp dcn\-gateway tcp neighbor"
|
|
-\fIDcn\-gateway\fP is a hypothetical host which usually keeps time
|
|
+.SH "netdate -l 30 udp dcn\-gate tcp neighbor"
|
|
+\fIDcn\-gate\fP is a hypothetical host which usually keeps time
|
|
accurate to within milliseconds of Coordinated Universal Time,
|
|
but may occasionally be eight hours off.
|
|
\fINeighbor\fP is a neighbor of the local host which keeps time
|
|
with moderate accuracy.
|
|
-The time will be set to that of \fIdcn\-gateway\fP if that and \fIneighbor\fP
|
|
+The time will be set to that of \fIdcn\-gate\fP if that and \fIneighbor\fP
|
|
agree to within thirty seconds, else it will not be set at all.
|
|
This is almost good enough for most circumstances, but won't do
|
|
when the local host's time is known to be wrong (e.g., after
|
|
a long downtime or a bad crash) and must be set to something.
|
|
If one of the hosts named is inaccurate or not responding, there is a problem.
|
|
-.SH "netdate -l 30 udp dcn\-gateway tcp neighbor neighbor2"
|
|
+.SH "netdate -l 30 udp dcn\-gate tcp neighbor neighbor2"
|
|
Only two of the three hosts named must agree on the time.
|
|
The time will still be set (to that of the first neighbor),
|
|
-even if \fIdcn\-gateway\fP is far off as long as the two neighbors agree.
|
|
+even if \fIdcn\-gate\fP is far off as long as the two neighbors agree.
|
|
This is probably good enough for most cases.
|
|
One can arbitrarily gerrymander the vote for more insurance
|
|
(and less clarity), as in the following example.
|
|
-.SH "netdate\ udp\ dcn\-gateway\ dcn1\ tcp\ bbn\-unix\ localhost\ neighbor"
|
|
+.SH "netdate\ udp\ dcn\-gate\ dcn1\ tcp\ bbn\-unix\ localhost\ neighbor"
|
|
Here \fIdcn1\fP and \fIbbn\-unix\fP are more hypothetical very accurate
|
|
timekeepers, at least one of which keeps time independently from
|
|
-\fIdcn\-gateway\fP, one hopes.
|
|
+\fIdcn\-gate\fP, one hopes.
|
|
It is very likely that the time will be set to that one of those three
|
|
very accurate hosts, as long as at least two of them agree, or at least
|
|
one of them agrees with the neighbor or the local host's time.
|
|
If all the foreign hosts disagree, the time will not be set,
|
|
since \fBlocalhost\fP will be chosen as best.
|
|
-.SH "netdate\ \-l\ 3\ localhost\ localhost\ udp\ dcn\-gateway\ dcn1\ tcp\ bbn\-unix"
|
|
+.SH "netdate\ \-l\ 3\ localhost\ localhost\ udp\ dcn\-gate\ dcn1\ tcp\ bbn\-unix"
|
|
This example gives \fBlocalhost\fP two votes and declares it to usually
|
|
have the most accurate time.
|
|
All three foreign hosts must agree within three seconds
|
|
@@ -95,9 +95,9 @@
|
|
Thus the time will be set only if it really needs to be.
|
|
.SH FILES
|
|
.nf
|
|
-/etc/inet/services for the time service port number
|
|
-/etc/inet/protocols for the protocol numbers
|
|
-/etc/wtmp to record time-setting
|
|
+/etc/services for the time service port number
|
|
+/etc/protocols for the protocol numbers
|
|
+/var/log/wtmp to record time-setting
|
|
.SH SEE ALSO
|
|
ARPANET Request for Comments 868, gettimeofday(2), date(1),
|
|
WWV (USA):
|
|
--- netdate.c
|
|
+++ netdate.c
|
|
@@ -1,4 +1,4 @@
|
|
-/*
|
|
+/*
|
|
NO WARRANTY
|
|
|
|
THERE IS NO WARRANTY FOR THIS PROGRAM, TO THE EXTENT PERMITTED BY
|
|
@@ -8,8 +8,8 @@
|
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
|
- ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
|
-
|
|
+ ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
|
+
|
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
|
|
ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
|
REDISTRIBUTE THE PROGRAM, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
|
@@ -18,13 +18,13 @@
|
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
|
- SUCH DAMAGES.
|
|
-
|
|
+ SUCH DAMAGES.
|
|
+
|
|
*/
|
|
|
|
/*
|
|
fixes for netdate 1.16
|
|
-1) utmp handling
|
|
+1) utmp handling
|
|
2) trying to read 64 bit on 64bit machines instead of 32bit
|
|
3) renamed getdate() to mygetdate() because getdate() is a UNIX98 function
|
|
4) reduced number of global vars
|
|
@@ -58,7 +58,7 @@
|
|
/* but only if we cant find anything better */
|
|
|
|
#ifndef WTMP_FILE
|
|
-#define WTMP "/etc/wtmp"
|
|
+#define WTMP "/var/log/wtmp"
|
|
#else
|
|
#define WTMP WTMP_FILE
|
|
#endif
|
|
@@ -66,7 +66,7 @@
|
|
|
|
char *defaultproto = "udp";
|
|
/* difference between 1900 (RFC868) and 1970 (UNIX) base times */
|
|
-#define NETBASE 2208988800
|
|
+#define NETBASE 2208988800u
|
|
|
|
long limit = 5;
|
|
#define MAXHOSTS 20
|
|
@@ -92,15 +92,13 @@
|
|
|
|
void usage (void);
|
|
int setproto (char *, struct timehost *);
|
|
-void main (int, char **);
|
|
int getdiff (struct timehost *);
|
|
int mygetdate (struct timehost *);
|
|
void printit (struct timehost *);
|
|
void tvsub (struct timeval *, struct timeval *, struct timeval *);
|
|
void printdiff (char *, struct timeval *);
|
|
-void timeout ();
|
|
+void timeout (void);
|
|
static int internettime (struct timehost *thishost);
|
|
-long getport (char *protoname);
|
|
|
|
static int internettime (struct timehost *thishost);
|
|
struct timehost *mungediffs(struct timehost *);
|
|
@@ -112,7 +110,7 @@
|
|
fprintf (stderr,
|
|
"usage: %s [ -l limit ] host ...\n"
|
|
"%s tries to find a group of at least two hosts whose times agree\n"
|
|
-"within %d seconds, and sets the time to that of the first host in the group.\n",
|
|
+"within %ld seconds, and sets the time to that of the first host in the group.\n",
|
|
whoami, whoami, limit);
|
|
fprintf (stderr,
|
|
"The limit may be set with the -l option. Setting it to zero (or supplying\n"
|
|
@@ -126,11 +124,9 @@
|
|
int verbose = 0;
|
|
int debug = 0;
|
|
|
|
-void
|
|
+int
|
|
main (int argc, char **argv)
|
|
{
|
|
- extern char *rindex();
|
|
- struct timehost *mungediffs();
|
|
register struct timehost *thishost;
|
|
int hostargs = 0;
|
|
|
|
@@ -170,7 +166,7 @@
|
|
if (*argv == NULL)
|
|
usage();
|
|
if (debug)
|
|
- fprintf (stderr, "%s: rdate %d; verbose %d; limit %d.\n",
|
|
+ fprintf (stderr, "%s: rdate %d; verbose %d; limit %ld.\n",
|
|
whoami, rdate, verbose, limit);
|
|
for (thishost = &timehosts[0]; *argv != NULL; argv++) {
|
|
if (thishost >= tophost) {
|
|
@@ -204,7 +200,7 @@
|
|
exit(1);
|
|
if ((thishost = mungediffs(thishost)) == NULL) {
|
|
fprintf (stderr,
|
|
- "No two hosts agree on the time within %d seconds\n",
|
|
+ "No two hosts agree on the time within %ld seconds\n",
|
|
limit);
|
|
exit(1);
|
|
}
|
|
@@ -273,7 +269,7 @@
|
|
and return the first of that group. If no two hosts agree,
|
|
give up.
|
|
*/
|
|
-
|
|
+
|
|
struct timehost *
|
|
mungediffs(struct timehost *tophost)
|
|
{
|
|
@@ -299,7 +295,7 @@
|
|
}
|
|
}
|
|
if (verbose) {
|
|
- printf (" %d\n", thishost -> count);
|
|
+ printf (" %ld\n", thishost -> count);
|
|
(void)fflush(stdout);
|
|
}
|
|
if (thishost -> count > goodhost -> count)
|
|
@@ -337,7 +333,7 @@
|
|
&& abs((thishost -> then.tv_sec - now.tv_sec) - thishost -> difference)
|
|
> limit) {
|
|
fprintf (stderr,
|
|
- "Time from %s has varied more than the limit of %d seconds\n",
|
|
+ "Time from %s has varied more than the limit of %ld seconds\n",
|
|
thishost -> hostname, limit);
|
|
printit(thishost);
|
|
exit(1);
|
|
@@ -346,22 +342,19 @@
|
|
perror ("netdate; settimeofday");
|
|
else {
|
|
int wf;
|
|
- if ((wf = open(WTMP, 1)) >= 0) {
|
|
|
|
/* this ist at least UGLY sometimes its timeval ut_tv */
|
|
-/* on others there is ut_time */
|
|
+/* on others there is ut_time */
|
|
|
|
-#ifndef _HAVE_UT_TV
|
|
- wtmp[0]->ut_time = now.tv_sec;
|
|
- wtmp[1]->ut_time = thishost -> then.tv_sec;
|
|
+#ifndef _HAVE_UT_TV
|
|
+ wtmp[0]->ut_time = now.tv_sec;
|
|
+ wtmp[1]->ut_time = thishost -> then.tv_sec;
|
|
#else
|
|
- wtmp[0]->ut_tv.tv_sec = now.tv_sec;
|
|
- wtmp[1]->ut_tv.tv_sec = thishost -> then.tv_sec;
|
|
-#endif
|
|
- (void)lseek(wf, 0L, 2);
|
|
- (void)write(wf, (char *)wtmp, sizeof(wtmp));
|
|
- (void)close(wf);
|
|
- }
|
|
+ wtmp[0]->ut_tv.tv_sec = now.tv_sec;
|
|
+ wtmp[1]->ut_tv.tv_sec = thishost -> then.tv_sec;
|
|
+#endif
|
|
+ updwtmp(WTMP, wtmp[0]);
|
|
+ updwtmp(WTMP, wtmp[1]);
|
|
set = 1;
|
|
}
|
|
printit(thishost);
|
|
@@ -371,8 +364,7 @@
|
|
void
|
|
printit(struct timehost *thishost)
|
|
{
|
|
- extern char *ctime();
|
|
- struct tm *tp, *localtime();
|
|
+ struct tm *tp;
|
|
struct timeval diff;
|
|
char newstring[128];
|
|
|
|
@@ -382,12 +374,12 @@
|
|
(void)sprintf(newstring, "%s ", thishost -> hostname);
|
|
tvsub(&diff, &thishost -> then, &now);
|
|
printdiff(&newstring[strlen(newstring)], &diff);
|
|
- printf ("%-24s %.19s.%03d", newstring,
|
|
+ printf ("%-24s %.19s.%03ld", newstring,
|
|
ctime((unsigned long *)&thishost -> then.tv_sec),
|
|
thishost -> then.tv_usec / 1000);
|
|
if (verbose) {
|
|
tp = localtime((unsigned long *)&thishost -> acked);
|
|
- printf(" at %02d:%02d:%02d.%03d",
|
|
+ printf(" at %02d:%02d:%02d.%03ld",
|
|
tp -> tm_hour, tp -> tm_min, tp -> tm_sec,
|
|
thishost -> acked.tv_usec / 1000);
|
|
tvsub(&diff, &thishost -> acked, &thishost -> asked);
|
|
@@ -421,7 +413,7 @@
|
|
|
|
static jmp_buf jb;
|
|
void
|
|
-timeout()
|
|
+timeout(void)
|
|
{
|
|
longjmp(jb, 1);
|
|
}
|
|
@@ -429,12 +421,12 @@
|
|
static int
|
|
internettime (struct timehost *thishost)
|
|
{
|
|
- register struct hostent *hp;
|
|
- struct sockaddr_in sin;
|
|
- long port;
|
|
+ struct addrinfo hints, *res, *res0 = NULL;
|
|
+ int error;
|
|
int nread;
|
|
|
|
- int buf; /* must be 32bit !! */
|
|
+ /* must be unsigned, it's assigned to tv_sec = __un__signed long! */
|
|
+ unsigned buf;
|
|
static int s = -1;
|
|
|
|
|
|
@@ -454,47 +446,74 @@
|
|
(void)signal(SIGALRM, timeout);
|
|
if (s != -1)
|
|
(void) close (s), s = -1;
|
|
- port = getport(thishost -> protoname);
|
|
- bzero((char *)&sin, sizeof (sin));
|
|
- sethostent(1);
|
|
- if ((hp = gethostbyname(thishost -> hostname)) == NULL) {
|
|
- fprintf(stderr, "%s: %s: unknown host\n",
|
|
- whoami, thishost -> hostname);
|
|
- goto out;
|
|
- }
|
|
- sin.sin_family = hp->h_addrtype;
|
|
- (void)alarm(20);
|
|
- s = socket(hp->h_addrtype, thishost -> socktype, 0 /*protonumber*/);
|
|
+ memset(&hints, 0, sizeof(hints));
|
|
+ hints.ai_family = PF_UNSPEC;
|
|
+ hints.ai_socktype = thishost->socktype;
|
|
+ hints.ai_flags = AI_CANONNAME;
|
|
+ error = getaddrinfo(thishost->hostname, "time", &hints, &res0);
|
|
+ if (error)
|
|
+ {
|
|
+ fprintf(stderr, "%s: %s: %s\n",
|
|
+ whoami, thishost->hostname, gai_strerror(error));
|
|
+ goto out;
|
|
+ }
|
|
+ for (res = res0; res; res = res->ai_next)
|
|
+ {
|
|
+ char hbuf[NI_MAXHOST];
|
|
+
|
|
+ (void)alarm(20);
|
|
+ if (getnameinfo (res->ai_addr, res->ai_addrlen, hbuf,
|
|
+ sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
|
|
+ strcpy(hbuf, "(invalid)");
|
|
+ printf("Trying %s...\r\n", hbuf);
|
|
+ s = socket(res->ai_family, res->ai_socktype,
|
|
+ 0 /* res->ai_protocol */);
|
|
+ if (s < 0)
|
|
+ {
|
|
+ alarm (0);
|
|
+ continue;
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
if (s < 0) {
|
|
- perror("netdate: socket");
|
|
- (void)alarm(0);
|
|
- goto out;
|
|
- }
|
|
- if (thishost -> socktype == SOCK_STREAM) {
|
|
- if (bind(s, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
|
|
- perror("netdate: bind");
|
|
- goto bad;
|
|
- }
|
|
+ perror("netdate: socket");
|
|
+ (void)alarm(0);
|
|
+ goto out;
|
|
+ }
|
|
+ if (res == NULL)
|
|
+ {
|
|
+ fprintf (stderr, "No host found\n");
|
|
+ (void)alarm(0);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (thishost->socktype == SOCK_STREAM) {
|
|
+ struct sockaddr_storage ss;
|
|
+
|
|
+ bzero((char *)&ss, sizeof (ss));
|
|
+ ss.ss_family = res->ai_family;
|
|
+ if (bind(s, (struct sockaddr *)&ss, res->ai_addrlen) < 0) {
|
|
+ perror("netdate: bind");
|
|
+ goto bad;
|
|
+ }
|
|
}
|
|
- bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
|
|
- sin.sin_port = port;
|
|
(void)gettimeofday (&thishost -> asked, (struct timezone *)0);
|
|
- if (connect(s, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
|
|
+ if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
|
|
perror("netdate: connect");
|
|
goto bad;
|
|
}
|
|
if (thishost -> socktype == SOCK_DGRAM) {
|
|
- if (write (s, "\n", 1) < 0) {
|
|
+ if (send (s, "\n", 1, 0) < 0) {
|
|
perror ("netdate: send");
|
|
goto bad;
|
|
}
|
|
}
|
|
|
|
/* see note below: */
|
|
-/* nread = read (s, (char *)&thishost -> then, sizeof (thishost -> then)); */
|
|
+/* nread = read (s, (char *)&thishost -> then, sizeof (thishost -> then)); */
|
|
|
|
thishost -> then.tv_sec=0L;
|
|
- nread = read (s, (char *)&buf,4);
|
|
+ nread = read (s, (char *)&buf,4);
|
|
(void)gettimeofday (&thishost -> acked, (struct timezone *)0);
|
|
(void)alarm(0);
|
|
now = thishost -> acked;
|
|
@@ -532,22 +551,7 @@
|
|
thishost -> bad = 1;
|
|
fprintf (stderr, "Connection with %s to %s failed.\n",
|
|
thishost -> protoname, thishost -> hostname);
|
|
+ if (res0)
|
|
+ freeaddrinfo (res0);
|
|
return(0);
|
|
}
|
|
-
|
|
-long
|
|
-getport(char *protoname)
|
|
-{
|
|
- register struct servent *sp;
|
|
- static long port;
|
|
- char *service = "time";
|
|
-
|
|
- if (port != 0)
|
|
- return(port);
|
|
- if ((sp = getservbyname(service, protoname)) == 0) {
|
|
- fprintf(stderr, "%s: %s/%s: unknown service\n",
|
|
- whoami, service, protoname);
|
|
- exit(1);
|
|
- }
|
|
- return (port = sp->s_port);
|
|
-}
|