iwinfo: when using nl80211, parse interface combinations instead of creating/deleting...
authorFelix Fietkau <nbd@openwrt.org>
Sat, 14 Sep 2013 14:46:51 +0000 (14:46 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Sat, 14 Sep 2013 14:46:51 +0000 (14:46 +0000)
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
SVN-Revision: 37983

package/network/utils/iwinfo/src/iwinfo_nl80211.c

index 9486ffc3f9aceee96949f99e5cf1fbc663d7dd5c..a258d2f2b208e722f4503e1bb479e55873d9ad1d 100644 (file)
@@ -2212,22 +2212,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)