forked from osmocom/wireshark
dumpcap: Add support for 802.11ac monitor modes
Add dumpcap support for configuring 80MHz, 80+80MHz, 160MHz monitor modes via nl80211. Change-Id: I2ae8955670c2a9b5051e2223d45ce522459f2c5f Reviewed-on: https://code.wireshark.org/review/13964 Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com> Petri-Dish: Gerald Combs <gerald@wireshark.org> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Michael Mann <mmann78@netscape.net>
This commit is contained in:
parent
7a1f75ed2f
commit
9f27e5d7d1
|
@ -174,6 +174,13 @@ if (NL_FOUND)
|
|||
}"
|
||||
HAVE_NL80211_SPLIT_WIPHY_DUMP
|
||||
)
|
||||
check_c_source_compiles(
|
||||
"#include <linux/nl80211.h>
|
||||
int main() {
|
||||
enum nl80211_attrs x = NL80211_ATTR_VHT_CAPABILITY;
|
||||
}"
|
||||
HAVE_NL80211_VHT_CAPABILITY
|
||||
)
|
||||
endif()
|
||||
|
||||
#
|
||||
|
|
|
@ -1297,6 +1297,7 @@ sync_pipe_run_command(char** argv, gchar **data, gchar **primary_msg,
|
|||
|
||||
int
|
||||
sync_interface_set_80211_chan(const gchar *iface, const char *freq, const gchar *type,
|
||||
const gchar *center_freq1, const gchar *center_freq2,
|
||||
gchar **data, gchar **primary_msg,
|
||||
gchar **secondary_msg, void (*update_cb)(void))
|
||||
{
|
||||
|
@ -1317,7 +1318,7 @@ sync_interface_set_80211_chan(const gchar *iface, const char *freq, const gchar
|
|||
argv = sync_pipe_add_arg(argv, &argc, iface);
|
||||
|
||||
if (type)
|
||||
opt = g_strdup_printf("%s,%s", freq, type);
|
||||
opt = g_strdup_printf("%s,%s,%s,%s", freq, type, center_freq1, center_freq2);
|
||||
else
|
||||
opt = g_strdup_printf("%s", freq);
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@ sync_pipe_kill(ws_process_id fork_child);
|
|||
/** Set wireless channel using dumpcap */
|
||||
extern int
|
||||
sync_interface_set_80211_chan(const gchar *iface, const char *freq, const gchar *type,
|
||||
const gchar *center_freq1, const gchar *center_freq2,
|
||||
gchar **data, gchar **primary_msg,
|
||||
gchar **secondary_msg, void (*update_cb)(void));
|
||||
|
||||
|
|
|
@ -266,6 +266,25 @@ static void parse_band_ht_capa(struct ws80211_interface *iface,
|
|||
}
|
||||
#endif /* NL80211_BAND_ATTR_HT_CAPA */
|
||||
|
||||
#ifdef HAVE_NL80211_VHT_CAPABILITY
|
||||
static void parse_band_vht_capa(struct ws80211_interface *iface,
|
||||
struct nlattr *tb)
|
||||
{
|
||||
guint32 chan_capa;
|
||||
if (!tb) return;
|
||||
|
||||
chan_capa = (nla_get_u32(tb) >> 2) & 3;
|
||||
if (chan_capa == 1) {
|
||||
iface->channel_types |= 1 << WS80211_CHAN_VHT160;
|
||||
}
|
||||
if (chan_capa == 2) {
|
||||
iface->channel_types |= 1 << WS80211_CHAN_VHT160;
|
||||
iface->channel_types |= 1 << WS80211_CHAN_VHT80P80;
|
||||
}
|
||||
iface->channel_types |= 1 << WS80211_CHAN_VHT80;
|
||||
}
|
||||
#endif /* HAVE_NL80211_VHT_CAPABILITY */
|
||||
|
||||
static void parse_supported_iftypes(struct ws80211_interface *iface,
|
||||
struct nlattr *tb)
|
||||
{
|
||||
|
@ -333,6 +352,9 @@ static void parse_wiphy_bands(struct ws80211_interface *iface,
|
|||
#ifdef NL80211_BAND_ATTR_HT_CAPA
|
||||
parse_band_ht_capa(iface, tb_band[NL80211_BAND_ATTR_HT_CAPA]);
|
||||
#endif /* NL80211_BAND_ATTR_HT_CAPA */
|
||||
#ifdef HAVE_NL80211_VHT_CAPABILITY
|
||||
parse_band_vht_capa(iface, tb_band[NL80211_BAND_ATTR_VHT_CAPA]);
|
||||
#endif /* HAVE_NL80211_VHT_CAPABILITY */
|
||||
parse_band_freqs(iface, tb_band[NL80211_BAND_ATTR_FREQS]);
|
||||
}
|
||||
}
|
||||
|
@ -489,10 +511,36 @@ static int get_iface_info_handler(struct nl_msg *msg, void *arg)
|
|||
}
|
||||
|
||||
if (tb_msg[NL80211_ATTR_WIPHY_FREQ]) {
|
||||
gboolean found_ch_width = FALSE;
|
||||
iface_info->pub->current_freq = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_FREQ]);
|
||||
iface_info->pub->current_chan_type = WS80211_CHAN_NO_HT;
|
||||
|
||||
if (tb_msg[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
|
||||
#ifdef HAVE_NL80211_VHT_CAPABILITY
|
||||
if (tb_msg[NL80211_ATTR_CHANNEL_WIDTH]) {
|
||||
switch (nla_get_u32(tb_msg[NL80211_ATTR_CHANNEL_WIDTH])) {
|
||||
case NL80211_CHAN_WIDTH_80:
|
||||
iface_info->pub->current_chan_type = WS80211_CHAN_VHT80;
|
||||
found_ch_width = TRUE;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_80P80:
|
||||
iface_info->pub->current_chan_type = WS80211_CHAN_VHT80P80;
|
||||
found_ch_width = TRUE;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_160:
|
||||
iface_info->pub->current_chan_type = WS80211_CHAN_VHT160;
|
||||
found_ch_width = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tb_msg[NL80211_ATTR_CENTER_FREQ1]) {
|
||||
iface_info->pub->current_center_freq1 =
|
||||
nla_get_u32(tb_msg[NL80211_ATTR_CENTER_FREQ1]);
|
||||
}
|
||||
if (tb_msg[NL80211_ATTR_CENTER_FREQ2]) {
|
||||
iface_info->pub->current_center_freq2 =
|
||||
nla_get_u32(tb_msg[NL80211_ATTR_CENTER_FREQ2]);
|
||||
}
|
||||
#endif
|
||||
if (!found_ch_width && tb_msg[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
|
||||
switch (nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_CHANNEL_TYPE])) {
|
||||
|
||||
case NL80211_CHAN_NO_HT:
|
||||
|
@ -598,7 +646,7 @@ static int ws80211_populate_devices(GArray *interfaces)
|
|||
int i;
|
||||
unsigned int j;
|
||||
|
||||
struct ws80211_iface_info pub = {-1, WS80211_CHAN_NO_HT, WS80211_FCS_ALL};
|
||||
struct ws80211_iface_info pub = {-1, WS80211_CHAN_NO_HT, -1, -1, WS80211_FCS_ALL};
|
||||
struct __iface_info iface_info;
|
||||
struct ws80211_interface *iface;
|
||||
|
||||
|
@ -722,7 +770,7 @@ nla_put_failure:
|
|||
}
|
||||
DIAG_ON(shorten-64-to-32)
|
||||
|
||||
int ws80211_set_freq(const char *name, int freq, int chan_type)
|
||||
int ws80211_set_freq(const char *name, int freq, int chan_type, int _U_ center_freq, int _U_ center_freq2)
|
||||
{
|
||||
int devidx, err;
|
||||
struct nl_msg *msg;
|
||||
|
@ -772,7 +820,23 @@ int ws80211_set_freq(const char *name, int freq, int chan_type)
|
|||
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, NL80211_CHAN_HT40PLUS);
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_NL80211_VHT_CAPABILITY
|
||||
case WS80211_CHAN_VHT80:
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH, NL80211_CHAN_WIDTH_80);
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ1, center_freq);
|
||||
break;
|
||||
|
||||
case WS80211_CHAN_VHT80P80:
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH, NL80211_CHAN_WIDTH_80P80);
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ1, center_freq);
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ2, center_freq2);
|
||||
break;
|
||||
|
||||
case WS80211_CHAN_VHT160:
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH, NL80211_CHAN_WIDTH_160);
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ1, center_freq);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -820,6 +884,13 @@ ws80211_str_to_chan_type(const gchar *s)
|
|||
ret = WS80211_CHAN_HT40MINUS;
|
||||
if (!strcmp(s, CHAN_HT40PLUS))
|
||||
ret = WS80211_CHAN_HT40PLUS;
|
||||
if (!strcmp(s, CHAN_VHT80))
|
||||
ret = WS80211_CHAN_VHT80;
|
||||
if (!strcmp(s, CHAN_VHT80P80))
|
||||
ret = WS80211_CHAN_VHT80P80;
|
||||
if (!strcmp(s, CHAN_VHT160))
|
||||
ret = WS80211_CHAN_VHT160;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -835,6 +906,12 @@ const gchar
|
|||
return CHAN_HT40MINUS;
|
||||
case WS80211_CHAN_HT40PLUS:
|
||||
return CHAN_HT40PLUS;
|
||||
case WS80211_CHAN_VHT80:
|
||||
return CHAN_VHT80;
|
||||
case WS80211_CHAN_VHT80P80:
|
||||
return CHAN_VHT80P80;
|
||||
case WS80211_CHAN_VHT160:
|
||||
return CHAN_VHT160;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -987,7 +1064,7 @@ int ws80211_get_iface_info(const char *name, struct ws80211_iface_info *iface_in
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ws80211_set_freq(const char *name, int freq, int chan_type)
|
||||
int ws80211_set_freq(const char *name, int freq, int chan_type, int _U_ center_freq, int _U_ center_freq2)
|
||||
{
|
||||
GList *airpcap_if_list;
|
||||
int err;
|
||||
|
@ -1145,7 +1222,7 @@ int ws80211_get_iface_info(const char *name _U_, struct ws80211_iface_info *ifac
|
|||
return -1;
|
||||
}
|
||||
|
||||
int ws80211_set_freq(const char *name _U_, int freq _U_, int _U_ chan_type)
|
||||
int ws80211_set_freq(const char *name _U_, int freq _U_, int _U_ chan_type, int _U_ center_freq, int _U_ center_freq2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -31,13 +31,19 @@ enum ws80211_channel_type {
|
|||
WS80211_CHAN_NO_HT,
|
||||
WS80211_CHAN_HT20,
|
||||
WS80211_CHAN_HT40MINUS,
|
||||
WS80211_CHAN_HT40PLUS
|
||||
WS80211_CHAN_HT40PLUS,
|
||||
WS80211_CHAN_VHT80,
|
||||
WS80211_CHAN_VHT80P80,
|
||||
WS80211_CHAN_VHT160
|
||||
};
|
||||
|
||||
#define CHAN_NO_HT "NOHT"
|
||||
#define CHAN_HT20 "HT20"
|
||||
#define CHAN_HT40MINUS "HT40-"
|
||||
#define CHAN_HT40PLUS "HT40+"
|
||||
#define CHAN_VHT80 "VHT80"
|
||||
#define CHAN_VHT80P80 "VHT80+80"
|
||||
#define CHAN_VHT160 "VHT160"
|
||||
|
||||
/* XXX This doesn't match AirpcapValidationType. Should it? */
|
||||
enum ws80211_fcs_validation {
|
||||
|
@ -59,6 +65,8 @@ struct ws80211_interface
|
|||
struct ws80211_iface_info {
|
||||
int current_freq;
|
||||
enum ws80211_channel_type current_chan_type;
|
||||
int current_center_freq1;
|
||||
int current_center_freq2;
|
||||
enum ws80211_fcs_validation current_fcs_validation;
|
||||
};
|
||||
|
||||
|
@ -92,9 +100,11 @@ void ws80211_free_interfaces(GArray *interfaces);
|
|||
* @param name The interface name.
|
||||
* @param freq The frequency in MHz.
|
||||
* @param chan_type The HT channel type (no, 20Mhz, 40Mhz...).
|
||||
* @param center_freq The center frequency in MHz (if 80MHz, 80+80MHz or 160MHz).
|
||||
* @param center_freq2 The 2nd center frequency in MHz (if 80+80MHz).
|
||||
* @return Zero on success, nonzero on failure.
|
||||
*/
|
||||
int ws80211_set_freq(const char *name, int freq, int chan_type);
|
||||
int ws80211_set_freq(const char *name, int freq, int chan_type, int _U_ center_freq, int _U_ center_freq2);
|
||||
|
||||
int ws80211_str_to_chan_type(const gchar *s); /* GTK+ only? */
|
||||
const gchar *ws80211_chan_type_to_str(int type); /* GTK+ only? */
|
||||
|
|
|
@ -205,6 +205,9 @@
|
|||
/* SPLIT_WIPHY_DUMP is supported */
|
||||
#cmakedefine HAVE_NL80211_SPLIT_WIPHY_DUMP 1
|
||||
|
||||
/* VHT_CAPABILITY is supported */
|
||||
#cmakedefine HAVE_NL80211_VHT_CAPABILITY 1
|
||||
|
||||
/* Define to 1 if you have the <Ntddndis.h> header file. */
|
||||
#cmakedefine HAVE_NTDDNDIS_H 1
|
||||
|
||||
|
|
|
@ -743,6 +743,12 @@ linux*)
|
|||
[enum nl80211_protocol_features x = NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP;],
|
||||
[AC_MSG_RESULT(yes) AC_DEFINE(HAVE_NL80211_SPLIT_WIPHY_DUMP, 1, [SPLIT_WIPHY_DUMP is supported])],
|
||||
[AC_MSG_RESULT(no)])
|
||||
|
||||
AC_MSG_CHECKING([for NL80211_VHT_CAPABILITY])
|
||||
AC_TRY_COMPILE([#include <linux/nl80211.h>],
|
||||
[enum nl80211_attrs x = NL80211_ATTR_VHT_CAPABILITY;],
|
||||
[AC_MSG_RESULT(yes) AC_DEFINE(HAVE_NL80211_VHT_CAPABILITY, 1, [VHT_CAPABILITY is supported])],
|
||||
[AC_MSG_RESULT(no)])
|
||||
;;
|
||||
|
||||
*)
|
||||
|
|
25
dumpcap.c
25
dumpcap.c
|
@ -486,7 +486,8 @@ print_usage(FILE *output)
|
|||
#ifdef HAVE_BPF_IMAGE
|
||||
fprintf(output, " -d print generated BPF code for capture filter\n");
|
||||
#endif
|
||||
fprintf(output, " -k set channel on wifi interface <freq>,[<type>]\n");
|
||||
fprintf(output, " -k set channel on wifi interface:\n"
|
||||
" <freq>,[<type>],[<center_freq1>],[<center_freq2>]\n");
|
||||
fprintf(output, " -S print statistics for each interface once per second\n");
|
||||
fprintf(output, " -M for -D, -L, and -S, produce machine-readable output\n");
|
||||
fprintf(output, "\n");
|
||||
|
@ -3648,23 +3649,33 @@ capture_loop_queue_packet_cb(u_char *pcap_opts_p, const struct pcap_pkthdr *phdr
|
|||
static int
|
||||
set_80211_channel(const char *iface, const char *opt)
|
||||
{
|
||||
int freq = 0, type, ret;
|
||||
int freq = 0;
|
||||
int type = -1;
|
||||
int center_freq1 = -1;
|
||||
int center_freq2 = -1;
|
||||
int args;
|
||||
int ret;
|
||||
gchar **options = NULL;
|
||||
|
||||
options = g_strsplit_set(opt, ",", 2);
|
||||
options = g_strsplit_set(opt, ",", 4);
|
||||
for (args = 0; options[args]; args++);
|
||||
|
||||
if (options[0])
|
||||
freq = atoi(options[0]);
|
||||
|
||||
if (options[1]) {
|
||||
if (args >= 1 && options[1]) {
|
||||
type = ws80211_str_to_chan_type(options[1]);
|
||||
if (type == -1) {
|
||||
ret = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else
|
||||
type = -1;
|
||||
|
||||
if (args >= 2 && options[2])
|
||||
center_freq1 = atoi(options[2]);
|
||||
|
||||
if (args >= 3 && options[3])
|
||||
center_freq2 = atoi(options[3]);
|
||||
|
||||
ret = ws80211_init();
|
||||
if (ret) {
|
||||
|
@ -3672,7 +3683,7 @@ set_80211_channel(const char *iface, const char *opt)
|
|||
ret = 2;
|
||||
goto out;
|
||||
}
|
||||
ret = ws80211_set_freq(iface, freq, type);
|
||||
ret = ws80211_set_freq(iface, freq, type, center_freq1, center_freq2);
|
||||
|
||||
if (ret) {
|
||||
cmdarg_err("%d: Failed to set channel: %s\n", abs(ret), g_strerror(abs(ret)));
|
||||
|
|
|
@ -170,7 +170,7 @@ tb80211_do_set_channel(char *iface, int freq, int type)
|
|||
|
||||
freq_s = g_strdup_printf("%d", freq);
|
||||
type_s = ws80211_chan_type_to_str(type);
|
||||
ret = sync_interface_set_80211_chan(iface, freq_s, type_s,
|
||||
ret = sync_interface_set_80211_chan(iface, freq_s, type_s, "-1", "-1",
|
||||
&data, &primary_msg, &secondary_msg, main_window_update);
|
||||
|
||||
/* Parse the error msg */
|
||||
|
|
|
@ -265,7 +265,8 @@ void WirelessFrame::setInterfaceInfo()
|
|||
|
||||
if (frequency.isEmpty() || chan_type < 0) return;
|
||||
|
||||
ret = sync_interface_set_80211_chan(cur_iface.toUtf8().constData(), frequency.toUtf8().constData(), chan_type_s,
|
||||
ret = sync_interface_set_80211_chan(cur_iface.toUtf8().constData(), frequency.toUtf8().constData(),
|
||||
chan_type_s, "-1", "-1",
|
||||
&data, &primary_msg, &secondary_msg, main_window_update);
|
||||
|
||||
g_free(data);
|
||||
|
@ -282,7 +283,7 @@ void WirelessFrame::setInterfaceInfo()
|
|||
int chan_type = ui->channelTypeComboBox->itemData(cur_type_idx).toInt();
|
||||
if (frequency < 0 || chan_type < 0) return;
|
||||
|
||||
if (ws80211_set_freq(cur_iface.toUtf8().constData(), frequency, chan_type) != 0) {
|
||||
if (ws80211_set_freq(cur_iface.toUtf8().constData(), frequency, chan_type, -1, -1) != 0) {
|
||||
QString err_str = tr("Unable to set channel or offset.");
|
||||
emit pushAdapterStatus(err_str);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue