aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2006-09-30 00:18:16 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2006-09-30 00:18:16 +0000
commit7935a5a992e103cefa15ae1f27219e745a2e11c4 (patch)
tree7d8bca25fd48f4a7a2e870861bf321432d18dbfd
parent70210168fcb1fb9bdbcd6fe92509cd9b1ef46eb9 (diff)
downloadbusybox-7935a5a992e103cefa15ae1f27219e745a2e11c4.tar.gz
libiproute/ll_map.c: fix bug 279
("On-demand net module loading fails with CONFIG_FEATURE_IFUPDOWN_IP")
-rw-r--r--networking/libiproute/ll_map.c36
1 files changed, 30 insertions, 6 deletions
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 <sys/socket.h> /* socket() */
+#include <net/if.h> /* struct ifreq and co. */
+#include <sys/ioctl.h> /* 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;
}