Kerberos: add kerberos_inject_longterm_key() helper function
[wireshark-sm.git] / ui / qt / wireless_frame.cpp
blob04a06e08644e0a4b2605cb9d349dcd1af8e4c8b4
1 /* wireless_frame.cpp
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
10 #include "wireless_frame.h"
11 #include <ui_wireless_frame.h>
13 #include "config.h"
15 #include <capture/capture_session.h>
16 #include <capture/capture_sync.h>
18 #include <capture/ws80211_utils.h>
20 #include "ui/ws_ui_util.h"
21 #include <wsutil/utf8_entities.h>
22 #include <wsutil/802_11-utils.h>
23 #include "main_application.h"
24 #include "utils/qt_ui_utils.h"
26 #include <QProcess>
27 #include <QAbstractItemView>
29 // To do:
30 // - Disable or hide invalid channel types.
31 // - Push more status messages ("switched to...") to the status bar.
32 // - Add a "Decrypt in the driver" checkbox?
33 // - Check for frequency and channel type changes.
34 // - Find something appropriate to run from the helperToolButton on Linux.
36 // Questions:
37 // - From our perspective, what's the difference between "NOHT" and "HT20"?
39 const int update_interval_ = 1500; // ms
41 WirelessFrame::WirelessFrame(QWidget *parent) :
42 QFrame(parent),
43 ui(new Ui::WirelessFrame),
44 interfaces_(NULL),
45 capture_in_progress_(false),
46 iface_timer_id_(-1)
48 ui->setupUi(this);
50 ui->helperToolButton->hide();
52 if (ws80211_init() == WS80211_INIT_OK) {
53 ui->stackedWidget->setEnabled(true);
54 ui->stackedWidget->setCurrentWidget(ui->interfacePage);
55 } else {
56 ui->stackedWidget->setEnabled(false);
57 ui->stackedWidget->setCurrentWidget(ui->noWirelessPage);
60 ui->fcsFilterFrame->setVisible(ws80211_has_fcs_filter());
62 updateInterfaceList();
63 connect(mainApp, &MainApplication::localInterfaceEvent,
64 this, &WirelessFrame::handleInterfaceEvent);
67 WirelessFrame::~WirelessFrame()
69 ws80211_free_interfaces(interfaces_);
70 delete ui;
73 void WirelessFrame::setCaptureInProgress(bool capture_in_progress)
75 capture_in_progress_ = capture_in_progress;
76 updateWidgets();
80 int WirelessFrame::startTimer(int interval)
82 if (iface_timer_id_ != -1) {
83 killTimer(iface_timer_id_);
84 iface_timer_id_ = -1;
86 iface_timer_id_ = QFrame::startTimer(interval);
87 return iface_timer_id_;
90 void WirelessFrame::handleInterfaceEvent(const char *ifname _U_, int added, int up _U_)
92 if (!added) {
93 // Unfortunately when an interface removed event is received the network
94 // interface is still present for a while in the system.
95 // To overcome this update the interface list after a while.
96 startTimer(update_interval_);
97 } else {
98 updateInterfaceList();
102 void WirelessFrame::timerEvent(QTimerEvent *event)
104 if (event->timerId() != iface_timer_id_) {
105 QFrame::timerEvent(event);
106 return;
108 killTimer(iface_timer_id_);
109 iface_timer_id_ = -1;
110 updateInterfaceList();
113 // Check to see if the ws80211 interface list matches the one in our
114 // combobox. Rebuild ours if necessary and select the first interface if
115 // the current selection goes away.
116 void WirelessFrame::updateInterfaceList()
118 ws80211_free_interfaces(interfaces_);
119 interfaces_ = ws80211_find_interfaces();
120 const QString old_iface = ui->interfaceComboBox->currentText();
121 unsigned iface_count = 0;
122 bool list_changed = false;
124 // Don't interfere with user activity.
125 if (ui->interfaceComboBox->view()->isVisible()
126 || ui->channelComboBox->view()->isVisible()
127 || ui->channelTypeComboBox->view()->isVisible()
128 || ui->fcsComboBox->view()->isVisible()) {
129 startTimer(update_interval_);
130 return;
133 if (interfaces_ && interfaces_->len > 0) {
134 iface_count = interfaces_->len;
137 if ((int) iface_count != ui->interfaceComboBox->count()) {
138 list_changed = true;
139 } else {
140 for (unsigned i = 0; i < iface_count; i++) {
141 struct ws80211_interface *iface = g_array_index(interfaces_, struct ws80211_interface *, i);
142 if (ui->interfaceComboBox->itemText(i).compare(iface->ifname) != 0) {
143 list_changed = true;
144 break;
149 if (list_changed) {
150 ui->interfaceComboBox->clear();
151 for (unsigned i = 0; i < iface_count; i++) {
152 struct ws80211_interface *iface = g_array_index(interfaces_, struct ws80211_interface *, i);
153 ui->interfaceComboBox->addItem(iface->ifname);
154 if (old_iface.compare(iface->ifname) == 0) {
155 ui->interfaceComboBox->setCurrentIndex(ui->interfaceComboBox->count() - 1);
160 if (ui->interfaceComboBox->currentText().compare(old_iface) != 0) {
161 getInterfaceInfo();
165 void WirelessFrame::updateWidgets()
167 bool enable_interface = false;
168 bool enable_channel = false;
169 bool enable_offset = false;
170 bool enable_show_fcs = false;
172 if (ui->interfaceComboBox->count() > 0) {
173 enable_interface = true;
174 enable_show_fcs = true;
177 if (enable_interface && ui->channelComboBox->count() > 0) {
178 enable_channel = true;
181 if (enable_channel && ui->channelTypeComboBox->count() > 1) {
182 enable_offset = true;
185 ui->interfaceComboBox->setEnabled(enable_interface);
186 ui->channelComboBox->setEnabled(enable_channel);
187 ui->channelTypeComboBox->setEnabled(enable_offset);
188 ui->fcsComboBox->setEnabled(!capture_in_progress_ && enable_show_fcs);
191 void WirelessFrame::on_helperToolButton_clicked()
193 const QString helper_path = ws80211_get_helper_path();
194 if (helper_path.isEmpty()) return;
196 QString command = QStringLiteral("\"%1\"").arg(helper_path);
197 QProcess::startDetached(command, QStringList());
200 void WirelessFrame::on_prefsToolButton_clicked()
202 emit showWirelessPreferences("wlan");
205 void WirelessFrame::getInterfaceInfo()
207 const QString cur_iface = ui->interfaceComboBox->currentText();
209 ui->channelComboBox->clear();
210 ui->channelTypeComboBox->clear();
211 ui->fcsComboBox->clear();
213 if (cur_iface.isEmpty()) {
214 updateWidgets();
215 return;
218 for (unsigned i = 0; i < interfaces_->len; i++) {
219 struct ws80211_interface *iface = g_array_index(interfaces_, struct ws80211_interface *, i);
220 if (cur_iface.compare(iface->ifname) == 0) {
221 struct ws80211_iface_info iface_info;
222 QString units = " GHz";
224 ws80211_get_iface_info(iface->ifname, &iface_info);
226 for (unsigned j = 0; j < iface->frequencies->len; j++) {
227 uint32_t frequency = g_array_index(iface->frequencies, uint32_t, j);
228 double ghz = frequency / 1000.0;
229 QString chan_str = QStringLiteral("%1 %2 %3%4")
230 .arg(ieee80211_mhz_to_chan(frequency))
231 .arg(UTF8_MIDDLE_DOT)
232 .arg(ghz, 0, 'f', 3)
233 .arg(units);
234 ui->channelComboBox->addItem(chan_str, frequency);
235 if ((int)frequency == iface_info.current_freq) {
236 ui->channelComboBox->setCurrentIndex(ui->channelComboBox->count() - 1);
238 units = QString();
240 // XXX - Do we need to make a distinction between WS80211_CHAN_NO_HT
241 // and WS80211_CHAN_HT20? E.g. is there a driver that won't capture
242 // HT frames if you use WS80211_CHAN_NO_HT?
243 ui->channelTypeComboBox->addItem("20 MHz", WS80211_CHAN_NO_HT);
244 if (iface_info.current_chan_type == WS80211_CHAN_NO_HT || iface_info.current_chan_type == WS80211_CHAN_HT20) {
245 ui->channelTypeComboBox->setCurrentIndex(0);
247 if (iface->channel_types & (1 << WS80211_CHAN_HT40MINUS)) {
248 ui->channelTypeComboBox->addItem("HT 40-", WS80211_CHAN_HT40MINUS);
249 if (iface_info.current_chan_type == WS80211_CHAN_HT40MINUS) {
250 ui->channelTypeComboBox->setCurrentIndex(ui->channelTypeComboBox->count() - 1);
253 if (iface->channel_types & (1 << WS80211_CHAN_HT40PLUS)) {
254 ui->channelTypeComboBox->addItem("HT 40+", WS80211_CHAN_HT40PLUS);
255 if (iface_info.current_chan_type == WS80211_CHAN_HT40PLUS) {
256 ui->channelTypeComboBox->setCurrentIndex(ui->channelTypeComboBox->count() - 1);
259 if (iface->channel_types & (1 << WS80211_CHAN_VHT80)) {
260 ui->channelTypeComboBox->addItem("VHT 80", WS80211_CHAN_VHT80);
261 if (iface_info.current_chan_type == WS80211_CHAN_VHT80) {
262 ui->channelTypeComboBox->setCurrentIndex(ui->channelTypeComboBox->count() - 1);
265 if (iface->channel_types & (1 << WS80211_CHAN_VHT160)) {
266 ui->channelTypeComboBox->addItem("VHT 160", WS80211_CHAN_VHT160);
267 if (iface_info.current_chan_type == WS80211_CHAN_VHT160) {
268 ui->channelTypeComboBox->setCurrentIndex(ui->channelTypeComboBox->count() - 1);
272 if (ws80211_has_fcs_filter()) {
273 ui->fcsComboBox->setCurrentIndex(iface_info.current_fcs_validation);
278 updateWidgets();
281 void WirelessFrame::setInterfaceInfo()
283 QString cur_iface = ui->interfaceComboBox->currentText();
284 int cur_chan_idx = ui->channelComboBox->currentIndex();
285 int cur_type_idx = ui->channelTypeComboBox->currentIndex();
286 int cur_fcs_idx = ui->fcsComboBox->currentIndex();
288 if (cur_iface.isEmpty() || cur_chan_idx < 0 || cur_type_idx < 0) return;
290 QString err_str;
292 #if defined(HAVE_LIBNL) && defined(HAVE_NL80211) && defined(HAVE_LIBPCAP)
293 int frequency = ui->channelComboBox->itemData(cur_chan_idx).toInt();
294 int chan_type = ui->channelTypeComboBox->itemData(cur_type_idx).toInt();
295 int bandwidth = getBandwidthFromChanType(chan_type);
296 int center_freq = getCenterFrequency(frequency, bandwidth);
297 const char *chan_type_s = ws80211_chan_type_to_str(chan_type);
298 char *center_freq_s = NULL;
299 char *data, *primary_msg, *secondary_msg;
300 int ret;
302 if (frequency < 0 || chan_type < 0) return;
304 if (center_freq != -1) {
305 center_freq_s = qstring_strdup(QString::number(center_freq));
308 ret = sync_interface_set_80211_chan(cur_iface.toUtf8().constData(),
309 QString::number(frequency).toUtf8().constData(), chan_type_s,
310 center_freq_s, NULL,
311 &data, &primary_msg, &secondary_msg, main_window_update);
313 g_free(center_freq_s);
314 g_free(data);
315 g_free(primary_msg);
316 g_free(secondary_msg);
318 /* Parse the error msg */
319 if (ret) {
320 err_str = tr("Unable to set channel or offset.");
322 #endif
324 if (cur_fcs_idx >= 0) {
325 if (ws80211_set_fcs_validation(cur_iface.toUtf8().constData(), (enum ws80211_fcs_validation) cur_fcs_idx) != 0) {
326 err_str = tr("Unable to set FCS validation behavior.");
330 if (!err_str.isEmpty()) {
331 mainApp->pushStatus(MainApplication::TemporaryStatus, err_str);
334 getInterfaceInfo();
337 int WirelessFrame::getCenterFrequency(int control_frequency, int bandwidth)
339 if (bandwidth < 80 || control_frequency < 5180)
340 return -1;
342 return ((control_frequency - 5180) / bandwidth) * bandwidth + 5180 + (bandwidth / 2) - 10;
345 int WirelessFrame::getBandwidthFromChanType(int chan_type)
347 switch (chan_type) {
348 case WS80211_CHAN_VHT80:
349 return 80;
350 case WS80211_CHAN_VHT160:
351 return 160;
352 default:
353 return -1;
357 void WirelessFrame::on_interfaceComboBox_activated(int)
359 getInterfaceInfo();
362 void WirelessFrame::on_channelComboBox_activated(int)
364 setInterfaceInfo();
367 void WirelessFrame::on_channelTypeComboBox_activated(int)
369 setInterfaceInfo();
372 void WirelessFrame::on_fcsComboBox_activated(int)
374 setInterfaceInfo();