diff options
author | Anders Broman <anders.broman@ericsson.com> | 2012-06-20 17:02:07 +0000 |
---|---|---|
committer | Anders Broman <anders.broman@ericsson.com> | 2012-06-20 17:02:07 +0000 |
commit | a2f2c490747cdf36ad9dfb6cc73237a8ed569a21 (patch) | |
tree | 8e5f3c84d0bf3beb499c04c1889d979ce2eedcca /ui/gtk/main_80211_toolbar.c | |
parent | 9ee113d384fdfb3fefea56e4d9a2fc511b7a729d (diff) | |
download | wireshark-a2f2c490747cdf36ad9dfb6cc73237a8ed569a21.tar.gz |
Add the toolbar of bug https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=6973
sligtly modified to compile on Windows. See if it breaks any other platform.
svn path=/trunk/; revision=43411
Diffstat (limited to 'ui/gtk/main_80211_toolbar.c')
-rw-r--r-- | ui/gtk/main_80211_toolbar.c | 426 |
1 files changed, 426 insertions, 0 deletions
diff --git a/ui/gtk/main_80211_toolbar.c b/ui/gtk/main_80211_toolbar.c new file mode 100644 index 0000000000..ac48654356 --- /dev/null +++ b/ui/gtk/main_80211_toolbar.c @@ -0,0 +1,426 @@ +/* main_80211_toolbar.c + * The 802.11 toolbar by Pontus Fuchs <pontus.fuchs@gmail.com> + * + * $Id$ + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * This file implements the "80211" toolbar for Wireshark. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <string.h> + +#include <gtk/gtk.h> + +#include "epan/prefs.h" + +#include "gtkglobals.h" +#include "stock_icons.h" + +#include "main.h" +#include "main_toolbar.h" + +#include "ui/recent.h" +#include "ui/gtk/old-gtk-compat.h" + +#include <ws80211_utils.h> +#include "capture_sync.h" + +static GtkWidget *tb80211_iface_list_box, *tb80211_freq_list_box, *tb80211_chan_type_box, *tb80211_info_label; + +static GArray *tb80211_interfaces; +static struct ws80211_interface *tb80211_current_iface; +static gint32 tb80211_current_freq = -1; +static gint32 tb80211_current_type = -1; + +static gboolean tb80211_dont_set_chan; +static gboolean tb80211_dont_set_iface; + +static void tb80211_set_info(char *errstr) +{ + gtk_label_set_markup(GTK_LABEL(tb80211_info_label), errstr); +} + +static +void add_channel_type(char *type, int oldtype, int index ) +{ + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(tb80211_chan_type_box), type); + + if (oldtype != -1 && oldtype == ws80211_str_to_chan_type(type)) { + gtk_combo_box_set_active(GTK_COMBO_BOX(tb80211_chan_type_box), index); + tb80211_current_type = oldtype; + } +} + +static +void tb80211_update_chan_type(void) +{ + static unsigned int tb80211_type_cnt; + unsigned int i; + int oldtype = -1; + for (i = 0; i < tb80211_type_cnt; i++) { + gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(tb80211_chan_type_box), 0); + } + + if (!tb80211_current_iface) { + return; + } + + oldtype = tb80211_current_type; + tb80211_current_type = -1; + + i = 0; + add_channel_type(CHAN_NO_HT, oldtype, i++); + + if (tb80211_current_iface->channel_types & (1 << WS80211_CHAN_HT20)) { + add_channel_type(CHAN_HT20, oldtype, i++); + } + if (tb80211_current_iface->channel_types & (1 << WS80211_CHAN_HT40MINUS)) { + add_channel_type(CHAN_HT40MINUS, oldtype, i++); + } + if (tb80211_current_iface->channel_types & (1 << WS80211_CHAN_HT40PLUS)) { + add_channel_type(CHAN_HT40PLUS, oldtype, i++); + } + tb80211_type_cnt = i; +} + +static +void tb80211_update_freq(void) +{ + static unsigned int tb80211_freq_cnt; + unsigned int i; + gchar *str; + gint32 oldfreq = 0; + + for (i = 0; i < tb80211_freq_cnt; i++) { + gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(tb80211_freq_list_box), 0); + } + + oldfreq = tb80211_current_freq; + tb80211_current_freq = -1; + + if (!tb80211_current_iface) + return; + + tb80211_freq_cnt = tb80211_current_iface->frequencies->len; + for (i = 0; i < tb80211_freq_cnt; i++) { + int freq; + freq = g_array_index(tb80211_current_iface->frequencies, int, i); + str = g_strdup_printf("%d MHz (%d)", freq, ws80211_frequency_to_channel(freq)); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(tb80211_freq_list_box), str); + g_free(str); + + if (freq == oldfreq) { + gtk_combo_box_set_active(GTK_COMBO_BOX(tb80211_freq_list_box), i); + tb80211_current_freq = oldfreq; + } + } +} + +static +void tb80211_update_freq_and_type(void) +{ + tb80211_dont_set_chan = TRUE; + tb80211_update_freq(); + tb80211_update_chan_type(); + tb80211_dont_set_chan = FALSE; +} + +/* Get currently selected channel type type enum */ +static +int get_selected_channel_type(void) +{ + int ret; + gchar *s = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(tb80211_chan_type_box)); + + ret = ws80211_str_to_chan_type(s); + + g_free(s); + return ret; +} + +/* Invoke dumpcap to set channel */ +static int +tb80211_do_set_channel(char *iface, int freq, int type) +{ + gchar *freq_s, *type_s; + gchar *data, *primary_msg, *secondary_msg; + int ret; + + 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, + &data, &primary_msg, &secondary_msg); + + /* Parse the error msg */ + if (ret && primary_msg) { + return atoi(primary_msg); + } + + g_free(data); + g_free(primary_msg); + g_free(secondary_msg); + g_free(freq_s); + return ret; +} + +/* Called on freq and type combo box change. */ +static void +tb80211_set_channel(void) +{ + gchar *info = NULL; + int err, selected_chan, new_type, new_freq; + + GtkComboBox *freq_combo = GTK_COMBO_BOX(tb80211_freq_list_box); + + GtkComboBox *type_combo = GTK_COMBO_BOX(tb80211_chan_type_box); + + selected_chan = gtk_combo_box_get_active(freq_combo); + if (selected_chan < 0) + return; + + new_freq = g_array_index(tb80211_current_iface->frequencies, int, selected_chan); + new_type = get_selected_channel_type(); + + err = tb80211_do_set_channel(tb80211_current_iface->ifname, new_freq, new_type); + if (err) { + info = g_strdup_printf("<b>Failed to set channel: %s</b>", g_strerror(abs(err))); + /* Try to set back to last working chan */ + err = tb80211_do_set_channel(tb80211_current_iface->ifname, tb80211_current_freq, tb80211_current_type); + if (err) { + gtk_combo_box_set_active(freq_combo, -1); + gtk_combo_box_set_active(type_combo, -1); + tb80211_current_freq = -1; + tb80211_current_type = -1; + } + else { + tb80211_update_freq_and_type(); + } + } + else { + info = g_strdup_printf("%s Switched to %d MHz (%d)", tb80211_current_iface->ifname, new_freq, ws80211_frequency_to_channel(new_freq)); + tb80211_current_freq = new_freq; + tb80211_current_type = new_type; + } + tb80211_set_info(info); + g_free(info); +} + +static void +tb80211_set_chan_cb(GtkWidget *widget _U_, gpointer data _U_) +{ + if (!tb80211_current_iface || tb80211_dont_set_chan) + return; + + tb80211_set_channel(); +} + +static void +tb80211_iface_changed_cb(GtkWidget *widget, gpointer data _U_) +{ + unsigned int i; + int ret; + struct ws80211_interface *iface; + struct ws80211_iface_info iface_info; + gchar *active; + GtkComboBoxText *combo = GTK_COMBO_BOX_TEXT(widget); + + if (tb80211_dont_set_iface) + return; + + active = gtk_combo_box_text_get_active_text(combo); + + if (!active || tb80211_dont_set_chan) + goto out_free; + + for (i = 0; i < tb80211_interfaces->len; i++) { + iface = g_array_index(tb80211_interfaces, struct ws80211_interface *, i); + if (strcmp(active, iface->ifname) == 0) { + tb80211_current_iface = iface; + break; + } + } + + tb80211_current_freq = -1; + tb80211_current_type = -1; + if (tb80211_current_iface) { + ret = ws80211_get_iface_info(tb80211_current_iface->ifname, &iface_info); + if (!ret) { + tb80211_current_freq = iface_info.current_freq; + tb80211_current_type = iface_info.current_chan_type; + } + } + tb80211_update_freq_and_type(); + +out_free: + g_free(active); +} + +static void +tb80211_update_interfaces(void) +{ + struct ws80211_interface *iface; + unsigned int i; + gboolean same = FALSE; + gchar *selected_iface = NULL, *info; + + if (tb80211_interfaces) { + selected_iface = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(tb80211_iface_list_box)); + + for (i = 0; i < tb80211_interfaces->len; i++) + gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(tb80211_iface_list_box), 0); + + ws80211_free_interfaces(tb80211_interfaces); + tb80211_interfaces = NULL; + tb80211_current_iface = NULL; + } + tb80211_interfaces = ws80211_find_interfaces(); + + if (!tb80211_interfaces) { + goto out_free; + } + + tb80211_dont_set_iface = TRUE; + for (i = 0; i < tb80211_interfaces->len; i++) { + iface = g_array_index(tb80211_interfaces, struct ws80211_interface *, i); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(tb80211_iface_list_box), iface->ifname); + + if (selected_iface && strcmp(selected_iface, iface->ifname) == 0) { + gtk_combo_box_set_active(GTK_COMBO_BOX(tb80211_iface_list_box), i); + tb80211_current_iface = iface; + same = TRUE; + } + } + tb80211_dont_set_iface = FALSE; + + /* Reset selectors if interface disappeared */ + if (!same) { + gtk_combo_box_set_active(GTK_COMBO_BOX(tb80211_iface_list_box), -1); + gtk_combo_box_set_active(GTK_COMBO_BOX(tb80211_freq_list_box), -1); + gtk_combo_box_set_active(GTK_COMBO_BOX(tb80211_chan_type_box), -1); + } + + info = g_strdup_printf("%d monitor interfaces found", tb80211_interfaces->len); + tb80211_set_info(info); + g_free(info); +out_free: + g_free(selected_iface); +} + +static void +tb80211_update_iface_cb(GtkWidget *widget _U_, gpointer data _U_) +{ + tb80211_update_interfaces(); +} + +static void +tb80211_add_label(gchar *text, GtkWidget *tb) +{ + GtkWidget *label; + GtkToolItem *label_ti; + + label_ti = gtk_tool_item_new(); + gtk_widget_show(GTK_WIDGET (label_ti)); + label = gtk_label_new(text); + gtk_widget_show(GTK_WIDGET (label)); + gtk_container_add(GTK_CONTAINER(label_ti), label); + gtk_toolbar_insert(GTK_TOOLBAR(tb), label_ti, -1); +} + +GtkWidget * +ws80211_toolbar_new(void) +{ + GtkWidget *tb80211_tb; + GtkToolItem *ti; + int ret; + + /* filter toolbar */ + tb80211_tb = gtk_toolbar_new(); + gtk_orientable_set_orientation(GTK_ORIENTABLE(tb80211_tb), + GTK_ORIENTATION_HORIZONTAL); + + gtk_widget_show(tb80211_tb); + + tb80211_add_label(" Interface: ", tb80211_tb); + + ti = gtk_tool_item_new(); + gtk_widget_show(GTK_WIDGET (ti)); + tb80211_iface_list_box = gtk_combo_box_text_new(); + g_signal_connect(tb80211_iface_list_box, "changed", G_CALLBACK(tb80211_iface_changed_cb), NULL); + gtk_container_add(GTK_CONTAINER(ti), tb80211_iface_list_box); + gtk_widget_show(GTK_WIDGET (tb80211_iface_list_box)); + gtk_toolbar_insert(GTK_TOOLBAR(tb80211_tb), ti, -1); + + ti = gtk_tool_button_new_from_stock(GTK_STOCK_REFRESH); + gtk_widget_set_tooltip_text(GTK_WIDGET(ti), "Refresh interfaces"); + g_signal_connect(ti, "clicked", G_CALLBACK(tb80211_update_iface_cb), NULL); + gtk_toolbar_insert(GTK_TOOLBAR(tb80211_tb), ti, -1); + gtk_widget_show(GTK_WIDGET(ti)); + + tb80211_add_label(" Frequency: ", tb80211_tb); + + ti = gtk_tool_item_new(); + gtk_widget_show(GTK_WIDGET (ti)); + tb80211_freq_list_box = gtk_combo_box_text_new(); + g_signal_connect(tb80211_freq_list_box, "changed", G_CALLBACK(tb80211_set_chan_cb), NULL); + gtk_container_add(GTK_CONTAINER(ti), tb80211_freq_list_box); + gtk_widget_show(GTK_WIDGET (tb80211_freq_list_box)); + gtk_toolbar_insert(GTK_TOOLBAR(tb80211_tb), ti, -1); + + ti = gtk_tool_item_new(); + gtk_widget_show(GTK_WIDGET (ti)); + tb80211_chan_type_box = gtk_combo_box_text_new(); + g_signal_connect(tb80211_chan_type_box, "changed", G_CALLBACK(tb80211_set_chan_cb), NULL); + gtk_container_add(GTK_CONTAINER(ti), tb80211_chan_type_box); + gtk_widget_show(GTK_WIDGET (tb80211_chan_type_box)); + gtk_toolbar_insert(GTK_TOOLBAR(tb80211_tb), ti, -1); + + ti = gtk_separator_tool_item_new(); + gtk_widget_show(GTK_WIDGET (ti)); + gtk_toolbar_insert(GTK_TOOLBAR(tb80211_tb), ti, -1); + + ti = gtk_tool_item_new(); + gtk_widget_show(GTK_WIDGET (ti)); + tb80211_info_label = gtk_label_new(""); + gtk_container_add(GTK_CONTAINER(ti), tb80211_info_label); + gtk_widget_show(GTK_WIDGET (tb80211_info_label)); + gtk_toolbar_insert(GTK_TOOLBAR(tb80211_tb), ti, -1); + + /* make current preferences effective */ + toolbar_redraw_all(); + + ret = ws80211_init(); + if (ret == -ENOTSUP) + tb80211_set_info("<b>Wireless support not enabled</b>"); + else if(ret) + tb80211_set_info("<b>Failed to initialize ws80211</b>"); + else { + tb80211_update_interfaces(); + } + + return tb80211_tb; +} |