forked from osmocom/wireshark
![Guy Harris](/assets/img/avatar_default.png)
as an argument, and, on an error, if they have an error message, have them set that "gchar *" to point to a g_malloc()ed string containing the error message, rather than taking a pointer to a buffer for that message as an argument. That's more like what's done in Wiretap, and doesn't impose an upper limit on the lengths of those error messages. If that pointer is null, don't allocate the message string and return it. Have that error message already have the "cant_get" processing applied to it, so nobody other than those routines need to call the "cant_get" routines to process the error messages. Have get_airpcap_interface_list() explicitly set "*err" to the appropriate error code. Clean up indentation. svn path=/trunk/; revision=20521
837 lines
25 KiB
C
837 lines
25 KiB
C
/* capture_prefs.c
|
|
* Dialog box for capture preferences
|
|
*
|
|
* $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.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
#include <string.h>
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "globals.h"
|
|
#include "capture_prefs.h"
|
|
#include "gtkglobals.h"
|
|
#include <epan/prefs.h>
|
|
#include "prefs_dlg.h"
|
|
#include "gui_utils.h"
|
|
#include "dlg_utils.h"
|
|
#include "simple_dialog.h"
|
|
#include "capture-pcap-util.h"
|
|
#include "capture_ui_utils.h"
|
|
#include "main.h"
|
|
#include "compat_macros.h"
|
|
|
|
#define DEVICE_KEY "device"
|
|
#define PROM_MODE_KEY "prom_mode"
|
|
#define CAPTURE_REAL_TIME_KEY "capture_real_time"
|
|
#define AUTO_SCROLL_KEY "auto_scroll"
|
|
#define SHOW_INFO_KEY "show_info"
|
|
|
|
#define CAPTURE_TABLE_ROWS 6
|
|
|
|
#define IFOPTS_CALLER_PTR_KEY "ifopts_caller_ptr"
|
|
#define IFOPTS_DIALOG_PTR_KEY "ifopts_dialog_ptr"
|
|
#define IFOPTS_TABLE_ROWS 2
|
|
#define IFOPTS_CLIST_COLS 4
|
|
#define IFOPTS_MAX_DESCR_LEN 128
|
|
#define IFOPTS_IF_NOSEL -1
|
|
|
|
/* interface options dialog */
|
|
static GtkWidget *cur_clist, *if_dev_lb, *if_name_lb, *if_descr_te, *if_hide_cb;
|
|
static gint ifrow; /* current interface row selected */
|
|
|
|
static void ifopts_edit_cb(GtkWidget *w, gpointer data);
|
|
static void ifopts_edit_ok_cb(GtkWidget *w, gpointer parent_w);
|
|
static void ifopts_edit_destroy_cb(GtkWidget *win, gpointer data);
|
|
static void ifopts_edit_ifsel_cb(GtkWidget *clist, gint row, gint column,
|
|
GdkEventButton *event, gpointer data);
|
|
static void ifopts_edit_descr_changed_cb(GtkEditable *ed, gpointer udata);
|
|
static void ifopts_edit_hide_changed_cb(GtkToggleButton *tbt, gpointer udata);
|
|
static void ifopts_options_add(GtkCList *clist, if_info_t *if_info);
|
|
static void ifopts_options_free(gchar *text[]);
|
|
static void ifopts_if_clist_add(void);
|
|
static void ifopts_write_new_descr(void);
|
|
static void ifopts_write_new_hide(void);
|
|
|
|
GtkWidget*
|
|
capture_prefs_show(void)
|
|
{
|
|
GtkWidget *main_tb, *main_vb;
|
|
GtkWidget *if_cb, *if_lb, *promisc_cb, *sync_cb, *auto_scroll_cb, *show_info_cb;
|
|
GtkWidget *ifopts_lb, *ifopts_bt;
|
|
GList *if_list, *combo_list;
|
|
int err;
|
|
int row = 0;
|
|
GtkTooltips *tooltips = gtk_tooltips_new();
|
|
|
|
/* Main vertical box */
|
|
main_vb = gtk_vbox_new(FALSE, 7);
|
|
gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
|
|
|
|
/* Main table */
|
|
main_tb = gtk_table_new(CAPTURE_TABLE_ROWS, 2, FALSE);
|
|
gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
|
|
gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
|
|
gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15);
|
|
gtk_widget_show(main_tb);
|
|
|
|
/* Default device */
|
|
if_lb = gtk_label_new("Default interface:");
|
|
gtk_table_attach_defaults(GTK_TABLE(main_tb), if_lb, 0, 1, row, row+1);
|
|
gtk_misc_set_alignment(GTK_MISC(if_lb), 1.0, 0.5);
|
|
gtk_widget_show(if_lb);
|
|
|
|
if_cb = gtk_combo_new();
|
|
/*
|
|
* XXX - what if we can't get the list?
|
|
*/
|
|
if_list = get_interface_list(&err, NULL);
|
|
combo_list = build_capture_combo_list(if_list, FALSE);
|
|
free_interface_list(if_list);
|
|
if (combo_list != NULL) {
|
|
gtk_combo_set_popdown_strings(GTK_COMBO(if_cb), combo_list);
|
|
free_capture_combo_list(combo_list);
|
|
}
|
|
if (prefs.capture_device)
|
|
gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry),
|
|
prefs.capture_device);
|
|
gtk_table_attach_defaults(GTK_TABLE(main_tb), if_cb, 1, 2, row, row+1);
|
|
gtk_tooltips_set_tip(tooltips, GTK_COMBO(if_cb)->entry,
|
|
"The default interface to be captured from.", NULL);
|
|
gtk_widget_show(if_cb);
|
|
OBJECT_SET_DATA(main_vb, DEVICE_KEY, if_cb);
|
|
row++;
|
|
|
|
/* Interface properties */
|
|
ifopts_lb = gtk_label_new("Interfaces:");
|
|
gtk_table_attach_defaults(GTK_TABLE(main_tb), ifopts_lb, 0, 1, row, row+1);
|
|
gtk_misc_set_alignment(GTK_MISC(ifopts_lb), 1.0, 0.5);
|
|
gtk_widget_show(ifopts_lb);
|
|
|
|
ifopts_bt = BUTTON_NEW_FROM_STOCK(WIRESHARK_STOCK_EDIT);
|
|
gtk_tooltips_set_tip(tooltips, ifopts_bt,
|
|
"Open a dialog box to set various interface options.", NULL);
|
|
SIGNAL_CONNECT(ifopts_bt, "clicked", ifopts_edit_cb, NULL);
|
|
gtk_table_attach_defaults(GTK_TABLE(main_tb), ifopts_bt, 1, 2, row, row+1);
|
|
row++;
|
|
|
|
/* Promiscuous mode */
|
|
promisc_cb = create_preference_check_button(main_tb, row++,
|
|
"Capture packets in promiscuous mode:", NULL,
|
|
prefs.capture_prom_mode);
|
|
gtk_tooltips_set_tip(tooltips, promisc_cb,
|
|
"Usually a network card will only capture the traffic sent to its own network address. "
|
|
"If you want to capture all traffic that the network card can \"see\", mark this option. "
|
|
"See the FAQ for some more details of capturing packets from a switched network.", NULL);
|
|
OBJECT_SET_DATA(main_vb, PROM_MODE_KEY, promisc_cb);
|
|
|
|
/* Real-time capture */
|
|
sync_cb = create_preference_check_button(main_tb, row++,
|
|
"Update list of packets in real time:", NULL,
|
|
prefs.capture_real_time);
|
|
gtk_tooltips_set_tip(tooltips, sync_cb,
|
|
"Update the list of packets while capture is in progress. "
|
|
"Don't use this option if you notice packet drops.", NULL);
|
|
OBJECT_SET_DATA(main_vb, CAPTURE_REAL_TIME_KEY, sync_cb);
|
|
|
|
/* Auto-scroll real-time capture */
|
|
auto_scroll_cb = create_preference_check_button(main_tb, row++,
|
|
"Automatic scrolling in live capture:", NULL,
|
|
prefs.capture_auto_scroll);
|
|
gtk_tooltips_set_tip(tooltips, auto_scroll_cb,
|
|
"Automatic scrolling of the packet list while live capture is in progress. ", NULL);
|
|
OBJECT_SET_DATA(main_vb, AUTO_SCROLL_KEY, auto_scroll_cb);
|
|
|
|
/* Show capture info dialog */
|
|
show_info_cb = create_preference_check_button(main_tb, row++,
|
|
"Hide capture info dialog:", NULL,
|
|
!prefs.capture_show_info);
|
|
gtk_tooltips_set_tip(tooltips, show_info_cb,
|
|
"Hide the capture info dialog while capturing. ", NULL);
|
|
OBJECT_SET_DATA(main_vb, SHOW_INFO_KEY, show_info_cb);
|
|
|
|
/* Show 'em what we got */
|
|
gtk_widget_show_all(main_vb);
|
|
|
|
return(main_vb);
|
|
}
|
|
|
|
void
|
|
capture_prefs_fetch(GtkWidget *w)
|
|
{
|
|
GtkWidget *if_cb, *promisc_cb, *sync_cb, *auto_scroll_cb, *show_info_cb;
|
|
gchar *if_text;
|
|
|
|
if_cb = (GtkWidget *)OBJECT_GET_DATA(w, DEVICE_KEY);
|
|
promisc_cb = (GtkWidget *)OBJECT_GET_DATA(w, PROM_MODE_KEY);
|
|
sync_cb = (GtkWidget *)OBJECT_GET_DATA(w, CAPTURE_REAL_TIME_KEY);
|
|
auto_scroll_cb = (GtkWidget *)OBJECT_GET_DATA(w, AUTO_SCROLL_KEY);
|
|
show_info_cb = (GtkWidget *)OBJECT_GET_DATA(w, SHOW_INFO_KEY);
|
|
|
|
if (prefs.capture_device != NULL) {
|
|
g_free(prefs.capture_device);
|
|
prefs.capture_device = NULL;
|
|
}
|
|
if_text = g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry)));
|
|
/* Strip out white space */
|
|
g_strstrip(if_text);
|
|
/* If there was nothing but white space, treat that as an
|
|
indication that the user doesn't want to wire in a default
|
|
device, and just wants the first device in the list chosen. */
|
|
if (*if_text == '\0') {
|
|
g_free(if_text);
|
|
if_text = NULL;
|
|
}
|
|
prefs.capture_device = if_text;
|
|
|
|
prefs.capture_prom_mode = GTK_TOGGLE_BUTTON (promisc_cb)->active;
|
|
|
|
prefs.capture_real_time = GTK_TOGGLE_BUTTON (sync_cb)->active;
|
|
|
|
prefs.capture_auto_scroll = GTK_TOGGLE_BUTTON (auto_scroll_cb)->active;
|
|
|
|
prefs.capture_show_info = !(GTK_TOGGLE_BUTTON (show_info_cb)->active);
|
|
}
|
|
|
|
void
|
|
capture_prefs_apply(GtkWidget *w _U_)
|
|
{
|
|
}
|
|
|
|
void
|
|
capture_prefs_destroy(GtkWidget *w)
|
|
{
|
|
GtkWidget *caller = gtk_widget_get_toplevel(w);
|
|
GtkWidget *dlg;
|
|
|
|
/* Is there an interface descriptions dialog associated with this
|
|
Preferences dialog? */
|
|
dlg = OBJECT_GET_DATA(caller, IFOPTS_DIALOG_PTR_KEY);
|
|
|
|
if (dlg != NULL) {
|
|
/* Yes. Destroy it. */
|
|
window_destroy(dlg);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Create an edit interface options dialog.
|
|
*/
|
|
static void
|
|
ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
|
|
{
|
|
GtkWidget *ifopts_edit_dlg, *cur_scr_win, *main_hb, *main_tb,
|
|
*cur_opts_fr, *ed_opts_fr, *main_vb,
|
|
*if_descr_lb, *if_hide_lb,
|
|
*bbox, *ok_bt, *cancel_bt;
|
|
const gchar *cur_titles[] = { "Device", "Description", "Comment", "Hide?" };
|
|
int row = 0;
|
|
|
|
GtkWidget *caller = gtk_widget_get_toplevel(w);
|
|
|
|
/* Has an edit dialog box already been opened for that top-level
|
|
widget? */
|
|
ifopts_edit_dlg = OBJECT_GET_DATA(caller, IFOPTS_DIALOG_PTR_KEY);
|
|
if (ifopts_edit_dlg != NULL) {
|
|
/* Yes. Just re-activate that dialog box. */
|
|
reactivate_window(ifopts_edit_dlg);
|
|
return;
|
|
}
|
|
|
|
/* create a new dialog */
|
|
ifopts_edit_dlg = dlg_window_new("Wireshark: Preferences: Interface Options");
|
|
gtk_window_set_default_size(GTK_WINDOW(ifopts_edit_dlg), DEF_WIDTH, 300);
|
|
|
|
main_vb = gtk_vbox_new(FALSE, 1);
|
|
gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
|
|
gtk_container_add(GTK_CONTAINER(ifopts_edit_dlg), main_vb);
|
|
gtk_widget_show(main_vb);
|
|
|
|
/* create current options frame */
|
|
cur_opts_fr = gtk_frame_new("Interfaces");
|
|
gtk_container_add(GTK_CONTAINER(main_vb), cur_opts_fr);
|
|
gtk_widget_show(cur_opts_fr);
|
|
|
|
/* create a scrolled window to pack the current options CList widget into */
|
|
cur_scr_win = scrolled_window_new(NULL, NULL);
|
|
gtk_container_border_width(GTK_CONTAINER(cur_scr_win), 3);
|
|
gtk_container_add(GTK_CONTAINER(cur_opts_fr), cur_scr_win);
|
|
gtk_widget_show(cur_scr_win);
|
|
|
|
/*
|
|
* Create current options CList.
|
|
*/
|
|
cur_clist = gtk_clist_new_with_titles(IFOPTS_CLIST_COLS, (gchar **) cur_titles);
|
|
gtk_clist_set_column_width(GTK_CLIST(cur_clist), 1, 230);
|
|
gtk_clist_set_column_width(GTK_CLIST(cur_clist), 2, 260);
|
|
gtk_clist_set_column_width(GTK_CLIST(cur_clist), 3, 40);
|
|
gtk_clist_column_titles_passive(GTK_CLIST(cur_clist));
|
|
gtk_container_add(GTK_CONTAINER(cur_scr_win), cur_clist);
|
|
SIGNAL_CONNECT(cur_clist, "select_row", ifopts_edit_ifsel_cb, NULL);
|
|
gtk_widget_show(cur_clist);
|
|
|
|
/* add interface names to cell */
|
|
ifopts_if_clist_add();
|
|
gtk_clist_columns_autosize(GTK_CLIST(cur_clist));
|
|
|
|
/* initialize variable that saves currently selected row in "if_clist" */
|
|
ifrow = IFOPTS_IF_NOSEL;
|
|
|
|
/* create edit options frame */
|
|
ed_opts_fr = gtk_frame_new("Properties");
|
|
gtk_box_pack_start(GTK_BOX(main_vb), ed_opts_fr, FALSE, FALSE, 0);
|
|
gtk_widget_show(ed_opts_fr);
|
|
|
|
main_hb = gtk_hbox_new(TRUE, 5);
|
|
gtk_container_border_width(GTK_CONTAINER(main_hb), 3);
|
|
gtk_container_add(GTK_CONTAINER(ed_opts_fr), main_hb);
|
|
gtk_widget_show(main_hb);
|
|
|
|
/* table to hold description text entry and hide button */
|
|
main_tb = gtk_table_new(IFOPTS_TABLE_ROWS, 4, FALSE);
|
|
gtk_box_pack_start(GTK_BOX(main_hb), main_tb, TRUE, FALSE, 10);
|
|
gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
|
|
gtk_table_set_col_spacings(GTK_TABLE(main_tb), 10);
|
|
gtk_widget_show(main_tb);
|
|
|
|
if_dev_lb = gtk_label_new("Device:");
|
|
gtk_table_attach_defaults(GTK_TABLE(main_tb), if_dev_lb, 0, 1, row, row+1);
|
|
gtk_misc_set_alignment(GTK_MISC(if_dev_lb), 1.0, 0.5);
|
|
gtk_widget_show(if_dev_lb);
|
|
|
|
if_dev_lb = gtk_label_new("");
|
|
gtk_table_attach_defaults(GTK_TABLE(main_tb), if_dev_lb, 1, 2, row, row+1);
|
|
gtk_misc_set_alignment(GTK_MISC(if_dev_lb), 0.0, 0.5);
|
|
gtk_widget_show(if_dev_lb);
|
|
row++;
|
|
|
|
if_name_lb = gtk_label_new("Description:");
|
|
gtk_table_attach_defaults(GTK_TABLE(main_tb), if_name_lb, 0, 1, row, row+1);
|
|
gtk_misc_set_alignment(GTK_MISC(if_name_lb), 1.0, 0.5);
|
|
gtk_widget_show(if_name_lb);
|
|
|
|
if_name_lb = gtk_label_new("");
|
|
gtk_table_attach_defaults(GTK_TABLE(main_tb), if_name_lb, 1, 2, row, row+1);
|
|
gtk_misc_set_alignment(GTK_MISC(if_name_lb), 0.0, 0.5);
|
|
gtk_widget_show(if_name_lb);
|
|
row++;
|
|
|
|
/* create interface description label and text entry */
|
|
if_descr_lb = gtk_label_new("Comment:");
|
|
gtk_table_attach_defaults(GTK_TABLE(main_tb), if_descr_lb, 0, 1, row, row+1);
|
|
gtk_misc_set_alignment(GTK_MISC(if_descr_lb), 1.0, 0.5);
|
|
gtk_widget_show(if_descr_lb);
|
|
|
|
if_descr_te = gtk_entry_new();
|
|
SIGNAL_CONNECT(if_descr_te, "changed", ifopts_edit_descr_changed_cb,
|
|
cur_clist);
|
|
gtk_entry_set_max_length(GTK_ENTRY(if_descr_te), IFOPTS_MAX_DESCR_LEN);
|
|
gtk_table_attach_defaults(GTK_TABLE(main_tb), if_descr_te, 1, 2, row, row+1);
|
|
gtk_widget_show(if_descr_te);
|
|
row++;
|
|
|
|
/* create hide interface label and button */
|
|
if_hide_lb = gtk_label_new("Hide interface?:");
|
|
gtk_table_attach_defaults(GTK_TABLE(main_tb), if_hide_lb, 0, 1, row, row+1);
|
|
gtk_misc_set_alignment(GTK_MISC(if_hide_lb), 1.0, 0.5);
|
|
gtk_widget_show(if_hide_lb);
|
|
|
|
if_hide_cb = gtk_check_button_new();
|
|
SIGNAL_CONNECT(if_hide_cb, "toggled", ifopts_edit_hide_changed_cb,
|
|
cur_clist);
|
|
gtk_table_attach_defaults(GTK_TABLE(main_tb), if_hide_cb, 1, 2, row, row+1);
|
|
gtk_widget_show(if_hide_cb);
|
|
row++;
|
|
|
|
/* button row: OK and Cancel buttons */
|
|
bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL);
|
|
gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
|
|
gtk_widget_show(bbox);
|
|
|
|
ok_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_OK);
|
|
SIGNAL_CONNECT(ok_bt, "clicked", ifopts_edit_ok_cb, ifopts_edit_dlg);
|
|
|
|
cancel_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CANCEL);
|
|
window_set_cancel_button(ifopts_edit_dlg, cancel_bt, window_cancel_button_cb);
|
|
|
|
gtk_widget_grab_default(ok_bt);
|
|
|
|
SIGNAL_CONNECT(ifopts_edit_dlg, "delete_event", window_delete_event_cb,
|
|
NULL);
|
|
/* Call a handler when we're destroyed, so we can inform
|
|
our caller, if any, that we've been destroyed. */
|
|
SIGNAL_CONNECT(ifopts_edit_dlg, "destroy", ifopts_edit_destroy_cb, NULL);
|
|
|
|
/* Set the key for the new dialog to point to our caller. */
|
|
OBJECT_SET_DATA(ifopts_edit_dlg, IFOPTS_CALLER_PTR_KEY, caller);
|
|
/* Set the key for the caller to point to us */
|
|
OBJECT_SET_DATA(caller, IFOPTS_DIALOG_PTR_KEY, ifopts_edit_dlg);
|
|
|
|
/* select the first row in if list, all option fields must exist for this */
|
|
gtk_clist_select_row(GTK_CLIST(cur_clist), 0, -1);
|
|
|
|
gtk_widget_show(ifopts_edit_dlg);
|
|
window_present(ifopts_edit_dlg);
|
|
}
|
|
|
|
/*
|
|
* User selected "OK". Create/write preferences strings.
|
|
*/
|
|
static void
|
|
ifopts_edit_ok_cb(GtkWidget *w _U_, gpointer parent_w)
|
|
{
|
|
if (ifrow != IFOPTS_IF_NOSEL) {
|
|
/* create/write new interfaces description string */
|
|
ifopts_write_new_descr();
|
|
|
|
/* create/write new "hidden" interfaces string */
|
|
ifopts_write_new_hide();
|
|
}
|
|
|
|
/* Now nuke this window. */
|
|
gtk_grab_remove(GTK_WIDGET(parent_w));
|
|
window_destroy(GTK_WIDGET(parent_w));
|
|
}
|
|
|
|
static void
|
|
ifopts_edit_destroy_cb(GtkWidget *win, gpointer data _U_)
|
|
{
|
|
GtkWidget *caller;
|
|
|
|
/* Get the widget that requested that we be popped up, if any.
|
|
(It should arrange to destroy us if it's destroyed, so
|
|
that we don't get a pointer to a non-existent window here.) */
|
|
caller = OBJECT_GET_DATA(win, IFOPTS_CALLER_PTR_KEY);
|
|
|
|
if (caller != NULL) {
|
|
/* Tell it we no longer exist. */
|
|
OBJECT_SET_DATA(caller, IFOPTS_DIALOG_PTR_KEY, NULL);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Interface selected callback; update displayed widgets.
|
|
*/
|
|
static void
|
|
ifopts_edit_ifsel_cb(GtkWidget *clist _U_,
|
|
gint row,
|
|
gint column _U_,
|
|
GdkEventButton *event _U_,
|
|
gpointer data _U_)
|
|
{
|
|
gchar *text;
|
|
|
|
/* save currently selected row */
|
|
ifrow = row;
|
|
|
|
/* get/display the interface device from current CList */
|
|
gtk_clist_get_text(GTK_CLIST(cur_clist), row, 0, &text);
|
|
/* is needed, as gtk_entry_set_text() will change text again (bug in GTK?) */
|
|
text = strdup(text);
|
|
gtk_label_set_text(GTK_LABEL(if_dev_lb), text);
|
|
g_free(text);
|
|
|
|
/* get/display the interface name from current CList */
|
|
gtk_clist_get_text(GTK_CLIST(cur_clist), row, 1, &text);
|
|
/* is needed, as gtk_entry_set_text() will change text again (bug in GTK?) */
|
|
text = strdup(text);
|
|
gtk_label_set_text(GTK_LABEL(if_name_lb), text);
|
|
g_free(text);
|
|
|
|
/* get/display the interface description from current CList */
|
|
gtk_clist_get_text(GTK_CLIST(cur_clist), row, 2, &text);
|
|
/* is needed, as gtk_entry_set_text() will change text again (bug in GTK?) */
|
|
text = strdup(text);
|
|
gtk_entry_set_text(GTK_ENTRY(if_descr_te), text);
|
|
g_free(text);
|
|
|
|
/* get/display the "hidden" button state from current CList */
|
|
gtk_clist_get_text(GTK_CLIST(cur_clist), row, 3, &text);
|
|
if (strcmp("Yes", text) == 0)
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(if_hide_cb), TRUE);
|
|
else
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(if_hide_cb), FALSE);
|
|
}
|
|
|
|
/*
|
|
* Comment text entry changed callback; update current CList.
|
|
*/
|
|
static void
|
|
ifopts_edit_descr_changed_cb(GtkEditable *ed, gpointer udata)
|
|
{
|
|
gchar *text;
|
|
|
|
if (ifrow == IFOPTS_IF_NOSEL)
|
|
return;
|
|
|
|
/* get current description text and set value in current CList */
|
|
text = gtk_editable_get_chars(GTK_EDITABLE(ed), 0, -1);
|
|
/* replace any reserved formatting characters "()," with spaces */
|
|
g_strdelimit(text, "(),", ' ');
|
|
gtk_clist_set_text(GTK_CLIST(udata), ifrow, 2, text);
|
|
g_free(text);
|
|
}
|
|
|
|
/*
|
|
* Hide toggle button changed callback; update current CList.
|
|
*/
|
|
static void
|
|
ifopts_edit_hide_changed_cb(GtkToggleButton *tbt, gpointer udata)
|
|
{
|
|
if (ifrow == IFOPTS_IF_NOSEL)
|
|
return;
|
|
|
|
/* get "hidden" button state and set text in current CList */
|
|
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tbt)) == TRUE)
|
|
gtk_clist_set_text(GTK_CLIST(udata), ifrow, 3, "Yes");
|
|
else
|
|
gtk_clist_set_text(GTK_CLIST(udata), ifrow, 3, "No");
|
|
}
|
|
|
|
/*
|
|
* Add any saved options that apply to cells in current CList.
|
|
*
|
|
* NOTE:
|
|
* Interfaces that have been removed from the machine or disabled and
|
|
* no longer apply are ignored. Therefore, if the user subsequently
|
|
* selects "OK", the options for these interfaces are lost (they're
|
|
* lost permanently if "Save" is selected).
|
|
*/
|
|
static void
|
|
ifopts_options_add(GtkCList *clist, if_info_t *if_info)
|
|
{
|
|
gint row;
|
|
gchar *p;
|
|
gchar *ifnm;
|
|
gchar *desc;
|
|
gchar *pr_descr;
|
|
gchar *text[] = { NULL, NULL, NULL, NULL };
|
|
|
|
/* add interface descriptions and "hidden" flag */
|
|
if (prefs.capture_devices_descr != NULL) {
|
|
/* create working copy of device descriptions */
|
|
pr_descr = g_strdup(prefs.capture_devices_descr);
|
|
|
|
/* if we find a description for this interface */
|
|
if ((ifnm = strstr(pr_descr, if_info->name)) != NULL) {
|
|
p = ifnm;
|
|
while (*p != '\0') {
|
|
/* found left parenthesis, start of description */
|
|
if (*p == '(') {
|
|
/* set device name text */
|
|
text[0] = g_strdup(if_info->name);
|
|
/* set OS description + device name text */
|
|
if (if_info->description != NULL)
|
|
text[1] = g_strdup(if_info->description);
|
|
else
|
|
text[1] = g_strdup("");
|
|
/* check if interface is "hidden" */
|
|
if (prefs.capture_devices_hide != NULL) {
|
|
if (strstr(prefs.capture_devices_hide, if_info->name) != NULL)
|
|
text[3] = g_strdup("Yes");
|
|
else
|
|
text[3] = g_strdup("No");
|
|
}
|
|
else
|
|
text[3] = g_strdup("No");
|
|
p++;
|
|
/* if syntax error */
|
|
if ((*p == '\0') || (*p == ',') || (*p == '(') || (*p == ')')) {
|
|
ifopts_options_free(text);
|
|
break;
|
|
}
|
|
/* save pointer to beginning of description */
|
|
desc = p;
|
|
p++;
|
|
/* if syntax error */
|
|
if ((*p == '\0') || (*p == ',') || (*p == '(') || (*p == ')')) {
|
|
ifopts_options_free(text);
|
|
break;
|
|
}
|
|
/* skip to end of description */
|
|
while (*p != '\0') {
|
|
/* end of description */
|
|
if (*p == ')') {
|
|
/* terminate and set description text */
|
|
*p = '\0';
|
|
text[2] = g_strdup(desc);
|
|
/* add row to CList */
|
|
row = gtk_clist_append(GTK_CLIST(clist), text);
|
|
gtk_clist_set_selectable(GTK_CLIST(clist), row,
|
|
FALSE);
|
|
ifopts_options_free(text);
|
|
break;
|
|
}
|
|
p++;
|
|
}
|
|
/* get out */
|
|
break;
|
|
}
|
|
else
|
|
p++;
|
|
}
|
|
}
|
|
/* if there's no description for this interface */
|
|
else {
|
|
/* set device name text */
|
|
text[0] = g_strdup(if_info->name);
|
|
/* set OS description + device name text */
|
|
if (if_info->description != NULL)
|
|
text[1] = g_strdup(if_info->description);
|
|
else
|
|
text[1] = g_strdup("");
|
|
/* set empty description */
|
|
text[2] = g_strdup("");
|
|
/* check if interface is "hidden" */
|
|
if (prefs.capture_devices_hide != NULL) {
|
|
if (strstr(prefs.capture_devices_hide, if_info->name) != NULL)
|
|
text[3] = g_strdup("Yes");
|
|
else
|
|
text[3] = g_strdup("No");
|
|
}
|
|
else
|
|
text[3] = g_strdup("No");
|
|
|
|
/* add row to CList */
|
|
row = gtk_clist_append(GTK_CLIST(clist), text);
|
|
gtk_clist_set_selectable(GTK_CLIST(clist), row, FALSE);
|
|
ifopts_options_free(text);
|
|
}
|
|
|
|
g_free(pr_descr);
|
|
}
|
|
/*
|
|
* If we do not have any descriptions, but have "hidden" interfaces.
|
|
*/
|
|
else if (prefs.capture_devices_hide != NULL) {
|
|
/* set device name text */
|
|
text[0] = g_strdup(if_info->name);
|
|
/* set OS description + device name text */
|
|
if (if_info->description != NULL)
|
|
text[1] = g_strdup(if_info->description);
|
|
else
|
|
text[1] = g_strdup("");
|
|
/* set empty description */
|
|
text[2] = g_strdup("");
|
|
/* check if interface is "hidden" */
|
|
if (strstr(prefs.capture_devices_hide, if_info->name) != NULL)
|
|
text[3] = g_strdup("Yes");
|
|
else
|
|
text[3] = g_strdup("No");
|
|
|
|
/* add row to CList */
|
|
row = gtk_clist_append(GTK_CLIST(clist), text);
|
|
gtk_clist_set_selectable(GTK_CLIST(clist), row, FALSE);
|
|
ifopts_options_free(text);
|
|
}
|
|
/*
|
|
* If we have no descriptions and no "hidden" interfaces.
|
|
*/
|
|
else {
|
|
/* set device name text */
|
|
text[0] = g_strdup(if_info->name);
|
|
/* set OS description + device name text */
|
|
if (if_info->description != NULL)
|
|
text[1] = g_strdup(if_info->description);
|
|
else
|
|
text[1] = g_strdup("");
|
|
/* set empty description */
|
|
text[2] = g_strdup("");
|
|
/* interface is not "hidden" */
|
|
text[3] = g_strdup("No");
|
|
|
|
/* add row to CList */
|
|
row = gtk_clist_append(GTK_CLIST(clist), text);
|
|
gtk_clist_set_selectable(GTK_CLIST(clist), row, FALSE);
|
|
ifopts_options_free(text);
|
|
}
|
|
}
|
|
|
|
static void
|
|
ifopts_options_free(gchar *text[])
|
|
{
|
|
gint i;
|
|
|
|
for (i=0; i < IFOPTS_CLIST_COLS; i++) {
|
|
if (text[i] != NULL) {
|
|
g_free(text[i]);
|
|
text[i] = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Add all interfaces to interfaces CList.
|
|
*/
|
|
static void
|
|
ifopts_if_clist_add(void)
|
|
{
|
|
GList *if_list;
|
|
int err;
|
|
gchar *err_str;
|
|
if_info_t *if_info;
|
|
guint i;
|
|
guint nitems;
|
|
|
|
if_list = get_interface_list(&err, &err_str);
|
|
if (if_list == NULL && err == CANT_GET_INTERFACE_LIST) {
|
|
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str);
|
|
g_free(err_str);
|
|
return;
|
|
}
|
|
|
|
/* Seems we need to be at list head for g_list_length()? */
|
|
if_list = g_list_first(if_list);
|
|
nitems = g_list_length(if_list);
|
|
|
|
/* add OS description + interface name text to CList */
|
|
for (i=0; i < nitems; i++) {
|
|
if_info = g_list_nth_data(if_list, i);
|
|
/* should never happen, but just in case */
|
|
if (if_info == NULL)
|
|
continue;
|
|
|
|
/* fill current options CList with current preference values */
|
|
ifopts_options_add(GTK_CLIST(cur_clist), if_info);
|
|
}
|
|
|
|
free_interface_list(if_list);
|
|
}
|
|
|
|
/*
|
|
* Create/write new interfaces description string based on current CList.
|
|
* Put it into the preferences value.
|
|
*/
|
|
static void
|
|
ifopts_write_new_descr(void)
|
|
{
|
|
gint i;
|
|
gboolean first_if = TRUE; /* flag to check if first in list */
|
|
gchar *ifnm;
|
|
gchar *desc;
|
|
gchar *tmp_descr;
|
|
gchar *new_descr;
|
|
|
|
/* new preferences interfaces description string */
|
|
new_descr = g_malloc0(MAX_VAL_LEN);
|
|
|
|
/* get description for each row (interface) */
|
|
for (i = 0; ;i++) {
|
|
/* get description */
|
|
if (gtk_clist_get_text(GTK_CLIST(cur_clist), i, 2, &desc) != 1)
|
|
break;
|
|
/* if no description, skip this interface */
|
|
if (strlen(desc) == 0)
|
|
continue;
|
|
|
|
/* get interface name */
|
|
gtk_clist_get_text(GTK_CLIST(cur_clist), i, 0, &ifnm);
|
|
|
|
/*
|
|
* create/cat interface description to new string
|
|
* (leave space for parens, comma and terminator)
|
|
*/
|
|
if (first_if == TRUE)
|
|
tmp_descr = g_strdup_printf("%s(%s)", ifnm, desc);
|
|
else
|
|
tmp_descr = g_strdup_printf(",%s(%s)", ifnm, desc);
|
|
strcat(new_descr, tmp_descr);
|
|
g_free(tmp_descr);
|
|
/* set first-in-list flag to false */
|
|
first_if = FALSE;
|
|
}
|
|
|
|
/* write new description string to preferences */
|
|
if (strlen(new_descr) > 0) {
|
|
g_free(prefs.capture_devices_descr);
|
|
prefs.capture_devices_descr = new_descr;
|
|
}
|
|
/* no descriptions */
|
|
else {
|
|
g_free(prefs.capture_devices_descr);
|
|
g_free(new_descr);
|
|
prefs.capture_devices_descr = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Create/write new "hidden" interfaces string based on current CList.
|
|
* Put it into the preferences value.
|
|
*/
|
|
static void
|
|
ifopts_write_new_hide(void)
|
|
{
|
|
gint i;
|
|
gint first_if = TRUE; /* flag to check if first in list */
|
|
gchar *ifnm;
|
|
gchar *hide;
|
|
gchar *tmp_hide;
|
|
gchar *new_hide;
|
|
|
|
/* new preferences "hidden" interfaces string */
|
|
new_hide = g_malloc0(MAX_VAL_LEN);
|
|
|
|
/* get "hidden" flag text for each row (interface) */
|
|
for (i = 0; ;i++) {
|
|
/* get flag */
|
|
if (gtk_clist_get_text(GTK_CLIST(cur_clist), i, 3, &hide) != 1)
|
|
break;
|
|
/* if flag text is "No", skip this interface */
|
|
if (strcmp("No", hide) == 0)
|
|
continue;
|
|
|
|
/* get interface name */
|
|
gtk_clist_get_text(GTK_CLIST(cur_clist), i, 0, &ifnm);
|
|
|
|
/*
|
|
* create/cat interface to new string
|
|
*/
|
|
if (first_if == TRUE)
|
|
tmp_hide = g_strdup_printf("%s", ifnm);
|
|
else
|
|
tmp_hide = g_strdup_printf(",%s", ifnm);
|
|
|
|
strcat(new_hide, tmp_hide);
|
|
g_free(tmp_hide);
|
|
/* set first-in-list flag to false */
|
|
first_if = FALSE;
|
|
}
|
|
|
|
/* write new "hidden" string to preferences */
|
|
if (strlen(new_hide) > 0) {
|
|
g_free(prefs.capture_devices_hide);
|
|
prefs.capture_devices_hide = new_hide;
|
|
}
|
|
/* no "hidden" interfaces */
|
|
else {
|
|
g_free(prefs.capture_devices_hide);
|
|
g_free(new_hide);
|
|
prefs.capture_devices_hide = NULL;
|
|
}
|
|
}
|
|
|
|
#endif /* HAVE_LIBPCAP */
|