From bfacdd543b92213a6f47ae0a58ac170286c4610a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 5 Oct 2014 10:26:05 +0000 Subject: [PATCH] iwinfo: fix handling of accessing nl80211 interfaces via radio* look up device path via uci instead of assuming a direct phy index Signed-off-by: Felix Fietkau git-svn-id: svn://svn.openwrt.org/openwrt/trunk@42759 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/network/utils/iwinfo/Makefile | 2 +- package/network/utils/iwinfo/src/Makefile | 7 +-- .../utils/iwinfo/src/include/iwinfo/utils.h | 6 +++ .../network/utils/iwinfo/src/iwinfo_nl80211.c | 50 ++++++++++++++++++- .../network/utils/iwinfo/src/iwinfo_utils.c | 41 +++++++++++++++ 5 files changed, 100 insertions(+), 6 deletions(-) diff --git a/package/network/utils/iwinfo/Makefile b/package/network/utils/iwinfo/Makefile index 7bd8fb28ef..7a122551b8 100644 --- a/package/network/utils/iwinfo/Makefile +++ b/package/network/utils/iwinfo/Makefile @@ -24,7 +24,7 @@ define Package/libiwinfo SECTION:=libs CATEGORY:=Libraries TITLE:=Generalized Wireless Information Library (iwinfo) - DEPENDS:=+PACKAGE_kmod-cfg80211:libnl-tiny + DEPENDS:=+PACKAGE_kmod-cfg80211:libnl-tiny +libuci ABI_VERSION:=$(PKG_RELEASE) MAINTAINER:=Jo-Philipp Wich endef diff --git a/package/network/utils/iwinfo/src/Makefile b/package/network/utils/iwinfo/src/Makefile index 572bef9f97..60341f7c2b 100644 --- a/package/network/utils/iwinfo/src/Makefile +++ b/package/network/utils/iwinfo/src/Makefile @@ -1,5 +1,6 @@ IWINFO_BACKENDS = $(BACKENDS) IWINFO_CFLAGS = $(CFLAGS) -std=gnu99 -fstrict-aliasing -Iinclude +IWINFO_LDFLAGS = -luci IWINFO_LIB = libiwinfo.so IWINFO_LIB_LDFLAGS = $(LDFLAGS) -shared @@ -36,9 +37,9 @@ endif $(CC) $(IWINFO_CFLAGS) $(FPIC) -c -o $@ $< compile: clean $(IWINFO_LIB_OBJ) $(IWINFO_LUA_OBJ) $(IWINFO_CLI_OBJ) - $(CC) $(IWINFO_LIB_LDFLAGS) -o $(IWINFO_LIB) $(IWINFO_LIB_OBJ) - $(CC) $(IWINFO_LUA_LDFLAGS) -o $(IWINFO_LUA) $(IWINFO_LUA_OBJ) - $(CC) $(IWINFO_CLI_LDFLAGS) -o $(IWINFO_CLI) $(IWINFO_CLI_OBJ) + $(CC) $(IWINFO_LDFLAGS) $(IWINFO_LIB_LDFLAGS) -o $(IWINFO_LIB) $(IWINFO_LIB_OBJ) + $(CC) $(IWINFO_LDFLAGS) $(IWINFO_LUA_LDFLAGS) -o $(IWINFO_LUA) $(IWINFO_LUA_OBJ) + $(CC) $(IWINFO_LDFLAGS) $(IWINFO_CLI_LDFLAGS) -o $(IWINFO_CLI) $(IWINFO_CLI_OBJ) clean: rm -f *.o $(IWINFO_LIB) $(IWINFO_LUA) $(IWINFO_CLI) diff --git a/package/network/utils/iwinfo/src/include/iwinfo/utils.h b/package/network/utils/iwinfo/src/include/iwinfo/utils.h index d58ec5fb75..d4f32e4d1e 100644 --- a/package/network/utils/iwinfo/src/include/iwinfo/utils.h +++ b/package/network/utils/iwinfo/src/include/iwinfo/utils.h @@ -21,11 +21,14 @@ #include #include +#include #include "iwinfo.h" #define LOG10_MAGIC 1.25892541179 +extern struct uci_context *uci_ctx; + int iwinfo_ioctl(int cmd, void *ifr); int iwinfo_dbm2mw(int in); @@ -44,4 +47,7 @@ int iwinfo_hardware_id_from_mtd(struct iwinfo_hardware_id *id); void iwinfo_parse_rsn(struct iwinfo_crypto_entry *c, uint8_t *data, uint8_t len, uint8_t defcipher, uint8_t defauth); +struct uci_section *iwinfo_uci_get_radio(const char *name, const char *type); +void iwinfo_uci_free(void); + #endif diff --git a/package/network/utils/iwinfo/src/iwinfo_nl80211.c b/package/network/utils/iwinfo/src/iwinfo_nl80211.c index 7711b61102..66ace26101 100644 --- a/package/network/utils/iwinfo/src/iwinfo_nl80211.c +++ b/package/network/utils/iwinfo/src/iwinfo_nl80211.c @@ -23,6 +23,7 @@ */ #include +#include #include "iwinfo_nl80211.h" #define min(x, y) ((x) < (y)) ? (x) : (y) @@ -209,6 +210,51 @@ static struct nl80211_msg_conveyor * nl80211_ctl(int cmd, int flags) return nl80211_new(nls->nlctrl, cmd, flags); } +static int nl80211_phy_idx_from_uci(const char *name) +{ + struct uci_section *s; + const char *opt; + char buf[128]; + glob_t gl; + FILE *f = NULL; + int idx = -1; + int err; + + s = iwinfo_uci_get_radio(name, "mac80211"); + if (!s) + goto free; + + opt = uci_lookup_option_string(uci_ctx, s, "path"); + if (!opt) + goto free; + + snprintf(buf, sizeof(buf), "/sys/devices/%s/ieee80211/*/index", opt); + err = glob(buf, 0, NULL, &gl); + if (err) + goto free; + + if (gl.gl_pathc) + f = fopen(gl.gl_pathv[0], "r"); + + globfree(&gl); + + if (!f) + goto free; + + err = fread(buf, 1, sizeof(buf) - 1, f); + fclose(f); + + if (err <= 0) + goto free; + + buf[err] = 0; + idx = atoi(buf); + +free: + iwinfo_uci_free(); + return idx; +} + static struct nl80211_msg_conveyor * nl80211_msg(const char *ifname, int cmd, int flags) { @@ -224,7 +270,7 @@ static struct nl80211_msg_conveyor * nl80211_msg(const char *ifname, if (!strncmp(ifname, "phy", 3)) phyidx = atoi(&ifname[3]); else if (!strncmp(ifname, "radio", 5)) - phyidx = atoi(&ifname[5]); + phyidx = nl80211_phy_idx_from_uci(ifname); else if (!strncmp(ifname, "mon.", 4)) ifidx = if_nametoindex(&ifname[4]); else @@ -510,7 +556,7 @@ static char * nl80211_phy2ifname(const char *ifname) else if (!strncmp(ifname, "phy", 3)) phyidx = atoi(&ifname[3]); else if (!strncmp(ifname, "radio", 5)) - phyidx = atoi(&ifname[5]); + phyidx = nl80211_phy_idx_from_uci(ifname); else return NULL; diff --git a/package/network/utils/iwinfo/src/iwinfo_utils.c b/package/network/utils/iwinfo/src/iwinfo_utils.c index 4a824337a9..b313ea2049 100644 --- a/package/network/utils/iwinfo/src/iwinfo_utils.c +++ b/package/network/utils/iwinfo/src/iwinfo_utils.c @@ -24,6 +24,7 @@ static int ioctl_socket = -1; +struct uci_context *uci_ctx = NULL; static int iwinfo_ioctl_socket(void) { @@ -365,3 +366,43 @@ void iwinfo_parse_rsn(struct iwinfo_crypto_entry *c, uint8_t *data, uint8_t len, data += 2 + (count * 4); len -= 2 + (count * 4); } + +struct uci_section *iwinfo_uci_get_radio(const char *name, const char *type) +{ + struct uci_ptr ptr = { + .package = "wireless", + .section = name, + }; + const char *opt; + + if (!uci_ctx) { + uci_ctx = uci_alloc_context(); + if (!uci_ctx) + return NULL; + } + + memset(&ptr, 0, sizeof(ptr)); + ptr.package = "wireless"; + ptr.section = name; + + if (uci_lookup_ptr(uci_ctx, &ptr, NULL, false)) + return NULL; + + if (!ptr.s || strcmp(ptr.s->type, "wifi-device") != 0) + return NULL; + + opt = uci_lookup_option_string(uci_ctx, ptr.s, "type"); + if (!opt || strcmp(opt, type) != 0) + return NULL; + + return ptr.s; +} + +void iwinfo_uci_free(void) +{ + if (!uci_ctx) + return; + + uci_free_context(uci_ctx); + uci_ctx = NULL; +}