aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2007-06-11 03:58:58 +0000
committerGerald Combs <gerald@wireshark.org>2007-06-11 03:58:58 +0000
commite9f1a0b692e19854f9e550e56e6a4dd392d316ac (patch)
tree34b32715c097282a72bc20784529bf82c5e01b0e
parentf07a01dd510a6ae5fb963123195c4f0e203216aa (diff)
One more step in privilege separation.
Add a capture_interface_list(), which works similar to get_interface_list() except that it forks dumpcap instead of calling the pcap routines directly. Use it in the GUI. Add a "-I" flag to dumpcap, which prints out verbose interface information. Tested under Windows and Linux. svn path=/trunk/; revision=22071
-rw-r--r--capture-pcap-util.h7
-rw-r--r--capture.c135
-rw-r--r--capture.h7
-rw-r--r--capture_opts.c96
-rw-r--r--capture_opts.h8
-rw-r--r--capture_sync.c254
-rw-r--r--capture_sync.h19
-rw-r--r--doc/dumpcap.pod9
-rw-r--r--dumpcap.c30
-rw-r--r--gtk/capture_dlg.c4
-rw-r--r--gtk/capture_if_dlg.c4
-rw-r--r--gtk/capture_prefs.c119
-rw-r--r--gtk/main.c2
-rw-r--r--tshark.c18
14 files changed, 566 insertions, 146 deletions
diff --git a/capture-pcap-util.h b/capture-pcap-util.h
index 545231704d..72b1f6742c 100644
--- a/capture-pcap-util.h
+++ b/capture-pcap-util.h
@@ -69,9 +69,10 @@ typedef struct {
GList *get_interface_list(int *err, char **err_str);
-/* Error values from "get_interface_list()". */
-#define CANT_GET_INTERFACE_LIST 0 /* error getting list */
-#define NO_INTERFACES_FOUND 1 /* list is empty */
+/* Error values from "get_interface_list()/capture_interface_list()". */
+#define CANT_GET_INTERFACE_LIST 1 /* error getting list */
+#define NO_INTERFACES_FOUND 2 /* list is empty */
+#define CANT_RUN_DUMPCAP 3 /* problem running 'dumpcap -I l' */
void free_interface_list(GList *if_list);
diff --git a/capture.c b/capture.c
index b5f83001b5..f3cdee6e16 100644
--- a/capture.c
+++ b/capture.c
@@ -40,6 +40,18 @@
#include <fcntl.h>
#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
#include <signal.h>
#include <errno.h>
@@ -47,6 +59,7 @@
#include <epan/packet.h>
#include <epan/dfilter/dfilter.h>
+#include <epan/ws_strsplit.h>
#include "file.h"
#include "capture.h"
#include "capture_sync.h"
@@ -69,7 +82,7 @@
-/**
+/**
* Start a capture.
*
* @return TRUE if the capture starts successfully, FALSE otherwise.
@@ -142,7 +155,7 @@ capture_kill_child(capture_options *capture_opts)
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_INFO, "Capture Kill");
/* kill the capture child */
- sync_pipe_kill(capture_opts);
+ sync_pipe_kill(capture_opts->fork_child);
}
@@ -209,7 +222,7 @@ guint32 drops)
break;
case CF_READ_ABORTED:
- /* User wants to quit program. Exit by leaving the main loop,
+ /* User wants to quit program. Exit by leaving the main loop,
so that any quit functions we registered get called. */
main_window_nested_quit();
return FALSE;
@@ -217,7 +230,7 @@ guint32 drops)
/* if we didn't captured even a single packet, close the file again */
if(cf_get_packet_count(capture_opts->cf) == 0 && !capture_opts->restart) {
- simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
+ simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
"%sNo packets captured!%s\n"
"\n"
"As no data was captured, closing the %scapture file!\n"
@@ -283,7 +296,7 @@ capture_input_new_file(capture_options *capture_opts, gchar *new_file)
case CF_OK:
break;
case CF_ERROR:
- /* Don't unlink (delete) the save file - leave it around,
+ /* Don't unlink (delete) the save file - leave it around,
for debugging purposes. */
g_free(capture_opts->save_file);
capture_opts->save_file = NULL;
@@ -307,7 +320,7 @@ capture_input_new_file(capture_options *capture_opts, gchar *new_file)
return TRUE;
}
-
+
/* capture child tells us we have new packets to read */
void
capture_input_new_packets(capture_options *capture_opts, int to_read)
@@ -339,7 +352,7 @@ capture_input_new_packets(capture_options *capture_opts, int to_read)
}
} else {
/* increase capture file packet counter by the number or incoming packets */
- cf_set_packet_count(capture_opts->cf,
+ cf_set_packet_count(capture_opts->cf,
cf_get_packet_count(capture_opts->cf) + to_read);
cf_callback_invoke(cf_cb_live_capture_fixed_continue, capture_opts->cf);
@@ -479,7 +492,7 @@ capture_input_closed(capture_options *capture_opts)
/* XXX: If -Q (quit-after-cap) then cf->count clr'd below so save it first */
packet_count_save = cf_get_packet_count(capture_opts->cf);
/* Tell the GUI, we are not doing a capture any more.
- Must be done after the cf_finish_tail(), so file lengths are displayed
+ Must be done after the cf_finish_tail(), so file lengths are displayed
correct. */
cf_callback_invoke(cf_cb_live_capture_update_finished, capture_opts->cf);
@@ -488,7 +501,7 @@ capture_input_closed(capture_options *capture_opts)
case CF_READ_OK:
if ((packet_count_save == 0) && !capture_opts->restart) {
- simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
+ simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
"%sNo packets captured!%s\n"
"\n"
"As no data was captured, closing the %scapture file!\n"
@@ -526,7 +539,7 @@ capture_input_closed(capture_options *capture_opts)
/* this is a normal mode capture and if no error happened, read in the capture file data */
if(capture_opts->save_file != NULL) {
- capture_input_read_all(capture_opts, cf_is_tempfile(capture_opts->cf),
+ capture_input_read_all(capture_opts, cf_is_tempfile(capture_opts->cf),
cf_get_drops_known(capture_opts->cf), cf_get_drops(capture_opts->cf));
}
}
@@ -563,5 +576,107 @@ capture_input_closed(capture_options *capture_opts)
}
}
+/**
+ * Fetch the interface list from a child process (dumpcap).
+ *
+ * @return A GList containing if_info_t structs if successful, NULL otherwise.
+ */
+
+/* XXX - We parse simple text output to get our interface list. Should
+ * we use "real" data serialization instead, e.g. via XML? */
+GList *
+capture_interface_list(int *err, char **err_str)
+{
+ GList *if_list = NULL;
+ int i, j;
+ gchar *msg;
+ gchar **raw_list, **if_parts, **addr_parts;
+ gchar *name;
+ if_info_t *if_info;
+ if_addr_t *if_addr;
+ struct addrinfo *ai;
+ struct sockaddr_in *sa4;
+ struct sockaddr_in6 *sa6;
+
+ g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List ...");
+
+ /* Try to get our interface list */
+ *err = sync_interface_list_open(&msg);
+ if(*err != 0) {
+ g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List failed!");
+ if (*err_str)
+ *err_str = msg;
+ else
+ g_free(msg);
+ return NULL;
+ }
+
+ /* Split our lines */
+ raw_list = g_strsplit(msg, "\n", 0);
+ g_free(msg);
+
+ for (i = 0; raw_list[i] != NULL; i++) {
+ if_parts = g_strsplit(raw_list[i], "\t", 4);
+ if (if_parts[0] == NULL || if_parts[1] == NULL || if_parts[2] == NULL ||
+ if_parts[3] == NULL) {
+ g_strfreev(if_parts);
+ continue;
+ }
+
+ /* Number followed by the name, e.g "1. eth0" */
+ name = strchr(if_parts[0], ' ');
+ if (name) {
+ name++;
+ } else {
+ g_strfreev(if_parts);
+ continue;
+ }
+
+ if_info = g_malloc0(sizeof(if_info_t));
+ if_info->name = g_strdup(name);
+ if (strlen(if_parts[1]) > 0)
+ if_info->description = g_strdup(if_parts[1]);
+ addr_parts = g_strsplit(if_parts[2], ",", 0);
+ for (j = 0; addr_parts[j] != NULL; j++) {
+ /* XXX - We're failing to convert IPv6 addresses (on Ubuntu, at least) */
+ if (getaddrinfo(addr_parts[j], NULL, NULL, &ai) == 0) {
+ if_addr = NULL;
+ switch (ai->ai_family) {
+ case AF_INET:
+ if_addr = g_malloc0(sizeof(if_addr_t));
+ if_addr->type = AT_IPv4;
+ sa4 = (struct sockaddr_in *) ai->ai_addr;
+ if_addr->ip_addr.ip4_addr = sa4->sin_addr.s_addr;
+ break;
+ case AF_INET6:
+ if_addr = g_malloc0(sizeof(if_addr_t));
+ if_addr->type = AT_IPv6;
+ sa6 = (struct sockaddr_in6 *) ai->ai_addr;
+ memcpy(&if_addr->ip_addr.ip6_addr, sa6->sin6_addr.s6_addr, 16);
+ break;
+ }
+ if (if_addr) {
+ if_info->ip_addr = g_slist_append(if_info->ip_addr, if_addr);
+ }
+ freeaddrinfo(ai);
+ }
+ }
+ if (strcmp(if_parts[3], "loopback") == 0)
+ if_info->loopback = TRUE;
+ g_strfreev(if_parts);
+ g_strfreev(addr_parts);
+ if_list = g_list_append(if_list, if_info);
+ }
+ g_strfreev(raw_list);
+
+ /* Check to see if we built a list */
+ if (if_list == NULL) {
+ if (*err_str)
+ *err_str = g_strdup("No interfaces found");
+ *err = NO_INTERFACES_FOUND;
+ }
+ return if_list;
+}
+
#endif /* HAVE_LIBPCAP */
diff --git a/capture.h b/capture.h
index c362dae5e5..f94883c561 100644
--- a/capture.h
+++ b/capture.h
@@ -33,7 +33,7 @@
#include "capture_opts.h"
-/**
+/**
* Start a capture session.
*
* @param capture_opts the numerous capture options
@@ -81,5 +81,10 @@ extern void capture_input_cfilter_error_message(capture_options *capture_opts, c
*/
extern void capture_input_closed(capture_options *capture_opts);
+/**
+ * Fetch the interface list from a child process.
+ */
+extern GList *capture_interface_list(int *err, char **err_str);
+
#endif /* capture.h */
diff --git a/capture_opts.c b/capture_opts.c
index 804b15deb5..e3005cea0e 100644
--- a/capture_opts.c
+++ b/capture_opts.c
@@ -31,6 +31,10 @@
#include <string.h>
#include <ctype.h>
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
#include <glib.h>
#include <epan/packet.h>
@@ -51,7 +55,7 @@ static gboolean capture_opts_output_to_pipe(const char *save_file, gboolean *is_
void
capture_opts_init(capture_options *capture_opts, void *cfile)
{
- capture_opts->cf = cfile;
+ capture_opts->cf = cfile;
capture_opts->cfilter = g_strdup(""); /* No capture filter string specified */
capture_opts->iface = NULL; /* Default is "pick the first interface" */
#ifdef _WIN32
@@ -77,7 +81,7 @@ capture_opts_init(capture_options *capture_opts, void *cfile)
capture_opts->has_autostop_files = FALSE;
capture_opts->autostop_files = 1;
- capture_opts->has_autostop_packets = FALSE;
+ capture_opts->has_autostop_packets = FALSE;
capture_opts->autostop_packets = 0;
capture_opts->has_autostop_filesize = FALSE;
capture_opts->autostop_filesize = 1024; /* 1 MB */
@@ -425,8 +429,9 @@ int capture_opts_list_link_layer_types(capture_options *capture_opts)
return 0;
}
-
-int capture_opts_list_interfaces()
+/* Return an ASCII-formatted list of interfaces. */
+int
+capture_opts_list_interfaces(gboolean verbose)
{
GList *if_list;
GList *if_entry;
@@ -434,12 +439,11 @@ int capture_opts_list_interfaces()
int err;
gchar *err_str;
int i;
-#if 0
GSList *ip_addr;
if_addr_t *if_addr;
- guint8 ipv4[4];
-#endif
-
+ char addr_str[NI_MAXHOST];
+ struct sockaddr_in sa4;
+ struct sockaddr_in6 sa6;
if_list = get_interface_list(&err, &err_str);
if (if_list == NULL) {
@@ -453,7 +457,7 @@ int capture_opts_list_interfaces()
cmdarg_err("There are no interfaces on which a capture can be done");
break;
}
- return 2;
+ return err;
}
i = 1; /* Interface id number */
@@ -461,28 +465,62 @@ int capture_opts_list_interfaces()
if_entry = g_list_next(if_entry)) {
if_info = if_entry->data;
printf("%d. %s", i++, if_info->name);
- if (if_info->description != NULL)
- printf(" (%s)", if_info->description);
-#if 0
- for(ip_addr = g_slist_nth(if_info->ip_addr, 0); ip_addr != NULL;
- ip_addr = g_slist_next(ip_addr)) {
- if_addr = ip_addr->data;
- switch(if_addr->type) {
- case AT_IPv4:
- memcpy(ipv4, (void *) &if_addr->ip_addr.ip4_addr, 4);
- printf(" %u.%u.%u.%u", ipv4[0], ipv4[1], ipv4[2], ipv4[3]);
- break;
- case AT_IPv6:
- /* XXX - display the IPv6 address without using stuff from epan */
- printf(" XXX-IPv6");
- break;
- default:
- printf(" unknown address type %u", if_addr->type);
+
+ if (!verbose) {
+ /* Add the description if it exists */
+ if (if_info->description != NULL)
+ printf(" (%s)", if_info->description);
+ } else {
+ /*
+ * Add the contents of the if_entry struct in a parseable format.
+ * Each if_entry element is tab-separated. Addresses are comma-
+ * separated.
+ */
+ /* XXX - Make sure our description doesn't contain a tab */
+ if (if_info->description != NULL)
+ printf("\t%s\t", if_info->description);
+ else
+ printf("\t\t");
+
+ for(ip_addr = g_slist_nth(if_info->ip_addr, 0); ip_addr != NULL;
+ ip_addr = g_slist_next(ip_addr)) {
+ if (ip_addr != g_slist_nth(if_info->ip_addr, 0))
+ printf(",");
+
+ if_addr = ip_addr->data;
+ switch(if_addr->type) {
+ case AT_IPv4:
+ sa4.sin_family = AF_INET;
+ sa4.sin_addr.s_addr = if_addr->ip_addr.ip4_addr;
+ if (getnameinfo((struct sockaddr *) &sa4, sizeof(sa4),
+ addr_str, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) == 0) {
+ printf(addr_str);
+ } else {
+ printf("<unknown IPv4>");
+ }
+ break;
+ case AT_IPv6:
+ sa6.sin6_family = AF_INET6;
+ memcpy(&sa6.sin6_addr.s6_addr, &if_addr->ip_addr.ip6_addr, 16);
+ if (getnameinfo((struct sockaddr *) &sa6, sizeof(sa6),
+ addr_str, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) == 0) {
+ printf(addr_str);
+ } else {
+ printf("<unknown IPv6>");
+ }
+ break;
+ default:
+ printf("<type unknown %u>", if_addr->type);
+ }
}
- }
-#endif
- printf("\n");
+ if (if_info->loopback)
+ printf("\tloopback");
+ else
+ printf("\tnetwork");
+
+ }
+ printf("\n");
}
free_interface_list(if_list);
diff --git a/capture_opts.h b/capture_opts.h
index ed797e6ea7..4cb76eb1a3 100644
--- a/capture_opts.h
+++ b/capture_opts.h
@@ -24,7 +24,7 @@
/** @file
- *
+ *
* Capture options (all parameters needed to do the actual capture)
*
*/
@@ -118,14 +118,14 @@ capture_opts_list_link_layer_types(capture_options *capture_opts);
/* list interfaces */
extern int
-capture_opts_list_interfaces(void);
+capture_opts_list_interfaces(gboolean verbose);
/* trim the snaplen entry */
-extern void
+extern void
capture_opts_trim_snaplen(capture_options *capture_opts, int snaplen_min);
/* trim the ring_num_files entry */
-extern void
+extern void
capture_opts_trim_ring_num_files(capture_options *capture_opts);
/* trim the interface entry */
diff --git a/capture_sync.c b/capture_sync.c
index 4b67d0cd58..4dac5a371a 100644
--- a/capture_sync.c
+++ b/capture_sync.c
@@ -508,6 +508,242 @@ sync_pipe_start(capture_options *capture_opts) {
return TRUE;
}
+/*
+ * Get an interface list using dumpcap. On success, msg points to
+ * a buffer containing the dumpcap output and returns 0. On failure, msg
+ * points to the error message returned by dumpcap, and returns dumpcap's
+ * exit value. In either case, msg must be freed with g_free().
+ */
+/* XXX - This duplicates a lot of code in sync_pipe_start() and sync_interface_list_open() */
+#define PIPE_BUF_SIZE 5120
+int
+sync_interface_list_open(gchar **msg) {
+#ifdef _WIN32
+ HANDLE sync_pipe_read; /* pipe used to send messages from child to parent */
+ HANDLE sync_pipe_write; /* pipe used to send messages from parent to child */
+ GString *args = g_string_sized_new(200);
+ gchar *quoted_arg;
+ SECURITY_ATTRIBUTES sa;
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ int i;
+#else
+ int sync_pipe[2]; /* pipe used to send messages from child to parent */
+ enum PIPES { PIPE_READ, PIPE_WRITE }; /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
+#endif
+ int fork_child = -1, fork_child_status;
+ int sync_pipe_read_fd = -1;
+ const char *progfile_dir;
+ char *exename;
+ int argc;
+ const char **argv;
+ GString *msg_buf = NULL;
+ gchar buf[PIPE_BUF_SIZE+1];
+ int count;
+
+ g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_interface_list_open");
+
+ if (!msg) {
+ /* We can't return anything */
+#ifdef _WIN32
+ g_string_free(args, TRUE);
+#endif
+ return -1;
+ }
+
+ progfile_dir = get_progfile_dir();
+ if (progfile_dir == NULL) {
+ /* We don't know where to find dumpcap. */
+ *msg = g_strdup("We don't know where to find dumpcap.");
+ return CANT_RUN_DUMPCAP;
+ }
+
+ /* Allocate the string pointer array with enough space for the
+ terminating NULL pointer. */
+ argc = 0;
+ argv = g_malloc(sizeof (char *));
+ *argv = NULL;
+
+ /* take Wireshark's absolute program path and replace "Wireshark" with "dumpcap" */
+ exename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "dumpcap", progfile_dir);
+
+ /* Make that the first argument in the argument list (argv[0]). */
+ argv = sync_pipe_add_arg(argv, &argc, exename);
+
+ /* Ask for the interface list */
+ argv = sync_pipe_add_arg(argv, &argc, "-I");
+ argv = sync_pipe_add_arg(argv, &argc, "l");
+
+
+ /* dumpcap should be running in capture child mode (hidden feature) */
+#ifndef DEBUG_CHILD
+ argv = sync_pipe_add_arg(argv, &argc, "-Z");
+#endif
+
+
+#ifdef _WIN32
+ /* init SECURITY_ATTRIBUTES */
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.bInheritHandle = TRUE;
+ sa.lpSecurityDescriptor = NULL;
+
+ /* Create a pipe for the child process */
+ /* (inrease this value if you have trouble while fast capture file switches) */
+ if (! CreatePipe(&sync_pipe_read, &sync_pipe_write, &sa, 5120)) {
+ /* Couldn't create the pipe between parent and child. */
+ *msg = g_strdup_printf("Couldn't create sync pipe: %s", strerror(errno));
+ g_free( (gpointer) argv);
+ return CANT_RUN_DUMPCAP;
+ }
+
+ /* init STARTUPINFO */
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+#ifdef DEBUG_CHILD
+ si.dwFlags = STARTF_USESHOWWINDOW;
+ si.wShowWindow = SW_SHOW;
+#else
+ si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
+ si.wShowWindow = SW_HIDE; /* this hides the console window */
+ si.hStdInput = NULL;
+ si.hStdOutput = sync_pipe_write;
+ si.hStdError = sync_pipe_write;
+ /*si.hStdError = (HANDLE) _get_osfhandle(2);*/
+#endif
+
+ /* convert args array into a single string */
+ /* XXX - could change sync_pipe_add_arg() instead */
+ /* there is a drawback here: the length is internally limited to 1024 bytes */
+ for(i=0; argv[i] != 0; i++) {
+ if(i != 0) g_string_append_c(args, ' '); /* don't prepend a space before the path!!! */
+ quoted_arg = protect_arg(argv[i]);
+ g_string_append(args, quoted_arg);
+ g_free(quoted_arg);
+ }
+
+ /* call dumpcap */
+ if(!CreateProcess(NULL, utf_8to16(args->str), NULL, NULL, TRUE,
+ CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
+ *msg = g_strdup_printf("Couldn't run %s in child process: error %u",
+ args->str, GetLastError());
+ CloseHandle(sync_pipe_read);
+ CloseHandle(sync_pipe_write);
+ g_free( (gpointer) argv);
+ return CANT_RUN_DUMPCAP;
+ }
+ fork_child = (int) pi.hProcess;
+ g_string_free(args, TRUE);
+
+ /* associate the operating system filehandle to a C run-time file handle */
+ /* (good file handle infos at: http://www.flounder.com/handles.htm) */
+ sync_pipe_read_fd = _open_osfhandle( (long) sync_pipe_read, _O_BINARY);
+
+#else /* _WIN32 */
+ if (pipe(sync_pipe) < 0) {
+ /* Couldn't create the pipe between parent and child. */
+ *msg = g_strdup_printf("Couldn't create sync pipe: %s", strerror(errno));
+ g_free(argv);
+ return CANT_RUN_DUMPCAP;
+ }
+
+ if ((fork_child = fork()) == 0) {
+ /*
+ * Child process - run dumpcap with the right arguments to make
+ * it just capture with the specified capture parameters
+ */
+ eth_close(1);
+ dup(sync_pipe[PIPE_WRITE]);
+ eth_close(sync_pipe[PIPE_READ]);
+ execv(exename, (gpointer)argv);
+ *msg = g_strdup_printf("Couldn't run %s in child process: %s",
+ exename, strerror(errno));
+ return CANT_RUN_DUMPCAP;
+ }
+
+ sync_pipe_read_fd = sync_pipe[PIPE_READ];
+#endif
+
+ g_free(exename);
+
+ /* Parent process - read messages from the child process over the
+ sync pipe. */
+ g_free( (gpointer) argv); /* free up arg array */
+
+ /* Close the write side of the pipe, so that only the child has it
+ open, and thus it completely closes, and thus returns to us
+ an EOF indication, if the child closes it (either deliberately
+ or by exiting abnormally). */
+#ifdef _WIN32
+ CloseHandle(sync_pipe_write);
+#else
+ eth_close(sync_pipe[PIPE_WRITE]);
+#endif
+
+ if (fork_child == -1) {
+ /* We couldn't even create the child process. */
+ *msg = g_strdup_printf("Couldn't create child process: %s", strerror(errno));
+ eth_close(sync_pipe_read_fd);
+ return CANT_RUN_DUMPCAP;
+ }
+
+ /* we might wait for a moment till child is ready, so update screen now */
+ main_window_update();
+
+ /* We were able to set up to read dumpcap's output. Do so and
+ return its exit value. */
+ msg_buf = g_string_new("");
+ while ((count = eth_read(sync_pipe_read_fd, buf, PIPE_BUF_SIZE)) > 0) {
+ buf[count] = '\0';
+ g_string_append(msg_buf, buf);
+ }
+
+ eth_close(sync_pipe_read_fd);
+
+ g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_interface_list_open: wait till child closed");
+
+#ifdef _WIN32
+ if (_cwait(&fork_child_status, fork_child, _WAIT_CHILD) == -1) {
+ g_string_free(msg_buf, TRUE);
+ *msg = g_strdup_printf("Child capture process stopped unexpectedly "
+ "(errno:%u)", errno);
+ return CANT_RUN_DUMPCAP;
+ }
+#else
+ if (wait(&fork_child_status) != -1) {
+ if (WIFEXITED(fork_child_status)) {
+ /* The child exited. */
+ fork_child_status = WEXITSTATUS(fork_child_status);
+ } else {
+ g_string_free(msg_buf, TRUE);
+ if (WIFSTOPPED(fork_child_status)) {
+ /* It stopped, rather than exiting. "Should not happen." */
+ *msg = g_strdup_printf("Child capture process stopped: %s",
+ sync_pipe_signame(WSTOPSIG(fork_child_status)));
+ } else if (WIFSIGNALED(fork_child_status)) {
+ /* It died with a signal. */
+ *msg = g_strdup_printf("Child capture process died: %s%s",
+ sync_pipe_signame(WTERMSIG(fork_child_status)),
+ WCOREDUMP(fork_child_status) ? " - core dumped" : "");
+ } else {
+ /* What? It had to either have exited, or stopped, or died with
+ a signal; what happened here? */
+ *msg = g_strdup_printf("Child capture process died: wait status %#o",
+ fork_child_status);
+ }
+ return CANT_RUN_DUMPCAP;
+ }
+ } else {
+ g_string_free(msg_buf, TRUE);
+ *msg = g_strdup_printf("Child capture process stopped unexpectedly "
+ "(errno:%u)", errno);
+ return CANT_RUN_DUMPCAP;
+ }
+#endif
+
+ *msg = msg_buf->str;
+ g_string_free(msg_buf, FALSE);
+ return fork_child_status;
+}
/* read a number of bytes from a pipe */
@@ -542,7 +778,7 @@ pipe_read_bytes(int pipe, char *bytes, int required) {
/* convert header values (indicator and 4-byte length) */
static void
-pipe_convert_header(const guchar *header, int header_len, char *indicator, int *block_len) {
+pipe_convert_header(const guchar *header, int header_len, char *indicator, int *block_len) {
g_assert(header_len == 4);
@@ -636,10 +872,10 @@ sync_pipe_input_cb(gint source, gpointer user_data)
capturing any more packets. Pick up its exit status, and
complain if it did anything other than exit with status 0.
- We don't have to worry about killing the child, if the sync pipe
- returned an error. Usually this error is caused as the child killed itself
- while going down. Even in the rare cases that this isn't the case,
- the child will get an error when writing to the broken pipe the next time,
+ We don't have to worry about killing the child, if the sync pipe
+ returned an error. Usually this error is caused as the child killed itself
+ while going down. Even in the rare cases that this isn't the case,
+ the child will get an error when writing to the broken pipe the next time,
cleaning itself up then. */
sync_pipe_wait_for_child(capture_opts);
@@ -896,11 +1132,11 @@ sync_pipe_stop(capture_options *capture_opts)
/* Wireshark has to exit, force the capture child to close */
void
-sync_pipe_kill(capture_options *capture_opts)
+sync_pipe_kill(int fork_child)
{
- if (capture_opts->fork_child != -1) {
+ if (fork_child != -1) {
#ifndef _WIN32
- kill(capture_opts->fork_child, SIGTERM); /* SIGTERM so it can clean up if necessary */
+ kill(fork_child, SIGTERM); /* SIGTERM so it can clean up if necessary */
#else
/* Remark: This is not the preferred method of closing a process!
* the clean way would be getting the process id of the child process,
@@ -920,7 +1156,7 @@ sync_pipe_kill(capture_options *capture_opts)
* us, as we might not be running in a console.
* And this also will require to have the process id.
*/
- TerminateProcess((HANDLE) (capture_opts->fork_child), 0);
+ TerminateProcess((HANDLE) (fork_child), 0);
#endif
}
}
diff --git a/capture_sync.h b/capture_sync.h
index a8b6e6edaf..5e3cb7c9e5 100644
--- a/capture_sync.h
+++ b/capture_sync.h
@@ -24,10 +24,10 @@
/** @file
- *
+ *
* Sync mode capture (internal interface).
*
- * Will start a new Wireshark child instance which will do the actual capture
+ * Will start a new Wireshark child instance which will do the actual capture
* work.
*/
@@ -35,10 +35,10 @@
#define __CAPTURE_SYNC_H__
-/**
+/**
* Start a new capture session.
* Create a capture child which is doing the real capture work.
- * The various capture_input_... functions will be called, if something had
+ * The various capture_input_... functions will be called, if something had
* happened.
*
* Most of the parameters are passed through the global capture_opts.
@@ -46,7 +46,7 @@
* @param capture_opts the options
* @return TRUE if a capture could be started, FALSE if not
*/
-extern gboolean
+extern gboolean
sync_pipe_start(capture_options *capture_opts);
/** User wants to stop capturing, gracefully close the capture child */
@@ -55,12 +55,17 @@ sync_pipe_stop(capture_options *capture_opts);
/** User wants to stop the program, just kill the child as soon as possible */
extern void
-sync_pipe_kill(capture_options *capture_opts);
+sync_pipe_kill(int fork_child);
-/** does the parent signalled the child to stop */
+/** Has the parent signalled the child to stop? */
#ifdef _WIN32
extern gboolean
signal_pipe_check_running(void);
#endif
+/** Get an interface list using dumpcap */
+extern int
+sync_interface_list_open(gchar **msg);
+
+
#endif /* capture_sync.h */
diff --git a/doc/dumpcap.pod b/doc/dumpcap.pod
index 765c8c9712..9e9ed8f3ae 100644
--- a/doc/dumpcap.pod
+++ b/doc/dumpcap.pod
@@ -14,6 +14,7 @@ S<[ B<-D> ]>
S<[ B<-f> E<lt>capture filterE<gt> ]>
S<[ B<-h> ]>
S<[ B<-i> E<lt>capture interfaceE<gt>|- ]>
+S<[ B<-I> E<lt>l|sE<gt> ]>
S<[ B<-L> ]>
S<[ B<-p> ]>
S<[ B<-s> E<lt>capture snaplenE<gt> ]>
@@ -155,6 +156,14 @@ standard libpcap format.
Note: the Win32 version of B<Dumpcap> doesn't support capturing from
pipes or stdin!
+=item -I
+
+If run with the B<l> argument, print a verbose, machine-readable interface
+list, similar to the B<-D> flag.
+
+If run with the B<s> argument, print statistics for each interface every
+second until the program terminates.
+
=item -L
List the data link types supported by the interface and exit. The reported
diff --git a/dumpcap.c b/dumpcap.c
index bf0eea7764..9a540407c8 100644
--- a/dumpcap.c
+++ b/dumpcap.c
@@ -115,6 +115,7 @@ print_usage(gboolean print_ver) {
fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
fprintf(output, " -D print list of interfaces and exit\n");
fprintf(output, " -L print list of link-layer types of iface and exit\n");
+ fprintf(output, " -I [l|s] print a detailed interface list (l) or interface statistics (s).\n");
fprintf(output, "\n");
fprintf(output, "Stop conditions:\n");
fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
@@ -161,7 +162,10 @@ cmdarg_err(const char *fmt, ...)
va_list ap;
if(capture_child) {
- /* XXX - convert to g_log */
+ /* Print a bare error */
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
} else {
va_start(ap, fmt);
fprintf(stderr, "dumpcap: ");
@@ -245,7 +249,7 @@ main(int argc, char *argv[])
gboolean list_link_layer_types = FALSE;
int status;
-#define OPTSTRING_INIT "a:b:c:Df:hi:Lps:vw:y:Z"
+#define OPTSTRING_INIT "a:b:c:Df:hI:i:Lps:vw:y:Z"
#ifdef _WIN32
#define OPTSTRING_WIN32 "B:"
@@ -275,7 +279,7 @@ main(int argc, char *argv[])
/* the default_log_handler will use stdout, which makes trouble in */
/* capture child mode, as it uses stdout for it's sync_pipe */
/* so do the filtering in the console_log_handler and not here */
- log_flags =
+ log_flags =
G_LOG_LEVEL_ERROR|
G_LOG_LEVEL_CRITICAL|
G_LOG_LEVEL_WARNING|
@@ -297,7 +301,7 @@ main(int argc, char *argv[])
log_flags,
console_log_handler, NULL /* user_data */);
- /* Set the initial values in the capture_opts. This might be overwritten
+ /* Set the initial values in the capture_opts. This might be overwritten
by the command line parameters. */
capture_opts_init(capture_opts, NULL);
@@ -326,7 +330,7 @@ main(int argc, char *argv[])
/* Assemble the run-time version information string */
runtime_info_str = g_string_new("Running ");
- get_runtime_version_info(runtime_info_str, NULL);
+ get_runtime_version_info(runtime_info_str, NULL);
show_version(comp_info_str, runtime_info_str);
g_string_free(comp_info_str, TRUE);
g_string_free(runtime_info_str, TRUE);
@@ -362,9 +366,15 @@ main(int argc, char *argv[])
/*** all non capture option specific ***/
case 'D': /* Print a list of capture devices and exit */
- status = capture_opts_list_interfaces();
+ status = capture_opts_list_interfaces(FALSE);
exit_main(status);
break;
+ /* XXX - We might want to use 'D' for this. Do we use GNU
+ * getopt on every platform (which supports optional arguments)? */
+ /* XXX - Implement interface stats */
+ case 'I':
+ status = capture_opts_list_interfaces(TRUE);
+ exit_main(status);
case 'L': /* Print list of link-layer types and exit */
list_link_layer_types = TRUE;
break;
@@ -473,7 +483,7 @@ console_log_handler(const char *log_domain, GLogLevelFlags log_level,
/* create a "timestamp" */
time(&curr);
- today = localtime(&curr);
+ today = localtime(&curr);
switch(log_level & G_LOG_LEVEL_MASK) {
case G_LOG_LEVEL_ERROR:
@@ -558,7 +568,7 @@ report_cfilter_error(const char *cfilter, const char *errmsg)
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Capture filter error: %s", errmsg);
pipe_write_block(1, SP_BAD_FILTER, errmsg);
} else {
- fprintf(stderr,
+ fprintf(stderr,
"Invalid capture filter: \"%s\"!\n"
"\n"
"That string isn't a valid capture filter (%s).\n"
@@ -571,9 +581,9 @@ void
report_capture_error(const char *error_msg, const char *secondary_error_msg)
{
if(capture_child) {
- g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
+ g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
"Primary Error: %s", error_msg);
- g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
+ g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
"Secondary Error: %s", secondary_error_msg);
sync_pipe_errmsg_to_parent(error_msg, secondary_error_msg);
} else {
diff --git a/gtk/capture_dlg.c b/gtk/capture_dlg.c
index 4420dbeab2..54b95b07bd 100644
--- a/gtk/capture_dlg.c
+++ b/gtk/capture_dlg.c
@@ -236,7 +236,7 @@ set_link_type_list(GtkWidget *linktype_om, GtkWidget *entry)
/*
* Try to get the list of known interfaces.
*/
- if_list = get_interface_list(&err, NULL);
+ if_list = capture_interface_list(&err, NULL);
if (if_list != NULL) {
/*
* We have the list - check it.
@@ -627,7 +627,7 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_)
}
#endif
- if_list = get_interface_list(&err, &err_str);
+ if_list = capture_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);
diff --git a/gtk/capture_if_dlg.c b/gtk/capture_if_dlg.c
index 37eb732303..b2114b481c 100644
--- a/gtk/capture_if_dlg.c
+++ b/gtk/capture_if_dlg.c
@@ -397,7 +397,7 @@ combo_channel_new(void)
gint if_list_comparator_alph (const void *first_arg, const void *second_arg){
const if_info_t *first = first_arg, *second = second_arg;
- if (first != NULL && first->description != NULL &&
+ if (first != NULL && first->description != NULL &&
second != NULL && second->description != NULL) {
return g_strcasecmp(first->description, second->description);
} else {
@@ -458,7 +458,7 @@ capture_if_cb(GtkWidget *w _U_, gpointer d _U_)
#endif
/* LOAD THE INTERFACES */
- if_list = get_interface_list(&err, &err_str);
+ if_list = capture_interface_list(&err, &err_str);
if_list = g_list_sort (if_list, if_list_comparator_alph);
if (if_list == NULL && err == CANT_GET_INTERFACE_LIST) {
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str);
diff --git a/gtk/capture_prefs.c b/gtk/capture_prefs.c
index f761b0174c..6033891d42 100644
--- a/gtk/capture_prefs.c
+++ b/gtk/capture_prefs.c
@@ -43,6 +43,7 @@
#include "capture_ui_utils.h"
#include "main.h"
#include "compat_macros.h"
+#include "capture.h"
#define DEVICE_KEY "device"
#define PROM_MODE_KEY "prom_mode"
@@ -108,7 +109,7 @@ capture_prefs_show(void)
/*
* XXX - what if we can't get the list?
*/
- if_list = get_interface_list(&err, NULL);
+ if_list = capture_interface_list(&err, NULL);
combo_list = build_capture_combo_list(if_list, FALSE);
free_interface_list(if_list);
if (combo_list != NULL) {
@@ -119,7 +120,7 @@ capture_prefs_show(void)
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,
+ 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);
@@ -132,7 +133,7 @@ capture_prefs_show(void)
gtk_widget_show(ifopts_lb);
ifopts_bt = BUTTON_NEW_FROM_STOCK(WIRESHARK_STOCK_EDIT);
- gtk_tooltips_set_tip(tooltips, ifopts_bt,
+ 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);
@@ -142,7 +143,7 @@ capture_prefs_show(void)
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,
+ 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);
@@ -251,7 +252,7 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
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);
@@ -260,7 +261,7 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
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);
@@ -269,18 +270,18 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
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.
*/
@@ -292,24 +293,24 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
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);
@@ -321,51 +322,51 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
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,
+ 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,
+ 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);
@@ -392,7 +393,7 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_)
/* 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);
}
@@ -406,11 +407,11 @@ 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));
@@ -443,31 +444,31 @@ ifopts_edit_ifsel_cb(GtkWidget *clist _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)
@@ -483,10 +484,10 @@ 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 */
@@ -503,7 +504,7 @@ 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");
@@ -515,9 +516,9 @@ ifopts_edit_hide_changed_cb(GtkToggleButton *tbt, gpointer udata)
* 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
+ * 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
@@ -529,12 +530,12 @@ ifopts_options_add(GtkCList *clist, if_info_t *if_info)
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;
@@ -580,7 +581,7 @@ ifopts_options_add(GtkCList *clist, if_info_t *if_info)
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,
+ gtk_clist_set_selectable(GTK_CLIST(clist), row,
FALSE);
ifopts_options_free(text);
break;
@@ -614,13 +615,13 @@ ifopts_options_add(GtkCList *clist, if_info_t *if_info)
}
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);
}
/*
@@ -641,7 +642,7 @@ ifopts_options_add(GtkCList *clist, if_info_t *if_info)
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);
@@ -662,7 +663,7 @@ ifopts_options_add(GtkCList *clist, if_info_t *if_info)
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);
@@ -674,7 +675,7 @@ 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]);
@@ -695,18 +696,18 @@ ifopts_if_clist_add(void)
if_info_t *if_info;
guint i;
guint nitems;
-
- if_list = get_interface_list(&err, &err_str);
+
+ if_list = capture_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);
@@ -717,7 +718,7 @@ ifopts_if_clist_add(void)
/* fill current options CList with current preference values */
ifopts_options_add(GTK_CLIST(cur_clist), if_info);
}
-
+
free_interface_list(if_list);
}
@@ -734,10 +735,10 @@ ifopts_write_new_descr(void)
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 */
@@ -746,7 +747,7 @@ ifopts_write_new_descr(void)
/* 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);
@@ -763,7 +764,7 @@ ifopts_write_new_descr(void)
/* 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);
@@ -790,10 +791,10 @@ ifopts_write_new_hide(void)
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 */
@@ -805,7 +806,7 @@ ifopts_write_new_hide(void)
/* get interface name */
gtk_clist_get_text(GTK_CLIST(cur_clist), i, 0, &ifnm);
-
+
/*
* create/cat interface to new string
*/
@@ -819,7 +820,7 @@ ifopts_write_new_hide(void)
/* 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);
diff --git a/gtk/main.c b/gtk/main.c
index beac1944d0..2853de6404 100644
--- a/gtk/main.c
+++ b/gtk/main.c
@@ -2568,7 +2568,7 @@ main(int argc, char *argv[])
/*** all non capture option specific ***/
case 'D': /* Print a list of capture devices and exit */
#ifdef HAVE_LIBPCAP
- capture_opts_list_interfaces();
+ capture_opts_list_interfaces(FALSE);
exit(0);
#else
capture_option_specified = TRUE;
diff --git a/tshark.c b/tshark.c
index 00c6c350a8..ab1edaed30 100644
--- a/tshark.c
+++ b/tshark.c
@@ -740,7 +740,7 @@ main(int argc, char *argv[])
*/
opterr = 0;
optind_initial = optind;
-
+
while ((opt = getopt(argc, argv, optstring)) != -1) {
switch (opt) {
case 'X':
@@ -750,7 +750,7 @@ main(int argc, char *argv[])
break;
}
}
-
+
optind = optind_initial;
opterr = 1;
@@ -948,7 +948,7 @@ main(int argc, char *argv[])
break;
case 'D': /* Print a list of capture devices and exit */
#ifdef HAVE_LIBPCAP
- status = capture_opts_list_interfaces();
+ status = capture_opts_list_interfaces(FALSE);
exit(status);
#else
capture_option_specified = TRUE;
@@ -1146,7 +1146,7 @@ main(int argc, char *argv[])
"specified with \"-e\".");
exit(1);
- }
+ }
/* If no capture filter or read filter has been specified, and there are
still command-line arguments, treat them as the tokens of a capture
@@ -1269,7 +1269,7 @@ main(int argc, char *argv[])
"a capture isn't being done.");
exit(1);
}
-
+
/* Note: TShark now allows the restriction of a _read_ file by packet count
* and byte count as well as a write file. Other autostop options remain valid
* only for a write file.
@@ -1486,7 +1486,7 @@ main(int argc, char *argv[])
/* Process the packets in the file */
#ifdef HAVE_LIBPCAP
- err = load_cap_file(&cfile, capture_opts.save_file, out_file_type,
+ err = load_cap_file(&cfile, capture_opts.save_file, out_file_type,
capture_opts.has_autostop_packets ? capture_opts.autostop_packets : 0,
capture_opts.has_autostop_filesize ? capture_opts.autostop_filesize : 0);
#else
@@ -2114,7 +2114,7 @@ report_counts_siginfo(int signum _U_)
#endif /* HAVE_LIBPCAP */
static int
-load_cap_file(capture_file *cf, char *save_file, int out_file_type,
+load_cap_file(capture_file *cf, char *save_file, int out_file_type,
int max_packet_count, gint64 max_byte_count)
{
gint linktype;
@@ -2401,7 +2401,7 @@ process_packet(capture_file *cf, gint64 offset, const struct wtap_pkthdr *whdr,
}
if (passed) {
- /* Keep the time of the current packet if the packet passed
+ /* Keep the time of the current packet if the packet passed
the read filter so that the delta time since last displayed
packet can be calculated */
prev_dis_ts = fdata.abs_ts;
@@ -2809,7 +2809,7 @@ print_packet(capture_file *cf, epan_dissect_t *edt)
case WRITE_FIELDS:
proto_tree_write_fields(output_fields, edt, stdout);
printf("\n");
- return !ferror(stdout);
+ return !ferror(stdout);
}
} else {
/* Just fill in the columns. */