Subject: bin/7482: xntpd fails with multiple interfaces at same address
To: None <gnats-bugs@gnats.netbsd.org>
From: Martin Husemann <martin@rumolt.teuto.de>
List: netbsd-bugs
Date: 04/26/1999 20:51:12
>Number: 7482
>Category: bin
>Synopsis: xntpd fails if multiple interfaces share the same address
>Confidential: no
>Severity: critical
>Priority: high
>Responsible: bin-bug-people (Utility Bug People)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Apr 26 20:50:01 1999
>Last-Modified:
>Originator: Martin Husemann
>Organization:
>Release: current as of April 27
>Environment:
System: NetBSD rumolt.teuto.de 1.4_ALPHA NetBSD 1.4_ALPHA (RUMOLT) #1: Wed Apr 7 07:27:08 MEST 1999 martin@hwart.teuto.de:/usr/src/sys-i4b/arch/i386/compile/RUMOLT i386
(this happens on newer kernels as well)
>Description:
If you have multiple interface with the same local address, i.e. one primary
ethernet interface and one or more point-to-point interfaces, xntpd won't
work, because it tries to bind multiple sockets to the same local address.
SO_REUSEADDR (which it already uses) doesn't seem to play the trick - which
I don't understand, but that's the same on i.e. FreeBSD and NetBSD 1.3, so
I instead made it soft-fail on that error instead of "fixing" the underlying
socket kernel code (which would be beyound my scope anyway).
>How-To-Repeat:
ifconfig a PPP interface at the same local address as your ethernet interface,
run xntpd.
>Fix:
*** ntp_io.c.orig Tue Apr 27 04:56:34 1999
--- ntp_io.c Tue Apr 27 05:11:24 1999
***************
*** 627,636 ****
--- 627,640 ----
for (i = 0; i < ninterfaces; i++)
{
inter_list[i].fd =
open_socket(&inter_list[i].sin,
inter_list[i].flags & INT_BROADCAST, 0);
+ if (inter_list[i].fd < 0) {
+ ninterfaces--;
+ memmove(&inter_list[i], &inter_list[i]+1, sizeof(inter_list[0])*(ninterfaces-i));
+ }
}
/*
* Now that we have opened all the sockets, turn off the reuse flag for
* security.
***************
*** 916,932 ****
* bind the local address.
*/
if (bind(fd, (struct sockaddr *)addr, sizeof(*addr)) < 0)
{
char buff[160];
! sprintf(buff,
! "bind() fd %d, family %d, port %d, addr %08lx, in_classd=%d flags=%d fails: %%m",
! fd, addr->sin_family, (int)ntohs(addr->sin_port),
! (u_long)ntohl(addr->sin_addr.s_addr),
! IN_CLASSD(ntohl(addr->sin_addr.s_addr)), flags);
! msyslog(LOG_ERR, buff);
closesocket(fd);
/*
* soft fail if opening a class D address
*/
if (IN_CLASSD(ntohl(addr->sin_addr.s_addr)))
--- 920,944 ----
* bind the local address.
*/
if (bind(fd, (struct sockaddr *)addr, sizeof(*addr)) < 0)
{
char buff[160];
! if (errno != EADDRINUSE) {
! sprintf(buff,
! "bind() fd %d, family %d, port %d, addr %08lx, in_classd=%d flags=%d fails: %%m",
! fd, addr->sin_family, (int)ntohs(addr->sin_port),
! (u_long)ntohl(addr->sin_addr.s_addr),
! IN_CLASSD(ntohl(addr->sin_addr.s_addr)), flags);
! msyslog(LOG_ERR, buff);
! }
closesocket(fd);
+
+ /*
+ * soft fail if duplicate address (multiple interfaces?)
+ */
+ if (errno == EADDRINUSE)
+ return -1;
/*
* soft fail if opening a class D address
*/
if (IN_CLASSD(ntohl(addr->sin_addr.s_addr)))
>Audit-Trail:
>Unformatted: