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: