bin/9379

Maxim Konovalov maxim at macomnet.ru
Sat Feb 28 11:40:18 PST 2004


The following reply was made to PR bin/9379; it has been noted by GNATS.

From: Maxim Konovalov <maxim at macomnet.ru>
To: bug-followup at freebsd.org
Cc: mtaylor at cybernet.com, Eugene Grosbein <eugen at 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


More information about the freebsd-bugs mailing list