From owner-freebsd-bugs@FreeBSD.ORG Sat Feb 28 11:40:18 2004 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id CAE1C16A4E6 for ; Sat, 28 Feb 2004 11:40:18 -0800 (PST) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id C0CEB43D3F for ; Sat, 28 Feb 2004 11:40:18 -0800 (PST) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) i1SJeIbv013625 for ; Sat, 28 Feb 2004 11:40:18 -0800 (PST) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.10/8.12.10/Submit) id i1SJeIcJ013624; Sat, 28 Feb 2004 11:40:18 -0800 (PST) (envelope-from gnats) Date: Sat, 28 Feb 2004 11:40:18 -0800 (PST) Message-Id: <200402281940.i1SJeIcJ013624@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org From: Maxim Konovalov Subject: Re: bin/9379 X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: Maxim Konovalov List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 28 Feb 2004 19:40:18 -0000 The following reply was made to PR bin/9379; it has been noted by GNATS. From: Maxim Konovalov To: bug-followup@freebsd.org Cc: mtaylor@cybernet.com, Eugene Grosbein 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 + #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