From owner-freebsd-net@FreeBSD.ORG Tue Jul 22 15:18:08 2008 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id EFA901065682 for ; Tue, 22 Jul 2008 15:18:08 +0000 (UTC) (envelope-from brooks@lor.one-eyed-alien.net) Received: from lor.one-eyed-alien.net (cl-162.ewr-01.us.sixxs.net [IPv6:2001:4830:1200:a1::2]) by mx1.freebsd.org (Postfix) with ESMTP id 6803C8FC27 for ; Tue, 22 Jul 2008 15:18:08 +0000 (UTC) (envelope-from brooks@lor.one-eyed-alien.net) Received: from lor.one-eyed-alien.net (localhost [127.0.0.1]) by lor.one-eyed-alien.net (8.14.2/8.14.2) with ESMTP id m6MFIlVt011804; Tue, 22 Jul 2008 10:18:47 -0500 (CDT) (envelope-from brooks@lor.one-eyed-alien.net) Received: (from brooks@localhost) by lor.one-eyed-alien.net (8.14.2/8.14.2/Submit) id m6MFIlsI011803; Tue, 22 Jul 2008 10:18:47 -0500 (CDT) (envelope-from brooks) Date: Tue, 22 Jul 2008 10:18:47 -0500 From: Brooks Davis To: Jens Rehsack Message-ID: <20080722151847.GI1699@lor.one-eyed-alien.net> References: <4884F401.4050103@web.de> <20080721204820.GE1699@lor.one-eyed-alien.net> <4884FFFF.9090908@web.de> <20080721222416.GG1699@lor.one-eyed-alien.net> <48850F72.90204@web.de> <20080721224618.GH1699@lor.one-eyed-alien.net> <48858948.9020403@web.de> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="FUFe+yI/t+r3nyH4" Content-Disposition: inline In-Reply-To: <48858948.9020403@web.de> User-Agent: Mutt/1.5.17 (2007-11-01) Cc: FreeBSD Net Subject: Re: SOLVED: lo0 not in ioctl( SIOCGIFCONF ) X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 22 Jul 2008 15:18:09 -0000 --FUFe+yI/t+r3nyH4 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Tue, Jul 22, 2008 at 07:16:24AM +0000, Jens Rehsack wrote: > Brooks Davis wrote: >> On Mon, Jul 21, 2008 at 10:36:34PM +0000, Jens Rehsack wrote: >>> Brooks Davis wrote: >>>> On Mon, Jul 21, 2008 at 09:30:39PM +0000, Jens Rehsack wrote: >>>>> Brooks Davis wrote: >>>>>>> Hi, >>>>>>>=20 >>>>>>> maybe this question is better asked in this list ... >>>>>>>=20 >>>>>>> I was searching why ports/net/p5-Net-Interface was not working as >>>>>>> expected and found some reasons. Most of them I can answer by imple= menting >>>>>>> some test code as attached, but now I'm wondering why em0 is shown = twice >>>>>>> and lo0 is not included. >>>>>>> The same situation on another machine .. >>>>>> The attachment didn't make it through. >>>>>>=20 >>>>>> -- Brooks >>>>> Copy&Paste starts here ... >>>>> #include >>>>> #include >>>>> #include >>>>> #include >>>>> #include >>>>> #include >>>>> #include >>>>> #include >>>>>=20 >>>>> #ifndef _SIZEOF_ADDR_IFREQ >>>>> #define _SIZEOF_ADDR_IFREQ(ifr) \ >>>>> ((ifr).ifr_addr.sa_len > sizeof(struct sockaddr) ? \ >>>>> (sizeof(struct ifreq) - sizeof(struct sockaddr) + \ >>>>> (ifr).ifr_addr.sa_len) : sizeof(struct ifreq)) >>>>> #endif >>>>>=20 >>>>> int >>>>> main() >>>>> { >>>>> struct ifconf ifc; >>>>> struct ifreq *ifr, *lifr; >>>>> int fd; >>>>> unsigned int n; >>>>>=20 >>>>> fd =3D socket( AF_INET, SOCK_STREAM, 0 ); >>>>> bzero(&ifc, sizeof(ifc)); >>>>> n =3D 3; >>>>> ifr =3D calloc( ifc.ifc_len, sizeof(*ifr) ); >>>>> do >>>>> { >>>>> n *=3D 2; >>>>> ifr =3D realloc( ifr, sizeof(*ifr) * n ); >>>>> bzero( ifr, sizeof(*ifr) * n ); >>>>> ifc.ifc_req =3D ifr; >>>>> ifc.ifc_len =3D n * sizeof(*ifr); >>>>> } while( ( ioctl( fd, SIOCGIFCONF, &ifc ) =3D=3D -1 ) || (=20 >>>>> ifc.ifc_len =3D=3D n * sizeof(*ifr)) ); >>>> There are several problems with this loop. First, icoctl won't return >>>> an error in the overflow case because that's not how SIOCGIFCONF works. >>>> SIOCGIFCONF is badly designed in a number of ways, but that's how it >>>> is. Second, checking that the array is completely full isn't at all >>>> reliable because what is returned is actually ifreq structures which >>>> might or might not vary in length as they contain addresses. Thus you >>>> need <=3D. Third, you should start by allocating a significant amount= of >>>> space. Yes, your algorithm is O(sqrt(n)), but allocating a larger >>>> value has effectively no cost so you might as well save some system ca= lls >>>> on average. >>> Thanks - that was the information I miss. I'll try tomorrow (it's=20 >>> slightly late here) and send back the result. >>> Using <=3D should produce an endless loop, but maybe checking if=20 >>> ifc.ifc_len <=3D (n/2) * sizeof(*ifr) could bring wanted results ... >>=20 >> Oops, you're right. Actually, the condition to check is probably >> (n*sizeof(*ifr) - ifc.ifc_len < sizeof(*ifr)). Actually, since the size >> of the returned values aren't actually a multiple of sizeof(*ifr), I'd >> probably switch to allocating a multiple of 4k. >=20 > Actually, because there're very different sizes of sockaddr's (sockaddr_i= n,=20 > sockaddr_in6, ...), I require at least a page must be left over. > Because of other OS may support return of errors in overflow, I didn't=20 > remove the check - finally it must run on AIX, Windows and Linux, too. >=20 >>>>> lifr =3D (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len]; >>>>>=20 >>>>> while (ifr < lifr) > { >>>>> printf( "%s\n", ifr->ifr_name ); >>>>> ifr =3D (struct ifreq *)(((char *)ifr) + _SIZEOF_ADDR_IFREQ(*= ifr)); >>>>> } >>>> This loop has two problems. First, the ifr's are variable length so y= ou >>>> immediately go off into the weeds. >>> The _SIZEOF_ADDR_IFREQ macro should handle that correctly, shouldn't it? >>=20 >> Right here as well. >=20 > Finally - I must enhance this using SA_LEN if available to support system= s=20 > without sa_len member support. I'll try it in office with our linux=20 > machines there, because I don't have any penguins at home ;) >=20 >>>> Second, there is at least one per >>>> interface and one per address so you to keep track of the last interfa= ce >>>> name and not repeat them. >>> Good point - if it's sure in this order, this is a good way to handle i= t. >>=20 >> It is in the current implementation and it's hard to imaging that we'd >> break that. >=20 > By the way, because I'm looking for interfaces, I skip everything which i= s=20 > no AF_LINK - should work, too (and does for my test-machines ...). >=20 > Final question: would it make sense to submit a patch against=20 > ports/net/p5-Net-Interface using this knowledge to unbreak the port, or= =20 I'd suggest doing both. We want it fixed in CPAN, but having it be useful = on FreeBSD would also be good. -- Brooks > /Jens > #include > #include > #include > #include > #include > #include > #include > #include > #include >=20 > /* FIXME use SA_LEN for systems like Linux */ > #ifndef _SIZEOF_ADDR_IFREQ > #define _SIZEOF_ADDR_IFREQ(ifr) \ > ((ifr).ifr_addr.sa_len > sizeof(struct sockaddr) ? \ > (sizeof(struct ifreq) - sizeof(struct sockaddr) + \ > (ifr).ifr_addr.sa_len) : sizeof(struct ifreq)) > #endif >=20 > int > main() > { > struct ifconf ifc; > struct ifreq *ifr, *lifr; > int fd; > unsigned int n; >=20 > fd =3D socket( AF_INET, SOCK_STREAM, 0 ); > bzero(&ifc, sizeof(ifc)); > n =3D 1; > ifr =3D calloc( ifc.ifc_len, sizeof(*ifr) ); > do > { > n *=3D 2; > ifr =3D realloc( ifr, PAGE_SIZE * n ); > bzero( ifr, PAGE_SIZE * n ); > ifc.ifc_req =3D ifr; > ifc.ifc_len =3D n * PAGE_SIZE; > } while( ( ioctl( fd, SIOCGIFCONF, &ifc ) =3D=3D -1 ) || ( ifc.if= c_len >=3D ( (n-1) * PAGE_SIZE)) ); >=20 > lifr =3D (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len]; >=20 > while (ifr < lifr) > { > struct sockaddr *sa =3D &ifr->ifr_ifru.ifru_addr; > if( AF_LINK =3D=3D sa->sa_family ) > { > printf( "%s\n", ifr->ifr_name ); > } > ifr =3D (struct ifreq *)(((char *)ifr) + _SIZEOF_ADDR_IFREQ(*ifr)= ); > } >=20 > return 0; > } --FUFe+yI/t+r3nyH4 Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.8 (FreeBSD) iD8DBQFIhfpXXY6L6fI4GtQRAtBRAKDhEpvRIkATfsa4HChBrxA20NSqZwCfUAyz 09yOhimYruPEua5tDSjX4IU= =omn2 -----END PGP SIGNATURE----- --FUFe+yI/t+r3nyH4--