Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 21 Jul 2008 17:46:18 -0500
From:      Brooks Davis <brooks@freebsd.org>
To:        Jens Rehsack <rehsack@web.de>
Cc:        FreeBSD Net <freebsd-net@freebsd.org>
Subject:   Re: lo0 not in ioctl( SIOCGIFCONF )
Message-ID:  <20080721224618.GH1699@lor.one-eyed-alien.net>
In-Reply-To: <48850F72.90204@web.de>
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>

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

--a8sldprk+5E/pDEv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

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 impleme=
nting
>>>>> some test code as attached, but now I'm wondering why em0 is shown tw=
ice
>>>>> 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 <stdio.h>
>>> #include <stdlib.h>
>>> #include <sys/socket.h>
>>> #include <net/if.h>
>>> #include <errno.h>
>>> #include <strings.h>
>>> #include <sys/ioctl.h>
>>> #include <ifaddrs.h>
>>>=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)) );
>>=20
>> 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 calls
>> on average.
>=20
> Thanks - that was the information I miss. I'll try tomorrow (it's slightl=
y=20
> late here) and send back the result.
> Using <=3D should produce an endless loop, but maybe checking if ifc.ifc_=
len=20
> <=3D (n/2) * sizeof(*ifr) could bring wanted results ...

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.

>>>     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(*if=
r));
>>>     }
>>=20
>> This loop has two problems.  First, the ifr's are variable length so you
>> immediately go off into the weeds.
>=20
> The _SIZEOF_ADDR_IFREQ macro should handle that correctly, shouldn't it?

Right here as well.

>>  Second, there is at least one per
>> interface and one per address so you to keep track of the last interface
>> name and not repeat them.
>=20
> Good point - if it's sure in this order, this is a good way to handle it.

It is in the current implementation and it's hard to imaging that we'd
break that.

-- Brooks

>> -- Brooks
>=20
> /Jens
>=20

--a8sldprk+5E/pDEv
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (FreeBSD)

iD8DBQFIhRG5XY6L6fI4GtQRAl1OAJ9/invMMLU4Ciuqk1VyV1U6z+m5zgCeIr+i
7tpMuvd086cG1D5KmdwIVH4=
=uCUk
-----END PGP SIGNATURE-----

--a8sldprk+5E/pDEv--



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