iwinfo: fix handling of accessing nl80211 interfaces via radio*
authorFelix Fietkau <nbd@openwrt.org>
Sun, 5 Oct 2014 10:26:05 +0000 (10:26 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Sun, 5 Oct 2014 10:26:05 +0000 (10:26 +0000)
look up device path via uci instead of assuming a direct phy index

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
SVN-Revision: 42759

package/network/utils/iwinfo/Makefile
package/network/utils/iwinfo/src/Makefile
package/network/utils/iwinfo/src/include/iwinfo/utils.h
package/network/utils/iwinfo/src/iwinfo_nl80211.c
package/network/utils/iwinfo/src/iwinfo_utils.c

index 7bd8fb28ef076d82017d5f6aebc1a72c949e34ff..7a122551b81b08a3de7ca864100f91d7d2235844 100644 (file)
@@ -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 <xm@subsignal.org>
 endef
index 572bef9f97e412a016453da7f508be850ce2fc35..60341f7c2b70c9af332857c63952958d869ebeb5 100644 (file)
@@ -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)
index d58ec5fb7539833e1eb4adc60a1511583f149e2d..d4f32e4d1ec9ef1f7242f0aa6cee4747542ef173 100644 (file)
 
 #include <sys/socket.h>
 #include <net/if.h>
+#include <uci.h>
 
 #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
index 7711b611020809d6844dd9d4c7368dc0f57ad35b..66ace26101c8c6a969a7fb9f62f563abb01c92c8 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include <limits.h>
+#include <glob.h>
 #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;
 
index 4a824337a973bee371e447298295c2471f0bcc10..b313ea2049ca540c24b1922d085485a845c346bf 100644 (file)
@@ -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;
+}