Bug#749345: if_nametoindex error behaviour assumptions
Package: libc6
Version: 2.13-38+deb7u1
As part of trying to determine the error behaviour of if_nametoindex,
I wrote and ran the attached test program. I discovered by looking at
the strace of a test run that if_nametoindex doesn't always properly
check the errno values from its system calls.
To reproduce:
* Compile the attached test program
cc -Wall if-nametoindex-test.c -o if-nametoindex-test
* Run it in a way which will make it fail
strace sh -c 'ulimit -n 4; exec ./t x
* Observe the strace output.
In my setup I see this:
open("/dev/null", O_RDONLY) = 3
access("/proc/net", R_OK) = 0
access("/proc/net/unix", R_OK) = 0
socket(PF_FILE, SOCK_DGRAM|SOCK_CLOEXEC, 0) = -1 EMFILE (Too many open files)
socket(PF_INET, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_IP) = -1 EMFILE (Too many open files)
access("/proc/net/if_inet6", R_OK) = 0
socket(PF_INET6, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_IP) = -1 EMFILE (Too many open files)
access("/proc/net/ax25", R_OK) = -1 ENOENT (No such file or directory)
access("/proc/net/nr", R_OK) = -1 ENOENT (No such file or directory)
access("/proc/net/rose", R_OK) = -1 ENOENT (No such file or directory)
access("/proc/net/ipx", R_OK) = -1 ENOENT (No such file or directory)
access("/proc/net/appletalk", R_OK) = -1 ENOENT (No such file or directory)
access("/proc/sys/net/econet", R_OK) = -1 ENOENT (No such file or directory)
access("/proc/sys/net/ash", R_OK) = -1 ENOENT (No such file or directory)
access("/proc/net/x25", R_OK) = -1 ENOENT (No such file or directory)
write(2, "got 0, No such file or directory"..., 33got 0, No such file or directory
) = 33
I think if_nametoindex should have immediately stopped when it got
EMFILE, and returned to the caller with errno still set to EMFILE.
It's also far from clear that ENOENT is the right return value to
provide if the protocol type walk falls off the end. ENXIO would seem
better. But I haven't looked at the glibc source code to see exactly
what code I'm exercising here.
Ian.
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/fcntl.h>
#include <assert.h>
int main(int argc, char **argv) {
int fd = open("/dev/null",O_RDONLY);
assert(fd>=0);
errno = 0;
int x = if_nametoindex(argv[1]);
fprintf(stderr, "got %d, %s\n", x, strerror(errno));
return 0;
}
Reply to: