aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--package/iwinfo/src/iwinfo_nl80211.c66
1 files changed, 57 insertions, 9 deletions
diff --git a/package/iwinfo/src/iwinfo_nl80211.c b/package/iwinfo/src/iwinfo_nl80211.c
index dd619e2d6f..544e701b9e 100644
--- a/package/iwinfo/src/iwinfo_nl80211.c
+++ b/package/iwinfo/src/iwinfo_nl80211.c
@@ -2155,22 +2155,70 @@ int nl80211_get_hwmodelist(const char *ifname, int *buf)
return *buf ? 0 : -1;
}
-int nl80211_get_mbssid_support(const char *ifname, int *buf)
+static int nl80211_get_ifcomb_cb(struct nl_msg *msg, void *arg)
{
- /* Test whether we can create another interface */
- char *nif = nl80211_ifadd(ifname);
+ struct nlattr **attr = nl80211_parse(msg);
+ struct nlattr *comb;
+ int *ret = arg;
+ int comb_rem, limit_rem, mode_rem;
+
+ *ret = 0;
+ if (!attr[NL80211_ATTR_INTERFACE_COMBINATIONS])
+ return NL_SKIP;
- if (nif)
+ nla_for_each_nested(comb, attr[NL80211_ATTR_INTERFACE_COMBINATIONS], comb_rem)
{
- *buf = (iwinfo_ifmac(nif) && iwinfo_ifup(nif));
+ static struct nla_policy iface_combination_policy[NUM_NL80211_IFACE_COMB] = {
+ [NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },
+ [NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },
+ };
+ struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];
+ 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 *limit;
- iwinfo_ifdown(nif);
- nl80211_ifdel(nif);
+ nla_parse_nested(tb_comb, NL80211_BAND_ATTR_MAX, comb, iface_combination_policy);
- return 0;
+ if (!tb_comb[NL80211_IFACE_COMB_LIMITS])
+ continue;
+
+ nla_for_each_nested(limit, tb_comb[NL80211_IFACE_COMB_LIMITS], limit_rem)
+ {
+ struct nlattr *mode;
+
+ nla_parse_nested(tb_limit, NUM_NL80211_IFACE_LIMIT, limit, iface_limit_policy);
+
+ if (!tb_limit[NL80211_IFACE_LIMIT_TYPES] ||
+ !tb_limit[NL80211_IFACE_LIMIT_MAX])
+ continue;
+
+ if (nla_get_u32(tb_limit[NL80211_IFACE_LIMIT_MAX]) < 2)
+ continue;
+
+ nla_for_each_nested(mode, tb_limit[NL80211_IFACE_LIMIT_TYPES], mode_rem) {
+ if (nla_type(mode) == NL80211_IFTYPE_AP)
+ *ret = 1;
+ }
+ }
}
- return -1;
+ return NL_SKIP;
+}
+
+int nl80211_get_mbssid_support(const char *ifname, int *buf)
+{
+ struct nl80211_msg_conveyor *req;
+
+ req = nl80211_msg(ifname, NL80211_CMD_GET_WIPHY, 0);
+ if (!req)
+ return -1;
+
+ nl80211_send(req, nl80211_get_ifcomb_cb, buf);
+ nl80211_free(req);
+ return 0;
}
int nl80211_get_hardware_id(const char *ifname, char *buf)