1 /* main_80211_toolbar.c
2 * The 802.11 toolbar by Pontus Fuchs <pontus.fuchs@gmail.com>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * This file implements the "80211" toolbar for Wireshark.
37 #include "epan/prefs.h"
39 #include "gtkglobals.h"
40 #include "stock_icons.h"
43 #include "main_toolbar.h"
45 #include "ui/recent.h"
46 #include "ui/gtk/old-gtk-compat.h"
47 #include "ui/ui_util.h"
48 #include "ui/gtk/main_80211_toolbar.h"
50 #include "ws80211_utils.h"
51 #include "capture_session.h"
52 #include "capture_sync.h"
54 static GtkWidget *tb80211_tb, *tb80211_iface_list_box, *tb80211_freq_list_box, *tb80211_chan_type_box, *tb80211_info_label;
56 static GArray *tb80211_interfaces;
57 static struct ws80211_interface *tb80211_current_iface;
58 static gint32 tb80211_current_freq = -1;
59 static gint32 tb80211_current_type = -1;
61 static gboolean tb80211_dont_set_chan;
62 static gboolean tb80211_dont_set_iface;
64 static void tb80211_set_info(const char *errstr)
66 gtk_label_set_markup(GTK_LABEL(tb80211_info_label), errstr);
70 void add_channel_type(const char *type, int oldtype, int indx )
72 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(tb80211_chan_type_box), type);
74 if (oldtype != -1 && oldtype == ws80211_str_to_chan_type(type)) {
75 gtk_combo_box_set_active(GTK_COMBO_BOX(tb80211_chan_type_box), indx);
76 tb80211_current_type = oldtype;
81 void tb80211_update_chan_type(void)
83 static unsigned int tb80211_type_cnt;
86 for (i = 0; i < tb80211_type_cnt; i++) {
87 gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(tb80211_chan_type_box), 0);
90 if (!tb80211_current_iface) {
94 oldtype = tb80211_current_type;
95 tb80211_current_type = -1;
98 add_channel_type(CHAN_NO_HT, oldtype, i++);
100 if (tb80211_current_iface->channel_types & (1 << WS80211_CHAN_HT20)) {
101 add_channel_type(CHAN_HT20, oldtype, i++);
103 if (tb80211_current_iface->channel_types & (1 << WS80211_CHAN_HT40MINUS)) {
104 add_channel_type(CHAN_HT40MINUS, oldtype, i++);
106 if (tb80211_current_iface->channel_types & (1 << WS80211_CHAN_HT40PLUS)) {
107 add_channel_type(CHAN_HT40PLUS, oldtype, i++);
109 tb80211_type_cnt = i;
113 void tb80211_update_freq(void)
115 static unsigned int tb80211_freq_cnt;
120 for (i = 0; i < tb80211_freq_cnt; i++) {
121 gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(tb80211_freq_list_box), 0);
124 oldfreq = tb80211_current_freq;
125 tb80211_current_freq = -1;
127 if (!tb80211_current_iface)
130 tb80211_freq_cnt = tb80211_current_iface->frequencies->len;
131 for (i = 0; i < tb80211_freq_cnt; i++) {
133 freq = g_array_index(tb80211_current_iface->frequencies, int, i);
134 str = g_strdup_printf("%d MHz (%d)", freq, ws80211_frequency_to_channel(freq));
135 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(tb80211_freq_list_box), str);
138 if (freq == oldfreq) {
139 gtk_combo_box_set_active(GTK_COMBO_BOX(tb80211_freq_list_box), i);
140 tb80211_current_freq = oldfreq;
146 void tb80211_update_freq_and_type(void)
148 tb80211_dont_set_chan = TRUE;
149 tb80211_update_freq();
150 tb80211_update_chan_type();
151 tb80211_dont_set_chan = FALSE;
155 /* Get currently selected channel type type enum */
157 int get_selected_channel_type(void)
160 gchar *s = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(tb80211_chan_type_box));
162 ret = ws80211_str_to_chan_type(s);
168 /* Invoke dumpcap to set channel */
170 tb80211_do_set_channel(char *iface, int freq, int type)
174 gchar *data, *primary_msg, *secondary_msg;
177 freq_s = g_strdup_printf("%d", freq);
178 type_s = ws80211_chan_type_to_str(type);
179 ret = sync_interface_set_80211_chan(iface, freq_s, type_s,
180 &data, &primary_msg, &secondary_msg, main_window_update);
182 /* Parse the error msg */
183 if (ret && primary_msg) {
184 return atoi(primary_msg);
188 g_free(secondary_msg);
193 /* Called on freq and type combo box change. */
195 tb80211_set_channel(void)
198 int err, selected_chan, new_type, new_freq;
200 GtkComboBox *freq_combo = GTK_COMBO_BOX(tb80211_freq_list_box);
202 GtkComboBox *type_combo = GTK_COMBO_BOX(tb80211_chan_type_box);
204 selected_chan = gtk_combo_box_get_active(freq_combo);
205 if (selected_chan < 0)
208 new_freq = g_array_index(tb80211_current_iface->frequencies, int, selected_chan);
209 new_type = get_selected_channel_type();
211 err = tb80211_do_set_channel(tb80211_current_iface->ifname, new_freq, new_type);
213 info = g_strdup_printf("<b>Failed to set channel: %s</b>", g_strerror(abs(err)));
214 /* Try to set back to last working chan */
215 err = tb80211_do_set_channel(tb80211_current_iface->ifname, tb80211_current_freq, tb80211_current_type);
217 gtk_combo_box_set_active(freq_combo, -1);
218 gtk_combo_box_set_active(type_combo, -1);
219 tb80211_current_freq = -1;
220 tb80211_current_type = -1;
223 tb80211_update_freq_and_type();
227 info = g_strdup_printf("%s Switched to %d MHz (%d)", tb80211_current_iface->ifname, new_freq, ws80211_frequency_to_channel(new_freq));
228 tb80211_current_freq = new_freq;
229 tb80211_current_type = new_type;
231 tb80211_set_info(info);
236 tb80211_set_chan_cb(GtkWidget *widget _U_, gpointer data _U_)
238 if (!tb80211_current_iface || tb80211_dont_set_chan)
241 tb80211_set_channel();
246 tb80211_iface_changed_cb(GtkWidget *widget, gpointer data _U_)
250 struct ws80211_interface *iface;
251 struct ws80211_iface_info iface_info;
254 if (tb80211_dont_set_iface)
257 active = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(widget));
259 if (!active || tb80211_dont_set_chan)
262 for (i = 0; i < tb80211_interfaces->len; i++) {
263 iface = g_array_index(tb80211_interfaces, struct ws80211_interface *, i);
264 if (strcmp(active, iface->ifname) == 0) {
265 tb80211_current_iface = iface;
270 tb80211_current_freq = -1;
271 tb80211_current_type = -1;
272 if (tb80211_current_iface) {
273 ret = ws80211_get_iface_info(tb80211_current_iface->ifname, &iface_info);
275 tb80211_current_freq = iface_info.current_freq;
276 tb80211_current_type = iface_info.current_chan_type;
279 tb80211_update_freq_and_type();
286 tb80211_refresh_interfaces(void)
288 struct ws80211_interface *iface;
290 gboolean same = FALSE;
291 gchar *selected_iface = NULL, *info;
296 if (tb80211_interfaces) {
297 selected_iface = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(tb80211_iface_list_box));
299 for (i = 0; i < tb80211_interfaces->len; i++)
300 gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(tb80211_iface_list_box), 0);
302 ws80211_free_interfaces(tb80211_interfaces);
303 tb80211_interfaces = NULL;
304 tb80211_current_iface = NULL;
306 tb80211_interfaces = ws80211_find_interfaces();
308 if (!tb80211_interfaces) {
312 tb80211_dont_set_iface = TRUE;
313 for (i = 0; i < tb80211_interfaces->len; i++) {
314 iface = g_array_index(tb80211_interfaces, struct ws80211_interface *, i);
315 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(tb80211_iface_list_box), iface->ifname);
317 if (selected_iface && strcmp(selected_iface, iface->ifname) == 0) {
318 gtk_combo_box_set_active(GTK_COMBO_BOX(tb80211_iface_list_box), i);
319 tb80211_current_iface = iface;
323 tb80211_dont_set_iface = FALSE;
325 /* Reset selectors if interface disappeared */
327 gtk_combo_box_set_active(GTK_COMBO_BOX(tb80211_iface_list_box), -1);
328 gtk_combo_box_set_active(GTK_COMBO_BOX(tb80211_freq_list_box), -1);
329 gtk_combo_box_set_active(GTK_COMBO_BOX(tb80211_chan_type_box), -1);
332 info = g_strdup_printf("%d monitor interfaces found", tb80211_interfaces->len);
333 tb80211_set_info(info);
336 g_free(selected_iface);
340 tb80211_add_label(const gchar *text, GtkWidget *tb)
343 GtkToolItem *label_ti;
345 label_ti = gtk_tool_item_new();
346 gtk_widget_show(GTK_WIDGET (label_ti));
347 label = gtk_label_new(text);
348 gtk_widget_show(GTK_WIDGET (label));
349 gtk_container_add(GTK_CONTAINER(label_ti), label);
350 gtk_toolbar_insert(GTK_TOOLBAR(tb), label_ti, -1);
354 ws80211_toolbar_new(void)
360 tb80211_tb = gtk_toolbar_new();
361 gtk_orientable_set_orientation(GTK_ORIENTABLE(tb80211_tb),
362 GTK_ORIENTATION_HORIZONTAL);
364 gtk_widget_show(tb80211_tb);
366 tb80211_add_label(" Interface: ", tb80211_tb);
368 ti = gtk_tool_item_new();
369 gtk_widget_show(GTK_WIDGET (ti));
370 tb80211_iface_list_box = gtk_combo_box_text_new();
371 g_signal_connect(tb80211_iface_list_box, "changed", G_CALLBACK(tb80211_iface_changed_cb), NULL);
372 gtk_container_add(GTK_CONTAINER(ti), tb80211_iface_list_box);
373 gtk_widget_show(GTK_WIDGET (tb80211_iface_list_box));
374 gtk_toolbar_insert(GTK_TOOLBAR(tb80211_tb), ti, -1);
376 tb80211_add_label(" Frequency: ", tb80211_tb);
378 ti = gtk_tool_item_new();
379 gtk_widget_show(GTK_WIDGET (ti));
380 tb80211_freq_list_box = gtk_combo_box_text_new();
382 g_signal_connect(tb80211_freq_list_box, "changed", G_CALLBACK(tb80211_set_chan_cb), NULL);
384 gtk_widget_set_sensitive(GTK_WIDGET(tb80211_freq_list_box), FALSE);
386 gtk_container_add(GTK_CONTAINER(ti), tb80211_freq_list_box);
387 gtk_widget_show(GTK_WIDGET (tb80211_freq_list_box));
388 gtk_toolbar_insert(GTK_TOOLBAR(tb80211_tb), ti, -1);
390 ti = gtk_tool_item_new();
391 gtk_widget_show(GTK_WIDGET (ti));
392 tb80211_chan_type_box = gtk_combo_box_text_new();
394 g_signal_connect(tb80211_chan_type_box, "changed", G_CALLBACK(tb80211_set_chan_cb), NULL);
396 gtk_widget_set_sensitive(GTK_WIDGET(tb80211_freq_list_box), FALSE);
398 gtk_container_add(GTK_CONTAINER(ti), tb80211_chan_type_box);
399 gtk_widget_show(GTK_WIDGET (tb80211_chan_type_box));
400 gtk_toolbar_insert(GTK_TOOLBAR(tb80211_tb), ti, -1);
402 ti = gtk_separator_tool_item_new();
403 gtk_widget_show(GTK_WIDGET (ti));
404 gtk_toolbar_insert(GTK_TOOLBAR(tb80211_tb), ti, -1);
406 ti = gtk_tool_item_new();
407 gtk_widget_show(GTK_WIDGET (ti));
408 tb80211_info_label = gtk_label_new("");
409 gtk_container_add(GTK_CONTAINER(ti), tb80211_info_label);
410 gtk_widget_show(GTK_WIDGET (tb80211_info_label));
411 gtk_toolbar_insert(GTK_TOOLBAR(tb80211_tb), ti, -1);
413 /* make current preferences effective */
414 toolbar_redraw_all();
416 ret = ws80211_init();
418 tb80211_set_info("<b>Failed to initialize ws80211</b>");
420 tb80211_refresh_interfaces();