lo0 not in ioctl( SIOCGIFCONF )
Brooks Davis
brooks at freebsd.org
Mon Jul 21 22:45:39 UTC 2008
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,
>>>>>
>>>>> maybe this question is better asked in this list ...
>>>>>
>>>>> 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 implementing
>>>>> 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.
>>>>
>>>> -- 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>
>>>
>>> #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
>>>
>>> int
>>> main()
>>> {
>>> struct ifconf ifc;
>>> struct ifreq *ifr, *lifr;
>>> int fd;
>>> unsigned int n;
>>>
>>> fd = socket( AF_INET, SOCK_STREAM, 0 );
>>> bzero(&ifc, sizeof(ifc));
>>> n = 3;
>>> ifr = calloc( ifc.ifc_len, sizeof(*ifr) );
>>> do
>>> {
>>> n *= 2;
>>> ifr = realloc( ifr, sizeof(*ifr) * n );
>>> bzero( ifr, sizeof(*ifr) * n );
>>> ifc.ifc_req = ifr;
>>> ifc.ifc_len = n * sizeof(*ifr);
>>> } while( ( ioctl( fd, SIOCGIFCONF, &ifc ) == -1 ) || (
>>> ifc.ifc_len == 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 <=. 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.
>
> Thanks - that was the information I miss. I'll try tomorrow (it's slightly
> late here) and send back the result.
> Using <= should produce an endless loop, but maybe checking if ifc.ifc_len
> <= (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 = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
>>>
>>> while (ifr < lifr) > {
>>> printf( "%s\n", ifr->ifr_name );
>>> ifr = (struct ifreq *)(((char *)ifr) + _SIZEOF_ADDR_IFREQ(*ifr));
>>> }
>>
>> This loop has two problems. First, the ifr's are variable length so you
>> immediately go off into the weeds.
>
> 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.
>
> 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
>
> /Jens
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 187 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-net/attachments/20080721/9fc682b5/attachment.pgp
More information about the freebsd-net
mailing list