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
This commit is contained in:
Gerald Combs 2007-06-11 03:58:58 +00:00
parent f07a01dd51
commit e9f1a0b692
14 changed files with 567 additions and 147 deletions

View File

@ -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);

135
capture.c
View File

@ -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 */

View File

@ -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 */

View File

@ -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);
}
}
#endif
printf("\n");
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);
}
}
if (if_info->loopback)
printf("\tloopback");
else
printf("\tnetwork");
}
printf("\n");
}
free_interface_list(if_list);

View File

@ -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 */

View File

@ -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
}
}

View File

@ -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 */

View File

@ -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

View File

@ -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 {

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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. */