aboutsummaryrefslogtreecommitdiffstats
path: root/gtk
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2003-09-08 21:44:42 +0000
committerGuy Harris <guy@alum.mit.edu>2003-09-08 21:44:42 +0000
commit81fc518ec6eb6366b2143e6b56d0b35307a76812 (patch)
treebd4a44095ff701e0c5af8a301d4fb1c8d61d39b3 /gtk
parent3185b945fbe1912d86f77aa9be84eb73dffb3d28 (diff)
From Nathan Jennings:
support for user-supplied interface descriptions; support for hiding interfaces in drop-down list in capture dialog. Clean up comments written to preferences file. svn path=/trunk/; revision=8419
Diffstat (limited to 'gtk')
-rw-r--r--gtk/capture_dlg.c165
-rw-r--r--gtk/capture_prefs.c884
2 files changed, 1036 insertions, 13 deletions
diff --git a/gtk/capture_dlg.c b/gtk/capture_dlg.c
index a6fa99f727..1331b69b14 100644
--- a/gtk/capture_dlg.c
+++ b/gtk/capture_dlg.c
@@ -1,7 +1,7 @@
/* capture_dlg.c
* Routines for packet capture windows
*
- * $Id: capture_dlg.c,v 1.79 2003/07/25 04:11:50 gram Exp $
+ * $Id: capture_dlg.c,v 1.80 2003/09/08 21:44:42 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@@ -104,6 +104,15 @@ capture_prep_close_cb(GtkWidget *close_bt, gpointer parent_w);
static void
capture_prep_destroy_cb(GtkWidget *win, gpointer user_data);
+static GList *
+capture_dev_descr_add(GList *if_list);
+
+static char *
+capture_dev_descr_find(gchar *devs_descr, gchar *if_name);
+
+static GList *
+capture_dev_hide(GList *if_list);
+
void
capture_stop_cb(GtkWidget *w _U_, gpointer d _U_)
{
@@ -221,8 +230,15 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_)
gtk_widget_show(if_lb);
if_cb = gtk_combo_new();
- if (if_list != NULL)
+ if (if_list != NULL) {
+ /* remove interface(s) from list if "hidden" */
+ if (prefs.capture_devices_hide != NULL)
+ if_list = capture_dev_hide(if_list);
+ /* prepend interface descriptions to device name */
+ if (prefs.capture_devices_descr != NULL)
+ if_list = capture_dev_descr_add(if_list);
gtk_combo_set_popdown_strings(GTK_COMBO(if_cb), if_list);
+ }
if (cfile.iface == NULL && prefs.capture_device != NULL) {
/* No interface was specified on the command line or in a previous
capture, but there is one specified in the preferences file;
@@ -789,7 +805,9 @@ capture_prep_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w) {
if_text =
g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry)));
- /* Windows combo entries have a description followed by the interface name */
+ /* Remove interface description. Also, Windows combo entries have a
+ description followed by the interface name. These two cases are
+ OK as long as they're in front (see capture_dev_descr_add()). */
if_name = strrchr(if_text, ' ');
if (if_name == NULL) {
if_name = if_text;
@@ -1057,4 +1075,145 @@ capture_prep_adjust_sensitivity(GtkWidget *tb _U_, gpointer parent_w)
}
+/*
+ * Prepend capture devices description to interface list. Remove OS (pcap)
+ * supplied description if present.
+ */
+static GList *
+capture_dev_descr_add(GList *if_list)
+{
+
+ GList *if_new_list = NULL;
+ char *osd;
+ char *tmp_descr;
+ gchar *tmp_devs_descr;
+ gchar *tmp_dev_name;
+ guint i;
+ guint nitems;
+
+ /* 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);
+
+ /* Create new interface list with "(descr) if_name". */
+ for (i=0; i < nitems; i++) {
+ tmp_dev_name = g_list_nth_data(if_list, i);
+ /* should never happen, but just in case */
+ if (tmp_dev_name == NULL) {
+ if (if_new_list != NULL)
+ free_interface_list(if_new_list);
+ return if_list;
+ }
+ /* create copy since capture_dev_descr_find() inserts terminator */
+ tmp_devs_descr = g_strdup(prefs.capture_devices_descr);
+ /* find matching description */
+ tmp_descr = capture_dev_descr_find(tmp_devs_descr, tmp_dev_name);
+ /* prepend description */
+ if (tmp_descr != NULL) {
+ /* remove OS (pcap) description */
+ if ((osd = strrchr(tmp_dev_name, ' ')) != NULL) {
+ osd++;
+ if (osd != NULL)
+ tmp_dev_name = osd;
+ }
+ if_new_list = g_list_append(if_new_list,
+ g_strdup_printf("%s %s", tmp_descr, tmp_dev_name));
+ }
+ /* no description for this interface, just copy name */
+ else {
+ if_new_list = g_list_append(if_new_list, g_strdup(tmp_dev_name));
+ }
+ g_free(tmp_devs_descr);
+ }
+
+ free_interface_list(if_list);
+ /* return pointer to new interface list with descriptions */
+ return if_new_list;
+}
+
+/*
+ * Find capture device description that matches interface name.
+ */
+static char *
+capture_dev_descr_find(gchar *devs_descr, gchar *if_name)
+{
+ char *p;
+ char *p2 = NULL;
+ char *descr = NULL;
+ int lp = 0;
+ int ct = 0;
+
+ if (if_name == NULL)
+ return NULL;
+
+ if ((p = strstr(devs_descr, if_name)) == NULL)
+ return NULL;
+
+ while (p != NULL) {
+ /* error: ran into next interface description */
+ if (*p == ',')
+ return NULL;
+ /* found left parenthesis, start of description */
+ else if (*p == '(') {
+ lp++;
+ /* save pointer to beginning of description */
+ p2 = p;
+ p++;
+ continue;
+ }
+ else if (*p == ')') {
+ /* end of description */
+ break;
+ }
+ else {
+ p++;
+ ct++;
+ }
+ }
+
+ if ((lp == 1) && (ct > 0) && (p2 != NULL)) {
+ /* set returned pointer to beginning of description */
+ descr = p2;
+ /* insert terminator */
+ *(p+1) = '\0';
+ return descr;
+ }
+ else
+ return NULL;
+}
+
+/*
+ * Remove "hidden" interface(s) from list.
+ */
+static GList *
+capture_dev_hide(GList *if_list)
+{
+ GList *if_new_list = NULL;
+ gchar *tmp_dev_name;
+ guint i;
+ guint nitems;
+
+ /* 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);
+
+ /* Create new list without "hidden" interfaces. */
+ for (i=0; i < nitems; i++) {
+ tmp_dev_name = g_list_nth_data(if_list, i);
+ /* should never happen, but just in case */
+ if (tmp_dev_name == NULL) {
+ if (if_new_list != NULL)
+ free_interface_list(if_new_list);
+ return if_list;
+ }
+ /* check if interface name is in "hidden" preferences string */
+ if (strstr(prefs.capture_devices_hide, tmp_dev_name) == NULL)
+ if_new_list = g_list_append(if_new_list, g_strdup(tmp_dev_name));
+ }
+
+ free_interface_list(if_list);
+ /* return pointer to new interface list */
+ return if_new_list;
+}
+
#endif /* HAVE_LIBPCAP */
diff --git a/gtk/capture_prefs.c b/gtk/capture_prefs.c
index 1af5e6d19b..3c4f091071 100644
--- a/gtk/capture_prefs.c
+++ b/gtk/capture_prefs.c
@@ -1,7 +1,7 @@
/* capture_prefs.c
* Dialog box for capture preferences
*
- * $Id: capture_prefs.c,v 1.17 2002/11/11 18:57:00 oabad Exp $
+ * $Id: capture_prefs.c,v 1.18 2003/09/08 21:44:42 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@@ -28,6 +28,7 @@
#ifdef HAVE_LIBPCAP
+#include <string.h>
#include <gtk/gtk.h>
#include <pcap.h>
@@ -38,21 +39,50 @@
#include "prefs.h"
#include "prefs_dlg.h"
#include "ui_util.h"
+#include "simple_dialog.h"
#include "pcap-util.h"
#include "main.h"
#include "compat_macros.h"
-#define DEVICE_KEY "device"
-#define PROM_MODE_KEY "prom_mode"
+#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 AUTO_SCROLL_KEY "auto_scroll"
+
+#define DEVOPTS_CALLER_PTR_KEY "devopts_caller_ptr"
+#define DEVOPTS_DIALOG_PTR_KEY "devopts_dialog_ptr"
+
+#define CAPTURE_TABLE_ROWS 5
+#define DEVICES_OPTS_ROWS 2
+#define IF_OPTS_CLIST_COLS 3
+#define IF_OPTS_MAX_DESCR_LEN 128
+
+/* interface options dialog */
+static GtkWidget *new_clist, *if_descr_te, *if_hide_cb;
+static gint ifrow; /* last 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_close_cb(GtkWidget *close_bt, 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_ifunsel_cb(GtkWidget *clist, gint row, gint column,
+ GdkEventButton *event, gpointer data);
+static void ifopts_old_options_add(GtkCList *clist);
+static gboolean ifopts_old_options_chk(GtkCList *clist, gchar *ifname);
+static void ifopts_new_options_add(GtkCList *clist, gchar *ifname);
+static void ifopts_options_free(gchar *text[]);
+static void ifopts_if_clist_add(GtkCList *clist);
+static void ifopts_write_new_descr(void);
+static void ifopts_write_new_hide(void);
-#define CAPTURE_TABLE_ROWS 4
GtkWidget*
capture_prefs_show(void)
{
GtkWidget *main_tb, *main_vb;
GtkWidget *if_cb, *if_lb, *promisc_cb, *sync_cb, *auto_scroll_cb;
+ GtkWidget *ifopts_lb, *ifopts_bt;
GList *if_list;
int err;
char err_str[PCAP_ERRBUF_SIZE];
@@ -69,7 +99,7 @@ capture_prefs_show(void)
gtk_widget_show(main_tb);
/* Default device */
- if_lb = gtk_label_new("Interface:");
+ if_lb = gtk_label_new("Default interface:");
gtk_table_attach_defaults(GTK_TABLE(main_tb), if_lb, 0, 1, 0, 1);
gtk_misc_set_alignment(GTK_MISC(if_lb), 1.0, 0.5);
gtk_widget_show(if_lb);
@@ -90,20 +120,30 @@ capture_prefs_show(void)
free_interface_list(if_list);
+ /* Interface options */
+ ifopts_lb = gtk_label_new("Interface options:");
+ gtk_table_attach_defaults(GTK_TABLE(main_tb), ifopts_lb, 0, 1, 1, 2);
+ gtk_misc_set_alignment(GTK_MISC(ifopts_lb), 1.0, 0.5);
+ gtk_widget_show(ifopts_lb);
+
+ ifopts_bt = gtk_button_new_with_label("Edit...");
+ SIGNAL_CONNECT(ifopts_bt, "clicked", ifopts_edit_cb, NULL);
+ gtk_table_attach_defaults(GTK_TABLE(main_tb), ifopts_bt, 1, 2, 1, 2 );
+
/* Promiscuous mode */
- promisc_cb = create_preference_check_button(main_tb, 1,
+ promisc_cb = create_preference_check_button(main_tb, 2,
"Capture packets in promiscuous mode:", NULL,
prefs.capture_prom_mode);
OBJECT_SET_DATA(main_vb, PROM_MODE_KEY, promisc_cb);
/* Real-time capture */
- sync_cb = create_preference_check_button(main_tb, 2,
+ sync_cb = create_preference_check_button(main_tb, 3,
"Update list of packets in real time:", NULL,
prefs.capture_real_time);
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, 3,
+ auto_scroll_cb = create_preference_check_button(main_tb, 4,
"Automatic scrolling in live capture:", NULL,
prefs.capture_auto_scroll);
OBJECT_SET_DATA(main_vb, AUTO_SCROLL_KEY, auto_scroll_cb);
@@ -154,8 +194,832 @@ capture_prefs_apply(GtkWidget *w _U_)
}
void
-capture_prefs_destroy(GtkWidget *w _U_)
+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, DEVOPTS_DIALOG_PTR_KEY);
+
+ if (dlg != NULL) {
+ /* Yes. Destroy it. */
+ gtk_widget_destroy(dlg);
+ }
+}
+
+/* Create an edit interface options dialog. */
+static void
+ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
+{
+ GtkWidget *ifopts_edit_dlg, *old_scr_win, *if_scr_win, *main_hb, *main_tb,
+ *old_opts_fr, *opts_fr,
+ *old_clist, *if_clist, *if_descr_lb, *if_hide_lb,
+ *bbox, *ok_bt, *cancel_bt;
+ gchar *old_titles[3] = { "Interface", "Description", "Hide?" };
+ gchar *if_title[1] = { "Interface" };
+
+ 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, DEVOPTS_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 = gtk_dialog_new();
+ gtk_window_set_title(GTK_WINDOW(ifopts_edit_dlg),
+ "Ethereal: Preferences: Interface Options");
+ SIGNAL_CONNECT(ifopts_edit_dlg, "destroy", ifopts_edit_destroy_cb, NULL);
+ gtk_container_border_width(GTK_CONTAINER(GTK_DIALOG(ifopts_edit_dlg)->vbox),
+ 5);
+
+ /*
+ * XXX - What code can be put here, or somewhere else, to get the Ethereal
+ * icon loaded for this window?
+ */
+
+ /* create old options frame */
+ old_opts_fr = gtk_frame_new("Previously saved options");
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(ifopts_edit_dlg)->vbox),
+ old_opts_fr);
+ gtk_widget_show(old_opts_fr);
+
+ /* create a scrolled window to pack the old options CList widget into */
+ old_scr_win = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(old_scr_win),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+ gtk_container_border_width(GTK_CONTAINER(old_scr_win), 3);
+ gtk_container_add(GTK_CONTAINER(old_opts_fr), old_scr_win);
+ gtk_widget_show(old_scr_win);
+
+ /* create old options CList (previously saved options) */
+ old_clist = gtk_clist_new_with_titles(3, old_titles);
+ gtk_clist_set_column_width(GTK_CLIST(old_clist), 0, 200);
+ gtk_clist_set_column_width(GTK_CLIST(old_clist), 1, 200);
+ gtk_clist_set_column_width(GTK_CLIST(old_clist), 2, 40);
+ gtk_clist_column_titles_passive(GTK_CLIST(old_clist));
+ gtk_container_add(GTK_CONTAINER(old_scr_win), old_clist);
+
+ /* add text to old options cells */
+ ifopts_old_options_add(GTK_CLIST(old_clist));
+ gtk_widget_show(old_clist);
+
+ /* create new options CList to hold currently edited values */
+ /* XXX - Since this is an "invisible" widget used only as a table
+ * for storing newly edited interface options, do we need to manually
+ * deallocate/free it? (It's never added to a window with
+ * gtk_container_add().) */
+ new_clist = gtk_clist_new(3);
+
+ /* create edit options frame */
+ opts_fr = gtk_frame_new("Edit interface options");
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(ifopts_edit_dlg)->vbox),
+ opts_fr);
+ gtk_widget_show(opts_fr);
+
+ main_hb = gtk_hbox_new(TRUE, 5);
+ gtk_container_border_width(GTK_CONTAINER(main_hb), 3);
+ gtk_container_add(GTK_CONTAINER(opts_fr), main_hb);
+ gtk_widget_show(main_hb);
+
+ /* create a scrolled window to pack the interface CList widget into */
+ if_scr_win = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(if_scr_win),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+ gtk_box_pack_start(GTK_BOX(main_hb), if_scr_win, TRUE, TRUE, 0);
+ gtk_widget_show(if_scr_win);
+
+ /* create interface CList */
+ if_clist = gtk_clist_new_with_titles(1, if_title);
+ SIGNAL_CONNECT(if_clist, "select_row", ifopts_edit_ifsel_cb, if_clist);
+ SIGNAL_CONNECT(if_clist, "unselect_row", ifopts_edit_ifunsel_cb, if_clist);
+ gtk_clist_set_column_width(GTK_CLIST(if_clist), 0, 75);
+ gtk_clist_column_titles_passive(GTK_CLIST(if_clist));
+ gtk_clist_set_selection_mode(GTK_CLIST(if_clist), GTK_SELECTION_SINGLE);
+ gtk_container_add(GTK_CONTAINER(if_scr_win), if_clist);
+
+ /* initialize variable that saves the last selected row in "if_clist" */
+ ifrow = -1;
+
+ /* add text to interface cell */
+ ifopts_if_clist_add(GTK_CLIST(if_clist));
+ gtk_widget_show(if_clist);
+
+ /* table to hold description text entry and hide button */
+ main_tb = gtk_table_new(DEVICES_OPTS_ROWS, 2, 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);
+
+ /* create interface description label and text entry */
+ if_descr_lb = gtk_label_new("Description:");
+ gtk_table_attach_defaults(GTK_TABLE(main_tb), if_descr_lb, 0, 1, 0, 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();
+ gtk_entry_set_max_length(GTK_ENTRY(if_descr_te), IF_OPTS_MAX_DESCR_LEN);
+ gtk_table_attach_defaults(GTK_TABLE(main_tb), if_descr_te, 1, 2, 0, 1);
+ gtk_widget_show(if_descr_te);
+
+ /* 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, 1, 2);
+ 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();
+ gtk_table_attach_defaults(GTK_TABLE(main_tb), if_hide_cb, 1, 2, 1, 2);
+ gtk_widget_show(if_hide_cb);
+
+ /* button row: OK and Cancel buttons */
+ bbox = gtk_hbutton_box_new();
+ gtk_button_box_set_layout(GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
+ gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 10);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(ifopts_edit_dlg)->action_area), bbox,
+ TRUE, FALSE, 0);
+ gtk_widget_show(bbox);
+
+#if GTK_MAJOR_VERSION < 2
+ ok_bt = gtk_button_new_with_label ("OK");
+#else
+ ok_bt = gtk_button_new_from_stock(GTK_STOCK_OK);
+#endif
+
+ /* Connect the OK button to ifdescr_edit_ok_cb function */
+ SIGNAL_CONNECT(ok_bt, "clicked", ifopts_edit_ok_cb, ifopts_edit_dlg);
+ GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT);
+ gtk_container_add(GTK_CONTAINER(bbox), ok_bt);
+ gtk_widget_grab_default(ok_bt);
+ gtk_widget_show(ok_bt);
+
+#if GTK_MAJOR_VERSION < 2
+ cancel_bt = gtk_button_new_with_label ("Cancel");
+#else
+ cancel_bt = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+#endif
+ /* Connect the Cancel button to destroy the widget */
+ SIGNAL_CONNECT(cancel_bt, "clicked", ifopts_edit_close_cb, ifopts_edit_dlg);
+ GTK_WIDGET_SET_FLAGS(cancel_bt, GTK_CAN_DEFAULT);
+ gtk_container_add(GTK_CONTAINER(bbox), cancel_bt);
+ gtk_widget_show(cancel_bt);
+
+ /* 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 DEVOPTS_CALLER_PTR_KEY for the new dialog to point to
+ our caller. */
+ OBJECT_SET_DATA(ifopts_edit_dlg, DEVOPTS_CALLER_PTR_KEY, caller);
+
+ /* Set the DEVOPTS_DIALOG_PTR_KEY for the caller to point to us */
+ OBJECT_SET_DATA(caller, DEVOPTS_DIALOG_PTR_KEY, ifopts_edit_dlg);
+
+ /* Catch the "key_press_event" signal in the window, so that we can
+ catch the ESC key being pressed and act as if the "Cancel" button
+ had been selected. */
+ /*dlg_set_cancel(ifopts_edit_dlg, cancel_bt);*/
+
+ gtk_widget_show(ifopts_edit_dlg);
+}
+
+/*
+ * User selected "OK". Create/write preferences strings.
+ */
+static void
+ifopts_edit_ok_cb(GtkWidget *w _U_, gpointer parent_w)
+{
+
+ /*
+ * Update option values in "new" CList for the last selected interface.
+ * (Is there a function that returns the currently selected row?)
+ */
+ if (ifrow != -1)
+ ifopts_edit_ifunsel_cb(NULL, ifrow, 0, NULL, NULL);
+
+ /* 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));
+ gtk_widget_destroy(GTK_WIDGET(parent_w));
+}
+
+static void
+ifopts_edit_close_cb(GtkWidget *close_bt _U_, gpointer parent_w)
{
+ gtk_grab_remove(GTK_WIDGET(parent_w));
+ gtk_widget_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, DEVOPTS_CALLER_PTR_KEY);
+
+ if (caller != NULL) {
+ /* Tell it we no longer exist. */
+ OBJECT_SET_DATA(caller, DEVOPTS_DIALOG_PTR_KEY, NULL);
+ }
+
+ /* Now nuke this window. */
+ gtk_grab_remove(GTK_WIDGET(win));
+ gtk_widget_destroy(GTK_WIDGET(win));
+}
+
+/*
+ * 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;
+
+ /* get/display the interface description from "new" CList */
+ gtk_clist_get_text(GTK_CLIST(new_clist), row, 1, &text);
+ gtk_entry_set_text(GTK_ENTRY(if_descr_te), text);
+
+ /* get/display the "hidden" button state from "new" CList */
+ gtk_clist_get_text(GTK_CLIST(new_clist), row, 2, &text);
+ if (*text == '1')
+ 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);
+
+ /* save currently selected row so we can update its values on "OK". */
+ ifrow = row;
+}
+
+/*
+ * Interface unselected callback; update "new" CList values.
+ *
+ * NOTE:
+ * This is also called from "ifopts_edit_ok_cb" to update values in
+ * the "new" CList for the last selected interface; only "row" is passed
+ * as a valid value. Others are "NULL" or "0".
+ */
+static void
+ifopts_edit_ifunsel_cb(GtkWidget *clist _U_,
+ gint row,
+ gint column _U_,
+ GdkEventButton *event _U_,
+ gpointer data _U_)
+{
+ gchar *text;
+ gchar state[2] = { '\0' };
+
+ /* get interface description and set value in "new" CList */
+ text = gtk_editable_get_chars(GTK_EDITABLE(if_descr_te), 0, -1);
+ /* replace any reserved formatting characters "()," with spaces */
+ g_strdelimit(text, "(),", ' ');
+ gtk_clist_set_text(GTK_CLIST(new_clist), row, 1, text);
+ g_free(text);
+
+ /* get "hidden" button state and set value in "new" CList */
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(if_hide_cb)) == TRUE)
+ state[0] = '1';
+ else
+ state[0] = '0';
+ gtk_clist_set_text(GTK_CLIST(new_clist), row, 2, state);
+}
+
+/*
+ * Add previously saved options to cells in "old" CList.
+ */
+static void
+ifopts_old_options_add(GtkCList *clist)
+{
+ gchar *p;
+ gchar *ifnm;
+ gchar *desc;
+ gchar *pr_descr;
+ gchar *pr_hide;
+ gchar *text[3] = { '\0' };
+ gint row;
+ gint ct;
+
+ /* add interface descriptions and "hidden" yes/no text */
+ if (prefs.capture_devices_descr != NULL) {
+ /* create working copy of device descriptions */
+ pr_descr = g_strdup(prefs.capture_devices_descr);
+ p = pr_descr;
+ ifnm = p;
+
+ while (*p != '\0') {
+ /* found comma, start of next interface(description) */
+ if (*p == ',') {
+ /* add existing text */
+ if (text[0] != NULL) {
+ row = gtk_clist_append(GTK_CLIST(clist), text);
+ gtk_clist_set_selectable(GTK_CLIST(clist), row, FALSE);
+ ifopts_options_free(text);
+ }
+ p++;
+ /* reset interface name pointer to start of new name */
+ ifnm = p;
+ }
+ /* found left parenthesis, start of description */
+ else if (*p == '(') {
+ /* terminate and set interface name text */
+ *p = '\0';
+ text[0] = g_strdup(ifnm);
+ /* check if interface is "hidden" */
+ if (prefs.capture_devices_hide != NULL) {
+ if (strstr(prefs.capture_devices_hide, ifnm) != NULL)
+ text[2] = g_strdup("Yes");
+ else
+ text[2] = g_strdup("No");
+ }
+ else
+ text[2] = g_strdup("No");
+ *p = '(';
+ 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[1] = g_strdup(desc);
+ *p = ')';
+ p++;
+ break;
+ }
+ p++;
+ }
+ /* if we reached last interface description, add text */
+ if (*p == '\0') {
+ if (text[0] != NULL) {
+ row = gtk_clist_append(GTK_CLIST(clist), text);
+ gtk_clist_set_selectable(GTK_CLIST(clist), row, FALSE);
+ ifopts_options_free(text);
+ }
+ }
+ }
+ else
+ p++;
+ }
+
+ g_free(pr_descr);
+ }
+
+ /*
+ * Only add "hidden" interface yes/no text here; since we may not have
+ * any descriptions, but have "hidden" interfaces.
+ */
+ if (prefs.capture_devices_hide != NULL) {
+ /* create working copy of hidden interfaces */
+ pr_hide = g_strdup(prefs.capture_devices_hide);
+ p = pr_hide;
+ ifnm = p;
+ ct = 0;
+
+ while (*p != '\0') {
+ /* found comma, start of next interface */
+ if ((*p == ',') && (ct > 0)) {
+ /* terminate and set text */
+ *p = '\0';
+ text[0] = g_strdup(ifnm);
+ /* set empty description */
+ text[1] = NULL;
+ /* set "hidden" text */
+ text[2] = g_strdup("Yes");
+ /* add text if not previously added */
+ if (!ifopts_old_options_chk(GTK_CLIST(clist), text[0])) {
+ row = gtk_clist_append(GTK_CLIST(clist), text);
+ gtk_clist_set_selectable(GTK_CLIST(clist), row, FALSE);
+ }
+ ifopts_options_free(text);
+ *p = ',';
+ p++;
+ ifnm = p;
+ ct = 0;
+ }
+ p++;
+ ct++;
+ }
+
+ /* if we reached last "hidden" interface in list */
+ if (ct > 0) {
+ /* set text */
+ text[0] = g_strdup(ifnm);
+ /* set empty description */
+ text[1] = NULL;
+ /* set "hidden" text */
+ text[2] = g_strdup("Yes");
+ /* add text if not previously added */
+ if (!ifopts_old_options_chk(GTK_CLIST(clist), text[0])) {
+ row = gtk_clist_append(GTK_CLIST(clist), text);
+ gtk_clist_set_selectable(GTK_CLIST(clist), row, FALSE);
+ }
+ ifopts_options_free(text);
+ }
+
+ g_free(pr_hide);
+ }
+}
+
+/*
+ * Check to see if interface has already been added to "old" options CList.
+ * Returns TRUE if it has, FALSE if it hasn't.
+ */
+static gboolean
+ifopts_old_options_chk(GtkCList *clist, gchar *ifname)
+{
+ gint i;
+ gchar *ifnm;
+
+ /* get interface name for each row */
+ for (i = 0; ;i++) {
+ if (gtk_clist_get_text(GTK_CLIST(clist), i, 0, &ifnm) != 1)
+ break;
+ if (strcmp(ifnm, ifname) == 0)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+ * Add any old options that apply to cells in "new" CList. The "new" CList
+ * is never displayed. It's used only as a table to store values as they're
+ * edited by the user.
+ *
+ * NOTE: Be careful here since interfaces may have been removed from the
+ * machine or disabled and no longer apply.
+ */
+static void
+ifopts_new_options_add(GtkCList *clist, gchar *ifname)
+{
+ gchar *p;
+ gchar *ifnm;
+ gchar *desc;
+ gchar *pr_descr;
+ gchar *text[3] = { '\0' };
+
+ /* 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, ifname)) != NULL) {
+ p = ifnm;
+ while (*p != '\0') {
+ /* found left parenthesis, start of description */
+ if (*p == '(') {
+ /* set interface name text */
+ text[0] = g_strdup(ifname);
+ /* check if interface is "hidden" */
+ if (prefs.capture_devices_hide != NULL) {
+ if (strstr(prefs.capture_devices_hide, ifname) != NULL)
+ text[2] = g_strdup("1");
+ else
+ text[2] = g_strdup("0");
+ }
+ else
+ text[2] = g_strdup("0");
+ 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[1] = g_strdup(desc);
+ /* add row to CList */
+ gtk_clist_append(GTK_CLIST(clist), text);
+ ifopts_options_free(text);
+ break;
+ }
+ p++;
+ }
+ /* get out */
+ break;
+ }
+ else
+ p++;
+ }
+ }
+ /* if there's no description for this interface */
+ else {
+ /* set interface name */
+ text[0] = g_strdup(ifname);
+ /* set empty description */
+ text[1] = NULL;
+ /* check if interface is "hidden" */
+ if (prefs.capture_devices_hide != NULL) {
+ if (strstr(prefs.capture_devices_hide, ifname) != NULL)
+ text[2] = g_strdup("1");
+ else
+ text[2] = g_strdup("0");
+ }
+ else
+ text[2] = g_strdup("0");
+
+ /* add row to CList */
+ gtk_clist_append(GTK_CLIST(clist), text);
+ 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 interface name */
+ text[0] = g_strdup(ifname);
+ /* set empty description */
+ text[1] = NULL;
+ /* check if interface is "hidden" */
+ if (strstr(prefs.capture_devices_hide, ifname) != NULL)
+ text[2] = g_strdup("1");
+ else
+ text[2] = g_strdup("0");
+
+ /* add row to CList */
+ gtk_clist_append(GTK_CLIST(clist), text);
+ ifopts_options_free(text);
+ }
+ /*
+ * If we have no descriptions and no "hidden" interfaces.
+ */
+ else {
+ /* set interface name */
+ text[0] = g_strdup(ifname);
+ /* set empty description */
+ text[1] = NULL;
+ /* interface is not "hidden" */
+ text[2] = g_strdup("0");
+
+ /* add row to CList */
+ gtk_clist_append(GTK_CLIST(clist), text);
+ ifopts_options_free(text);
+ }
+}
+
+static void
+ifopts_options_free(gchar *text[])
+{
+ gint i;
+
+ for (i=0; i < IF_OPTS_CLIST_COLS; i++) {
+ if (text[i] != NULL) {
+ g_free(text[i]);
+ text[i] = NULL;
+ }
+ }
+}
+
+/*
+ * Add interfaces to displayed interfaces CList. Also, fill "new" options CList.
+ */
+static void
+ifopts_if_clist_add(GtkCList *clist)
+{
+ GList *if_list;
+ int err;
+ char err_str[PCAP_ERRBUF_SIZE];
+ gchar *text[1];
+ 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_WARN, NULL, "Can't get list of interfaces: %s",
+ 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 interface name text to CList */
+ for (i=0; i < nitems; i++) {
+ text[0] = g_list_nth_data(if_list, i);
+ /* should never happen, but just in case */
+ if (text[0] == NULL)
+ continue;
+ gtk_clist_append(GTK_CLIST(clist), text);
+ /* fill "new" options CList with previously saved values */
+ ifopts_new_options_add(GTK_CLIST(new_clist), text[0]);
+ }
+
+ free_interface_list(if_list);
+}
+
+/*
+ * Create/write new interfaces description string based on "new" CList.
+ */
+static void
+ifopts_write_new_descr(void)
+{
+ gint i;
+ gint first_if = 1; /* flag to check if 1st in list */
+ gchar *ifnm;
+ gchar *desc;
+ gchar *tmp_descr;
+ gchar *new_descr;
+
+ /* new preferences interfaces description string */
+ new_descr = g_malloc0(MAX_VAL_LEN);
+ if (new_descr == NULL) {
+ simple_dialog(ESD_TYPE_WARN, NULL, "Error (1) saving interface "
+ "descriptions: malloc failure");
+ return;
+ }
+
+ /*
+ * current row's interface description string
+ * (leave space for parens, comma and terminator)
+ */
+ /*
+ * XXX - Currently, MAX_WIN_IF_NAME_LEN is 511. This should be large
+ * enough for *nix. ;o)
+ */
+ tmp_descr = g_malloc0(IF_OPTS_MAX_DESCR_LEN + MAX_WIN_IF_NAME_LEN + 4);
+ if (tmp_descr == NULL) {
+ simple_dialog(ESD_TYPE_WARN, NULL, "Error (2) saving interface "
+ "descriptions: malloc failure");
+ g_free(new_descr);
+ return;
+ }
+
+ /* get description for each row (interface) */
+ for (i = 0; ;i++) {
+ /* get description */
+ if (gtk_clist_get_text(GTK_CLIST(new_clist), i, 1, &desc) != 1)
+ break;
+ /* if no description, skip this interface */
+ if (strlen(desc) == 0)
+ continue;
+ /* get interface name */
+ gtk_clist_get_text(GTK_CLIST(new_clist), i, 0, &ifnm);
+
+ /*
+ * create/cat interface description to new string
+ * (leave space for parens, comma and terminator)
+ */
+ if ((strlen(ifnm) + strlen(desc) + 4 +
+ strlen(new_descr)) < MAX_VAL_LEN) {
+ if (first_if == 1)
+ snprintf(tmp_descr, IF_OPTS_MAX_DESCR_LEN+MAX_WIN_IF_NAME_LEN+4,
+ "%s(%s)", ifnm, desc);
+ else
+ snprintf(tmp_descr, IF_OPTS_MAX_DESCR_LEN+MAX_WIN_IF_NAME_LEN+4,
+ ",%s(%s)", ifnm, desc);
+ strcat(new_descr, tmp_descr);
+ /* set first-in-list flag to false */
+ first_if = 0;
+ }
+ /* interface name + description is too large */
+ else {
+ simple_dialog(ESD_TYPE_WARN, NULL, "Error saving interface "
+ "description for:\n%s\n(too long)", ifnm);
+ continue;
+ }
+ }
+
+ /* 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 "new" CList.
+ */
+static void
+ifopts_write_new_hide(void)
+{
+ gint i;
+ gint first_if = 1; /* flag to check if 1st in list */
+ gchar *ifnm;
+ gchar *hide;
+ gchar *tmp_hide;
+ gchar *new_hide;
+
+ /* new preferences "hidden" interfaces string */
+ new_hide = g_malloc0(MAX_VAL_LEN);
+ if (new_hide == NULL) {
+ simple_dialog(ESD_TYPE_WARN, NULL, "Error (1) saving \"hidden\" "
+ "interfaces: malloc failure");
+ return;
+ }
+
+ /*
+ * current row's interface name if "hidden"
+ * (leave space for comma and terminator)
+ */
+ /*
+ * XXX - Currently, MAX_WIN_IF_NAME_LEN is 511. This should be large
+ * enough for *nix. ;o)
+ */
+ tmp_hide = g_malloc0(MAX_WIN_IF_NAME_LEN + 2);
+ if (tmp_hide == NULL) {
+ simple_dialog(ESD_TYPE_WARN, NULL, "Error (2) saving \"hidden\" "
+ "interfaces: malloc failure");
+ g_free(new_hide);
+ return;
+ }
+
+ /* get "hidden" flag for each row (interface) */
+ for (i = 0; ;i++) {
+ /* get flag */
+ if (gtk_clist_get_text(GTK_CLIST(new_clist), i, 2, &hide) != 1)
+ break;
+ /* if flag is not "1", skip this interface */
+ if (*hide == '0')
+ continue;
+ /* get interface name */
+ gtk_clist_get_text(GTK_CLIST(new_clist), i, 0, &ifnm);
+
+ /*
+ * create/cat interface to new string
+ * (leave space for comma and terminator)
+ */
+ if ((strlen(ifnm) + 2 + strlen(new_hide)) < MAX_VAL_LEN) {
+ if (first_if == 1)
+ snprintf(tmp_hide, MAX_WIN_IF_NAME_LEN+2, "%s", ifnm);
+ else
+ snprintf(tmp_hide, MAX_WIN_IF_NAME_LEN+2, ",%s", ifnm);
+ strcat(new_hide, tmp_hide);
+ /* set first-in-list flag to false */
+ first_if = 0;
+ }
+ /* interface name is too large */
+ else {
+ simple_dialog(ESD_TYPE_WARN, NULL, "Error saving \"hidden\" "
+ "interface for:\n%s\n(too long)", ifnm);
+ continue;
+ }
+ }
+
+ /* 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 */