Subject: bin/35479: /usr/sbin/timedc fails
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: None <djv@bedford.net>
List: netbsd-bugs
Date: 01/25/2007 06:40:01
>Number: 35479
>Category: bin
>Synopsis: /usr/sbin/timedc is inoperable and has been for some time
>Confidential: no
>Severity: critical
>Priority: medium
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu Jan 25 06:40:01 +0000 2007
>Originator: djv@bedford.net
>Release: NetBSD 3.1_STABLE
>Organization:
>Environment:
System: NetBSD jezebel.chuck 3.1_STABLE NetBSD 3.1_STABLE (GENERIC.CGD) #0: Mon Jan 22 08:25:25 EST 2007 root@jezebel.chuck:/usr/src/sys/arch/i386/compile/GENERIC.CGD i386
Architecture: i386
Machine: i386
>Description:
This pr reports and fixes two bugs.
Bug 1, timedc will not accept commands and will not execute them.
This renders timed/timedc crippled. This is due to an (old) coding
error in timedc.c
Bug 2, timedc reports spuriously that "host x will not tell us the
date" for certain hosts in the clockdiff command. This is due to
an (old) coding error in file cmds.c This bug cannot be seen until
Bug 1 is fixed, of course.
>How-To-Repeat:
Start timed daemon. Run the timedc utility. Give any command.
Once bug 1 is fixed, commands start working. Some hosts, however,
will not report their date. This is because these hosts (OpenBSD,
notably) expect the timedc program to connect from a privileged
port to the udp time service; bug 2 keeps this from happening.
>Fix:
<how to correct or work around the problem, if known
(multiple lines)>
Apply these diffs in /usr/src/usr.sbin/timed/timedc and remake.
--- cmds.c.orig 2007-01-24 22:33:51.000000000 -0500
+++ cmds.c 2007-01-24 22:34:30.000000000 -0500
@@ -483,10 +483,11 @@
return(-1);
}
+ memset(&sin, 0, sizeof sin);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = 0;
for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) {
- sin.sin_port = htons((u_short)port);
+ sin.sin_port = port;
if (bind(sock, (struct sockaddr*)&sin, sizeof (sin)) >= 0)
break;
if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) {
--- timedc.c.orig 2007-01-24 16:38:21.000000000 -0500
+++ timedc.c 2007-01-24 16:38:55.000000000 -0500
@@ -184,7 +184,7 @@
char **argp = margv;
margc = 0;
- for (cp = cmdline; cp < margv[MAX_MARGV - 1] && *cp;) {
+ for (cp = cmdline; margc < MAX_MARGV - 1 && *cp;) {
while (isspace((unsigned char)*cp))
cp++;
if (*cp == '\0')
Discusion: The cmds.c bug probably originated in the last century,
when SGI released the code. The htons call is evidently not needed;
but at that time SGI hardware was Motorola 680X0 and htons is a
no-op on such bigendian machinery. Eliminating the htons call on
little-endian machines results in a port assignment in the 0-1023
range as demanded by some hosts, and as appears to be the intent
of the programmer. This bug only surfaces in the timedc "clockdiff"
command. I do not know if the memset is necessary, but it gives
me a good feeling.
The timedc.c bug is simply a coding error. It might have worked
at some point in time, purely by chance, depending on where cmdline
and margv are placed in memory. The software was never tested,
evidently, after the bug was introduced; this bug is very old. I
pr'ed it to OpenBSD in ~1998, if I recall correctly. (I was running
a pmax at the time). I had to find it anew (I had forgotten about
it) for NetBSD now that I am using NetBSD. The htons bug I just
found today. With the htons bug, the program will open an
unprivileged port, which often works.
While timed/timedc are obsoleted by ntpd, they retain usefulness
on small LANs without permanent access to a remote time master,
and without super-critical synchronization requirements. I use
them in conjunction with rdate(8) -a on my local master. LAN hosts
are kept within a few dozens of ms (usually within 5ms), and hourly
rdate -a to a remote master seldom drifts off more than a hundred
ms; synchronization is over ppp on a 56Kb modem.
>Unformatted: