+ char *res;
+ struct nl80211_msg_conveyor *req;
+
+ res = nl80211_phy2ifname(ifname);
+ req = nl80211_msg(res ? res : ifname, NL80211_CMD_GET_INTERFACE, 0);
+ *buf = IWINFO_OPMODE_UNKNOWN;
+
+ if (req)
+ {
+ nl80211_send(req, nl80211_get_mode_cb, buf);
+ nl80211_free(req);
+ }
+
+ return (*buf == IWINFO_OPMODE_UNKNOWN) ? -1 : 0;
+}
+
+
+struct nl80211_ssid_bssid {
+ unsigned char *ssid;
+ unsigned char bssid[7];
+};
+
+static int nl80211_get_ssid_bssid_cb(struct nl_msg *msg, void *arg)
+{
+ int ielen;
+ unsigned char *ie;
+ struct nl80211_ssid_bssid *sb = arg;
+ struct nlattr **tb = nl80211_parse(msg);
+ struct nlattr *bss[NL80211_BSS_MAX + 1];
+
+ static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
+ [NL80211_BSS_INFORMATION_ELEMENTS] = { },
+ [NL80211_BSS_STATUS] = { .type = NLA_U32 },
+ };
+
+ if (!tb[NL80211_ATTR_BSS] ||
+ nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],
+ bss_policy) ||
+ !bss[NL80211_BSS_BSSID] ||
+ !bss[NL80211_BSS_STATUS] ||
+ !bss[NL80211_BSS_INFORMATION_ELEMENTS])
+ {
+ return NL_SKIP;
+ }
+
+ switch (nla_get_u32(bss[NL80211_BSS_STATUS]))
+ {
+ case NL80211_BSS_STATUS_ASSOCIATED:
+ case NL80211_BSS_STATUS_AUTHENTICATED:
+ case NL80211_BSS_STATUS_IBSS_JOINED:
+
+ if (sb->ssid)
+ {
+ ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
+ ielen = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
+
+ while (ielen >= 2 && ielen >= ie[1])
+ {
+ if (ie[0] == 0)
+ {
+ memcpy(sb->ssid, ie + 2, min(ie[1], IWINFO_ESSID_MAX_SIZE));
+ return NL_SKIP;
+ }
+
+ ielen -= ie[1] + 2;
+ ie += ie[1] + 2;
+ }
+ }
+ else
+ {
+ sb->bssid[0] = 1;
+ memcpy(sb->bssid + 1, nla_data(bss[NL80211_BSS_BSSID]), 6);
+ return NL_SKIP;
+ }
+
+ default:
+ return NL_SKIP;
+ }