Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 28 Jul 2008 07:48:22 GMT
From:      Jens Rehsack <rehsack@web.de>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   ports/126025: [PATCH] net/p5-Net-Interface - fix problem with larger sockaddr that struct ifreq
Message-ID:  <200807280748.m6S7mMx1032318@www.freebsd.org>
Resent-Message-ID: <200807280750.m6S7o2a0059204@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>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 <sys/socket.h>
 #include <net/if.h>
 #include <errno.h>
+#include <strings.h>
 
 #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 <sys/socket.h>
+ #include <net/if.h>
+ #include <errno.h>
++#include <strings.h>
+ 
+ #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:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200807280748.m6S7mMx1032318>