* Parts of this code are derived from the Linux iw utility.
*/
+#include <sys/stat.h>
#include <limits.h>
#include <glob.h>
#include <fnmatch.h>
return rv;
}
+static int nl80211_get_band(int nla_type)
+{
+ switch (nla_type)
+ {
+ case NL80211_BAND_2GHZ:
+ return IWINFO_BAND_24;
+ case NL80211_BAND_5GHZ:
+ return IWINFO_BAND_5;
+ case NL80211_BAND_6GHZ:
+ return IWINFO_BAND_6;
+ case NL80211_BAND_60GHZ:
+ return IWINFO_BAND_60;
+ }
+
+ return 0;
+}
+
static int nl80211_msg_error(struct sockaddr_nl *nla,
struct nlmsgerr *err, void *arg)
return idx;
}
+static bool nl80211_is_ifname(const char *name)
+{
+ struct stat st;
+ char buffer[PATH_MAX];
+
+ snprintf(buffer, sizeof(buffer), "/sys/class/net/%s", name);
+ return !lstat(buffer, &st);
+}
+
static struct nl80211_msg_conveyor * nl80211_msg(const char *ifname,
int cmd, int flags)
{
if (!strncmp(ifname, "mon.", 4))
ifidx = if_nametoindex(&ifname[4]);
- else
+ else if (nl80211_is_ifname(ifname))
ifidx = if_nametoindex(ifname);
-
- if (!ifidx) {
+ else
+ {
phyidx = nl80211_phy_idx_from_phy(ifname);
if (phyidx < 0)
phyidx = nl80211_phy_idx_from_uci(ifname);
#define nl80211_wait(family, group, ...) \
__nl80211_wait(family, group, __VA_ARGS__, 0)
-
+/* This is linux's ieee80211_freq_khz_to_channel() which is:
+ * SPDX-License-Identifier: GPL-2.0
+ * Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2013-2014 Intel Mobile Communications GmbH
+ * Copyright 2017 Intel Deutschland GmbH
+ * Copyright (C) 2018-2022 Intel Corporation
+ */
static int nl80211_freq2channel(int freq)
{
if (freq == 2484)
return (freq - 2407) / 5;
else if (freq >= 4910 && freq <= 4980)
return (freq - 4000) / 5;
- else if(freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 6)
+ else if (freq < 5925)
+ return (freq - 5000) / 5;
+ else if (freq == 5935)
+ return 2;
+ else if (freq <= 45000) /* DMG band lower limit */
+ /* see 802.11ax D6.1 27.3.22.2 */
+ return (freq - 5950) / 5;
+ else if (freq >= 58320 && freq <= 70200)
return (freq - 56160) / 2160;
else
- return (freq - 5000) / 5;
+ return 0;
}
-static int nl80211_channel2freq(int channel, const char *band)
+/* This is linux's ieee80211_channel_to_freq_khz() which is:
+ * SPDX-License-Identifier: GPL-2.0
+ * Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2013-2014 Intel Mobile Communications GmbH
+ * Copyright 2017 Intel Deutschland GmbH
+ * Copyright (C) 2018-2022 Intel Corporation
+ */
+static int nl80211_channel2freq(int channel, const char *band, bool ax)
{
+ if (channel < 1)
+ return 0;
+
if (!band || band[0] != 'a')
{
if (channel == 14)
else if (channel < 14)
return (channel * 5) + 2407;
}
- else if ( strcmp(band, "ad") == 0)
+ else if (strcmp(band, "ad") == 0)
{
- return 56160 + 2160 * channel;
+ if (channel < 7)
+ return 56160 + 2160 * channel;
+ }
+ else if (ax)
+ {
+ if (channel == 2)
+ return 5935;
+ if (channel < 233)
+ return (channel * 5) + 5950;
}
else
{
static int nl80211_get_frequency(const char *ifname, int *buf)
{
- char *res, channel[4], hwmode[3];
+ char *res, channel[4] = { 0 }, hwmode[3] = { 0 }, ax[2] = { 0 };
/* try to find frequency from interface info */
res = nl80211_phy2ifname(ifname);
/* failed, try to find frequency from hostapd info */
if ((*buf == 0) &&
nl80211_hostapd_query(ifname, "hw_mode", hwmode, sizeof(hwmode),
- "channel", channel, sizeof(channel)) == 2)
+ "channel", channel, sizeof(channel),
+ "ieee80211ax", ax, sizeof(ax)) >= 2)
{
- *buf = nl80211_channel2freq(atoi(channel), hwmode);
+ *buf = nl80211_channel2freq(atoi(channel), hwmode, ax[0] == '1');
}
/* failed, try to find frequency from scan results */
static int nl80211_get_modelist_cb(struct nl_msg *msg, void *arg)
{
struct nl80211_modes *m = arg;
- int bands_remain, freqs_remain;
+ int bands_remain;
struct nlattr **attr = nl80211_parse(msg);
struct nlattr *bands[NL80211_BAND_ATTR_MAX + 1];
- struct nlattr *freqs[NL80211_FREQUENCY_ATTR_MAX + 1];
- struct nlattr *band, *freq;
- uint32_t freq_mhz;
+ struct nlattr *band;
if (attr[NL80211_ATTR_WIPHY_BANDS])
{
nla_for_each_nested(band, attr[NL80211_ATTR_WIPHY_BANDS], bands_remain)
{
+ m->bands |= nl80211_get_band(band->nla_type);
+
nla_parse(bands, NL80211_BAND_ATTR_MAX,
nla_data(band), nla_len(band), NULL);
}
}
}
-
- if (bands[NL80211_BAND_ATTR_FREQS]) {
- nla_for_each_nested(freq, bands[NL80211_BAND_ATTR_FREQS],
- freqs_remain)
- {
- nla_parse(freqs, NL80211_FREQUENCY_ATTR_MAX,
- nla_data(freq), nla_len(freq), NULL);
-
- if (!freqs[NL80211_FREQUENCY_ATTR_FREQ])
- continue;
-
- freq_mhz = nla_get_u32(freqs[NL80211_FREQUENCY_ATTR_FREQ]);
-
- if (freq_mhz > 2400 && freq_mhz < 2485)
- {
- m->bands |= IWINFO_BAND_24;
- }
- else if (freq_mhz > 5000 && freq_mhz < 5850)
- {
- m->bands |= IWINFO_BAND_5;
- }
- else if (freq_mhz > 6000 && freq_mhz < 7120)
- {
- m->bands |= IWINFO_BAND_6;
- }
- else if (freq_mhz >= 56160)
- {
- m->bands |= IWINFO_BAND_60;
- }
- }
- }
}
m->ok = 1;