Browse Source

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 <nbd@openwrt.org>

git-svn-id: svn+ssh://svn.openwrt.org/openwrt/trunk@42759 3c298f89-4303-0410-b956-a3cf2f4a3e73
nbd 9 years ago
parent
commit
fe7133f7e5
4 changed files with 99 additions and 5 deletions
  1. 4 3
      Makefile
  2. 6 0
      include/iwinfo/utils.h
  3. 48 2
      iwinfo_nl80211.c
  4. 41 0
      iwinfo_utils.c

+ 4 - 3
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)

+ 6 - 0
include/iwinfo/utils.h

@@ -21,11 +21,14 @@
 
 #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

+ 48 - 2
iwinfo_nl80211.c

@@ -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;
 

+ 41 - 0
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;
+}