lo0 not in ioctl( SIOCGIFCONF )

Brooks Davis brooks at freebsd.org
Mon Jul 21 22:23:37 UTC 2008


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.

>     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.  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.

-- Brooks

> 
>     return 0;
> }
> _______________________________________________
> freebsd-net at freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-net
> To unsubscribe, send any mail to "freebsd-net-unsubscribe at freebsd.org"
> 
-------------- 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/7f05d287/attachment.pgp


More information about the freebsd-net mailing list