#define min(x, y) ((x) < (y)) ? (x) : (y)
+#define BIT(x) (1ULL<<(x))
+
static struct nl80211_state *nls = NULL;
static void nl80211_close(void)
return &cv;
err:
-nla_put_failure:
- if (cb)
- nl_cb_put(cb);
-
if (req)
nlmsg_free(req);
snprintf(buf, sizeof(buf), "/sys/devices/%s/ieee80211/*/index", opt); /**/
if (glob(buf, 0, NULL, &gl))
+ snprintf(buf, sizeof(buf), "/sys/devices/platform/%s/ieee80211/*/index", opt); /**/
+
+ if (glob(buf, 0, NULL, &gl))
return -1;
if (gl.gl_pathc > 0)
if (!opt)
return -1;
- snprintf(buf, sizeof(buf), "/sys/class/ieee80211/*", opt); /**/
+ snprintf(buf, sizeof(buf), "/sys/class/ieee80211/*"); /**/
if (glob(buf, 0, NULL, &gl))
return -1;
static char * nl80211_phy2ifname(const char *ifname)
{
- int fd, ifidx = -1, cifidx = -1, phyidx = -1;
+ int ifidx = -1, cifidx = -1, phyidx = -1;
char buffer[64];
static char nif[IFNAMSIZ] = { 0 };
((ifidx < 0) || (cifidx < ifidx)))
{
ifidx = cifidx;
- strncpy(nif, e->d_name, sizeof(nif));
+ strncpy(nif, e->d_name, sizeof(nif) - 1);
}
}
}
static char * nl80211_ifadd(const char *ifname)
{
- int phyidx;
char *rv = NULL, path[PATH_MAX];
static char nif[IFNAMSIZ] = { 0 };
- struct nl80211_msg_conveyor *req, *res;
+ struct nl80211_msg_conveyor *req;
FILE *sysfs;
req = nl80211_msg(ifname, NL80211_CMD_NEW_INTERFACE, 0);
if (phy)
{
snprintf(buf, sizeof(buf), "/var/run/wifi-%s.pid", phy);
- if ((fd = open(buf, O_RDONLY)) > 0)
+ if ((fd = open(buf, O_RDONLY)) >= 0)
{
if (read(fd, buf, sizeof(buf)) > 0)
pid = atoi(buf);
struct nlattr *bss[NL80211_BSS_MAX + 1];
static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
- [NL80211_BSS_INFORMATION_ELEMENTS] = { },
+ [NL80211_BSS_INFORMATION_ELEMENTS] = { 0 },
[NL80211_BSS_STATUS] = { .type = NLA_U32 },
};
res = nl80211_phy2ifname(ifname);
req = nl80211_msg(res ? res : ifname, NL80211_CMD_GET_SCAN, NLM_F_DUMP);
- sb.ssid = buf;
+ sb.ssid = (unsigned char *)buf;
*buf = 0;
if (req)
return -1;
}
+static int nl80211_get_txpower_cb(struct nl_msg *msg, void *arg)
+{
+ int *buf = arg;
+ struct nlattr **tb = nl80211_parse(msg);
+
+ if (tb[NL80211_ATTR_WIPHY_TX_POWER_LEVEL])
+ *buf = iwinfo_mbm2dbm(nla_get_u32(tb[NL80211_ATTR_WIPHY_TX_POWER_LEVEL]));
+
+ return NL_SKIP;
+}
static int nl80211_get_txpower(const char *ifname, int *buf)
{
-#if 0
char *res;
- char path[PATH_MAX];
+ struct nl80211_msg_conveyor *req;
- res = nl80211_ifname2phy(ifname);
- snprintf(path, sizeof(path), "/sys/kernel/debug/ieee80211/%s/power",
- res ? res : ifname);
+ res = nl80211_phy2ifname(ifname);
+ req = nl80211_msg(res ? res : ifname, NL80211_CMD_GET_INTERFACE, 0);
- if ((*buf = nl80211_readint(path)) > -1)
- return 0;
-#endif
+ if (req)
+ {
+ *buf = 0;
+ nl80211_send(req, nl80211_get_txpower_cb, buf);
+ nl80211_free(req);
+ if (*buf)
+ return 0;
+ }
- return wext_ops.txpower(ifname, buf);
+ return -1;
}
}
+static void nl80211_parse_rateinfo(struct nlattr **ri,
+ struct iwinfo_rate_entry *re)
+{
+ if (ri[NL80211_RATE_INFO_BITRATE32])
+ re->rate = nla_get_u32(ri[NL80211_RATE_INFO_BITRATE32]) * 100;
+ else if (ri[NL80211_RATE_INFO_BITRATE])
+ re->rate = nla_get_u16(ri[NL80211_RATE_INFO_BITRATE]) * 100;
+
+ if (ri[NL80211_RATE_INFO_VHT_MCS])
+ {
+ re->is_vht = 1;
+ re->mcs = nla_get_u8(ri[NL80211_RATE_INFO_VHT_MCS]);
+
+ if (ri[NL80211_RATE_INFO_VHT_NSS])
+ re->nss = nla_get_u8(ri[NL80211_RATE_INFO_VHT_NSS]);
+ }
+ else if (ri[NL80211_RATE_INFO_MCS])
+ {
+ re->is_ht = 1;
+ re->mcs = nla_get_u8(ri[NL80211_RATE_INFO_MCS]);
+ }
+
+ if (ri[NL80211_RATE_INFO_5_MHZ_WIDTH])
+ re->mhz = 5;
+ else if (ri[NL80211_RATE_INFO_10_MHZ_WIDTH])
+ re->mhz = 10;
+ else if (ri[NL80211_RATE_INFO_40_MHZ_WIDTH])
+ re->mhz = 40;
+ else if (ri[NL80211_RATE_INFO_80_MHZ_WIDTH])
+ re->mhz = 80;
+ else if (ri[NL80211_RATE_INFO_80P80_MHZ_WIDTH] ||
+ ri[NL80211_RATE_INFO_160_MHZ_WIDTH])
+ re->mhz = 160;
+ else
+ re->mhz = 20;
+
+ if (ri[NL80211_RATE_INFO_SHORT_GI])
+ re->is_short_gi = 1;
+
+ re->is_40mhz = (re->mhz == 40);
+}
+
static int nl80211_get_assoclist_cb(struct nl_msg *msg, void *arg)
{
struct nl80211_array_buf *arr = arg;
struct nlattr **attr = nl80211_parse(msg);
struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
+ struct nl80211_sta_flag_update *sta_flags;
static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
[NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
[NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
[NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
[NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
+ [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_TX_RETRIES] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_T_OFFSET] = { .type = NLA_U64 },
+ [NL80211_STA_INFO_STA_FLAGS] =
+ { .minlen = sizeof(struct nl80211_sta_flag_update) },
};
static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
if (sinfo[NL80211_STA_INFO_RX_BITRATE] &&
!nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy))
- {
- if (rinfo[NL80211_RATE_INFO_BITRATE])
- e->rx_rate.rate =
- nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]) * 100;
-
- if (rinfo[NL80211_RATE_INFO_MCS])
- e->rx_rate.mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
-
- if (rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
- e->rx_rate.is_40mhz = 1;
-
- if (rinfo[NL80211_RATE_INFO_SHORT_GI])
- e->rx_rate.is_short_gi = 1;
- }
+ nl80211_parse_rateinfo(rinfo, &e->rx_rate);
if (sinfo[NL80211_STA_INFO_TX_BITRATE] &&
!nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy))
+ nl80211_parse_rateinfo(rinfo, &e->tx_rate);
+
+ if (sinfo[NL80211_STA_INFO_RX_BYTES])
+ e->rx_bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
+
+ if (sinfo[NL80211_STA_INFO_TX_BYTES])
+ e->tx_bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
+
+ if (sinfo[NL80211_STA_INFO_TX_RETRIES])
+ e->tx_retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
+
+ if (sinfo[NL80211_STA_INFO_TX_FAILED])
+ e->tx_failed = nla_get_u32(sinfo[NL80211_STA_INFO_TX_FAILED]);
+
+ if (sinfo[NL80211_STA_INFO_T_OFFSET])
+ e->t_offset = nla_get_u64(sinfo[NL80211_STA_INFO_T_OFFSET]);
+
+ /* Station flags */
+ if (sinfo[NL80211_STA_INFO_STA_FLAGS])
{
- if (rinfo[NL80211_RATE_INFO_BITRATE])
- e->tx_rate.rate =
- nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]) * 100;
+ sta_flags = (struct nl80211_sta_flag_update *)
+ nla_data(sinfo[NL80211_STA_INFO_STA_FLAGS]);
+
+ if (sta_flags->mask & BIT(NL80211_STA_FLAG_AUTHORIZED) &&
+ sta_flags->set & BIT(NL80211_STA_FLAG_AUTHORIZED))
+ e->is_authorized = 1;
+
+ if (sta_flags->mask & BIT(NL80211_STA_FLAG_AUTHENTICATED) &&
+ sta_flags->set & BIT(NL80211_STA_FLAG_AUTHENTICATED))
+ e->is_authenticated = 1;
- if (rinfo[NL80211_RATE_INFO_MCS])
- e->tx_rate.mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
+ if (sta_flags->mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) &&
+ sta_flags->set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE))
+ e->is_preamble_short = 1;
- if (rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
- e->tx_rate.is_40mhz = 1;
+ if (sta_flags->mask & BIT(NL80211_STA_FLAG_WME) &&
+ sta_flags->set & BIT(NL80211_STA_FLAG_WME))
+ e->is_wme = 1;
- if (rinfo[NL80211_RATE_INFO_SHORT_GI])
- e->tx_rate.is_short_gi = 1;
+ if (sta_flags->mask & BIT(NL80211_STA_FLAG_MFP) &&
+ sta_flags->set & BIT(NL80211_STA_FLAG_MFP))
+ e->is_mfp = 1;
+
+ if (sta_flags->mask & BIT(NL80211_STA_FLAG_TDLS_PEER) &&
+ sta_flags->set & BIT(NL80211_STA_FLAG_TDLS_PEER))
+ e->is_tdls = 1;
}
}
static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
[NL80211_BSS_TSF] = { .type = NLA_U64 },
[NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
- [NL80211_BSS_BSSID] = { },
+ [NL80211_BSS_BSSID] = { 0 },
[NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
[NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
- [NL80211_BSS_INFORMATION_ELEMENTS] = { },
+ [NL80211_BSS_INFORMATION_ELEMENTS] = { 0 },
[NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
[NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
[NL80211_BSS_STATUS] = { .type = NLA_U32 },
[NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 },
- [NL80211_BSS_BEACON_IES] = { },
+ [NL80211_BSS_BEACON_IES] = { 0 },
};
if (!tb[NL80211_ATTR_BSS] ||
break;
case 'e':
- out[len++] = '\e'; in++;
+ out[len++] = '\033'; in++;
break;
case 'x':
struct nlattr *freqs[NL80211_FREQUENCY_ATTR_MAX + 1];
struct nlattr *band, *freq;
- static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
- [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 },
- [NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG },
- [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG },
- [NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG },
- [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },
- [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 },
- };
-
nla_for_each_nested(band, attr[NL80211_ATTR_WIPHY_BANDS], bands_remain)
{
nla_parse(bands, NL80211_BAND_ATTR_MAX,
static int nl80211_get_countrylist(const char *ifname, char *buf, int *len)
{
- int i, count;
+ int count;
struct iwinfo_country_entry *e = (struct iwinfo_country_entry *)buf;
const struct iwinfo_iso3166_label *l;
e->iso3166 = l->iso3166;
e->ccode[0] = (l->iso3166 / 256);
e->ccode[1] = (l->iso3166 % 256);
+ e->ccode[2] = 0;
}
*len = (count * sizeof(struct iwinfo_country_entry));
static int nl80211_get_hwmodelist(const char *ifname, int *buf)
{
struct nl80211_msg_conveyor *req;
- struct nl80211_modes m = { };
+ struct nl80211_modes m = { 0 };
req = nl80211_msg(ifname, NL80211_CMD_GET_WIPHY, 0);
if (req)
static int nl80211_get_htmodelist(const char *ifname, int *buf)
{
struct nl80211_msg_conveyor *req;
- struct nl80211_modes m = { };
+ struct nl80211_modes m = { 0 };
req = nl80211_msg(ifname, NL80211_CMD_GET_WIPHY, 0);
if (req)
static int nl80211_get_hardware_id(const char *ifname, char *buf)
{
- int rv;
+ int rv = -1;
char *res;
/* Got a radioX pseudo interface, find some interface on it or create one */