From mika@obelix.cs.caltech.edu  Thu Oct  2 00:49:45 1997
Received: from vlsi.cs.caltech.edu (vlsi.cs.caltech.edu [131.215.131.129])
          by hub.freebsd.org (8.8.7/8.8.7) with SMTP id AAA10793
          for <FreeBSD-gnats-submit@freebsd.org>; Thu, 2 Oct 1997 00:49:43 -0700 (PDT)
Received: from obelix.cs.caltech.edu by vlsi.cs.caltech.edu (4.1/1.34.1)
	id AA22854; Thu, 2 Oct 97 00:49:41 PDT
Received: (from mika@localhost)
	by obelix.cs.caltech.edu (8.8.7/8.8.7) id AAA01846;
	Thu, 2 Oct 1997 00:49:40 -0700 (PDT)
Message-Id: <199710020749.AAA01846@obelix.cs.caltech.edu>
Date: Thu, 2 Oct 1997 00:49:40 -0700 (PDT)
From: Mika Nystroem <mika@cs.caltech.edu>
Reply-To: mika@cs.caltech.edu
To: FreeBSD-gnats-submit@freebsd.org
Subject:
X-Send-Pr-Version: 3.2

>Number:         4678
>Category:       bin
>Synopsis:       amd does not treat multiple interfaces on remote server properly (earlier PR amended)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Oct  2 00:50:01 PDT 1997
>Closed-Date:    Mon Apr 13 05:13:56 PDT 1998
>Last-Modified:  Mon Apr 13 05:14:08 PDT 1998
>Originator:     
>Release:        
>Organization:
>Environment:

	

Description: 

amd will pick the wrong IP address for a remote server.  It picks the first
one returned by gethostbyname() rather than the one (if any) on a locally
connected network.

How-To-Repeat: 

attempt to mount automatically a filesystem stored on an IP gateway.  This
fails nondeterministically, and leads to system failure since the amd is
stuck in D wait in the kernel.

Fix: 
	
This works in the simplest cases:

*** amd.c.orig	Tue Sep  2 03:53:17 1997
--- amd.c	Wed Oct  1 23:41:13 1997
***************
*** 72,77 ****
--- 72,80 ----
  char *arch = ARCH_REP;			/* Name of current architecture */
  char *endian = ARCH_ENDIAN;		/* Big or Little endian */
  char *wire;
+ unsigned long mysubnet;		        /* subnet address for my machine
+ 					   corresponding to "wire"
+ 					 */
  int foreground = 1;			/* This is the top-level server */
  int mypid;				/* Current process id */
  int immediate_abort;			/* Should close-down unmounts be retried */
***************
*** 271,277 ****
  	orig_umask = umask(0);
  
  	/*
! 	 * Figure out primary network name
  	 */
  	wire = getwire();
  
--- 274,280 ----
  	orig_umask = umask(0);
  
  	/*
! 	 * Figure out primary network name; side-effect: sets "mysubnet"
  	 */
  	wire = getwire();
  
*** srvr_nfs.c.orig	Sat Feb 22 16:07:42 1997
--- srvr_nfs.c	Thu Oct  2 00:19:49 1997
***************
*** 591,596 ****
--- 591,599 ----
  	}
  }
  
+ 
+ extern unsigned long mysubnet;
+ 
  /*
   * Find an nfs server for a host.
   */
***************
*** 653,665 ****
  	 * Get here if we can't find an entry
  	 */
  	if (hp) {
  		switch (hp->h_addrtype) {
  		case AF_INET:
  			ip = ALLOC(sockaddr_in);
  			bzero((voidp) ip, sizeof(*ip));
  			ip->sin_family = AF_INET;
! 			bcopy((voidp) hp->h_addr, (voidp) &ip->sin_addr, sizeof(ip->sin_addr));
! 
  			ip->sin_port = htons(NFS_PORT);
  			break;
  
--- 656,696 ----
  	 * Get here if we can't find an entry
  	 */
  	if (hp) {
+ 	        int i, j;
+ 		unsigned long tmpaddr;
+ 
  		switch (hp->h_addrtype) {
  		case AF_INET:
  			ip = ALLOC(sockaddr_in);
  			bzero((voidp) ip, sizeof(*ip));
  			ip->sin_family = AF_INET;
! 			/*
! 			 * pick host address that is on the same subnet
! 			 * as mysubnet if possible; otherwise, pick the first
! 			 * one.
! 			 */
! 			for (i=0; hp->h_addr_list[i]; i++) {
! 			  bcopy ((voidp)hp->h_addr_list[i], (voidp)&tmpaddr,
! 				 sizeof(tmpaddr));
! 			  for (j=0; j < 4; j++) {
! 			    if ((0xff & (mysubnet >> 8*j)) == 0) continue;
! 			    if ((0xff & (mysubnet >> 8*j)) !=
! 				(0xff & (tmpaddr >> 8*j))) break;
! 			  }
! 			  if (j == 4) {
! 			    
! 			    /* we found a matching subnet address */
! 			    break;
! 			  }
! 			}
! 			if (!hp->h_addr_list[i]) {
! 			  /* no interface matching current subnet; pick one */
! 			  bcopy((voidp) hp->h_addr, (voidp) &ip->sin_addr, sizeof(ip->sin_addr));
! 			}
! 			else {
! 			  /* we found a matching subnet interface */
! 			  bcopy((voidp) hp->h_addr_list[i], (voidp) &ip->sin_addr, sizeof(ip->sin_addr));
! 			}
  			ip->sin_port = htons(NFS_PORT);
  			break;
  
*** wire.c.orig	Sat Feb 22 16:07:46 1997
--- wire.c	Wed Oct  1 23:44:54 1997
***************
*** 85,90 ****
--- 85,92 ----
  #define clist (ifc.ifc_ifcu.ifcu_req)
  #define count (ifc.ifc_len/sizeof(struct ifreq))
  
+ extern unsigned long mysubnet;
+ 
  char *getwire P((void));
  char *getwire()
  {
***************
*** 136,141 ****
--- 138,145 ----
  	/*
  	 * Scan the list looking for a suitable interface
  	 */
+ 	mysubnet = 0;
+ 
  	for (cp = buf; cp < cplim; cp += size(ifr)) {
  		addrlist *al;
  		ifr = (struct ifreq *) cp;
***************
*** 227,236 ****
  			/* This is probably very wrong. */
  			np = getnetbyaddr(subnet, AF_INET);
  #endif /* IN_CLASSA */
! 			if (np)
  				s = np->n_name;
  			else {
  				subnet = address & netmask;
  				hp = gethostbyaddr((char *) &subnet, 4, AF_INET);
  				if (hp)
  					s = hp->h_name;
--- 231,243 ----
  			/* This is probably very wrong. */
  			np = getnetbyaddr(subnet, AF_INET);
  #endif /* IN_CLASSA */
! 			if (np) {
  				s = np->n_name;
+ 				mysubnet = np->n_net;
+ 			}
  			else {
  				subnet = address & netmask;
+ 				mysubnet = subnet;
  				hp = gethostbyaddr((char *) &subnet, 4, AF_INET);
  				if (hp)
  					s = hp->h_name;
>Description:
>How-To-Repeat:
>Fix:
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: gnats-admin->freebsd-bugs 
Responsible-Changed-By: joerg 
Responsible-Changed-When: Sun Oct 19 20:45:33 MEST 1997 
Responsible-Changed-Why:  
Misfiled PR. 
State-Changed-From-To: open->closed 
State-Changed-By: dfr 
State-Changed-When: Mon Apr 13 05:13:56 PDT 1998 
State-Changed-Why:  
Fix applied 
>Unformatted:
Submitter-Id:   current-users
Originator:     Mika Nystroem
Organization:   Caltech Computer Science
Confidential:   no
Synopsis:       amd does not treat multiple interfaces on remote server properly (earlier PR amended)
Severity:       critical
Priority:       high
Category:       bin
Release:        FreeBSD 3.0-CURRENT i386
Class:          sw-bug
