summaryrefslogtreecommitdiff
path: root/ui/qt/wireless_frame.cpp
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2015-06-11 15:05:44 -0700
committerGerald Combs <gerald@wireshark.org>2015-06-16 03:45:54 +0000
commitece4b01f218ab4e71233580e199e830b83958c99 (patch)
treef7503d8f097b6e3f6406dd3f6b0c69bb46b97909 /ui/qt/wireless_frame.cpp
parent2a3fa1418544469e7dc6f0e0fddb6eaab507b71a (diff)
downloadwireshark-ece4b01f218ab4e71233580e199e830b83958c99.tar.gz
Add the wireless toolbar.
Add the wireless toolbar to the Qt UI. Start adding AirPcap support to ui/80211_utils. Add FCS validation routines to ws80211_utils. Move a bunch of AirPcap routines that require epan from caputils to ui/gtk. They were required for driver key management, which we'll leave to the AirPcap Control Panel in the Qt UI. Move frequency-utils to wsutil. Change-Id: I44446758046621d183f5c2ba9f6526bf01e084f1 Reviewed-on: https://code.wireshark.org/review/8910 Petri-Dish: Gerald Combs <gerald@wireshark.org> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Gerald Combs <gerald@wireshark.org>
Diffstat (limited to 'ui/qt/wireless_frame.cpp')
-rw-r--r--ui/qt/wireless_frame.cpp313
1 files changed, 313 insertions, 0 deletions
diff --git a/ui/qt/wireless_frame.cpp b/ui/qt/wireless_frame.cpp
new file mode 100644
index 0000000000..c56a8b317d
--- /dev/null
+++ b/ui/qt/wireless_frame.cpp
@@ -0,0 +1,313 @@
+/* wireless_frame.cpp
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "wireless_frame.h"
+#include "ui_wireless_frame.h"
+
+#include "config.h"
+
+#include <glib.h>
+
+#include <capchild/capture_session.h>
+#include <capchild/capture_sync.h>
+
+#include <caputils/ws80211_utils.h>
+
+#include <ui/ui_util.h>
+#include <ui/utf8_entities.h>
+
+#include <QProcess>
+
+// To do:
+// - Disable or hide invalid channel types.
+// - Push more status messages ("switched to...") to the status bar.
+// - Add a "Decrypt in the driver" checkbox?
+// - Check for frequency and channel type changes.
+
+// Questions:
+// - From our perspective, what's the difference between "NOHT" and "HT20"?
+
+const int update_interval_ = 1500; // ms
+
+WirelessFrame::WirelessFrame(QWidget *parent) :
+ QFrame(parent),
+ ui(new Ui::WirelessFrame),
+ interfaces_(NULL),
+ capture_in_progress_(false)
+{
+ ui->setupUi(this);
+
+ ui->helperToolButton->hide();
+
+ if (ws80211_init() == 0) {
+ ui->stackedWidget->setEnabled(true);
+ ui->stackedWidget->setCurrentWidget(ui->interfacePage);
+
+#ifdef Q_OS_WIN
+ // We should arguably add ws80211_get_helper_name and ws80211_get_helper_tooltip.
+ // This works for now and is translatable.
+ ui->helperToolButton->setText(tr("AirPcap Control Panel"));
+ ui->helperToolButton->setToolTip(tr("Open the AirPcap Control Panel"));
+ ui->helperToolButton->show();
+ ui->helperToolButton->setEnabled(ws80211_get_helper_path() != NULL);
+#endif
+
+ } else {
+ ui->stackedWidget->setEnabled(false);
+ ui->stackedWidget->setCurrentWidget(ui->noWirelessPage);
+ }
+
+ ui->fcsFilterFrame->setVisible(ws80211_has_fcs_filter());
+
+ updateWidgets();
+ startTimer(update_interval_);
+}
+
+WirelessFrame::~WirelessFrame()
+{
+ delete ui;
+}
+
+void WirelessFrame::setCaptureInProgress(bool capture_in_progress)
+{
+ capture_in_progress_ = capture_in_progress;
+ updateWidgets();
+}
+
+// Check to see if the ws80211 interface list matches the one in our
+// combobox. Rebuild ours if necessary and select the first interface if
+// the current selection goes away.
+void WirelessFrame::timerEvent(QTimerEvent *)
+{
+ ws80211_free_interfaces(interfaces_);
+ interfaces_ = ws80211_find_interfaces();
+ const QString old_iface = ui->interfaceComboBox->currentText();
+ guint iface_count = 0;
+ bool list_changed = false;
+
+ if (interfaces_ && interfaces_->len > 0) {
+ iface_count = interfaces_->len;
+ }
+
+ if ((int) iface_count != ui->interfaceComboBox->count()) {
+ list_changed = true;
+ } else {
+ for (guint i = 0; i < iface_count; i++) {
+ struct ws80211_interface *iface = g_array_index(interfaces_, struct ws80211_interface *, i);
+ if (ui->interfaceComboBox->itemText(i).compare(iface->ifname) != 0) {
+ list_changed = true;
+ break;
+ }
+ }
+ }
+
+ if (list_changed) {
+ ui->interfaceComboBox->clear();
+ for (guint i = 0; i < iface_count; i++) {
+ struct ws80211_interface *iface = g_array_index(interfaces_, struct ws80211_interface *, i);
+ ui->interfaceComboBox->addItem(iface->ifname);
+ if (old_iface.compare(iface->ifname) == 0) {
+ ui->interfaceComboBox->setCurrentIndex(ui->interfaceComboBox->count() - 1);
+ }
+ }
+ }
+
+ if (ui->interfaceComboBox->currentText().compare(old_iface) != 0) {
+ on_channelComboBox_activated(ui->interfaceComboBox->currentIndex());
+ }
+}
+
+Q_DECLARE_METATYPE(struct ws80211_interface *)
+void WirelessFrame::updateWidgets()
+{
+ bool enable_interface = false;
+ bool enable_channel = false;
+ bool enable_offset = false;
+ bool enable_show_fcs = false;
+
+ if (ui->interfaceComboBox->count() > 0) {
+ enable_interface = true;
+ enable_show_fcs = true;
+ }
+
+ if (enable_interface && ui->channelComboBox->count() > 0) {
+ enable_channel = true;
+ }
+
+ if (enable_channel && ui->channelTypeComboBox->count() > 1) {
+ enable_offset = true;
+ }
+
+ ui->interfaceComboBox->setEnabled(enable_interface);
+ ui->channelComboBox->setEnabled(enable_channel);
+ ui->channelTypeComboBox->setEnabled(enable_offset);
+ ui->fcsComboBox->setEnabled(!capture_in_progress_ && enable_show_fcs);
+}
+
+void WirelessFrame::on_helperToolButton_clicked()
+{
+ const QString helper_path = ws80211_get_helper_path();
+ if (helper_path.isEmpty()) return;
+
+ QString command = QString("\"%1\"").arg(helper_path);
+ QProcess::startDetached(command);
+}
+
+void WirelessFrame::on_prefsToolButton_clicked()
+{
+ emit showWirelessPreferences(QString("wlan"));
+}
+
+void WirelessFrame::on_interfaceComboBox_currentIndexChanged(const QString &cur_iface)
+{
+ ui->channelComboBox->clear();
+ ui->channelTypeComboBox->clear();
+ if (cur_iface.isEmpty()) {
+ updateWidgets();
+ return;
+ }
+
+ for (guint i = 0; i < interfaces_->len; i++) {
+ struct ws80211_interface *iface = g_array_index(interfaces_, struct ws80211_interface *, i);
+ if (cur_iface.compare(iface->ifname) == 0) {
+ struct ws80211_iface_info iface_info;
+ QString units = " GHz";
+
+ ws80211_get_iface_info(iface->ifname, &iface_info);
+
+ for (guint i = 0; i < iface->frequencies->len; i++) {
+ guint32 frequency = g_array_index(iface->frequencies, guint32, i);
+ double ghz = frequency / 1000.0;
+ QString chan_str = QString("%1 " UTF8_MIDDLE_DOT " %2%3")
+ .arg(ws80211_frequency_to_channel(frequency))
+ .arg(ghz, 0, 'f', 3)
+ .arg(units);
+ ui->channelComboBox->addItem(chan_str, frequency);
+ if ((int)frequency == iface_info.current_freq) {
+ ui->channelComboBox->setCurrentIndex(ui->channelComboBox->count() - 1);
+ }
+ units = QString();
+ }
+ // XXX - Do we need to make a distinction between WS80211_CHAN_NO_HT
+ // and WS80211_CHAN_HT20? E.g. is there a driver that won't capture
+ // HT frames if you use WS80211_CHAN_NO_HT?
+ ui->channelTypeComboBox->addItem("20 MHz", WS80211_CHAN_NO_HT);
+ if (iface_info.current_chan_type == WS80211_CHAN_NO_HT || iface_info.current_chan_type == WS80211_CHAN_HT20) {
+ ui->channelTypeComboBox->setCurrentIndex(0);
+ }
+ if (iface->channel_types & (1 << WS80211_CHAN_HT40MINUS)) {
+ ui->channelTypeComboBox->addItem("HT 40-", WS80211_CHAN_HT40MINUS);
+ if (iface_info.current_chan_type == WS80211_CHAN_HT40MINUS) {
+ ui->channelTypeComboBox->setCurrentIndex(ui->channelTypeComboBox->count() - 1);
+ }
+ }
+ if (iface->channel_types & (1 << WS80211_CHAN_HT40PLUS)) {
+ ui->channelTypeComboBox->addItem("HT 40+", WS80211_CHAN_HT40PLUS);
+ if (iface_info.current_chan_type == WS80211_CHAN_HT40PLUS) {
+ ui->channelTypeComboBox->setCurrentIndex(ui->channelTypeComboBox->count() - 1);
+ }
+ }
+
+ if (ws80211_has_fcs_filter()) {
+ ui->fcsComboBox->setCurrentIndex(iface_info.current_fcs_validation);
+ }
+ }
+ }
+ updateWidgets();
+}
+
+void WirelessFrame::setChannel()
+{
+ QString cur_iface = ui->interfaceComboBox->currentText();
+ int cur_chan_idx = ui->channelComboBox->currentIndex();
+ int cur_type_idx = ui->channelTypeComboBox->currentIndex();
+
+ if (cur_iface.isEmpty() || cur_chan_idx < 0 || cur_type_idx < 0) return;
+
+#ifdef Q_OS_WIN
+ int frequency = ui->channelComboBox->itemData(cur_chan_idx).toInt();
+ 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) {
+ QString err_str = tr("Unable to set channel or offset.");
+ emit pushAdapterStatus(err_str);
+ }
+#else // Assume we have to go through dumpcap.
+ const QString frequency = ui->channelComboBox->itemData(cur_chan_idx).toString();
+ int chan_type = ui->channelTypeComboBox->itemData(cur_type_idx).toInt();
+ const gchar *chan_type_s = ws80211_chan_type_to_str(chan_type);
+ gchar *data, *primary_msg, *secondary_msg;
+ int ret;
+
+ if (frequency.isEmpty() || chan_type < 0) return;
+
+ ret = sync_interface_set_80211_chan(cur_iface.toUtf8().constData(), frequency.toUtf8().constData(), chan_type_s,
+ &data, &primary_msg, &secondary_msg, main_window_update);
+
+ g_free(data);
+ g_free(primary_msg);
+ g_free(secondary_msg);
+
+ /* Parse the error msg */
+ if (ret) {
+ QString err_str = tr("Unable to set channel or offset.");
+ emit pushAdapterStatus(err_str);
+ }
+#endif
+
+ updateWidgets();
+}
+
+void WirelessFrame::on_channelComboBox_activated(int)
+{
+ setChannel();
+}
+
+void WirelessFrame::on_channelTypeComboBox_activated(int)
+{
+ setChannel();
+}
+
+void WirelessFrame::on_fcsComboBox_activated(int index)
+{
+ QString cur_iface = ui->interfaceComboBox->currentText();
+ if (cur_iface.isEmpty()) return;
+
+ if (ws80211_set_fcs_validation(cur_iface.toUtf8().constData(), (enum ws80211_fcs_validation) index) != 0) {
+ QString err_str = tr("Unable to set FCS validation behavior.");
+ emit pushAdapterStatus(err_str);
+ }
+ updateWidgets();
+}
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */