+static char * nl80211_phy2ifname(const char *ifname)
+{
+ int fd, ifidx = -1, cifidx = -1, phyidx = -1;
+ char buffer[64];
+ static char nif[IFNAMSIZ] = { 0 };
+
+ DIR *d;
+ struct dirent *e;
+
+ if (!ifname)
+ return NULL;
+ else if (!strncmp(ifname, "phy", 3))
+ phyidx = atoi(&ifname[3]);
+ else if (!strncmp(ifname, "radio", 5))
+ phyidx = atoi(&ifname[5]);
+
+ memset(nif, 0, sizeof(nif));
+
+ if (phyidx > -1)
+ {
+ if ((d = opendir("/sys/class/net")) != NULL)
+ {
+ while ((e = readdir(d)) != NULL)
+ {
+ snprintf(buffer, sizeof(buffer),
+ "/sys/class/net/%s/phy80211/index", e->d_name);
+
+ if (nl80211_readint(buffer) == phyidx)
+ {
+ snprintf(buffer, sizeof(buffer),
+ "/sys/class/net/%s/ifindex", e->d_name);
+
+ if ((cifidx = nl80211_readint(buffer)) >= 0 &&
+ ((ifidx < 0) || (cifidx < ifidx)))
+ {
+ ifidx = cifidx;
+ strncpy(nif, e->d_name, sizeof(nif));
+ }
+ }
+ }
+
+ closedir(d);
+ }
+ }
+
+ return nif[0] ? nif : NULL;
+}
+
+static int nl80211_get_mode_cb(struct nl_msg *msg, void *arg)
+{
+ int *mode = arg;
+ struct nlattr **tb = nl80211_parse(msg);
+ const int ifmodes[NL80211_IFTYPE_MAX + 1] = {
+ IWINFO_OPMODE_UNKNOWN, /* unspecified */
+ IWINFO_OPMODE_ADHOC, /* IBSS */
+ IWINFO_OPMODE_CLIENT, /* managed */
+ IWINFO_OPMODE_MASTER, /* AP */
+ IWINFO_OPMODE_AP_VLAN, /* AP/VLAN */
+ IWINFO_OPMODE_WDS, /* WDS */
+ IWINFO_OPMODE_MONITOR, /* monitor */
+ IWINFO_OPMODE_MESHPOINT, /* mesh point */
+ IWINFO_OPMODE_P2P_CLIENT, /* P2P-client */
+ IWINFO_OPMODE_P2P_GO, /* P2P-GO */
+ };
+
+ if (tb[NL80211_ATTR_IFTYPE])
+ *mode = ifmodes[nla_get_u32(tb[NL80211_ATTR_IFTYPE])];
+
+ return NL_SKIP;
+}
+
+
+static int nl80211_get_mode(const char *ifname, int *buf)
+{
+ 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;
+}
+