From 7935a5a992e103cefa15ae1f27219e745a2e11c4 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Sat, 30 Sep 2006 00:18:16 +0000 Subject: libiproute/ll_map.c: fix bug 279 ("On-demand net module loading fails with CONFIG_FEATURE_IFUPDOWN_IP") --- networking/libiproute/ll_map.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) (limited to 'networking/libiproute') diff --git a/networking/libiproute/ll_map.c b/networking/libiproute/ll_map.c index 48775122c..a14fa4e42 100644 --- a/networking/libiproute/ll_map.c +++ b/networking/libiproute/ll_map.c @@ -17,8 +17,11 @@ #include "libnetlink.h" #include "ll_map.h" -struct idxmap -{ +#include /* socket() */ +#include /* struct ifreq and co. */ +#include /* ioctl() & SIOCGIFINDEX */ + +struct idxmap { struct idxmap * next; int index; int type; @@ -129,6 +132,7 @@ int ll_name_to_index(char *name) static char ncache[16]; static int icache; struct idxmap *im; + int sock_fd; int i; if (name == NULL) @@ -144,19 +148,39 @@ int ll_name_to_index(char *name) } } } + /* We have not found the interface in our cache, but the kernel + * may still know about it. One reason is that we may be using + * module on-demand loading, which means that the kernel will + * load the module and make the interface exist only when + * we explicitely request it (check for dev_load() in net/core/dev.c). + * I can think of other similar scenario, but they are less common... + * Jean II */ + sock_fd = socket(AF_INET, SOCK_DGRAM, 0); + if (sock_fd) { + struct ifreq ifr; + int ret; + strncpy(ifr.ifr_name, name, IFNAMSIZ); + ifr.ifr_ifindex = -1; + ret = ioctl(sock_fd, SIOCGIFINDEX, &ifr); + close(sock_fd); + if (ret >= 0) + /* In theory, we should redump the interface list + * to update our cache, this is left as an exercise + * to the reader... Jean II */ + return ifr.ifr_ifindex; + } + return 0; } int ll_init_map(struct rtnl_handle *rth) { if (rtnl_wilddump_request(rth, AF_UNSPEC, RTM_GETLINK) < 0) { - perror("Cannot send dump request"); - exit(1); + bb_perror_msg_and_die("cannot send dump request"); } if (rtnl_dump_filter(rth, ll_remember_index, &idxmap, NULL, NULL) < 0) { - fprintf(stderr, "Dump terminated\n"); - exit(1); + bb_error_msg_and_die("dump terminated"); } return 0; } -- cgit v1.2.3