/* capture_dlg.c
* Routines for packet capture windows
*
- * $Id: capture_dlg.c,v 1.7 1999/10/02 07:13:20 guy Exp $
+ * $Id: capture_dlg.c,v 1.18 2000/01/18 09:24:57 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
# include "config.h"
#endif
+#ifdef HAVE_LIBPCAP
+
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#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>
# 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 "capture_dlg.h"
#include "prefs_dlg.h"
+#include "simple_dialog.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"
-
-/* Capture filter key */
-#define E_CAP_FILT_TE_KEY "cap_filt_te"
-
-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_SYNC_KEY "cap_sync"
+#define E_CAP_AUTO_SCROLL_KEY "cap_auto_scroll"
+#define E_CAP_RESOLVE_KEY "cap_resolve"
static void
capture_prep_file_cb(GtkWidget *w, gpointer te);
static void
capture_prep_close_cb(GtkWidget *close_bt, gpointer parent_w);
-static void
-search_for_if_cb(gpointer data, gpointer user_data);
-
-static void
-free_if_cb(gpointer data, gpointer user_data);
-
void
capture_prep_cb(GtkWidget *w, gpointer d)
{
*file_hb, *file_bt, *file_te,
*caplen_hb,
*bbox, *ok_bt, *cancel_bt, *snap_lb,
- *snap_sb, *sync_cb, *resolv_cb;
+ *snap_sb, *sync_cb, *auto_scroll_cb, *resolv_cb;
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)
- 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");
gtk_widget_show(if_lb);
if_cb = gtk_combo_new();
- gtk_combo_set_popdown_strings(GTK_COMBO(if_cb), if_list);
+ if (if_list != NULL)
+ 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);
else if (if_list)
gtk_box_pack_start(GTK_BOX(if_hb), if_cb, FALSE, FALSE, 0);
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);
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_SIGNAL_FUNC(filter_dialog_cb), NULL);
gtk_box_pack_start(GTK_BOX(filter_hb), filter_bt, FALSE, TRUE, 0);
gtk_widget_show(filter_bt);
gtk_container_add(GTK_CONTAINER(main_vb), sync_cb);
gtk_widget_show(sync_cb);
+ auto_scroll_cb = gtk_check_button_new_with_label("Automatic scrolling in live capture");
+ 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 = gtk_check_button_new_with_label("Enable name resolution");
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(resolv_cb), g_resolving_actif);
gtk_container_add(GTK_CONTAINER(main_vb), resolv_cb);
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_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);
gtk_widget_show(cap_open_w);
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;
+ *auto_scroll_cb, *resolv_cb;
+ gchar *if_text;
+ gchar *if_name;
gchar *filter_text;
gchar *save_file;
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);
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_text =
+ g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry)));
+ if_name = strtok(if_text, " \t");
+ if (if_name == NULL) {
+ simple_dialog(ESD_TYPE_WARN, NULL,
+ "You didn't specify an interface on which to capture packets.");
+ g_free(if_name);
+ return;
+ }
if (cf.iface)
g_free(cf.iface);
- cf.iface =
- g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry)));
-
+ cf.iface = g_strdup(if_name);
+ g_free(if_text);
+
+ /* XXX - don't try to get clever and set "cf.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 (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);
- }
+ g_assert(filter_text != NULL);
+ cf.cfilter = g_strdup(filter_text);
save_file = gtk_entry_get_text(GTK_ENTRY(file_te));
if (save_file && save_file[0]) {
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
- }
-
- free(ifc.ifc_buf);
- close(sock);
-
- 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;
- }
-
- return il;
-
-fail:
- if (il != NULL) {
- g_list_foreach(il, free_if_cb, NULL);
- g_list_free(il);
- }
- 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);
-}
-
-
+#endif /* HAVE_LIBPCAP */