nl80211: align path to phy mapping logic with mac80211.sh
authorJo-Philipp Wich <jo@mein.io>
Tue, 15 Oct 2019 12:21:38 +0000 (14:21 +0200)
committerJo-Philipp Wich <jo@mein.io>
Tue, 15 Oct 2019 12:50:56 +0000 (14:50 +0200)
The mac80211.sh implementation of the uci "path" option compares the
readlink() results of each /sys/class/ieee80211/*/device link to find
the proper phy directory while iwinfo so far tried to construct a full
path out of the uci value.

The iwinfo approach appears to fail under certain circumstances, e.g.
with Hyper-V systems utilizing PCI passthrough for the radio devices.

This commit mimicks the behaviour of mac80211.sh more closely to
achieve the same results.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
iwinfo_nl80211.c

index 4d20489ded3bf50686fe93ebcc01774f2d2f89f9..c7b0222e152485f4ca756edbca89d9ea10ba3057 100644 (file)
@@ -26,6 +26,7 @@
 #include <glob.h>
 #include <fnmatch.h>
 #include <stdarg.h>
+#include <stdlib.h>
 
 #include "iwinfo_nl80211.h"
 
@@ -234,26 +235,49 @@ static struct nl80211_msg_conveyor * nl80211_ctl(int cmd, int flags)
 
 static int nl80211_phy_idx_from_uci_path(struct uci_section *s)
 {
-       const char *opt;
-       char buf[128];
+       size_t linklen, pathlen;
+       char buf[128], *link;
+       struct dirent *e;
+       const char *path;
        int idx = -1;
-       glob_t gl;
+       DIR *d;
 
-       opt = uci_lookup_option_string(uci_ctx, s, "path");
-       if (!opt)
+       path = uci_lookup_option_string(uci_ctx, s, "path");
+       if (!path)
                return -1;
 
-       snprintf(buf, sizeof(buf), "/sys/devices/%s/ieee80211/*/index", opt);  /**/
-       if (glob(buf, 0, NULL, &gl))
-               snprintf(buf, sizeof(buf), "/sys/devices/platform/%s/ieee80211/*/index", opt);  /**/
+       if ((d = opendir("/sys/class/ieee80211")) != NULL)
+       {
+               while ((e = readdir(d)) != NULL)
+               {
+                       snprintf(buf, sizeof(buf), "/sys/class/ieee80211/%s/device", e->d_name);
 
-       if (glob(buf, 0, NULL, &gl))
-               return -1;
+                       link = realpath(buf, NULL);
 
-       if (gl.gl_pathc > 0)
-               idx = nl80211_readint(gl.gl_pathv[0]);
+                       if (link == NULL)
+                               continue;
 
-       globfree(&gl);
+                       linklen = strlen(link);
+                       pathlen = strlen(path);
+
+                       if (pathlen >= linklen || strcmp(link + (linklen - pathlen), path))
+                               linklen = 0;
+
+                       free(link);
+
+                       if (linklen == 0)
+                               continue;
+
+                       snprintf(buf, sizeof(buf), "/sys/class/ieee80211/%s/index", e->d_name);
+
+                       idx = nl80211_readint(buf);
+
+                       if (idx >= 0)
+                               break;
+               }
+
+               closedir(d);
+       }
 
        return idx;
 }