From owner-freebsd-net@FreeBSD.ORG  Mon Jul 21 22:37:48 2008
Return-Path: <owner-freebsd-net@FreeBSD.ORG>
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 2E958106564A;
	Mon, 21 Jul 2008 22:37:48 +0000 (UTC) (envelope-from rehsack@web.de)
Received: from fmmailgate02.web.de (fmmailgate02.web.de [217.72.192.227])
	by mx1.freebsd.org (Postfix) with ESMTP id AD23C8FC16;
	Mon, 21 Jul 2008 22:37:47 +0000 (UTC) (envelope-from rehsack@web.de)
Received: from smtp08.web.de (fmsmtp08.dlan.cinetic.de [172.20.5.216])
	by fmmailgate02.web.de (Postfix) with ESMTP id 5CA60E6AF2AF;
	Tue, 22 Jul 2008 00:36:56 +0200 (CEST)
Received: from [87.149.238.94] (helo=waldorf.muppets.liwing.de)
	by smtp08.web.de with esmtp (TLSv1:AES256-SHA:256)
	(WEB.DE 4.109 #226)
	id 1KL400-00024s-00; Tue, 22 Jul 2008 00:36:56 +0200
Message-ID: <48850F72.90204@web.de>
Date: Mon, 21 Jul 2008 22:36:34 +0000
From: Jens Rehsack <rehsack@web.de>
User-Agent: Thunderbird 2.0.0.14 (X11/20080703)
MIME-Version: 1.0
To: Brooks Davis <brooks@freebsd.org>
References: <4884F401.4050103@web.de>
	<20080721204820.GE1699@lor.one-eyed-alien.net>
	<4884FFFF.9090908@web.de>
	<20080721222416.GG1699@lor.one-eyed-alien.net>
In-Reply-To: <20080721222416.GG1699@lor.one-eyed-alien.net>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Sender: rehsack@web.de
X-Sender: rehsack@web.de
X-Provags-ID: V01U2FsdGVkX19cVSb72bhnq2LlCXeug4W2Hiz0y7l631i6o9Zg
	kQHCzE+2oRsuA7LkQ2DKOA3TZtD37dKv9hl3DWJXOcNxvgUQNY H2wrvydn0=
Cc: FreeBSD Net <freebsd-net@freebsd.org>
Subject: Re: 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 <freebsd-net.freebsd.org>
List-Unsubscribe: <http://lists.freebsd.org/mailman/listinfo/freebsd-net>,
	<mailto:freebsd-net-request@freebsd.org?subject=unsubscribe>
List-Archive: <http://lists.freebsd.org/pipermail/freebsd-net>
List-Post: <mailto:freebsd-net@freebsd.org>
List-Help: <mailto:freebsd-net-request@freebsd.org?subject=help>
List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/freebsd-net>,
	<mailto:freebsd-net-request@freebsd.org?subject=subscribe>
X-List-Received-Date: Mon, 21 Jul 2008 22:37:48 -0000

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

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

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

> -- Brooks

/Jens