*/
#include <limits.h>
+#include <glob.h>
+#include <fnmatch.h>
#include "iwinfo_nl80211.h"
#define min(x, y) ((x) < (y)) ? (x) : (y)
return rv;
}
+static int nl80211_readstr(const char *path, char *buffer, int length)
+{
+ int fd;
+ int rv = -1;
+
+ if ((fd = open(path, O_RDONLY)) > -1)
+ {
+ if ((rv = read(fd, buffer, length - 1)) > 0)
+ {
+ if (buffer[rv - 1] == '\n')
+ rv--;
+
+ buffer[rv] = 0;
+ }
+
+ close(fd);
+ }
+
+ return rv;
+}
+
static int nl80211_msg_error(struct sockaddr_nl *nla,
struct nlmsgerr *err, void *arg)
return nl80211_new(nls->nlctrl, cmd, flags);
}
+static int nl80211_phy_idx_from_uci_path(struct uci_section *s)
+{
+ const char *opt;
+ char buf[128];
+ int idx = -1;
+ glob_t gl;
+
+ opt = uci_lookup_option_string(uci_ctx, s, "path");
+ if (!opt)
+ return -1;
+
+ snprintf(buf, sizeof(buf), "/sys/devices/%s/ieee80211/*/index", opt); /**/
+ if (glob(buf, 0, NULL, &gl))
+ return -1;
+
+ if (gl.gl_pathc > 0)
+ idx = nl80211_readint(gl.gl_pathv[0]);
+
+ globfree(&gl);
+
+ return idx;
+}
+
+static int nl80211_phy_idx_from_uci_macaddr(struct uci_section *s)
+{
+ const char *opt;
+ char buf[128];
+ int i, idx = -1;
+ glob_t gl;
+
+ opt = uci_lookup_option_string(uci_ctx, s, "macaddr");
+ if (!opt)
+ return -1;
+
+ snprintf(buf, sizeof(buf), "/sys/class/ieee80211/*", opt); /**/
+ if (glob(buf, 0, NULL, &gl))
+ return -1;
+
+ for (i = 0; i < gl.gl_pathc; i++)
+ {
+ snprintf(buf, sizeof(buf), "%s/macaddress", gl.gl_pathv[i]);
+ if (nl80211_readstr(buf, buf, sizeof(buf)) <= 0)
+ continue;
+
+ if (fnmatch(opt, buf, FNM_CASEFOLD))
+ continue;
+
+ snprintf(buf, sizeof(buf), "%s/index", gl.gl_pathv[i]);
+ if ((idx = nl80211_readint(buf)) > -1)
+ break;
+ }
+
+ globfree(&gl);
+
+ return idx;
+}
+
+static int nl80211_phy_idx_from_uci_phy(struct uci_section *s)
+{
+ const char *opt;
+ char buf[128];
+
+ opt = uci_lookup_option_string(uci_ctx, s, "phy");
+ if (!opt)
+ return -1;
+
+ snprintf(buf, sizeof(buf), "/sys/class/ieee80211/%s/index", opt);
+ return nl80211_readint(buf);
+}
+
+static int nl80211_phy_idx_from_uci(const char *name)
+{
+ struct uci_section *s;
+ int idx = -1;
+
+ s = iwinfo_uci_get_radio(name, "mac80211");
+ if (!s)
+ goto free;
+
+ idx = nl80211_phy_idx_from_uci_path(s);
+
+ if (idx < 0)
+ idx = nl80211_phy_idx_from_uci_macaddr(s);
+
+ if (idx < 0)
+ idx = nl80211_phy_idx_from_uci_phy(s);
+
+free:
+ iwinfo_uci_free();
+ return idx;
+}
+
static struct nl80211_msg_conveyor * nl80211_msg(const char *ifname,
int cmd, int flags)
{
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
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;
[NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },
[NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },
};
- struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];
+ struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB+1];
static struct nla_policy iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {
[NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },
[NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },
};
- struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT];
+ struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT+1];
struct nlattr *limit;
- nla_parse_nested(tb_comb, NL80211_BAND_ATTR_MAX, comb, iface_combination_policy);
+ nla_parse_nested(tb_comb, NUM_NL80211_IFACE_COMB, comb, iface_combination_policy);
if (!tb_comb[NL80211_IFACE_COMB_LIMITS])
continue;
return 0;
}
+static int nl80211_lookup_phyname(const char *section, char *buf)
+{
+ int idx;
+
+ if ((idx = nl80211_phy_idx_from_uci(section)) < 0)
+ return -1;
+
+ sprintf(buf, "phy%d", idx);
+ return 0;
+}
+
const struct iwinfo_ops nl80211_ops = {
.name = "nl80211",
.probe = nl80211_probe,
.scanlist = nl80211_get_scanlist,
.freqlist = nl80211_get_freqlist,
.countrylist = nl80211_get_countrylist,
+ .lookup_phy = nl80211_lookup_phyname,
.close = nl80211_close
};