From owner-freebsd-ports-bugs@FreeBSD.ORG Mon Jul 28 07:50:02 2008 Return-Path: Delivered-To: freebsd-ports-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 43E52106567C for ; Mon, 28 Jul 2008 07:50:02 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 21A218FC15 for ; Mon, 28 Jul 2008 07:50:02 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.2/8.14.2) with ESMTP id m6S7o2ZI059205 for ; Mon, 28 Jul 2008 07:50:02 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.2/8.14.1/Submit) id m6S7o2a0059204; Mon, 28 Jul 2008 07:50:02 GMT (envelope-from gnats) Resent-Date: Mon, 28 Jul 2008 07:50:02 GMT Resent-Message-Id: <200807280750.m6S7o2a0059204@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-ports-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Jens Rehsack Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 380421065682 for ; Mon, 28 Jul 2008 07:48:23 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id 27EEE8FC1A for ; Mon, 28 Jul 2008 07:48:23 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.2/8.14.2) with ESMTP id m6S7mMow032319 for ; Mon, 28 Jul 2008 07:48:22 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.2/8.14.1/Submit) id m6S7mMx1032318; Mon, 28 Jul 2008 07:48:22 GMT (envelope-from nobody) Message-Id: <200807280748.m6S7mMx1032318@www.freebsd.org> Date: Mon, 28 Jul 2008 07:48:22 GMT From: Jens Rehsack To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: ports/126025: [PATCH] net/p5-Net-Interface - fix problem with larger sockaddr that struct ifreq X-BeenThere: freebsd-ports-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Ports bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 28 Jul 2008 07:50:02 -0000 >Number: 126025 >Category: ports >Synopsis: [PATCH] net/p5-Net-Interface - fix problem with larger sockaddr that struct ifreq >Confidential: no >Severity: serious >Priority: low >Responsible: freebsd-ports-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Mon Jul 28 07:50:01 UTC 2008 >Closed-Date: >Last-Modified: >Originator: Jens Rehsack >Release: FreeBSD7-STABLE >Organization: >Environment: FreeBSD waldorf.muppets.liwing.de 7.0-STABLE FreeBSD 7.0-STABLE #1: Wed Jun 11 16:38:38 UTC 2008 root@waldorf.muppets.liwing.de:/usr/obj/usr/src/sys/WALDORF amd64 >Description: There is nothing more to tell than net/p5-Net-Interface has problems with return values from ioctl(SIOCGIFCONF) with ifreq structs bigger than sizeof(struct ifreq) and didn't expect duplicate name entries because of the return of one entry per interface and one per address. See http://docs.freebsd.org/cgi/getmsg.cgi?fetch=110470+0+archive/2008/freebsd-net/20080727.freebsd-net for entire discussion with Brooks Davis to figure out all the problems. >How-To-Repeat: >Fix: Patch attached with submission follows: Index: net/p5-Net-Interface/work/Net-Interface-0.08/Interface.xs =================================================================== diff -u net/p5-Net-Interface/work/Net-Interface-0.08/Interface.xs.orig net/p5-Net-Interface/work/Net-Interface-0.08/Interface.xs --- net/p5-Net-Interface/work/Net-Interface-0.08/Interface.xs.orig 2006-03-14 00:53:31.000000000 +0000 +++ net/p5-Net-Interface/work/Net-Interface-0.08/Interface.xs 2008-07-28 07:32:22.000000000 +0000 @@ -8,6 +8,7 @@ #include #include #include +#include #ifdef __cplusplus } @@ -36,6 +37,25 @@ #endif /* +** Fix up missing of struct sockaddr field sa_len +*/ + +#ifndef SA_LEN +#define SA_LEN(sa) ((sa).sa_len) +#endif + +/* +** Fix up variable length of struct ifr and missing of struct sockaddr field SA_LEN +*/ + +#ifndef _SIZEOF_ADDR_IFREQ +#define _SIZEOF_ADDR_IFREQ(ifr) \ + (SA_LEN((ifr).ifr_addr) > sizeof(struct sockaddr) ? \ + (sizeof(struct ifreq) - sizeof(struct sockaddr) + \ + SA_LEN((ifr).ifr_addr)) : sizeof(struct ifreq)) +#endif + +/* ** Fix up slightly damaged ifreq entries */ @@ -69,34 +89,50 @@ } sockaddr_all; #define NI_REF_CHECK(ref) \ - if (!SvROK (ref) || !SvOBJECT (SvRV(ref)) || !SvREADONLY (SvRV(ref))) \ + if (!SvROK (ref) || !SvOBJECT (SvRV(ref)) || !SvREADONLY (SvRV(ref))) \ croak ("Can't call method \"%s\" without a valid object reference", GvNAME (CvGV (cv))); #define NI_CONNECT(fd) \ - if ((fd = socket (PF_INET, SOCK_DGRAM, 0)) == -1) \ - XSRETURN_EMPTY; + if ((fd = socket (PF_INET, SOCK_DGRAM, 0)) == -1) \ + XSRETURN_EMPTY; #define NI_ACCESS(fd,value,buf) \ - if (ioctl (fd, value, buf) == -1) { \ - NI_DISCONNECT (fd); \ - XSRETURN_EMPTY; \ - } + if (ioctl (fd, value, buf) == -1) { \ + NI_DISCONNECT (fd); \ + XSRETURN_EMPTY; \ + } #define NI_DISCONNECT(fd) close (fd) -#define NI_NEW_REF(rv,sv,stash) \ - sv = newSV (0); \ - rv = sv_2mortal (newRV_noinc (sv)); \ - sv_bless (rv, stash); \ - SvGROW (sv, sizeof (ifreq)); \ - SvREADONLY_on (sv); \ - XPUSHs (rv); +/* +** max size of struct ifreq can be > PATH_MAX -> let's alloc PAGE_SIZE +*/ +#define NI_NEW_REF(rv,sv,stash) \ + sv = newSV (0); \ + rv = sv_2mortal (newRV_noinc (sv)); \ + sv_bless (rv, stash); \ + SvGROW (sv, PAGE_SIZE); \ + SvREADONLY_on (sv); \ + XPUSHs (rv); + +#define NI_NEW_IFREQ_REF(rv,sv,stash,ifr) \ + sv = newSV (0); \ + rv = sv_2mortal (newRV_noinc (sv)); \ + sv_bless (rv, stash); \ + SvGROW (sv, _SIZEOF_ADDR_IFREQ(*ifr)); \ + SvREADONLY_on (sv); \ + XPUSHs (rv); #define NI_MAX_ARGS(x) \ - if (items > x) \ - croak ("Too many arguments for method \"%s\"", GvNAME (CvGV (cv))) + if (items > x) \ + croak ("Too many arguments for method \"%s\"", GvNAME (CvGV (cv))) -MODULE = Net::Interface PACKAGE = Net::Interface +/* +** Fix up for perl's New()/Renew() interface +*/ +typedef struct { uint8_t pgsize_array[PAGE_SIZE]; } pgsize_as; + +MODULE = Net::Interface PACKAGE = Net::Interface #sub ifa_broadaddr () { &ifa_ifu. &ifu_broadaddr;} #sub ifa_dstaddr () { &ifa_ifu. &ifu_dstaddr;} @@ -109,7 +145,7 @@ PREINIT: struct ifconf ifc; - ifreq *ifr; + struct ifreq *ifr, *lifr; int fd, n; HV *stash; SV *rv, *sv; @@ -117,36 +153,48 @@ PPCODE: { NI_CONNECT (fd); + bzero(&ifc, sizeof(ifc)); #ifdef SIOCGIFCOUNT if (ioctl (fd, SIOCGIFCOUNT, &ifc) != -1) { - New (0xbad, ifr, ifc.ifc_len, struct ifreq); - ifc.ifc_req = ifr; - ifc.ifc_len *= sizeof (ifreq); - if (ioctl (fd, SIOCGIFCONF, &ifc) == -1) { - Safefree (ifr); - close (fd); - XSRETURN_EMPTY; - } + New (0xbad, ifr, ifc.ifc_len, struct ifreq); + ifc.ifc_req = ifr; + ifc.ifc_len *= sizeof (*ifr); + if (ioctl (fd, SIOCGIFCONF, &ifc) == -1) { + Safefree (ifr); + close (fd); + XSRETURN_EMPTY; + } } else #endif - { - n = 3; - New (0xbad, ifr, n, ifreq); - do { - n *= 2; - Renew (ifr, n, ifreq); - ifc.ifc_req = ifr; - ifc.ifc_len = n * sizeof (ifreq); - } - while (ioctl (fd, SIOCGIFCONF, &ifc) == -1 || - ifc.ifc_len == n * sizeof (ifreq)); - NI_DISCONNECT (fd); - } + { + n = 1; + /* New (0xbad, ifr, n, pgsize_as); */ + ifr = (struct ifreq *)safemalloc( (MEM_SIZE)((n)*sizeof(pgsize_as)) ); + do { + n *= 2; + ifr = (struct ifreq *)saferealloc( (Malloc_t)ifr, (MEM_SIZE)(n*sizeof(pgsize_as)) ); + ifc.ifc_req = ifr; + ifc.ifc_len = n * sizeof(pgsize_as); + } + while( ( ioctl( fd, SIOCGIFCONF, &ifc ) == -1 ) || + ( ifc.ifc_len >= ( (n-1) * sizeof(pgsize_as))) ); + NI_DISCONNECT (fd); + } stash = SvROK (ref) ? SvSTASH (SvRV (ref)) : gv_stashsv (ref, 0); - for (n = ifc.ifc_len / sizeof (ifreq); n; --n, ++ifr) { - NI_NEW_REF (rv, sv, stash); - Move (ifr, SvPVX (sv), 1, ifreq); + + lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len]; + while (ifr < lifr) + { + struct sockaddr *sa = &ifr->ifr_ifru.ifru_addr; + if( AF_LINK != sa->sa_family ) /* collect only the AF_LINK entries */ + { + ifr = (struct ifreq *)(((char *)ifr) + _SIZEOF_ADDR_IFREQ(*ifr)); + continue; + } + NI_NEW_IFREQ_REF (rv, sv, stash, ifr); + Move (ifr, SvPVX (sv), 1, _SIZEOF_ADDR_IFREQ(*ifr)); + ifr = (struct ifreq *)(((char *)ifr) + _SIZEOF_ADDR_IFREQ(*ifr)); } Safefree (ifc.ifc_req); } @@ -165,10 +213,10 @@ { NI_MAX_ARGS (2); stash = SvROK (ST (0)) ? SvSTASH (SvRV (ST (0))) : - gv_stashsv (ST (0), 0); + gv_stashsv (ST (0), 0); NI_NEW_REF (rv, sv, stash); Move (SvPV (ST (1), PL_na), ((ifreq *) SvPVX (sv))->ifr_name, - SvCUR (ST (1)) + 1, char); + SvCUR (ST (1)) + 1, char); NI_CONNECT (fd); NI_ACCESS (fd, SIOCGIFFLAGS, SvPVX (sv)); NI_DISCONNECT (fd); @@ -210,37 +258,37 @@ ST (0) = &PL_sv_undef; switch (ix) { case NI_FLAGS: - NI_ACCESS (fd, SIOCGIFFLAGS, ifr); - XST_mIV (0, ifr->ifr_flags); - break; + NI_ACCESS (fd, SIOCGIFFLAGS, ifr); + XST_mIV (0, ifr->ifr_flags); + break; case NI_MTU: - NI_ACCESS (fd, SIOCGIFMTU, ifr); - XST_mIV (0, ifr->ifr_mtu); - break; + NI_ACCESS (fd, SIOCGIFMTU, ifr); + XST_mIV (0, ifr->ifr_mtu); + break; case NI_METRIC: - NI_ACCESS (fd, SIOCGIFMETRIC, ifr); - XST_mIV (0, ifr->ifr_metric); - break; + NI_ACCESS (fd, SIOCGIFMETRIC, ifr); + XST_mIV (0, ifr->ifr_metric); + break; } if (items == 2) { - switch (ix) { - case NI_FLAGS: - ifr->ifr_flags = SvIV (ST (1)); - NI_ACCESS (fd, SIOCSIFFLAGS, ifr); - break; - - case NI_MTU: - ifr->ifr_mtu = SvIV (ST (1)); - NI_ACCESS (fd, SIOCSIFMTU, ifr); - break; - - case NI_METRIC: - ifr->ifr_metric = SvIV (ST (1)); - NI_ACCESS (fd, SIOCSIFMETRIC, ifr); - break; - } + switch (ix) { + case NI_FLAGS: + ifr->ifr_flags = SvIV (ST (1)); + NI_ACCESS (fd, SIOCSIFFLAGS, ifr); + break; + + case NI_MTU: + ifr->ifr_mtu = SvIV (ST (1)); + NI_ACCESS (fd, SIOCSIFMTU, ifr); + break; + + case NI_METRIC: + ifr->ifr_metric = SvIV (ST (1)); + NI_ACCESS (fd, SIOCSIFMETRIC, ifr); + break; + } } NI_DISCONNECT (fd); XSRETURN (1); @@ -272,74 +320,74 @@ ST (0) = &PL_sv_undef; switch (ix) { case NI_ADDR: - NI_ACCESS (fd, SIOCGIFADDR, ifr); - break; + NI_ACCESS (fd, SIOCGIFADDR, ifr); + break; case NI_BRDADDR: - NI_ACCESS (fd, SIOCGIFBRDADDR, ifr); - break; + NI_ACCESS (fd, SIOCGIFBRDADDR, ifr); + break; case NI_NETMASK: - NI_ACCESS (fd, SIOCGIFNETMASK, ifr); - break; + NI_ACCESS (fd, SIOCGIFNETMASK, ifr); + break; #ifdef SIOCGIFHWADDR case NI_HWADDR: NI_ACCESS (fd, SIOCGIFHWADDR, ifr); break; #endif case NI_DSTADDR: - NI_ACCESS (fd, SIOCGIFDSTADDR, ifr); - break; + NI_ACCESS (fd, SIOCGIFDSTADDR, ifr); + break; } Move (&(ifr->ifr_addr), &sa, 1, sockaddr_all); if (items == 2) { - switch (ix) { - case NI_ADDR: - NI_ACCESS (fd, SIOCGIFADDR, ifr); - break; - - case NI_BRDADDR: - NI_ACCESS (fd, SIOCGIFBRDADDR, ifr); - break; - - case NI_NETMASK: - NI_ACCESS (fd, SIOCGIFNETMASK, ifr); - break; + switch (ix) { + case NI_ADDR: + NI_ACCESS (fd, SIOCGIFADDR, ifr); + break; + + case NI_BRDADDR: + NI_ACCESS (fd, SIOCGIFBRDADDR, ifr); + break; + + case NI_NETMASK: + NI_ACCESS (fd, SIOCGIFNETMASK, ifr); + break; /* #ifdef SIOCGIFHWADDR - case NI_HWADDR: - NI_ACCESS (fd, SIOCGIFHWADDR, ifr); - break; + case NI_HWADDR: + NI_ACCESS (fd, SIOCGIFHWADDR, ifr); + break; #endif */ - case NI_DSTADDR: - NI_ACCESS (fd, SIOCGIFDSTADDR, ifr); - break; - } + case NI_DSTADDR: + NI_ACCESS (fd, SIOCGIFDSTADDR, ifr); + break; + } } NI_DISCONNECT (fd); array = (GIMME_V == G_ARRAY); if (array) { - EXTEND (sp, 2); - PUSHs (sv_2mortal (newSViv (sa.sa.sa_family))); + EXTEND (sp, 2); + PUSHs (sv_2mortal (newSViv (sa.sa.sa_family))); } switch (sa.sa.sa_family) { case AF_INET: - if (array) - PUSHs (sv_2mortal (newSViv (sizeof (sa.sin.sin_addr)))); - PUSHs (sv_2mortal (newSVpv ((char *) &sa.sin.sin_addr, - sizeof (sa.sin.sin_addr)))); - break; + if (array) + PUSHs (sv_2mortal (newSViv (sizeof (sa.sin.sin_addr)))); + PUSHs (sv_2mortal (newSVpv ((char *) &sa.sin.sin_addr, + sizeof (sa.sin.sin_addr)))); + break; case AF_FILE: - if (array) + if (array) /*Does not work */ -/* PUSHs (sv_2mortal (newSViv (sizeof (sa.sin.sin_addr))));*/ +/* PUSHs (sv_2mortal (newSViv (sizeof (sa.sin.sin_addr))));*/ /* Bad hack to get hardware address, copied INET mechanism from above, returned last four digits of MAC, munge address and abs size to 6 */ - PUSHs (sv_2mortal (newSViv (IFHWADDRLEN))); - PUSHs (sv_2mortal (newSVpv ((char *) (&sa.sa.sa_data), - IFHWADDRLEN))); + PUSHs (sv_2mortal (newSViv (IFHWADDRLEN))); + PUSHs (sv_2mortal (newSVpv ((char *) (&sa.sa.sa_data), + IFHWADDRLEN))); } } Index: net/p5-Net-Interface/Makefile =================================================================== diff -u net/p5-Net-Interface/Makefile.orig net/p5-Net-Interface/Makefile --- net/p5-Net-Interface/Makefile.orig 2008-07-28 07:34:36.000000000 +0000 +++ net/p5-Net-Interface/Makefile 2008-07-28 07:16:42.000000000 +0000 @@ -7,6 +7,7 @@ PORTNAME= Net-Interface PORTVERSION= 0.08 +PORTREVISION= 1 CATEGORIES= net perl5 MASTER_SITES= CPAN PKGNAMEPREFIX= p5- Index: net/p5-Net-Interface/files/patch-aa =================================================================== diff -uN net/p5-Net-Interface/files/patch-aa --- /dev/null 2008-07-28 07:35:11.000000000 +0000 +++ net/p5-Net-Interface/files/patch-aa 2008-07-28 07:32:32.000000000 +0000 @@ -0,0 +1,376 @@ +--- Interface.xs.orig 2006-03-14 00:53:31.000000000 +0000 ++++ Interface.xs 2008-07-28 07:32:22.000000000 +0000 +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + + #ifdef __cplusplus + } +@@ -36,6 +37,25 @@ + #endif + + /* ++** Fix up missing of struct sockaddr field sa_len ++*/ ++ ++#ifndef SA_LEN ++#define SA_LEN(sa) ((sa).sa_len) ++#endif ++ ++/* ++** Fix up variable length of struct ifr and missing of struct sockaddr field SA_LEN ++*/ ++ ++#ifndef _SIZEOF_ADDR_IFREQ ++#define _SIZEOF_ADDR_IFREQ(ifr) \ ++ (SA_LEN((ifr).ifr_addr) > sizeof(struct sockaddr) ? \ ++ (sizeof(struct ifreq) - sizeof(struct sockaddr) + \ ++ SA_LEN((ifr).ifr_addr)) : sizeof(struct ifreq)) ++#endif ++ ++/* + ** Fix up slightly damaged ifreq entries + */ + +@@ -69,34 +89,50 @@ + } sockaddr_all; + + #define NI_REF_CHECK(ref) \ +- if (!SvROK (ref) || !SvOBJECT (SvRV(ref)) || !SvREADONLY (SvRV(ref))) \ ++ if (!SvROK (ref) || !SvOBJECT (SvRV(ref)) || !SvREADONLY (SvRV(ref))) \ + croak ("Can't call method \"%s\" without a valid object reference", GvNAME (CvGV (cv))); + + #define NI_CONNECT(fd) \ +- if ((fd = socket (PF_INET, SOCK_DGRAM, 0)) == -1) \ +- XSRETURN_EMPTY; ++ if ((fd = socket (PF_INET, SOCK_DGRAM, 0)) == -1) \ ++ XSRETURN_EMPTY; + + #define NI_ACCESS(fd,value,buf) \ +- if (ioctl (fd, value, buf) == -1) { \ +- NI_DISCONNECT (fd); \ +- XSRETURN_EMPTY; \ +- } ++ if (ioctl (fd, value, buf) == -1) { \ ++ NI_DISCONNECT (fd); \ ++ XSRETURN_EMPTY; \ ++ } + + #define NI_DISCONNECT(fd) close (fd) + +-#define NI_NEW_REF(rv,sv,stash) \ +- sv = newSV (0); \ +- rv = sv_2mortal (newRV_noinc (sv)); \ +- sv_bless (rv, stash); \ +- SvGROW (sv, sizeof (ifreq)); \ +- SvREADONLY_on (sv); \ +- XPUSHs (rv); ++/* ++** max size of struct ifreq can be > PATH_MAX -> let's alloc PAGE_SIZE ++*/ ++#define NI_NEW_REF(rv,sv,stash) \ ++ sv = newSV (0); \ ++ rv = sv_2mortal (newRV_noinc (sv)); \ ++ sv_bless (rv, stash); \ ++ SvGROW (sv, PAGE_SIZE); \ ++ SvREADONLY_on (sv); \ ++ XPUSHs (rv); ++ ++#define NI_NEW_IFREQ_REF(rv,sv,stash,ifr) \ ++ sv = newSV (0); \ ++ rv = sv_2mortal (newRV_noinc (sv)); \ ++ sv_bless (rv, stash); \ ++ SvGROW (sv, _SIZEOF_ADDR_IFREQ(*ifr)); \ ++ SvREADONLY_on (sv); \ ++ XPUSHs (rv); + + #define NI_MAX_ARGS(x) \ +- if (items > x) \ +- croak ("Too many arguments for method \"%s\"", GvNAME (CvGV (cv))) ++ if (items > x) \ ++ croak ("Too many arguments for method \"%s\"", GvNAME (CvGV (cv))) + +-MODULE = Net::Interface PACKAGE = Net::Interface ++/* ++** Fix up for perl's New()/Renew() interface ++*/ ++typedef struct { uint8_t pgsize_array[PAGE_SIZE]; } pgsize_as; ++ ++MODULE = Net::Interface PACKAGE = Net::Interface + + #sub ifa_broadaddr () { &ifa_ifu. &ifu_broadaddr;} + #sub ifa_dstaddr () { &ifa_ifu. &ifu_dstaddr;} +@@ -109,7 +145,7 @@ + + PREINIT: + struct ifconf ifc; +- ifreq *ifr; ++ struct ifreq *ifr, *lifr; + int fd, n; + HV *stash; + SV *rv, *sv; +@@ -117,36 +153,48 @@ + PPCODE: + { + NI_CONNECT (fd); ++ bzero(&ifc, sizeof(ifc)); + #ifdef SIOCGIFCOUNT + if (ioctl (fd, SIOCGIFCOUNT, &ifc) != -1) { +- New (0xbad, ifr, ifc.ifc_len, struct ifreq); +- ifc.ifc_req = ifr; +- ifc.ifc_len *= sizeof (ifreq); +- if (ioctl (fd, SIOCGIFCONF, &ifc) == -1) { +- Safefree (ifr); +- close (fd); +- XSRETURN_EMPTY; +- } ++ New (0xbad, ifr, ifc.ifc_len, struct ifreq); ++ ifc.ifc_req = ifr; ++ ifc.ifc_len *= sizeof (*ifr); ++ if (ioctl (fd, SIOCGIFCONF, &ifc) == -1) { ++ Safefree (ifr); ++ close (fd); ++ XSRETURN_EMPTY; ++ } + } + else + #endif +- { +- n = 3; +- New (0xbad, ifr, n, ifreq); +- do { +- n *= 2; +- Renew (ifr, n, ifreq); +- ifc.ifc_req = ifr; +- ifc.ifc_len = n * sizeof (ifreq); +- } +- while (ioctl (fd, SIOCGIFCONF, &ifc) == -1 || +- ifc.ifc_len == n * sizeof (ifreq)); +- NI_DISCONNECT (fd); +- } ++ { ++ n = 1; ++ /* New (0xbad, ifr, n, pgsize_as); */ ++ ifr = (struct ifreq *)safemalloc( (MEM_SIZE)((n)*sizeof(pgsize_as)) ); ++ do { ++ n *= 2; ++ ifr = (struct ifreq *)saferealloc( (Malloc_t)ifr, (MEM_SIZE)(n*sizeof(pgsize_as)) ); ++ ifc.ifc_req = ifr; ++ ifc.ifc_len = n * sizeof(pgsize_as); ++ } ++ while( ( ioctl( fd, SIOCGIFCONF, &ifc ) == -1 ) || ++ ( ifc.ifc_len >= ( (n-1) * sizeof(pgsize_as))) ); ++ NI_DISCONNECT (fd); ++ } + stash = SvROK (ref) ? SvSTASH (SvRV (ref)) : gv_stashsv (ref, 0); +- for (n = ifc.ifc_len / sizeof (ifreq); n; --n, ++ifr) { +- NI_NEW_REF (rv, sv, stash); +- Move (ifr, SvPVX (sv), 1, ifreq); ++ ++ lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len]; ++ while (ifr < lifr) ++ { ++ struct sockaddr *sa = &ifr->ifr_ifru.ifru_addr; ++ if( AF_LINK != sa->sa_family ) /* collect only the AF_LINK entries */ ++ { ++ ifr = (struct ifreq *)(((char *)ifr) + _SIZEOF_ADDR_IFREQ(*ifr)); ++ continue; ++ } ++ NI_NEW_IFREQ_REF (rv, sv, stash, ifr); ++ Move (ifr, SvPVX (sv), 1, _SIZEOF_ADDR_IFREQ(*ifr)); ++ ifr = (struct ifreq *)(((char *)ifr) + _SIZEOF_ADDR_IFREQ(*ifr)); + } + Safefree (ifc.ifc_req); + } +@@ -165,10 +213,10 @@ + { + NI_MAX_ARGS (2); + stash = SvROK (ST (0)) ? SvSTASH (SvRV (ST (0))) : +- gv_stashsv (ST (0), 0); ++ gv_stashsv (ST (0), 0); + NI_NEW_REF (rv, sv, stash); + Move (SvPV (ST (1), PL_na), ((ifreq *) SvPVX (sv))->ifr_name, +- SvCUR (ST (1)) + 1, char); ++ SvCUR (ST (1)) + 1, char); + NI_CONNECT (fd); + NI_ACCESS (fd, SIOCGIFFLAGS, SvPVX (sv)); + NI_DISCONNECT (fd); +@@ -210,37 +258,37 @@ + ST (0) = &PL_sv_undef; + switch (ix) { + case NI_FLAGS: +- NI_ACCESS (fd, SIOCGIFFLAGS, ifr); +- XST_mIV (0, ifr->ifr_flags); +- break; ++ NI_ACCESS (fd, SIOCGIFFLAGS, ifr); ++ XST_mIV (0, ifr->ifr_flags); ++ break; + + case NI_MTU: +- NI_ACCESS (fd, SIOCGIFMTU, ifr); +- XST_mIV (0, ifr->ifr_mtu); +- break; ++ NI_ACCESS (fd, SIOCGIFMTU, ifr); ++ XST_mIV (0, ifr->ifr_mtu); ++ break; + + case NI_METRIC: +- NI_ACCESS (fd, SIOCGIFMETRIC, ifr); +- XST_mIV (0, ifr->ifr_metric); +- break; ++ NI_ACCESS (fd, SIOCGIFMETRIC, ifr); ++ XST_mIV (0, ifr->ifr_metric); ++ break; + } + if (items == 2) { +- switch (ix) { +- case NI_FLAGS: +- ifr->ifr_flags = SvIV (ST (1)); +- NI_ACCESS (fd, SIOCSIFFLAGS, ifr); +- break; +- +- case NI_MTU: +- ifr->ifr_mtu = SvIV (ST (1)); +- NI_ACCESS (fd, SIOCSIFMTU, ifr); +- break; +- +- case NI_METRIC: +- ifr->ifr_metric = SvIV (ST (1)); +- NI_ACCESS (fd, SIOCSIFMETRIC, ifr); +- break; +- } ++ switch (ix) { ++ case NI_FLAGS: ++ ifr->ifr_flags = SvIV (ST (1)); ++ NI_ACCESS (fd, SIOCSIFFLAGS, ifr); ++ break; ++ ++ case NI_MTU: ++ ifr->ifr_mtu = SvIV (ST (1)); ++ NI_ACCESS (fd, SIOCSIFMTU, ifr); ++ break; ++ ++ case NI_METRIC: ++ ifr->ifr_metric = SvIV (ST (1)); ++ NI_ACCESS (fd, SIOCSIFMETRIC, ifr); ++ break; ++ } + } + NI_DISCONNECT (fd); + XSRETURN (1); +@@ -272,74 +320,74 @@ + ST (0) = &PL_sv_undef; + switch (ix) { + case NI_ADDR: +- NI_ACCESS (fd, SIOCGIFADDR, ifr); +- break; ++ NI_ACCESS (fd, SIOCGIFADDR, ifr); ++ break; + + case NI_BRDADDR: +- NI_ACCESS (fd, SIOCGIFBRDADDR, ifr); +- break; ++ NI_ACCESS (fd, SIOCGIFBRDADDR, ifr); ++ break; + + case NI_NETMASK: +- NI_ACCESS (fd, SIOCGIFNETMASK, ifr); +- break; ++ NI_ACCESS (fd, SIOCGIFNETMASK, ifr); ++ break; + #ifdef SIOCGIFHWADDR + case NI_HWADDR: + NI_ACCESS (fd, SIOCGIFHWADDR, ifr); + break; + #endif + case NI_DSTADDR: +- NI_ACCESS (fd, SIOCGIFDSTADDR, ifr); +- break; ++ NI_ACCESS (fd, SIOCGIFDSTADDR, ifr); ++ break; + } + Move (&(ifr->ifr_addr), &sa, 1, sockaddr_all); + if (items == 2) { +- switch (ix) { +- case NI_ADDR: +- NI_ACCESS (fd, SIOCGIFADDR, ifr); +- break; +- +- case NI_BRDADDR: +- NI_ACCESS (fd, SIOCGIFBRDADDR, ifr); +- break; +- +- case NI_NETMASK: +- NI_ACCESS (fd, SIOCGIFNETMASK, ifr); +- break; ++ switch (ix) { ++ case NI_ADDR: ++ NI_ACCESS (fd, SIOCGIFADDR, ifr); ++ break; ++ ++ case NI_BRDADDR: ++ NI_ACCESS (fd, SIOCGIFBRDADDR, ifr); ++ break; ++ ++ case NI_NETMASK: ++ NI_ACCESS (fd, SIOCGIFNETMASK, ifr); ++ break; + /* + #ifdef SIOCGIFHWADDR +- case NI_HWADDR: +- NI_ACCESS (fd, SIOCGIFHWADDR, ifr); +- break; ++ case NI_HWADDR: ++ NI_ACCESS (fd, SIOCGIFHWADDR, ifr); ++ break; + #endif + */ +- case NI_DSTADDR: +- NI_ACCESS (fd, SIOCGIFDSTADDR, ifr); +- break; +- } ++ case NI_DSTADDR: ++ NI_ACCESS (fd, SIOCGIFDSTADDR, ifr); ++ break; ++ } + } + NI_DISCONNECT (fd); + array = (GIMME_V == G_ARRAY); + if (array) { +- EXTEND (sp, 2); +- PUSHs (sv_2mortal (newSViv (sa.sa.sa_family))); ++ EXTEND (sp, 2); ++ PUSHs (sv_2mortal (newSViv (sa.sa.sa_family))); + } + switch (sa.sa.sa_family) { + case AF_INET: +- if (array) +- PUSHs (sv_2mortal (newSViv (sizeof (sa.sin.sin_addr)))); +- PUSHs (sv_2mortal (newSVpv ((char *) &sa.sin.sin_addr, +- sizeof (sa.sin.sin_addr)))); +- break; ++ if (array) ++ PUSHs (sv_2mortal (newSViv (sizeof (sa.sin.sin_addr)))); ++ PUSHs (sv_2mortal (newSVpv ((char *) &sa.sin.sin_addr, ++ sizeof (sa.sin.sin_addr)))); ++ break; + + case AF_FILE: +- if (array) ++ if (array) + /*Does not work */ +-/* PUSHs (sv_2mortal (newSViv (sizeof (sa.sin.sin_addr))));*/ ++/* PUSHs (sv_2mortal (newSViv (sizeof (sa.sin.sin_addr))));*/ + /* Bad hack to get hardware address, copied INET mechanism from above, + returned last four digits of MAC, munge address and abs size to 6 */ +- PUSHs (sv_2mortal (newSViv (IFHWADDRLEN))); +- PUSHs (sv_2mortal (newSVpv ((char *) (&sa.sa.sa_data), +- IFHWADDRLEN))); ++ PUSHs (sv_2mortal (newSViv (IFHWADDRLEN))); ++ PUSHs (sv_2mortal (newSVpv ((char *) (&sa.sa.sa_data), ++ IFHWADDRLEN))); + } + } + >Release-Note: >Audit-Trail: >Unformatted: