Bug#312554: libc6: if_nameindex(3) returns broken list of network interfaces
Package: libc6
Version: 2.3.2.ds1-22
Severity: normal
if_nameindex(3) returns only a subset of all network interfaces, and
lists some of them multiple times. This contradicts the man page
if_nameindex(3posix) and the libc6.info docs which state
NAME
if_nameindex - return all network interface names and indexes
and
-- Function: struct if_nameindex * if_nameindex (void)
This function returns an array of `if_nameindex'
structures, one for every interface that is present.
respectively.
The returned list
- does not contain "all network interface names" like the man page says.
It only includes those which have an IPv4 address configured on them.
- does not contain "one [structure] for every interface present" like
the libc6 info page says.
It contains one if_nameindex structure for every IPv4 address
configured on the interface.
According to empirical studies, the list returned by if_nameindex(3)
is determined according to this logic:
return_list = []
for interface in list_of_all_interfaces:
if is_up(interface):
for ipv4_addr in addr_list(interface, AF_INET):
return_list.append(interface)
return return_list
However, the if_nameindex documentation suggests that the list
should be created using this logic:
return_list = []
for interface in list_of_all_interfaces:
if is_up(interface):
return_list.append(interface)
return return_list
I used this short test program:
#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);
}
In my case, this program prints
0 1 lo
1 1 lo
2 12 eth0
3 12 eth0
4 12 eth0
while I have an additional interface dummy0 which is up, but has no IPv4
addresses configured. The complete output of "ip addr" is as follows:
1: lo: <LOOPBACK,UP> mtu 16436 qdisc noqueue
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet 169.254.185.103/16 scope link lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
12: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether aa::bb:cc:dd:ee brd ff:ff:ff:ff:ff:ff
inet 169.254.28.139/16 scope link eth0
inet 192.168.1.2/24 brd 192.168.1.255 scope global eth0
inet 192.168.1.1/24 scope global eth0
inet6 2001:6f8:abcd:abcd::1007/64 scope global
valid_lft forever preferred_lft forever
[ ... another 10 inet6 addrs deleted ... ]
13: dummy0: <BROADCAST,NOARP,UP> mtu 1500 qdisc noqueue
link/ether 56:b4:4e:e7:91:3a brd ff:ff:ff:ff:ff:ff
inet6 2001:6f8:abcd:abce::1007/128 scope global
valid_lft forever preferred_lft forever
[ ... another 10 inet6 addrs deleted ... ]
This behaviour plainly contradicts the documentation.
I suggest as solutions to either:
a) simplify the logic behind if_nameindex(3) such that it lists all
interfaces in state "up" regardless of any addresses possibly
configured on them
b) change the info documentation to actually describe the current
behaviour of "List all interfaces with IPv4 addresses configured
as many times as the number of IPv4 addresses on the interface.
This violates the POSIX definition of if_nameindex." :-)
The described erroneous behaviour also occurs with the stock Debian
kernel from kernel-image-2.6.8-2-686 2.6.8-16, so this is not an
issue specific to a certain version of the Linux kernel.
-- System Information:
Debian Release: 3.1
APT prefers unstable
APT policy: (700, 'unstable'), (100, 'experimental')
Architecture: i386 (i686)
Kernel: Linux 2.6.11.10-swsusp2-ndim-2
Locale: LANG=C, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8)
Versions of packages libc6 depends on:
ii libdb1-compat 2.1.3-7 The Berkeley database routines [gl
-- no debconf information
Reply to: