chandef is parsed and updated based on user phymode [HT40+|HT40-|80MHz] config. Scan flag NL80211_SCAN_FLAG_WIDE_BAND_SCAN is set to indicate the presence of chandef in nl_msg. Added print in extended features dump. Supported extended features: * [ WIDE_BAND_SCAN ]: wide band scan (40Mhz, 80Mhz) Wide Band Scan Commands: ----------------------- dev <devname> scan freq <freq> [HT40+|HT40-|80MHz] [ap-force] dev <devname> scan trigger freq <freq> [HT40+|HT40-|80MHz] [ap-force] Examples: --------- iw wlan0 scan freq 5180 HT40+ iw wlan0 scan trigger freq 5260 80Mhz ap-force Signed-off-by: Sathishkumar Muruganandam <murugana@xxxxxxxxxxxxxx> --- info.c | 2 ++ scan.c | 53 +++++++++++++++++++++++++++++++++++++++++------------ util.c | 5 +++-- 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/info.c b/info.c index 38362d8744b7..14b397d34f79 100644 --- a/info.c +++ b/info.c @@ -686,6 +686,8 @@ broken_combination: ext_feat_print(tb, EXT_KEY_ID, "extended key ID support"); ext_feat_print(tb, STA_TX_PWR, "TX power control per station"); ext_feat_print(tb, SAE_OFFLOAD, "SAE offload support"); + ext_feat_print(tb, NL80211_EXT_FEATURE_WIDE_BAND_SCAN, + "WIDE_BAND_SCAN", "wide band scan (40Mhz, 80Mhz)"); } if (tb_msg[NL80211_ATTR_COALESCE_RULE]) { diff --git a/scan.c b/scan.c index 1418da73a624..b8a00f26b85a 100644 --- a/scan.c +++ b/scan.c @@ -378,19 +378,23 @@ static int handle_scan(struct nl80211_state *state, enum { NONE, FREQ, + MODE, + CHECK_SCAN_FLAG_AP, IES, SSID, MESHID, DURATION, DONE, } parse = NONE; - int freq; + int freq = 0; unsigned int duration = 0; bool passive = false, have_ssids = false, have_freqs = false; + bool have_chandef = false; bool duration_mandatory = false; size_t ies_len = 0, meshid_len = 0; unsigned char *ies = NULL, *meshid = NULL, *tmpies = NULL; unsigned int flags = 0; + struct chandef chandef; ssids = nlmsg_alloc(); if (!ssids) @@ -407,7 +411,6 @@ static int handle_scan(struct nl80211_state *state, case NONE: if (strcmp(argv[i], "freq") == 0) { parse = FREQ; - have_freqs = true; break; } else if (strcmp(argv[i], "ies") == 0) { parse = IES; @@ -453,14 +456,33 @@ static int handle_scan(struct nl80211_state *state, err = 1; goto nla_put_failure; case FREQ: - freq = strtoul(argv[i], &eptr, 10); - if (eptr != argv[i] + strlen(argv[i])) { - /* failed to parse as number -- maybe a tag? */ - i--; - parse = NONE; - continue; + parse_freqchan(&chandef, false, argc - i, argv + i, NULL); + if (!chandef.control_freq || have_freqs) { + freq = strtoul(argv[i], &eptr, 10); + if (eptr != argv[i] + strlen(argv[i])) { + /* failed to parse as number -- maybe a tag? */ + i--; + parse = NONE; + continue; + } + NLA_PUT_U32(freqs, i, freq); + } else { + if (chandef.width == NL80211_CHAN_WIDTH_20_NOHT) { + have_freqs = true; + NLA_PUT_U32(freqs, i, chandef.control_freq); + } else { + parse = MODE; + } } - NLA_PUT_U32(freqs, i, freq); + break; + case MODE: + have_chandef = true; + flags |= NL80211_SCAN_FLAG_WIDE_BAND_SCAN; + parse = CHECK_SCAN_FLAG_AP; + break; + case CHECK_SCAN_FLAG_AP: + if (strcmp(argv[i], "ap-force") == 0) + flags |= NL80211_SCAN_FLAG_AP; break; case IES: if (ies) @@ -508,8 +530,11 @@ static int handle_scan(struct nl80211_state *state, if (!passive) nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids); - if (have_freqs) + if (have_chandef) + put_chandef(msg, &chandef); + else if (have_freqs) nla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs); + if (flags) NLA_PUT_U32(msg, NL80211_ATTR_SCAN_FLAGS, flags); if (duration) @@ -2337,20 +2362,24 @@ static int handle_scan_combined(struct nl80211_state *state, dump_argv[0] = argv[0]; return handle_cmd(state, id, dump_argc, dump_argv); } -TOPLEVEL(scan, "[-u] [freq <freq>*] [duration <dur>] [ies <hex as 00:11:..>] [meshid <meshid>] [lowpri,flush,ap-force,duration-mandatory] [randomise[=<addr>/<mask>]] [ssid <ssid>*|passive]", 0, 0, +TOPLEVEL(scan, "[-u] [freq <freq>*] [HT40+|HT40-|80MHz] [duration <dur>] [ies <hex as 00:11:..>] [meshid <meshid>] [lowpri,flush,ap-force,duration-mandatory] [randomise[=<addr>/<mask>]] [ssid <ssid>*|passive]", 0, 0, CIB_NETDEV, handle_scan_combined, "Scan on the given frequencies and probe for the given SSIDs\n" "(or wildcard if not given) unless passive scanning is requested.\n" + "If channel mode/width is provided along with frequency, wide band\n" + "scan results on primary frequency of channel mode/width is printed.\n" "If -u is specified print unknown data in the scan results.\n" "Specified (vendor) IEs must be well-formed."); COMMAND(scan, dump, "[-u]", NL80211_CMD_GET_SCAN, NLM_F_DUMP, CIB_NETDEV, handle_scan_dump, "Dump the current scan results. If -u is specified, print unknown\n" "data in scan results."); -COMMAND(scan, trigger, "[freq <freq>*] [duration <dur>] [ies <hex as 00:11:..>] [meshid <meshid>] [lowpri,flush,ap-force,duration-mandatory] [randomise[=<addr>/<mask>]] [ssid <ssid>*|passive]", +COMMAND(scan, trigger, "[freq <freq>*] [HT40+|HT40-|80MHz] [duration <dur>] [ies <hex as 00:11:..>] [meshid <meshid>] [lowpri,flush,ap-force,duration-mandatory] [randomise[=<addr>/<mask>]] [ssid <ssid>*|passive]", NL80211_CMD_TRIGGER_SCAN, 0, CIB_NETDEV, handle_scan, "Trigger a scan on the given frequencies with probing for the given\n" "SSIDs (or wildcard if not given) unless passive scanning is requested.\n" + "If channel mode/width is provided along with frequency, wide band\n" + "scan on primary frequency of channel mode/width is requested.\n" "Duration(in TUs), if specified, will be used to set dwell times.\n"); diff --git a/util.c b/util.c index cbac5ad46b7d..82a55d116719 100644 --- a/util.c +++ b/util.c @@ -749,6 +749,9 @@ int parse_freqchan(struct chandef *chandef, bool chan, int argc, char **argv, if (!argv[0]) goto out; + + memset(chandef, 0, sizeof(struct chandef)); + freq = strtoul(argv[0], &end, 10); if (*end) { res = 1; @@ -757,8 +760,6 @@ int parse_freqchan(struct chandef *chandef, bool chan, int argc, char **argv, _parsed += 1; - memset(chandef, 0, sizeof(struct chandef)); - if (chan) { enum nl80211_band band; -- 2.7.4