forked from osmocom/wireshark
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:
parent
f07a01dd51
commit
e9f1a0b692
|
@ -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);
|
||||
|
||||
|
|
117
capture.c
117
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"
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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>
|
||||
|
@ -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,27 +465,61 @@ 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 (!verbose) {
|
||||
/* Add the description if it exists */
|
||||
if (if_info->description != NULL)
|
||||
printf(" (%s)", if_info->description);
|
||||
#if 0
|
||||
} 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:
|
||||
memcpy(ipv4, (void *) &if_addr->ip_addr.ip4_addr, 4);
|
||||
printf(" %u.%u.%u.%u", ipv4[0], ipv4[1], ipv4[2], ipv4[3]);
|
||||
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:
|
||||
/* XXX - display the IPv6 address without using stuff from epan */
|
||||
printf(" XXX-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(" unknown address type %u", if_addr->type);
|
||||
printf("<type unknown %u>", if_addr->type);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (if_info->loopback)
|
||||
printf("\tloopback");
|
||||
else
|
||||
printf("\tnetwork");
|
||||
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
free_interface_list(if_list);
|
||||
|
|
|
@ -118,7 +118,7 @@ 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
|
||||
|
|
244
capture_sync.c
244
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 */
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
16
dumpcap.c
16
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:"
|
||||
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
@ -696,7 +697,7 @@ ifopts_if_clist_add(void)
|
|||
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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue