iwinfo: nl80211: add support for printing the device path for a phy
authorFelix Fietkau <nbd@nbd.name>
Wed, 9 Jun 2021 11:57:23 +0000 (13:57 +0200)
committerFelix Fietkau <nbd@nbd.name>
Wed, 9 Jun 2021 11:57:26 +0000 (13:57 +0200)
Will be used to replace the shell code from mac80211.sh

Signed-off-by: Felix Fietkau <nbd@nbd.name>
include/iwinfo.h
iwinfo_cli.c
iwinfo_nl80211.c

index 3fc414be492dfdcbe35199d502aa8ed785bc0730..f7097cc15922d5ffb5b0ce0a5dcc240825946721 100644 (file)
@@ -293,6 +293,7 @@ struct iwinfo_ops {
        int (*countrylist)(const char *, char *, int *);
        int (*survey)(const char *, char *, int *);
        int (*lookup_phy)(const char *, char *);
+       int (*phy_path)(const char *phyname, const char **path);
        void (*close)(void);
 };
 
index 8691f3125f913174d654fea00d4ec79a40446de5..456c67a2a5812015636b35b589385f4fa2219cb3 100644 (file)
@@ -875,6 +875,16 @@ static void lookup_phy(const struct iwinfo_ops *iw, const char *section)
 }
 
 
+static void lookup_path(const struct iwinfo_ops *iw, const char *phy)
+{
+       const char *path;
+
+       if (!iw->phy_path || iw->phy_path(phy, &path) || !path)
+               return;
+
+       printf("%s\n", path);
+}
+
 int main(int argc, char **argv)
 {
        int i, rv = 0;
@@ -934,6 +944,10 @@ int main(int argc, char **argv)
                }
                else
                {
+                       if (!strcmp(argv[2], "path")) {
+                               lookup_path(iw, argv[3]);
+                               return 0;
+                       }
                        switch (argv[2][0])
                        {
                        case 'p':
index eea521e445bd1179e81fac64a95d4884253eaa0b..be90824832d8068d0043d6e0be40f16ed6d928a8 100644 (file)
@@ -233,6 +233,66 @@ static struct nl80211_msg_conveyor * nl80211_ctl(int cmd, int flags)
        return nl80211_new(nls->nlctrl, cmd, flags);
 }
 
+static const char *nl80211_phy_path_str(const char *phyname)
+{
+       static char path[PATH_MAX];
+       const char *prefix = "/sys/devices/";
+       int prefix_len = strlen(prefix);
+       int buf_len, offset;
+       struct dirent *e;
+       char buf[128], *link;
+       int phy_id;
+       int seq = 0;
+       DIR *d;
+
+       if (strncmp(phyname, "phy", 3) != 0)
+               return NULL;
+
+       phy_id = atoi(phyname + 3);
+       buf_len = snprintf(buf, sizeof(buf), "/sys/class/ieee80211/%s/device", phyname);
+       link = realpath(buf, path);
+       if (!link)
+               return NULL;
+
+       if (strncmp(link, prefix, prefix_len) != 0)
+               return NULL;
+
+       link += prefix_len;
+
+       prefix = "platform/";
+       prefix_len = strlen(prefix);
+       if (!strncmp(link, prefix, prefix_len) && strstr(link, "/pci"))
+               link += prefix_len;
+
+       snprintf(buf + buf_len, sizeof(buf) - buf_len, "/ieee80211");
+       d = opendir(buf);
+       if (!d)
+               return link;
+
+       while ((e = readdir(d)) != NULL) {
+               int cur_id;
+
+               if (strncmp(e->d_name, "phy", 3) != 0)
+                       continue;
+
+               cur_id = atoi(e->d_name + 3);
+               if (cur_id >= phy_id)
+                       continue;
+
+               seq++;
+       }
+
+       closedir(d);
+
+       if (!seq)
+               return link;
+
+       offset = link - path + strlen(link);
+       snprintf(path + offset, sizeof(path) - offset, "+%d", seq);
+
+       return link;
+}
+
 static int nl80211_phy_idx_from_uci_path(struct uci_section *s)
 {
        size_t linklen, pathlen;
@@ -3429,6 +3489,21 @@ static int nl80211_lookup_phyname(const char *section, char *buf)
        return 0;
 }
 
+static int nl80211_phy_path(const char *phyname, const char **path)
+{
+       if (strncmp(phyname, "phy", 3) != 0)
+               return -1;
+
+       if (strchr(phyname, '/'))
+               return -1;
+
+       *path = nl80211_phy_path_str(phyname);
+       if (!*path)
+               return -1;
+
+       return 0;
+}
+
 const struct iwinfo_ops nl80211_ops = {
        .name             = "nl80211",
        .probe            = nl80211_probe,
@@ -3463,5 +3538,6 @@ const struct iwinfo_ops nl80211_ops = {
        .countrylist      = nl80211_get_countrylist,
        .survey           = nl80211_get_survey,
        .lookup_phy       = nl80211_lookup_phyname,
+       .phy_path         = nl80211_phy_path,
        .close            = nl80211_close
 };