From 4aca87515a5083ae0e31ce3177189fd43b6d05ac Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 3 Jan 2015 13:58:15 +0100 Subject: patch to Vanilla Tomato 1.28 --- .../router/busybox/networking/libiproute/ll_map.c | 146 +++++++++++++-------- 1 file changed, 91 insertions(+), 55 deletions(-) (limited to 'release/src/router/busybox/networking/libiproute/ll_map.c') diff --git a/release/src/router/busybox/networking/libiproute/ll_map.c b/release/src/router/busybox/networking/libiproute/ll_map.c index b7a82842..2ed7fbbb 100644 --- a/release/src/router/busybox/networking/libiproute/ll_map.c +++ b/release/src/router/busybox/networking/libiproute/ll_map.c @@ -1,3 +1,4 @@ +/* vi: set sw=4 ts=4: */ /* * ll_map.c * @@ -10,27 +11,37 @@ * */ -#include -#include -#include -#include +#include /* struct ifreq and co. */ +#include "libbb.h" #include "libnetlink.h" - -struct idxmap -{ - struct idxmap * next; - int index; - int type; - int alen; - unsigned flags; - unsigned char addr[8]; - char name[16]; +#include "ll_map.h" + +struct idxmap { + struct idxmap *next; + int index; + int type; + int alen; + unsigned flags; + unsigned char addr[8]; + char name[16]; }; static struct idxmap *idxmap[16]; -int ll_remember_index(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) +static struct idxmap *find_by_index(int idx) +{ + struct idxmap *im; + + for (im = idxmap[idx & 0xF]; im; im = im->next) + if (im->index == idx) + return im; + return NULL; +} + +int ll_remember_index(const struct sockaddr_nl *who UNUSED_PARAM, + struct nlmsghdr *n, + void *arg UNUSED_PARAM) { int h; struct ifinfomsg *ifi = NLMSG_DATA(n); @@ -43,33 +54,28 @@ int ll_remember_index(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi))) return -1; - memset(tb, 0, sizeof(tb)); parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n)); if (tb[IFLA_IFNAME] == NULL) return 0; - h = ifi->ifi_index&0xF; + h = ifi->ifi_index & 0xF; - for (imp=&idxmap[h]; (im=*imp)!=NULL; imp = &im->next) + for (imp = &idxmap[h]; (im = *imp) != NULL; imp = &im->next) if (im->index == ifi->ifi_index) - break; - - if (im == NULL) { - im = malloc(sizeof(*im)); - if (im == NULL) - return 0; - im->next = *imp; - im->index = ifi->ifi_index; - *imp = im; - } + goto found; + im = xmalloc(sizeof(*im)); + im->next = *imp; + im->index = ifi->ifi_index; + *imp = im; + found: im->type = ifi->ifi_type; im->flags = ifi->ifi_flags; if (tb[IFLA_ADDRESS]) { int alen; im->alen = alen = RTA_PAYLOAD(tb[IFLA_ADDRESS]); - if (alen > sizeof(im->addr)) + if (alen > (int)sizeof(im->addr)) alen = sizeof(im->addr); memcpy(im->addr, RTA_DATA(tb[IFLA_ADDRESS]), alen); } else { @@ -86,9 +92,9 @@ const char *ll_idx_n2a(int idx, char *buf) if (idx == 0) return "*"; - for (im = idxmap[idx&0xF]; im; im = im->next) - if (im->index == idx) - return im->name; + im = find_by_index(idx); + if (im) + return im->name; snprintf(buf, 16, "if%d", idx); return buf; } @@ -101,17 +107,19 @@ const char *ll_index_to_name(int idx) return ll_idx_n2a(idx, nbuf); } +#ifdef UNUSED int ll_index_to_type(int idx) { struct idxmap *im; if (idx == 0) return -1; - for (im = idxmap[idx&0xF]; im; im = im->next) - if (im->index == idx) - return im->type; + im = find_by_index(idx); + if (im) + return im->type; return -1; } +#endif unsigned ll_index_to_flags(int idx) { @@ -119,46 +127,74 @@ unsigned ll_index_to_flags(int idx) if (idx == 0) return 0; - - for (im = idxmap[idx&0xF]; im; im = im->next) - if (im->index == idx) - return im->flags; + im = find_by_index(idx); + if (im) + return im->flags; return 0; } -int ll_name_to_index(char *name) +int xll_name_to_index(const char *const name) { + int ret = 0; + int sock_fd; + +/* caching is not warranted - no users which repeatedly call it */ +#ifdef UNUSED static char ncache[16]; static int icache; + struct idxmap *im; int i; if (name == NULL) - return 0; - if (icache && strcmp(name, ncache) == 0) - return icache; - for (i=0; i<16; i++) { + goto out; + if (icache && strcmp(name, ncache) == 0) { + ret = icache; + goto out; + } + for (i = 0; i < 16; i++) { for (im = idxmap[i]; im; im = im->next) { if (strcmp(im->name, name) == 0) { icache = im->index; strcpy(ncache, name); - return im->index; + ret = im->index; + goto out; } } } - return 0; + /* 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 */ +#endif + + sock_fd = socket(AF_INET, SOCK_DGRAM, 0); + if (sock_fd >= 0) { + struct ifreq ifr; + int tmp; + + strncpy_IFNAMSIZ(ifr.ifr_name, name); + ifr.ifr_ifindex = -1; + tmp = ioctl(sock_fd, SIOCGIFINDEX, &ifr); + close(sock_fd); + if (tmp >= 0) + /* In theory, we should redump the interface list + * to update our cache, this is left as an exercise + * to the reader... Jean II */ + ret = ifr.ifr_ifindex; + } +/* out:*/ + if (ret <= 0) + bb_error_msg_and_die("cannot find device \"%s\"", name); + return ret; } 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); - } - - if (rtnl_dump_filter(rth, ll_remember_index, &idxmap, NULL, NULL) < 0) { - fprintf(stderr, "Dump terminated\n"); - exit(1); - } + xrtnl_wilddump_request(rth, AF_UNSPEC, RTM_GETLINK); + xrtnl_dump_filter(rth, ll_remember_index, &idxmap); return 0; } -- cgit v1.2.3-54-g00ecf