Bug#312093: netspeed: network interfaces showing up multiple times

Hans Ulrich Niedermann Hans Ulrich Niedermann <debian@n-dimensional.de>, 312093@bugs.debian.org
Wed, 08 Jun 2005 15:24:24 +0200


Joergen Scheibengruber <Joergen.Scheibengruber@informatik.uni-ulm.de> writes:

> On Wed, 2005-06-08 at 00:55 +0200, Hans Ulrich Niedermann wrote:

>> It seems (without reading the code, just from observing netspeed's
>> behaviour) that netspeed currently does something like this to find
>> the list of interface to possibly monitor (monitor_interfaces):
>> 
>>     monitor_interfaces = []
>>     for interface in list_of_all_interfaces:
>>        if is_up(interface):
>>            for ipv4_addr in addr_list(interface, AF_INET):
>>                monitor_interfaces.append(interface)
>> 
>> I'd suggest changing that logic into:
>> 
>>     monitor_interfaces = []
>>     for interface in list_of_all_interfaces:
>>        if is_up(interface):
>>            monitor_interfaces.append(interface)
>> 
>> This
>> 
>>   a) makes it independent of the address family
>>   b) adds the interface at most once to the list
>>   c) is more simple logic
>> 
>> No drawbacks. :)
>
> Well, actually it has been doing nr. 2 all the time. But the
> infrastructure which is there maybe makes it seem like nr. 1.
>
> So all released versions use the glibc function if_nameindex() to get
> the list of devices. I don't know how it assembles the list.

Obviously in a way wrong for what we want.

But we should read the corresponding docs first. The man page says:

   NAME
       if_nameindex - return all network interface names and indexes

and the info page says:

 -- Function: struct if_nameindex * if_nameindex (void)
     This function returns an array of `if_nameindex' structures, one
     for every interface that is present.  

which suggests that the glibc behaviour of
   a) listing only interfaces with IPv4 addresses (it says
      "all" or "every" interface in the docs)
   b) listing interfaces as many times as they have IPv4 addresses
      bound to them
is wrong.

Short test program, in case someone needs it:

#include <stdio.h>
#include <net/if.h>

int main(int argc, char *argv[])
{
        int i;
        struct if_nameindex *ifs = if_nameindex();
        if (ifs == NULL) {
                perror("could not run if_nameindex");
                return 1;
        }
        for (i=0; (i>=0) && (ifs[i].if_index != 0) && (ifs[i].if_name != NULL); i++) {
                printf("%3d  %3d  %s\n", i, ifs[i].if_index, ifs[i].if_name);
        }
        if_freenameindex(ifs);
}

This lists (Debian libc6 2.3.2.ds1-22) the network interface for every
IPv4 address which is bound to an interface which is "up". So every
"up" network interface is listed as many times as it has IPv4
addresses bound to it, ignoring any IPv6 or other addresses bound to
the interface.

The intuitively expected behaviour when reading the man page would be
for if_nameindex(3) to list all network interfaces which are up,
regardless of any addresses which might or might not be bound to them.

> The version in cvs now uses libgtop2 to get the list of devices, which
> simply returns all entries of /proc/net/dev.

Hopefully it does something else on non-Linux platforms (which do not
have /proc/net/dev).

> So it would be interssting how /proc/net/dev looks in your case. If we
> don't have multiple entries there, we're all done already :)

No, there are no duplicate entries in /proc/net/dev.

> Otherwise, it would be interessting if multiple devices always show up
> one after each other or if the list is completely mixed (which would
> make removing duplicates a little bit more difficult then trivial ;))

I have only seen them show up one after the other. Which makes sense
in a kind of way, but should be verified by examining the (presumedly
buggy) glibc source code first.

Hmm. It seems we're not the first people to have those kinds of
problems:

http://lists.gnu.org/archive/html/bug-inetutils/2001-02/msg00013.html

Perhaps we should file a bug against libc6, or move this bug to libc6?

Uli