/* capture_dlg.c
* Routines for packet capture windows
*
- * $Id: capture_dlg.c,v 1.9 1999/11/06 02:05:32 guy Exp $
+ * $Id: capture_dlg.c,v 1.33 2000/09/15 05:32:48 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
#include <time.h>
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-
-#ifdef HAVE_NET_IF_H
-#include <net/if.h>
-#endif
-
-#include <signal.h>
-#include <errno.h>
-
#ifdef NEED_SNPRINTF_H
-# ifdef HAVE_STDARG_H
-# include <stdarg.h>
-# else
-# include <varargs.h>
-# endif
# include "snprintf.h"
#endif
-#ifdef HAVE_SYS_SOCKIO_H
-# include <sys/sockio.h>
-#endif
-
-#include <wiretap/wtap.h>
#include "capture.h"
#include "globals.h"
#include "main.h"
+#include "ui_util.h"
#include "capture_dlg.h"
-#include "prefs_dlg.h"
+#include "filter_prefs.h"
+#include "simple_dialog.h"
+#include "dlg_utils.h"
#include "util.h"
/* Capture callback data keys */
-#define E_CAP_IFACE_KEY "cap_iface"
-#define E_CAP_FILT_KEY "cap_filter_te"
-#define E_CAP_FILE_TE_KEY "cap_file_te"
-#define E_CAP_COUNT_KEY "cap_count"
-#define E_CAP_SNAP_KEY "cap_snap"
-#define E_CAP_SYNC_KEY "cap_sync"
-#define E_CAP_RESOLVE_KEY "cap_resolve"
-
-static GList*
-get_interface_list();
+#define E_CAP_IFACE_KEY "cap_iface"
+#define E_CAP_FILT_KEY "cap_filter_te"
+#define E_CAP_FILE_TE_KEY "cap_file_te"
+#define E_CAP_COUNT_KEY "cap_count"
+#define E_CAP_SNAP_KEY "cap_snap"
+#define E_CAP_PROMISC_KEY "cap_promisc"
+#define E_CAP_SYNC_KEY "cap_sync"
+#define E_CAP_AUTO_SCROLL_KEY "cap_auto_scroll"
+#define E_CAP_RESOLVE_KEY "cap_resolve"
+
+#define E_FS_CALLER_PTR_KEY "fs_caller_ptr"
+#define E_FILE_SEL_DIALOG_PTR_KEY "file_sel_dialog_ptr"
static void
capture_prep_file_cb(GtkWidget *w, gpointer te);
static void
cap_prep_fs_cancel_cb(GtkWidget *w, gpointer data);
+static void
+cap_prep_fs_destroy_cb(GtkWidget *win, gpointer data);
+
static void
capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
capture_prep_close_cb(GtkWidget *close_bt, gpointer parent_w);
static void
-search_for_if_cb(gpointer data, gpointer user_data);
+capture_prep_destroy_cb(GtkWidget *win, gpointer user_data);
-static void
-free_if_cb(gpointer data, gpointer user_data);
+/*
+ * Keep a static pointer to the current "Capture Preferences" window, if
+ * any, so that if somebody tries to do "Capture:Start" while there's
+ * already a "Capture Preferences" window up, we just pop up the existing
+ * one, rather than creating a new one.
+ */
+static GtkWidget *cap_open_w;
void
capture_prep_cb(GtkWidget *w, gpointer d)
{
- GtkWidget *cap_open_w, *if_cb, *if_lb,
- *count_lb, *count_cb, *main_vb, *if_hb, *count_hb,
- *filter_hb, *filter_bt, *filter_te,
- *file_hb, *file_bt, *file_te,
- *caplen_hb,
+ GtkWidget *if_cb, *if_lb,
+ *count_lb, *count_cb, *main_vb,
+ *filter_bt, *filter_te,
+ *file_bt, *file_te,
+ *caplen_hb, *table,
*bbox, *ok_bt, *cancel_bt, *snap_lb,
- *snap_sb, *sync_cb, *resolv_cb;
+ *snap_sb, *promisc_cb, *sync_cb, *auto_scroll_cb, *resolv_cb;
+ GtkAccelGroup *accel_group;
GtkAdjustment *adj;
GList *if_list, *count_list = NULL;
gchar *count_item1 = "0 (Infinite)", count_item2[16];
+ int err;
+ char err_str[PCAP_ERRBUF_SIZE];
- if_list = get_interface_list();
- if (if_list == NULL)
+ if (cap_open_w != NULL) {
+ /* There's already a "Capture Preferences" dialog box; reactivate it. */
+ reactivate_window(cap_open_w);
return;
+ }
+
+ 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);
+ }
- cap_open_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_window_set_title(GTK_WINDOW(cap_open_w), "Ethereal: Capture Preferences");
+ cap_open_w = dlg_window_new("Ethereal: Capture Preferences");
+ gtk_signal_connect(GTK_OBJECT(cap_open_w), "destroy",
+ GTK_SIGNAL_FUNC(capture_prep_destroy_cb), NULL);
+
+ /* Accelerator group for the accelerators (or, as they're called in
+ Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
+ Ctrl+<key> is an accelerator). */
+ accel_group = gtk_accel_group_new();
+ gtk_window_add_accel_group(GTK_WINDOW(cap_open_w), accel_group);
- /* Container for each row of widgets */
main_vb = gtk_vbox_new(FALSE, 3);
gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
gtk_container_add(GTK_CONTAINER(cap_open_w), main_vb);
gtk_widget_show(main_vb);
+ /* Table : container of the first 4 rows */
+ table = gtk_table_new (4, 2, FALSE);
+ gtk_table_set_row_spacings(GTK_TABLE (table), 5);
+ gtk_table_set_col_spacings(GTK_TABLE (table), 5);
+ gtk_container_add(GTK_CONTAINER(main_vb), table);
+ gtk_widget_show(table);
+
/* Interface row */
- if_hb = gtk_hbox_new(FALSE, 3);
- gtk_container_add(GTK_CONTAINER(main_vb), if_hb);
- gtk_widget_show(if_hb);
if_lb = gtk_label_new("Interface:");
- gtk_box_pack_start(GTK_BOX(if_hb), if_lb, FALSE, FALSE, 0);
+ gtk_table_attach_defaults(GTK_TABLE(table), if_lb, 0, 1, 0, 1);
gtk_widget_show(if_lb);
if_cb = gtk_combo_new();
- gtk_combo_set_popdown_strings(GTK_COMBO(if_cb), if_list);
- if (cf.iface)
- gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), cf.iface);
+ if (if_list != NULL)
+ gtk_combo_set_popdown_strings(GTK_COMBO(if_cb), if_list);
+ if (cfile.iface)
+ gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), cfile.iface);
else if (if_list)
gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), if_list->data);
- gtk_box_pack_start(GTK_BOX(if_hb), if_cb, FALSE, FALSE, 0);
+ gtk_table_attach_defaults(GTK_TABLE(table), if_cb, 1, 2, 0, 1);
gtk_widget_show(if_cb);
- while (if_list) {
- g_free(if_list->data);
- if_list = g_list_remove_link(if_list, if_list);
- }
+ free_interface_list(if_list);
/* Count row */
- count_hb = gtk_hbox_new(FALSE, 3);
- gtk_container_add(GTK_CONTAINER(main_vb), count_hb);
- gtk_widget_show(count_hb);
count_lb = gtk_label_new("Count:");
- gtk_box_pack_start(GTK_BOX(count_hb), count_lb, FALSE, FALSE, 0);
+ gtk_table_attach_defaults(GTK_TABLE(table), count_lb, 0, 1, 1, 2);
gtk_widget_show(count_lb);
count_list = g_list_append(count_list, count_item1);
- if (cf.count) {
- snprintf(count_item2, 15, "%d", cf.count);
+ if (cfile.count) {
+ snprintf(count_item2, 15, "%d", cfile.count);
count_list = g_list_append(count_list, count_item2);
}
count_cb = gtk_combo_new();
gtk_combo_set_popdown_strings(GTK_COMBO(count_cb), count_list);
- gtk_box_pack_start(GTK_BOX(count_hb), count_cb, FALSE, FALSE, 0);
+ gtk_table_attach_defaults(GTK_TABLE(table), count_cb, 1, 2, 1, 2);
gtk_widget_show(count_cb);
while (count_list)
count_list = g_list_remove_link(count_list, count_list);
/* Filter row */
- filter_hb = gtk_hbox_new(FALSE, 3);
- gtk_container_add(GTK_CONTAINER(main_vb), filter_hb);
- gtk_widget_show(filter_hb);
filter_bt = gtk_button_new_with_label("Filter:");
gtk_signal_connect(GTK_OBJECT(filter_bt), "clicked",
- GTK_SIGNAL_FUNC(prefs_cb), (gpointer) E_PR_PG_FILTER);
- gtk_box_pack_start(GTK_BOX(filter_hb), filter_bt, FALSE, TRUE, 0);
+ GTK_SIGNAL_FUNC(filter_browse_cb), NULL);
+ gtk_table_attach_defaults(GTK_TABLE(table), filter_bt, 0, 1, 2, 3);
gtk_widget_show(filter_bt);
filter_te = gtk_entry_new();
- if (cf.cfilter) gtk_entry_set_text(GTK_ENTRY(filter_te), cf.cfilter);
+ if (cfile.cfilter) gtk_entry_set_text(GTK_ENTRY(filter_te), cfile.cfilter);
gtk_object_set_data(GTK_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
- gtk_box_pack_start(GTK_BOX(filter_hb), filter_te, TRUE, TRUE, 0);
+ gtk_table_attach_defaults(GTK_TABLE(table), filter_te, 1, 2, 2, 3);
gtk_widget_show(filter_te);
/* File row */
- file_hb = gtk_hbox_new(FALSE, 1);
- gtk_container_add(GTK_CONTAINER(main_vb), file_hb);
- gtk_widget_show(file_hb);
file_bt = gtk_button_new_with_label("File:");
- gtk_box_pack_start(GTK_BOX(file_hb), file_bt, FALSE, FALSE, 3);
+ gtk_table_attach_defaults(GTK_TABLE(table), file_bt, 0, 1, 3, 4);
gtk_widget_show(file_bt);
file_te = gtk_entry_new();
- gtk_box_pack_start(GTK_BOX(file_hb), file_te, TRUE, TRUE, 3);
+ gtk_table_attach_defaults(GTK_TABLE(table), file_te, 1, 2, 3, 4);
gtk_widget_show(file_te);
gtk_signal_connect(GTK_OBJECT(file_bt), "clicked",
gtk_box_pack_start(GTK_BOX(caplen_hb), snap_lb, FALSE, FALSE, 6);
gtk_widget_show(snap_lb);
- adj = (GtkAdjustment *) gtk_adjustment_new((float) cf.snap,
+ adj = (GtkAdjustment *) gtk_adjustment_new((float) cfile.snap,
MIN_PACKET_SIZE, WTAP_MAX_PACKET_SIZE, 1.0, 10.0, 0.0);
snap_sb = gtk_spin_button_new (adj, 0, 0);
gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (snap_sb), TRUE);
gtk_box_pack_start (GTK_BOX(caplen_hb), snap_sb, FALSE, FALSE, 3);
gtk_widget_show(snap_sb);
- sync_cb = gtk_check_button_new_with_label("Update list of packets in real time");
+ promisc_cb = dlg_check_button_new_with_label_with_mnemonic(
+ "Capture packets in _promiscuous mode", accel_group);
+ gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(promisc_cb), promisc_mode);
+ gtk_container_add(GTK_CONTAINER(main_vb), promisc_cb);
+ gtk_widget_show(promisc_cb);
+
+ sync_cb = dlg_check_button_new_with_label_with_mnemonic(
+ "_Update list of packets in real time", accel_group);
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(sync_cb), sync_mode);
gtk_container_add(GTK_CONTAINER(main_vb), sync_cb);
gtk_widget_show(sync_cb);
- resolv_cb = gtk_check_button_new_with_label("Enable name resolution");
+ auto_scroll_cb = dlg_check_button_new_with_label_with_mnemonic(
+ "_Automatic scrolling in live capture", accel_group);
+ gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(auto_scroll_cb), auto_scroll_live);
+ gtk_container_add(GTK_CONTAINER(main_vb), auto_scroll_cb);
+ gtk_widget_show(auto_scroll_cb);
+
+ resolv_cb = dlg_check_button_new_with_label_with_mnemonic(
+ "Enable _name resolution", accel_group);
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(resolv_cb), g_resolving_actif);
gtk_container_add(GTK_CONTAINER(main_vb), resolv_cb);
gtk_widget_show(resolv_cb);
gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_FILE_TE_KEY, file_te);
gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_COUNT_KEY, count_cb);
gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_SNAP_KEY, snap_sb);
+ gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_PROMISC_KEY, promisc_cb);
gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_SYNC_KEY, sync_cb);
+ gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_AUTO_SCROLL_KEY, auto_scroll_cb);
gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_RESOLVE_KEY, resolv_cb);
+ /* Catch the "activate" signal on the frame number and file name text
+ entries, so that if the user types Return there, we act as if the
+ "OK" button had been selected, as happens if Return is typed if some
+ widget that *doesn't* handle the Return key has the input focus. */
+ dlg_set_activate(filter_te, ok_bt);
+ dlg_set_activate(file_te, ok_bt);
+
+ /* 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(cap_open_w, cancel_bt);
+
+ /* XXX - why does not
+
+ gtk_widget_grab_focus(if_cb);
+
+ give the initial focus to the "Interface" combo box?
+
+ Or should I phrase that as "why does GTK+ continually frustrate
+ attempts to make GUIs driveable from the keyboard?" We have to
+ go catch the activate signal on every single GtkEntry widget
+ (rather than having widgets whose activate signal is *not*
+ caught not catch the Return keystroke, so that it passes on,
+ ultimately, to the window, which can activate the default
+ widget, i.e. the "OK" button); we have to catch the "key_press_event"
+ signal and have the handler check for ESC, so that we can have ESC
+ activate the "Cancel" button; in order to support Alt+<key> mnemonics
+ for buttons and the like, we may have to construct an accelerator
+ group by hand and set up the accelerators by hand (if that even
+ works - I've not tried it yet); we have to do a "gtk_widget_grab_focus()"
+ to keep some container widget from getting the initial focus, so that
+ you don't have to tab into the first widget in order to start typing
+ in it; and it now appears that you simply *can't* make a combo box
+ get the initial focus, at least not in the obvious fashion. Sigh.... */
+
gtk_widget_show(cap_open_w);
}
static void
capture_prep_file_cb(GtkWidget *w, gpointer file_te)
{
+ GtkWidget *caller = gtk_widget_get_toplevel(w);
GtkWidget *fs;
+ /* Has a file selection dialog box already been opened for that top-level
+ widget? */
+ fs = gtk_object_get_data(GTK_OBJECT(caller), E_FILE_SEL_DIALOG_PTR_KEY);
+
+ if (fs != NULL) {
+ /* Yes. Just re-activate that dialog box. */
+ reactivate_window(fs);
+ return;
+ }
+
fs = gtk_file_selection_new ("Ethereal: Capture File");
gtk_object_set_data(GTK_OBJECT(fs), E_CAP_FILE_TE_KEY, file_te);
+ /* Set the E_FS_CALLER_PTR_KEY for the new dialog to point to our caller. */
+ gtk_object_set_data(GTK_OBJECT(fs), E_FS_CALLER_PTR_KEY, caller);
+
+ /* Set the E_FILE_SEL_DIALOG_PTR_KEY for the caller to point to us */
+ gtk_object_set_data(GTK_OBJECT(caller), E_FILE_SEL_DIALOG_PTR_KEY, fs);
+
+ /* Call a handler when the file selection box is destroyed, so we can inform
+ our caller, if any, that it's been destroyed. */
+ gtk_signal_connect(GTK_OBJECT(fs), "destroy",
+ GTK_SIGNAL_FUNC(cap_prep_fs_destroy_cb), NULL);
+
gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->ok_button),
"clicked", (GtkSignalFunc) cap_prep_fs_ok_cb, fs);
/* Connect the cancel_button to destroy the widget */
gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->cancel_button),
"clicked", (GtkSignalFunc) cap_prep_fs_cancel_cb, fs);
+
+ /* 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(fs, GTK_FILE_SELECTION(fs)->cancel_button);
gtk_widget_show(fs);
}
gtk_widget_destroy(GTK_WIDGET(data));
}
+static void
+cap_prep_fs_destroy_cb(GtkWidget *win, gpointer data)
+{
+ GtkWidget *caller;
+
+ /* Get the widget that requested that we be popped up.
+ (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 = gtk_object_get_data(GTK_OBJECT(win), E_FS_CALLER_PTR_KEY);
+
+ /* Tell it we no longer exist. */
+ gtk_object_set_data(GTK_OBJECT(caller), E_FILE_SEL_DIALOG_PTR_KEY, NULL);
+
+ /* Now nuke this window. */
+ gtk_grab_remove(GTK_WIDGET(win));
+ gtk_widget_destroy(GTK_WIDGET(win));
+}
+
static void
capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w) {
- GtkWidget *if_cb, *filter_te, *file_te, *count_cb, *snap_sb, *sync_cb,
- *resolv_cb;
+ GtkWidget *if_cb, *filter_te, *file_te, *count_cb, *snap_sb, *promisc_cb,
+ *sync_cb, *auto_scroll_cb, *resolv_cb;
+ gchar *if_text;
+ gchar *if_name;
gchar *filter_text;
gchar *save_file;
file_te = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_FILE_TE_KEY);
count_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_COUNT_KEY);
snap_sb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_SNAP_KEY);
+ promisc_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_PROMISC_KEY);
sync_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_SYNC_KEY);
+ auto_scroll_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_AUTO_SCROLL_KEY);
resolv_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_RESOLVE_KEY);
- if (cf.iface)
- g_free(cf.iface);
- cf.iface =
+ if_text =
g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry)));
-
- filter_text = gtk_entry_get_text(GTK_ENTRY(filter_te));
- if (cf.cfilter)
- g_free(cf.cfilter);
- cf.cfilter = NULL; /* ead 06/16/99 */
- if (filter_text && filter_text[0]) {
- cf.cfilter = g_strdup(filter_text);
+ if_name = strtok(if_text, " \t");
+ if (if_name == NULL) {
+ simple_dialog(ESD_TYPE_CRIT, NULL,
+ "You didn't specify an interface on which to capture packets.");
+ g_free(if_name);
+ return;
}
+ if (cfile.iface)
+ g_free(cfile.iface);
+ cfile.iface = g_strdup(if_name);
+ g_free(if_text);
+
+ /* XXX - don't try to get clever and set "cfile.filter" to NULL if the
+ filter string is empty, as an indication that we don't have a filter
+ and thus don't have to set a filter when capturing - the version of
+ libpcap in Red Hat Linux 6.1, and versions based on later patches
+ in that series, don't bind the AF_PACKET socket to an interface
+ until a filter is set, which means they aren't bound at all if
+ no filter is set, which means no packets arrive as input on that
+ socket, which means Ethereal never sees any packets. */
+ filter_text = gtk_entry_get_text(GTK_ENTRY(filter_te));
+ if (cfile.cfilter)
+ g_free(cfile.cfilter);
+ g_assert(filter_text != NULL);
+ cfile.cfilter = g_strdup(filter_text);
save_file = gtk_entry_get_text(GTK_ENTRY(file_te));
if (save_file && save_file[0]) {
save_file = NULL;
}
- cf.count = atoi(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(count_cb)->entry)));
+ cfile.count = atoi(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(count_cb)->entry)));
- cf.snap = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(snap_sb));
- if (cf.snap < 1)
- cf.snap = WTAP_MAX_PACKET_SIZE;
- else if (cf.snap < MIN_PACKET_SIZE)
- cf.snap = MIN_PACKET_SIZE;
+ cfile.snap = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(snap_sb));
+ if (cfile.snap < 1)
+ cfile.snap = WTAP_MAX_PACKET_SIZE;
+ else if (cfile.snap < MIN_PACKET_SIZE)
+ cfile.snap = MIN_PACKET_SIZE;
+
+ promisc_mode = GTK_TOGGLE_BUTTON (promisc_cb)->active;
sync_mode = GTK_TOGGLE_BUTTON (sync_cb)->active;
+ auto_scroll_live = GTK_TOGGLE_BUTTON (auto_scroll_cb)->active;
+
g_resolving_actif = GTK_TOGGLE_BUTTON (resolv_cb)->active;
gtk_widget_destroy(GTK_WIDGET(parent_w));
gtk_widget_destroy(GTK_WIDGET(parent_w));
}
-struct search_user_data {
- char *name;
- int found;
-};
-
-static GList *
-get_interface_list() {
- GList *il = NULL;
- gint nonloopback_pos = 0;
- struct ifreq *ifr, *last;
- struct ifconf ifc;
- struct ifreq ifrflags;
- int sock = socket(AF_INET, SOCK_DGRAM, 0);
- struct search_user_data user_data;
- pcap_t *pch;
- gchar err_str[PCAP_ERRBUF_SIZE];
-
- if (sock < 0)
- {
- simple_dialog(ESD_TYPE_WARN, NULL,
- "Can't list interfaces: error opening socket.");
- return NULL;
- }
-
- /* Since we have to grab the interface list all at once, we'll make
- plenty of room */
- ifc.ifc_len = 1024 * sizeof(struct ifreq);
- ifc.ifc_buf = malloc(ifc.ifc_len);
-
- if (ioctl(sock, SIOCGIFCONF, &ifc) < 0 ||
- ifc.ifc_len < sizeof(struct ifreq))
- {
- simple_dialog(ESD_TYPE_WARN, NULL,
- "Can't list interfaces: SIOCGIFCONF error: %s", strerror(errno));
- goto fail;
- }
-
- ifr = (struct ifreq *) ifc.ifc_req;
- last = (struct ifreq *) ((char *) ifr + ifc.ifc_len);
- while (ifr < last)
- {
- /*
- * Skip addresses that begin with "dummy", or that include a ":"
- * (the latter are Solaris virtuals).
- */
- if (strncmp(ifr->ifr_name, "dummy", 5) == 0 ||
- strchr(ifr->ifr_name, ':') != NULL)
- goto next;
-
- /*
- * If we already have this interface name on the list, don't add
- * it (SIOCGIFCONF returns, at least on BSD-flavored systems, one
- * entry per interface *address*; if an interface has multiple
- * addresses, we get multiple entries for it).
- */
- user_data.name = ifr->ifr_name;
- user_data.found = FALSE;
- g_list_foreach(il, search_for_if_cb, &user_data);
- if (user_data.found)
- goto next;
-
- /*
- * Get the interface flags.
- */
- memset(&ifrflags, 0, sizeof ifrflags);
- strncpy(ifrflags.ifr_name, ifr->ifr_name, sizeof ifrflags.ifr_name);
- if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
- if (errno == ENXIO)
- goto next;
- simple_dialog(ESD_TYPE_WARN, NULL,
- "Can't list interfaces: SIOCGIFFLAGS error on %s: %s",
- ifr->ifr_name, strerror(errno));
- goto fail;
- }
-
- /*
- * Skip interfaces that aren't up.
- */
- if (!(ifrflags.ifr_flags & IFF_UP))
- goto next;
-
- /*
- * Skip interfaces that we can't open with "libpcap".
- */
- pch = pcap_open_live(ifr->ifr_name, WTAP_MAX_PACKET_SIZE, 0, 0, err_str);
- if (pch == NULL)
- goto next;
- pcap_close(pch);
-
- /*
- * If it's a loopback interface, add it at the end of the list,
- * otherwise add it after the last non-loopback interface,
- * so all loopback interfaces go at the end - we don't want a
- * loopback interface to be the default capture device unless there
- * are no non-loopback devices.
- */
- if ((ifrflags.ifr_flags & IFF_LOOPBACK) ||
- strncmp(ifr->ifr_name, "lo", 2) == 0)
- il = g_list_insert(il, g_strdup(ifr->ifr_name), -1);
- else {
- il = g_list_insert(il, g_strdup(ifr->ifr_name), nonloopback_pos);
- /* Insert the next non-loopback interface after this one. */
- nonloopback_pos++;
- }
-
-next:
-#ifdef HAVE_SA_LEN
- ifr = (struct ifreq *) ((char *) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);
-#else
- ifr = (struct ifreq *) ((char *) ifr + sizeof(struct ifreq));
-#endif
- }
+static void
+capture_prep_destroy_cb(GtkWidget *win, gpointer user_data)
+{
+ GtkWidget *capture_prep_filter_w;
+ GtkWidget *fs;
- free(ifc.ifc_buf);
- close(sock);
+ /* Is there a filter edit/selection dialog associated with this
+ Capture Preferences dialog? */
+ capture_prep_filter_w = gtk_object_get_data(GTK_OBJECT(win), E_FILT_DIALOG_PTR_KEY);
- if (il == NULL) {
- simple_dialog(ESD_TYPE_WARN, NULL,
- "There are no network interfaces that can be opened.\n"
- "Please check to make sure you have sufficient permission\n"
- "to capture packets.");
- return NULL;
+ if (capture_prep_filter_w != NULL) {
+ /* Yes. Destroy it. */
+ gtk_widget_destroy(capture_prep_filter_w);
}
- return il;
+ /* Is there a file selection dialog associated with this
+ Print File dialog? */
+ fs = gtk_object_get_data(GTK_OBJECT(win), E_FILE_SEL_DIALOG_PTR_KEY);
-fail:
- if (il != NULL) {
- g_list_foreach(il, free_if_cb, NULL);
- g_list_free(il);
+ if (fs != NULL) {
+ /* Yes. Destroy it. */
+ gtk_widget_destroy(fs);
}
- free(ifc.ifc_buf);
- close(sock);
- return NULL;
-}
-static void
-search_for_if_cb(gpointer data, gpointer user_data)
-{
- struct search_user_data *search_user_data = user_data;
-
- if (strcmp((char *)data, search_user_data->name) == 0)
- search_user_data->found = TRUE;
-}
-
-static void
-free_if_cb(gpointer data, gpointer user_data)
-{
- g_free(data);
+ /* Note that we no longer have a "Capture Preferences" dialog box. */
+ cap_open_w = NULL;
}
#endif /* HAVE_LIBPCAP */