From nobody  Thu Jan  7 16:26:53 1999
Received: (from nobody@localhost)
          by hub.freebsd.org (8.8.8/8.8.8) id QAA01895;
          Thu, 7 Jan 1999 16:26:53 -0800 (PST)
          (envelope-from nobody)
Message-Id: <199901080026.QAA01895@hub.freebsd.org>
Date: Thu, 7 Jan 1999 16:26:53 -0800 (PST)
From: mtaylor@cybernet.com
To: freebsd-gnats-submit@freebsd.org
Subject: pppd does not go through all interfaces looking for interface to ARP
X-Send-Pr-Version: www-1.0

>Number:         9379
>Category:       bin
>Synopsis:       pppd does not go through all interfaces looking for interface to ARP
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    maxim
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jan  7 16:30:00 PST 1999
>Closed-Date:    Fri Apr 09 10:03:32 PDT 2004
>Last-Modified:  Fri Apr 09 10:03:32 PDT 2004
>Originator:     Mark J. Taylor
>Release:        2.2.7
>Organization:
Cybernet Systems
>Environment:
>Description:
/src/usr.sbin/pppd/sys-bsd.c has "#define MAX_IFS 32".
I have a machine with 16 slip, 16 ppp, and 16 tun devices, plus
"normal" devices like Ethernets.
pppd will only look at the first 32 ports to determine which interface
to proxy ARP on, so my Ethernet interface may (will) be missed unless
MAX_IFS is higher.
My Digiboard has 16 ports, and I want to use then for either SLIP or
PPP.  This means that I need at least 16 slip and 16 ppp devices.
If I have two, then there will be even more trouble!

>How-To-Repeat:
Re-write sys-bsd.c to NOT use a large static buffer: go through
each interface using IOCTLs for every interface, not one huge
SIOCGIFCONF call.

"/sbin/ifconfig -l" can do it...

>Fix:

>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->suspended 
State-Changed-By: mike 
State-Changed-When: Thu Jul 19 14:05:55 PDT 2001 
State-Changed-Why:  

Awaiting fix and committer. 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=9379 

From: Eugene Grosbein <eugen@grosbein.pp.ru>
To: bug-followup@freebsd.org
Cc:  
Subject: Re: bin/9379: pppd does not go through all interfaces looking for interface to ARP
Date: Sat, 5 Apr 2003 23:02:49 +0800

 I wonder if there will be a fix and a committer :-)
 
 Eugene Grosbein

From: Maxim Konovalov <maxim@macomnet.ru>
To: bug-followup@freebsd.org
Cc: mtaylor@cybernet.com, Eugene Grosbein <eugen@grosbein.pp.ru>
Subject: Re: bin/9379
Date: Sat, 28 Feb 2004 22:38:04 +0300 (MSK)

 Hello,
 
 I have stolen NetBSD's SIOCGIFCONF->getifaddrs convertions code.  I'd
 appreciate if you test an enclosed diff.  Thank you!
 
 Index: sys-bsd.c
 ===================================================================
 RCS file: /home/ncvs/src/usr.sbin/pppd/sys-bsd.c,v
 retrieving revision 1.19
 diff -u -r1.19 sys-bsd.c
 --- sys-bsd.c	5 Nov 2002 05:58:31 -0000	1.19
 +++ sys-bsd.c	28 Feb 2004 19:21:06 -0000
 @@ -76,6 +76,8 @@
  #endif
  #endif
 
 +#include <ifaddrs.h>
 +
  #include "pppd.h"
  #include "fsm.h"
  #include "ipcp.h"
 @@ -1362,84 +1364,69 @@
   * get_ether_addr - get the hardware address of an interface on the
   * the same subnet as ipaddr.
   */
 -#define MAX_IFS		32
 -
  static int
  get_ether_addr(ipaddr, hwaddr)
      u_int32_t ipaddr;
      struct sockaddr_dl *hwaddr;
  {
 -    struct ifreq *ifr, *ifend, *ifp;
      u_int32_t ina, mask;
      struct sockaddr_dl *dla;
 -    struct ifreq ifreq;
 -    struct ifconf ifc;
 -    struct ifreq ifs[MAX_IFS];
 -
 -    ifc.ifc_len = sizeof(ifs);
 -    ifc.ifc_req = ifs;
 -    if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
 -	syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m");
 -	return 0;
 -    }
 +    struct ifaddrs *ifap, *ifa, *ifp;
 
      /*
       * Scan through looking for an interface with an Internet
       * address on the same subnet as `ipaddr'.
       */
 -    ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
 -    for (ifr = ifc.ifc_req; ifr < ifend;
 -		ifr = (struct ifreq *) ((char *)&ifr->ifr_addr
 -		    + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr)))) {
 -	if (ifr->ifr_addr.sa_family == AF_INET) {
 -	    ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
 -	    strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
 -	    /*
 -	     * Check that the interface is up, and not point-to-point
 -	     * or loopback.
 -	     */
 -	    if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
 -		continue;
 -	    if ((ifreq.ifr_flags &
 -		 (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
 -		 != (IFF_UP|IFF_BROADCAST))
 -		continue;
 -	    /*
 -	     * Get its netmask and check that it's on the right subnet.
 -	     */
 -	    if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
 +    if (getifaddrs(&ifap) != 0) {
 +	syslog(LOG_ERR, "getifaddrs: %m");
 +	return 0;
 +    }
 +    for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
 +	if (ifa->ifa_addr->sa_family != AF_INET)
 +	    continue;
 +	ina = ((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr;
 +	/*
 +	 * Check that the interface is up, and not point-to-point
 +	 * or loopback.
 +	 */
 +	if ((ifa->ifa_flags &
 +	    (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
 +	    != (IFF_UP|IFF_BROADCAST))
  		continue;
 -	    mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
 -	    if ((ipaddr & mask) != (ina & mask))
 +	/*
 +	 * Get its netmask and check that it's on the right subnet.
 +	 */
 +	mask = ((struct sockaddr_in *) ifa->ifa_netmask)->sin_addr.s_addr;
 +	if ((ipaddr & mask) != (ina & mask))
  		continue;
 -
 -	    break;
 -	}
 +	break;
      }
 -
 -    if (ifr >= ifend)
 +    if (!ifa) {
 +	freeifaddrs(ifap);
  	return 0;
 -    syslog(LOG_INFO, "found interface %s for proxy arp", ifr->ifr_name);
 +    }
 +    syslog(LOG_INFO, "found interface %s for proxy arp", ifa->ifa_name);
 
      /*
       * Now scan through again looking for a link-level address
       * for this interface.
       */
 -    ifp = ifr;
 -    for (ifr = ifc.ifc_req; ifr < ifend; ) {
 -	if (strcmp(ifp->ifr_name, ifr->ifr_name) == 0
 -	    && ifr->ifr_addr.sa_family == AF_LINK) {
 -	    /*
 -	     * Found the link-level address - copy it out
 -	     */
 -	    dla = (struct sockaddr_dl *) &ifr->ifr_addr;
 -	    BCOPY(dla, hwaddr, dla->sdl_len);
 -	    return 1;
 -	}
 -	ifr = (struct ifreq *) ((char *)&ifr->ifr_addr
 -	    + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr)));
 +    ifp = ifa;
 +    for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
 +	if (strcmp(ifp->ifa_name, ifa->ifa_name) != 0)
 +	    continue;
 +	if (ifa->ifa_addr->sa_family != AF_LINK)
 +	    continue;
 +	/*
 +	 * Found the link-level address - copy it out
 +	 */
 +	dla = (struct sockaddr_dl *) ifa->ifa_addr;
 +	BCOPY(dla, hwaddr, dla->sdl_len);
 +	freeifaddrs(ifap);
 +	return 1;
      }
 
 +    freeifaddrs(ifap);
      return 0;
  }
 
 @@ -1456,9 +1443,7 @@
      u_int32_t addr;
  {
      u_int32_t mask, nmask, ina;
 -    struct ifreq *ifr, *ifend, ifreq;
 -    struct ifconf ifc;
 -    struct ifreq ifs[MAX_IFS];
 +    struct ifaddrs *ifap, *ifa;
 
      addr = ntohl(addr);
      if (IN_CLASSA(addr))	/* determine network mask for address class */
 @@ -1473,41 +1458,31 @@
      /*
       * Scan through the system's network interfaces.
       */
 -    ifc.ifc_len = sizeof(ifs);
 -    ifc.ifc_req = ifs;
 -    if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
 -	syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m");
 +    if (getifaddrs(&ifap) != 0) {
 +	syslog(LOG_WARNING, "getifaddrs: %m");
  	return mask;
      }
 -    ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
 -    for (ifr = ifc.ifc_req; ifr < ifend;
 -		ifr = (struct ifreq *) ((char *)&ifr->ifr_addr
 -		    + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr)))) {
 +    for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
  	/*
  	 * Check the interface's internet address.
  	 */
 -	if (ifr->ifr_addr.sa_family != AF_INET)
 +	if (ifa->ifa_addr->sa_family != AF_INET)
  	    continue;
 -	ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
 +	ina = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
  	if ((ntohl(ina) & nmask) != (addr & nmask))
  	    continue;
  	/*
  	 * Check that the interface is up, and not point-to-point or loopback.
  	 */
 -	strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
 -	if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
 -	    continue;
 -	if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
 -	    != IFF_UP)
 +	if ((ifa->ifa_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK)) != IFF_UP)
  	    continue;
  	/*
  	 * Get its netmask and OR it into our mask.
  	 */
 -	if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
 -	    continue;
 -	mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
 +	mask |= ((struct sockaddr_in *)&ifa->ifa_netmask)->sin_addr.s_addr;
      }
 
 +    freeifaddrs(ifap);
      return mask;
  }
 
 %%%
 
 --
 Maxim Konovalov

From: Eugene Grosbein <eugen@grosbein.pp.ru>
To: Maxim Konovalov <maxim@macomnet.ru>
Cc: bug-followup@freebsd.org
Subject: Re: bin/9379
Date: Sun, 29 Feb 2004 11:07:54 +0700

 On Sat, Feb 28, 2004 at 10:38:04PM +0300, Maxim Konovalov wrote:
 
 > I have stolen NetBSD's SIOCGIFCONF->getifaddrs convertions code.  I'd
 > appreciate if you test an enclosed diff.  Thank you!
 
 Sorry, I have not such configuration and can not test this "in wild".
 
 Eugene
State-Changed-From-To: suspended->closed 
State-Changed-By: maxim 
State-Changed-When: Fri Apr 9 10:01:40 PDT 2004 
State-Changed-Why:  
Fixed in rev. 1.20 src/usr.sbin/pppd/sys-bsd.c.  No MFC intended. 


Responsible-Changed-From-To: freebsd-bugs->maxim 
Responsible-Changed-By: maxim 
Responsible-Changed-When: Fri Apr 9 10:01:40 PDT 2004 
Responsible-Changed-Why:  
All bugs in the patch are mine. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=9379 
>Unformatted:
