forked from osmocom/wireshark
HUGE STEP (hopefully toward the right direction):
remove a lot of redundant code from tethereal and use (move) stuff from capture_loop.c instead. concentrate common capture related code in capture_opts.c, e.g. trying to find the right interface to capture from (command line option, preference, first usable) instead of duplicating this code over several files. remove redundant code from dumpcap.c this also implements command line option -D (and indexed interfaces at -i) for Ethereal and Dumpcap (as we have it in Tethereal already for a while) svn path=/trunk/; revision=16787
This commit is contained in:
parent
459c0b07b2
commit
79217bab2e
|
@ -178,6 +178,7 @@ tethereal_SOURCES = \
|
|||
$(ETHEREAL_COMMON_SRC) \
|
||||
$(TETHEREAL_TAP_SRC) \
|
||||
capture_opts.c \
|
||||
capture_loop.c \
|
||||
tethereal-tap-register.c \
|
||||
tethereal.c
|
||||
|
||||
|
|
206
capture_loop.c
206
capture_loop.c
|
@ -61,97 +61,41 @@
|
|||
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "wiretap/wtap.h"
|
||||
#include "wiretap/wtap-capture.h"
|
||||
#include "wiretap/libpcap.h"
|
||||
|
||||
|
||||
#include <pcap.h>
|
||||
#include "capture-pcap-util.h"
|
||||
|
||||
#include "capture.h"
|
||||
#include "capture_loop.h"
|
||||
#include "capture_sync.h"
|
||||
|
||||
#include "conditions.h"
|
||||
#include "capture_stop_conditions.h"
|
||||
#include "ringbuffer.h"
|
||||
|
||||
#include "wiretap/libpcap.h"
|
||||
#include "wiretap/wtap.h"
|
||||
#include "wiretap/wtap-capture.h"
|
||||
|
||||
#include "simple_dialog.h"
|
||||
#include "util.h"
|
||||
#include "log.h"
|
||||
#include "file_util.h"
|
||||
|
||||
|
||||
#include "capture_loop.h"
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* We don't want to do a "select()" on the pcap_t's file descriptor on
|
||||
* BSD (because "select()" doesn't work correctly on BPF devices on at
|
||||
* least some releases of some flavors of BSD), and we don't want to do
|
||||
* it on Windows (because "select()" is something for sockets, not for
|
||||
* arbitrary handles). (Note that "Windows" here includes Cygwin;
|
||||
* even in its pretend-it's-UNIX environment, we're using WinPcap, not
|
||||
* a UNIX libpcap.)
|
||||
*
|
||||
* We *do* want to do it on other platforms, as, on other platforms (with
|
||||
* the possible exception of Ultrix and Digital UNIX), the read timeout
|
||||
* doesn't expire if no packets have arrived, so a "pcap_dispatch()" call
|
||||
* will block until packets arrive, causing the UI to hang.
|
||||
*
|
||||
* XXX - the various BSDs appear to define BSD in <sys/param.h>; we don't
|
||||
* want to include it if it's not present on this platform, however.
|
||||
* This needs to be static, so that the SIGUSR1 handler can clear the "go"
|
||||
* flag.
|
||||
*/
|
||||
#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && \
|
||||
!defined(__bsdi__) && !defined(__APPLE__) && !defined(_WIN32) && \
|
||||
!defined(__CYGWIN__)
|
||||
# define MUST_DO_SELECT
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct _loop_data {
|
||||
/* common */
|
||||
gboolean go; /* TRUE as long as we're supposed to keep capturing */
|
||||
int err; /* if non-zero, error seen while capturing */
|
||||
gint packets_curr; /* Number of packets we have already captured */
|
||||
gint packets_max; /* Number of packets we're supposed to capture - 0 means infinite */
|
||||
gint packets_sync_pipe; /* packets not already send out to the sync_pipe */
|
||||
|
||||
/* pcap "input file" */
|
||||
pcap_t *pcap_h; /* pcap handle */
|
||||
gboolean pcap_err; /* TRUE if error from pcap */
|
||||
#ifdef MUST_DO_SELECT
|
||||
int pcap_fd; /* pcap file descriptor */
|
||||
#endif
|
||||
|
||||
/* capture pipe (unix only "input file") */
|
||||
gboolean from_cap_pipe; /* TRUE if we are capturing data from a capture pipe */
|
||||
#ifndef _WIN32
|
||||
struct pcap_hdr cap_pipe_hdr;
|
||||
struct pcaprec_modified_hdr cap_pipe_rechdr;
|
||||
int cap_pipe_fd; /* the file descriptor of the capture pipe */
|
||||
gboolean cap_pipe_modified; /* TRUE if data in the pipe uses modified pcap headers */
|
||||
gboolean cap_pipe_byte_swapped; /* TRUE if data in the pipe is byte swapped */
|
||||
unsigned int cap_pipe_bytes_to_read;/* Used by cap_pipe_dispatch */
|
||||
unsigned int cap_pipe_bytes_read; /* Used by cap_pipe_dispatch */
|
||||
enum {
|
||||
STATE_EXPECT_REC_HDR,
|
||||
STATE_READ_REC_HDR,
|
||||
STATE_EXPECT_DATA,
|
||||
STATE_READ_DATA
|
||||
} cap_pipe_state;
|
||||
|
||||
enum { PIPOK, PIPEOF, PIPERR, PIPNEXIST } cap_pipe_err;
|
||||
#endif
|
||||
|
||||
/* wiretap (output file) */
|
||||
wtap_dumper *wtap_pdh;
|
||||
gint wtap_linktype;
|
||||
|
||||
} loop_data;
|
||||
static loop_data ld;
|
||||
|
||||
|
||||
/*
|
||||
|
@ -169,10 +113,10 @@ static void capture_loop_get_errmsg(char *errmsg, int errmsglen, const char *fna
|
|||
#ifndef _WIN32
|
||||
/* Take care of byte order in the libpcap headers read from pipes.
|
||||
* (function taken from wiretap/libpcap.c) */
|
||||
static void
|
||||
cap_pipe_adjust_header(loop_data *ld, struct pcap_hdr *hdr, struct pcaprec_hdr *rechdr)
|
||||
void
|
||||
cap_pipe_adjust_header(gboolean byte_swapped, struct pcap_hdr *hdr, struct pcaprec_hdr *rechdr)
|
||||
{
|
||||
if (ld->cap_pipe_byte_swapped) {
|
||||
if (byte_swapped) {
|
||||
/* Byte-swap the record header fields. */
|
||||
rechdr->ts_sec = BSWAP32(rechdr->ts_sec);
|
||||
rechdr->ts_usec = BSWAP32(rechdr->ts_usec);
|
||||
|
@ -203,7 +147,7 @@ cap_pipe_adjust_header(loop_data *ld, struct pcap_hdr *hdr, struct pcaprec_hdr *
|
|||
* header.
|
||||
* N.B. : we can't read the libpcap formats used in RedHat 6.1 or SuSE 6.3
|
||||
* because we can't seek on pipes (see wiretap/libpcap.c for details) */
|
||||
static int
|
||||
int
|
||||
cap_pipe_open_live(char *pipename, struct pcap_hdr *hdr, loop_data *ld,
|
||||
char *errmsg, int errmsgl)
|
||||
{
|
||||
|
@ -219,7 +163,7 @@ cap_pipe_open_live(char *pipename, struct pcap_hdr *hdr, loop_data *ld,
|
|||
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "cap_pipe_open_live: %s", pipename);
|
||||
|
||||
/*
|
||||
* XXX Ethereal blocks until we return
|
||||
* XXX (T)Ethereal blocks until we return
|
||||
*/
|
||||
if (strcmp(pipename, "-") == 0)
|
||||
fd = 0; /* read from stdin */
|
||||
|
@ -375,7 +319,7 @@ error:
|
|||
|
||||
/* We read one record from the pipe, take care of byte order in the record
|
||||
* header, write the record to the capture file, and update capture statistics. */
|
||||
static int
|
||||
int
|
||||
cap_pipe_dispatch(int fd, loop_data *ld, struct pcap_hdr *hdr,
|
||||
struct pcaprec_modified_hdr *rechdr, guchar *data,
|
||||
char *errmsg, int errmsgl)
|
||||
|
@ -446,10 +390,10 @@ cap_pipe_dispatch(int fd, loop_data *ld, struct pcap_hdr *hdr,
|
|||
|
||||
case PD_REC_HDR_READ:
|
||||
/* We've read the header. Take care of byte order. */
|
||||
cap_pipe_adjust_header(ld, hdr, &rechdr->hdr);
|
||||
cap_pipe_adjust_header(ld->cap_pipe_byte_swapped, hdr, &rechdr->hdr);
|
||||
if (rechdr->hdr.incl_len > WTAP_MAX_PACKET_SIZE) {
|
||||
g_snprintf(errmsg, errmsgl, "Frame %u too long (%d bytes)",
|
||||
ld->packets_curr+1, rechdr->hdr.incl_len);
|
||||
ld->packet_count+1, rechdr->hdr.incl_len);
|
||||
break;
|
||||
}
|
||||
ld->cap_pipe_state = STATE_EXPECT_DATA;
|
||||
|
@ -462,7 +406,7 @@ cap_pipe_dispatch(int fd, loop_data *ld, struct pcap_hdr *hdr,
|
|||
phdr.caplen = rechdr->hdr.incl_len;
|
||||
phdr.len = rechdr->hdr.orig_len;
|
||||
|
||||
capture_loop_packet_cb((u_char *)ld, &phdr, data);
|
||||
ld->packet_cb((u_char *)ld, &phdr, data);
|
||||
|
||||
ld->cap_pipe_state = STATE_EXPECT_REC_HDR;
|
||||
return 1;
|
||||
|
@ -487,8 +431,9 @@ cap_pipe_dispatch(int fd, loop_data *ld, struct pcap_hdr *hdr,
|
|||
|
||||
|
||||
/* open the capture input file (pcap or capture pipe) */
|
||||
static int capture_loop_open_input(capture_options *capture_opts, loop_data *ld, char *errmsg, int errmsg_len) {
|
||||
gboolean capture_loop_open_input(capture_options *capture_opts, loop_data *ld, char *errmsg, int errmsg_len) {
|
||||
gchar open_err_str[PCAP_ERRBUF_SIZE];
|
||||
gchar *sync_msg_str;
|
||||
const char *set_linktype_err_str;
|
||||
#ifdef _WIN32
|
||||
int err;
|
||||
|
@ -502,6 +447,9 @@ static int capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
|
|||
|
||||
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_open_input : %s", capture_opts->iface);
|
||||
|
||||
|
||||
/* XXX - opening Winsock on tethereal? */
|
||||
|
||||
/* Initialize Windows Socket if we are in a WIN32 OS
|
||||
This needs to be done before querying the interface for network/netmask */
|
||||
#ifdef _WIN32
|
||||
|
@ -563,7 +511,7 @@ static int capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
|
|||
#ifdef _WIN32
|
||||
/* try to set the capture buffer size */
|
||||
if (pcap_setbuff(ld->pcap_h, capture_opts->buffer_size * 1024 * 1024) != 0) {
|
||||
simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
|
||||
sync_msg_str = g_strdup_printf(
|
||||
"%sCouldn't set the capture buffer size!%s\n"
|
||||
"\n"
|
||||
"The capture buffer size of %luMB seems to be too high for your machine,\n"
|
||||
|
@ -571,6 +519,8 @@ static int capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
|
|||
"\n"
|
||||
"Nonetheless, the capture is started.\n",
|
||||
simple_dialog_primary_start(), simple_dialog_primary_end(), capture_opts->buffer_size);
|
||||
sync_pipe_errmsg_to_parent(sync_msg_str);
|
||||
g_free(sync_msg_str);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -592,13 +542,14 @@ static int capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
|
|||
/* On Win32 OSes, the capture devices are probably available to all
|
||||
users; don't warn about permissions problems.
|
||||
|
||||
Do, however, warn that WAN devices aren't supported. */
|
||||
Do, however, warn about the lack of 64-bit support, and warn that
|
||||
WAN devices aren't supported. */
|
||||
g_snprintf(errmsg, errmsg_len,
|
||||
"%sThe capture session could not be initiated!%s\n"
|
||||
"\n"
|
||||
"(%s)\n"
|
||||
"\n"
|
||||
"Please check that you have the proper interface specified.\n"
|
||||
"Please check that \"%s\" is the proper interface.\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Help can be found at:\n"
|
||||
|
@ -618,6 +569,7 @@ static int capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
|
|||
"support for it on Windows NT 4.0 or Windows Vista (Beta 1).",
|
||||
simple_dialog_primary_start(), simple_dialog_primary_end(),
|
||||
open_err_str,
|
||||
capture_opts->iface,
|
||||
simple_dialog_primary_start(), simple_dialog_primary_end());
|
||||
return FALSE;
|
||||
#else
|
||||
|
@ -630,16 +582,16 @@ static int capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
|
|||
/* Pipe doesn't exist, so output message for interface */
|
||||
|
||||
/* If we got a "can't find PPA for XXX" message, warn the user (who
|
||||
is running Ethereal on HP-UX) that they don't have a version
|
||||
is running (T)Ethereal on HP-UX) that they don't have a version
|
||||
of libpcap that properly handles HP-UX (libpcap 0.6.x and later
|
||||
versions, which properly handle HP-UX, say "can't find /dev/dlpi
|
||||
PPA for XXX" rather than "can't find PPA for XXX"). */
|
||||
if (strncmp(open_err_str, ppamsg, sizeof ppamsg - 1) == 0)
|
||||
libpcap_warn =
|
||||
"\n\n"
|
||||
"You are running Ethereal with a version of the libpcap library\n"
|
||||
"You are running (T)Ethereal with a version of the libpcap library\n"
|
||||
"that doesn't handle HP-UX network devices well; this means that\n"
|
||||
"Ethereal may not be able to capture packets.\n"
|
||||
"(T)Ethereal may not be able to capture packets.\n"
|
||||
"\n"
|
||||
"To fix this, you should install libpcap 0.6.2, or a later version\n"
|
||||
"of libpcap, rather than libpcap 0.4 or 0.5.x. It is available in\n"
|
||||
|
@ -666,6 +618,7 @@ static int capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
|
|||
#endif
|
||||
}
|
||||
|
||||
/* XXX - will this work for tethereal? */
|
||||
#ifdef MUST_DO_SELECT
|
||||
if (!ld->from_cap_pipe) {
|
||||
#ifdef HAVE_PCAP_GET_SELECTABLE_FD
|
||||
|
@ -678,8 +631,11 @@ static int capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
|
|||
|
||||
/* Does "open_err_str" contain a non-empty string? If so, "pcap_open_live()"
|
||||
returned a warning; print it, but keep capturing. */
|
||||
if (open_err_str[0] != '\0')
|
||||
g_warning("%s.", open_err_str);
|
||||
if (open_err_str[0] != '\0') {
|
||||
sync_msg_str = g_strdup_printf("%s.", open_err_str);
|
||||
sync_pipe_errmsg_to_parent(sync_msg_str);
|
||||
g_free(sync_msg_str);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -712,7 +668,7 @@ static void capture_loop_close_input(loop_data *ld) {
|
|||
|
||||
|
||||
/* init the capture filter */
|
||||
static int capture_loop_init_filter(loop_data *ld, const gchar * iface, gchar * cfilter, char *errmsg, int errmsg_len) {
|
||||
gboolean capture_loop_init_filter(pcap_t *pcap_h, gboolean from_cap_pipe, const gchar * iface, gchar * cfilter, char *errmsg, int errmsg_len) {
|
||||
bpf_u_int32 netnum, netmask;
|
||||
gchar lookup_net_err_str[PCAP_ERRBUF_SIZE];
|
||||
struct bpf_program fcode;
|
||||
|
@ -721,7 +677,7 @@ static int capture_loop_init_filter(loop_data *ld, const gchar * iface, gchar *
|
|||
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_init_filter: %s", cfilter);
|
||||
|
||||
/* capture filters only work on real interfaces */
|
||||
if (cfilter && !ld->from_cap_pipe) {
|
||||
if (cfilter && !from_cap_pipe) {
|
||||
/* A capture filter was specified; set it up. */
|
||||
if (pcap_lookupnet(iface, &netnum, &netmask, lookup_net_err_str) < 0) {
|
||||
/*
|
||||
|
@ -733,13 +689,15 @@ static int capture_loop_init_filter(loop_data *ld, const gchar * iface, gchar *
|
|||
* a difference (only filters that check for IP broadcast addresses
|
||||
* use the netmask).
|
||||
*/
|
||||
/*cmdarg_err(
|
||||
"Warning: Couldn't obtain netmask info (%s).", lookup_net_err_str);*/
|
||||
netmask = 0;
|
||||
}
|
||||
if (pcap_compile(ld->pcap_h, &fcode, cfilter, 1, netmask) < 0) {
|
||||
if (pcap_compile(pcap_h, &fcode, cfilter, 1, netmask) < 0) {
|
||||
dfilter_t *rfcode = NULL;
|
||||
gchar *safe_cfilter = simple_dialog_format_message(cfilter);
|
||||
gchar *safe_cfilter_error_msg = simple_dialog_format_message(
|
||||
pcap_geterr(ld->pcap_h));
|
||||
pcap_geterr(pcap_h));
|
||||
|
||||
/* filter string invalid, did the user tried a display filter? */
|
||||
#ifndef DUMPCAP
|
||||
|
@ -753,7 +711,7 @@ static int capture_loop_init_filter(loop_data *ld, const gchar * iface, gchar *
|
|||
"Note that display filters and capture filters don't have the same syntax,\n"
|
||||
"so you can't use most display filter expressions as capture filters.\n"
|
||||
"\n"
|
||||
"See the help for a description of the capture filter syntax.",
|
||||
"See the User's Guide for a description of the capture filter syntax.",
|
||||
simple_dialog_primary_start(), safe_cfilter,
|
||||
simple_dialog_primary_end(), safe_cfilter_error_msg);
|
||||
dfilter_free(rfcode);
|
||||
|
@ -764,7 +722,7 @@ static int capture_loop_init_filter(loop_data *ld, const gchar * iface, gchar *
|
|||
"%sInvalid capture filter: \"%s\"!%s\n"
|
||||
"\n"
|
||||
"That string isn't a valid capture filter (%s).\n"
|
||||
"See the help for a description of the capture filter syntax.",
|
||||
"See the User's Guide for a description of the capture filter syntax.",
|
||||
simple_dialog_primary_start(), safe_cfilter,
|
||||
simple_dialog_primary_end(), safe_cfilter_error_msg);
|
||||
}
|
||||
|
@ -772,9 +730,9 @@ static int capture_loop_init_filter(loop_data *ld, const gchar * iface, gchar *
|
|||
g_free(safe_cfilter);
|
||||
return FALSE;
|
||||
}
|
||||
if (pcap_setfilter(ld->pcap_h, &fcode) < 0) {
|
||||
if (pcap_setfilter(pcap_h, &fcode) < 0) {
|
||||
g_snprintf(errmsg, errmsg_len, "Can't install filter (%s).",
|
||||
pcap_geterr(ld->pcap_h));
|
||||
pcap_geterr(pcap_h));
|
||||
#ifdef HAVE_PCAP_FREECODE
|
||||
pcap_freecode(&fcode);
|
||||
#endif
|
||||
|
@ -790,7 +748,7 @@ static int capture_loop_init_filter(loop_data *ld, const gchar * iface, gchar *
|
|||
|
||||
|
||||
/* open the wiretap part of the capture output file */
|
||||
static int capture_loop_init_wiretap_output(capture_options *capture_opts, int save_file_fd, loop_data *ld, char *errmsg, int errmsg_len) {
|
||||
gboolean capture_loop_init_wiretap_output(capture_options *capture_opts, int save_file_fd, loop_data *ld, char *errmsg, int errmsg_len) {
|
||||
int pcap_encap;
|
||||
int file_snaplen;
|
||||
int err;
|
||||
|
@ -815,7 +773,7 @@ static int capture_loop_init_wiretap_output(capture_options *capture_opts, int s
|
|||
if (ld->wtap_linktype == WTAP_ENCAP_UNKNOWN) {
|
||||
g_snprintf(errmsg, errmsg_len,
|
||||
"The network you're capturing from is of a type"
|
||||
" that Ethereal doesn't support (data link type %d).", pcap_encap);
|
||||
" that (T)Ethereal doesn't support (data link type %d).", pcap_encap);
|
||||
return FALSE;
|
||||
}
|
||||
if (capture_opts->multi_files_on) {
|
||||
|
@ -828,6 +786,7 @@ static int capture_loop_init_wiretap_output(capture_options *capture_opts, int s
|
|||
|
||||
if (ld->wtap_pdh == NULL) {
|
||||
/* We couldn't set up to write to the capture file. */
|
||||
/* XXX - use cf_open_error_message from tethereal instead? */
|
||||
switch (err) {
|
||||
|
||||
case WTAP_ERR_CANT_OPEN:
|
||||
|
@ -861,7 +820,7 @@ static int capture_loop_init_wiretap_output(capture_options *capture_opts, int s
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean capture_loop_close_output(capture_options *capture_opts, loop_data *ld, int *err_close) {
|
||||
gboolean capture_loop_close_output(capture_options *capture_opts, loop_data *ld, int *err_close) {
|
||||
|
||||
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_close_output");
|
||||
|
||||
|
@ -970,7 +929,7 @@ capture_loop_dispatch(capture_options *capture_opts, loop_data *ld,
|
|||
* "select()" says we can read from it without blocking; go for
|
||||
* it.
|
||||
*/
|
||||
inpkts = pcap_dispatch(ld->pcap_h, 1, capture_loop_packet_cb, (u_char *)ld);
|
||||
inpkts = pcap_dispatch(ld->pcap_h, 1, ld->packet_cb, (u_char *)ld);
|
||||
if (inpkts < 0) {
|
||||
ld->pcap_err = TRUE;
|
||||
ld->go = FALSE;
|
||||
|
@ -993,7 +952,7 @@ capture_loop_dispatch(capture_options *capture_opts, loop_data *ld,
|
|||
#ifdef LOG_CAPTURE_VERBOSE
|
||||
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from pcap_dispatch");
|
||||
#endif
|
||||
inpkts = pcap_dispatch(ld->pcap_h, 1, capture_loop_packet_cb, (u_char *) ld);
|
||||
inpkts = pcap_dispatch(ld->pcap_h, 1, ld->packet_cb, (u_char *) ld);
|
||||
if (inpkts < 0) {
|
||||
ld->pcap_err = TRUE;
|
||||
ld->go = FALSE;
|
||||
|
@ -1015,7 +974,7 @@ capture_loop_dispatch(capture_options *capture_opts, loop_data *ld,
|
|||
|
||||
inpkts = 0;
|
||||
while( (in = pcap_next_ex(ld->pcap_h, &pkt_header, &pkt_data)) == 1) {
|
||||
capture_loop_packet_cb( (u_char *) ld, pkt_header, pkt_data);
|
||||
ld->packet_cb( (u_char *) ld, pkt_header, pkt_data);
|
||||
inpkts++;
|
||||
}
|
||||
|
||||
|
@ -1039,7 +998,7 @@ capture_loop_dispatch(capture_options *capture_opts, loop_data *ld,
|
|||
|
||||
/* open the output file (temporary/specified name/ringbuffer) */
|
||||
/* Returns TRUE if the file opened successfully, FALSE otherwise. */
|
||||
static gboolean
|
||||
gboolean
|
||||
capture_loop_open_output(capture_options *capture_opts, int *save_file_fd,
|
||||
char *errmsg, int errmsg_len) {
|
||||
|
||||
|
@ -1141,22 +1100,16 @@ signal_pipe_stopped(void)
|
|||
/*g_warning("check pipe: handle: %x result: %u avail: %u", handle, result, avail);*/
|
||||
|
||||
if(!result || avail > 0) {
|
||||
/* XXX - doesn't work with dumpcap as a command line tool */
|
||||
/* as we have no input pipe, need to find a way to circumvent this */
|
||||
/* peek failed or some bytes really available */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* pipe ok and no bytes available */
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* This needs to be static, so that the SIGUSR1 handler can clear the "go"
|
||||
* flag.
|
||||
*/
|
||||
static loop_data ld;
|
||||
|
||||
/* Do the low-level work of a capture.
|
||||
Returns TRUE if it succeeds, FALSE otherwise. */
|
||||
int
|
||||
|
@ -1164,7 +1117,9 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
{
|
||||
time_t upd_time, cur_time;
|
||||
time_t start_time;
|
||||
int err_close, inpkts;
|
||||
int err_close;
|
||||
int inpkts;
|
||||
gint inpkts_to_sync_pipe = 0; /* packets not already send out to the sync_pipe */
|
||||
condition *cnd_file_duration = NULL;
|
||||
condition *cnd_autostop_files = NULL;
|
||||
condition *cnd_autostop_size = NULL;
|
||||
|
@ -1181,16 +1136,15 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
|
||||
/* init the loop data */
|
||||
ld.go = TRUE;
|
||||
ld.packets_curr = 0;
|
||||
ld.packet_count = 0;
|
||||
if (capture_opts->has_autostop_packets)
|
||||
ld.packets_max = capture_opts->autostop_packets;
|
||||
ld.packet_max = capture_opts->autostop_packets;
|
||||
else
|
||||
ld.packets_max = 0; /* no limit */
|
||||
ld.packet_max = 0; /* no limit */
|
||||
ld.err = 0; /* no error seen yet */
|
||||
ld.wtap_linktype = WTAP_ENCAP_UNKNOWN;
|
||||
ld.pcap_err = FALSE;
|
||||
ld.from_cap_pipe = FALSE;
|
||||
ld.packets_sync_pipe = 0;
|
||||
ld.wtap_pdh = NULL;
|
||||
#ifndef _WIN32
|
||||
ld.cap_pipe_fd = -1;
|
||||
|
@ -1198,6 +1152,8 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
#ifdef MUST_DO_SELECT
|
||||
ld.pcap_fd = 0;
|
||||
#endif
|
||||
ld.packet_cb = capture_loop_packet_cb;
|
||||
|
||||
|
||||
/* We haven't yet gotten the capture statistics. */
|
||||
*stats_known = FALSE;
|
||||
|
@ -1228,7 +1184,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
}
|
||||
|
||||
/* init the input filter from the network interface (capture pipe will do nothing) */
|
||||
if (!capture_loop_init_filter(&ld, capture_opts->iface, capture_opts->cfilter, errmsg, sizeof(errmsg))) {
|
||||
if (!capture_loop_init_filter(ld.pcap_h, ld.from_cap_pipe, capture_opts->iface, capture_opts->cfilter, errmsg, sizeof(errmsg))) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -1293,7 +1249,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
#endif
|
||||
|
||||
if (inpkts > 0) {
|
||||
ld.packets_sync_pipe += inpkts;
|
||||
inpkts_to_sync_pipe += inpkts;
|
||||
|
||||
/* check capture size condition */
|
||||
if (cnd_autostop_size != NULL && cnd_eval(cnd_autostop_size,
|
||||
|
@ -1315,7 +1271,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
}
|
||||
wtap_dump_flush(ld.wtap_pdh);
|
||||
sync_pipe_filename_to_parent(capture_opts->save_file);
|
||||
ld.packets_sync_pipe = 0;
|
||||
inpkts_to_sync_pipe = 0;
|
||||
} else {
|
||||
/* File switch failed: stop here */
|
||||
ld.go = FALSE;
|
||||
|
@ -1343,15 +1299,15 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
}*/
|
||||
|
||||
/* Let the parent process know. */
|
||||
if (ld.packets_sync_pipe) {
|
||||
if (inpkts_to_sync_pipe) {
|
||||
/* do sync here */
|
||||
wtap_dump_flush(ld.wtap_pdh);
|
||||
|
||||
/* Send our parent a message saying we've written out "ld.sync_packets"
|
||||
/* Send our parent a message saying we've written out "inpkts_to_sync_pipe"
|
||||
packets to the capture file. */
|
||||
sync_pipe_packet_count_to_parent(ld.packets_sync_pipe);
|
||||
sync_pipe_packet_count_to_parent(inpkts_to_sync_pipe);
|
||||
|
||||
ld.packets_sync_pipe = 0;
|
||||
inpkts_to_sync_pipe = 0;
|
||||
}
|
||||
|
||||
/* check capture duration condition */
|
||||
|
@ -1379,7 +1335,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
cnd_reset(cnd_autostop_size);
|
||||
wtap_dump_flush(ld.wtap_pdh);
|
||||
sync_pipe_filename_to_parent(capture_opts->save_file);
|
||||
ld.packets_sync_pipe = 0;
|
||||
inpkts_to_sync_pipe = 0;
|
||||
} else {
|
||||
/* File switch failed: stop here */
|
||||
ld.go = FALSE;
|
||||
|
@ -1575,8 +1531,8 @@ capture_loop_packet_cb(u_char *user, const struct pcap_pkthdr *phdr,
|
|||
int err;
|
||||
|
||||
/* if the user told us to stop after x packets, do we have enough? */
|
||||
ld->packets_curr++;
|
||||
if ((ld->packets_max > 0) && (ld->packets_curr >= ld->packets_max))
|
||||
ld->packet_count++;
|
||||
if ((ld->packet_max > 0) && (ld->packet_count >= ld->packet_max))
|
||||
{
|
||||
ld->go = FALSE;
|
||||
}
|
||||
|
|
110
capture_loop.h
110
capture_loop.h
|
@ -40,4 +40,114 @@ extern int capture_loop_start(capture_options *capture_opts, gboolean *stats_kn
|
|||
extern void capture_loop_stop(void);
|
||||
|
||||
|
||||
/*** the following is internal only (should be moved to capture_loop_int.h) ***/
|
||||
|
||||
|
||||
/*
|
||||
* We don't want to do a "select()" on the pcap_t's file descriptor on
|
||||
* BSD (because "select()" doesn't work correctly on BPF devices on at
|
||||
* least some releases of some flavors of BSD), and we don't want to do
|
||||
* it on Windows (because "select()" is something for sockets, not for
|
||||
* arbitrary handles). (Note that "Windows" here includes Cygwin;
|
||||
* even in its pretend-it's-UNIX environment, we're using WinPcap, not
|
||||
* a UNIX libpcap.)
|
||||
*
|
||||
* We *do* want to do it on other platforms, as, on other platforms (with
|
||||
* the possible exception of Ultrix and Digital UNIX), the read timeout
|
||||
* doesn't expire if no packets have arrived, so a "pcap_dispatch()" call
|
||||
* will block until packets arrive, causing the UI to hang.
|
||||
*
|
||||
* XXX - the various BSDs appear to define BSD in <sys/param.h>; we don't
|
||||
* want to include it if it's not present on this platform, however.
|
||||
*/
|
||||
#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && \
|
||||
!defined(__bsdi__) && !defined(__APPLE__) && !defined(_WIN32) && \
|
||||
!defined(__CYGWIN__)
|
||||
# define MUST_DO_SELECT
|
||||
#endif
|
||||
|
||||
typedef void (*capture_packet_cb_fct)(u_char *, const struct pcap_pkthdr *, const u_char *);
|
||||
|
||||
|
||||
/* moved from capture_loop.c here, so we can combine it (and the related functions) with tethereal */
|
||||
/* XXX - should be moved back to capture_loop.c */
|
||||
/* E: capture_loop.c only (Ethereal/dumpcap) T: tethereal only */
|
||||
typedef struct _loop_data {
|
||||
/* common */
|
||||
gboolean go; /* TRUE as long as we're supposed to keep capturing */
|
||||
int err; /* E: if non-zero, error seen while capturing */
|
||||
gint packet_count; /* Number of packets we have already captured */
|
||||
gint packet_max; /* E: Number of packets we're supposed to capture - 0 means infinite */
|
||||
|
||||
jmp_buf stopenv; /* T: starting point of loop (jump back this point on SIG...) */
|
||||
|
||||
char *save_file; /* T: Name of file to which we're writing */
|
||||
gboolean output_to_pipe; /* T: output to a pipe, flush outut file immediately */
|
||||
capture_packet_cb_fct packet_cb; /* callback for a single captured packet */
|
||||
|
||||
/* pcap "input file" */
|
||||
pcap_t *pcap_h; /* pcap handle */
|
||||
gboolean pcap_err; /* E: TRUE if error from pcap */
|
||||
#ifdef MUST_DO_SELECT
|
||||
int pcap_fd; /* pcap file descriptor */
|
||||
#endif
|
||||
|
||||
/* capture pipe (unix only "input file") */
|
||||
gboolean from_cap_pipe; /* TRUE if we are capturing data from a capture pipe */
|
||||
#ifndef _WIN32
|
||||
struct pcap_hdr cap_pipe_hdr; /* ? */
|
||||
struct pcaprec_modified_hdr cap_pipe_rechdr; /* ? */
|
||||
int cap_pipe_fd; /* the file descriptor of the capture pipe */
|
||||
gboolean cap_pipe_modified; /* TRUE if data in the pipe uses modified pcap headers */
|
||||
gboolean cap_pipe_byte_swapped; /* TRUE if data in the pipe is byte swapped */
|
||||
unsigned int cap_pipe_bytes_to_read;/* Used by cap_pipe_dispatch */
|
||||
unsigned int cap_pipe_bytes_read; /* Used by cap_pipe_dispatch */
|
||||
enum {
|
||||
STATE_EXPECT_REC_HDR,
|
||||
STATE_READ_REC_HDR,
|
||||
STATE_EXPECT_DATA,
|
||||
STATE_READ_DATA
|
||||
} cap_pipe_state;
|
||||
enum { PIPOK, PIPEOF, PIPERR, PIPNEXIST } cap_pipe_err;
|
||||
#endif
|
||||
|
||||
/* wiretap (output file) */
|
||||
wtap_dumper *wtap_pdh;
|
||||
gint wtap_linktype;
|
||||
|
||||
} loop_data;
|
||||
|
||||
|
||||
|
||||
/** init the capture filter */
|
||||
extern gboolean
|
||||
capture_loop_init_filter(pcap_t *pcap_h, gboolean from_cap_pipe, const gchar * iface, gchar * cfilter, char *errmsg, int errmsg_len);
|
||||
|
||||
/** Take care of byte order in the libpcap headers read from pipes. */
|
||||
extern void
|
||||
cap_pipe_adjust_header(gboolean byte_swapped, struct pcap_hdr *hdr, struct pcaprec_hdr *rechdr);
|
||||
|
||||
#ifdef HAVE_LIBPCAP
|
||||
#ifndef _WIN32
|
||||
extern int
|
||||
cap_pipe_open_live(char *, struct pcap_hdr *, loop_data *, char *, int);
|
||||
|
||||
extern int
|
||||
cap_pipe_dispatch(int, loop_data *, struct pcap_hdr *, \
|
||||
struct pcaprec_modified_hdr *, guchar *, char *, int);
|
||||
#endif /* _WIN32 */
|
||||
#endif
|
||||
|
||||
extern gboolean
|
||||
capture_loop_open_input(capture_options *capture_opts, loop_data *ld, char *errmsg, int errmsg_len);
|
||||
|
||||
extern gboolean
|
||||
capture_loop_open_output(capture_options *capture_opts, int *save_file_fd, char *errmsg, int errmsg_len);
|
||||
|
||||
extern gboolean
|
||||
capture_loop_init_wiretap_output(capture_options *capture_opts, int save_file_fd, loop_data *ld, char *errmsg, int errmsg_len);
|
||||
|
||||
extern gboolean
|
||||
capture_loop_close_output(capture_options *capture_opts, loop_data *ld, int *err_close);
|
||||
|
||||
#endif /* capture_loop.h */
|
||||
|
|
193
capture_opts.c
193
capture_opts.c
|
@ -43,6 +43,11 @@
|
|||
#include "clopts_common.h"
|
||||
#include "cmdarg_err.h"
|
||||
|
||||
#include "capture-pcap-util.h"
|
||||
#include "capture_ui_utils.h"
|
||||
|
||||
|
||||
|
||||
void
|
||||
capture_opts_init(capture_options *capture_opts, void *cfile)
|
||||
{
|
||||
|
@ -282,6 +287,70 @@ get_pipe_arguments(capture_options *capture_opts, const char *arg)
|
|||
#endif
|
||||
|
||||
|
||||
void
|
||||
capture_opts_add_iface_opt(capture_options *capture_opts, const char *optarg)
|
||||
{
|
||||
long adapter_index;
|
||||
char *p;
|
||||
GList *if_list;
|
||||
if_info_t *if_info;
|
||||
int err;
|
||||
gchar err_str[PCAP_ERRBUF_SIZE];
|
||||
gchar *cant_get_if_list_errstr;
|
||||
|
||||
|
||||
/*
|
||||
* If the argument is a number, treat it as an index into the list
|
||||
* of adapters, as printed by "tethereal -D".
|
||||
*
|
||||
* This should be OK on UNIX systems, as interfaces shouldn't have
|
||||
* names that begin with digits. It can be useful on Windows, where
|
||||
* more than one interface can have the same name.
|
||||
*/
|
||||
adapter_index = strtol(optarg, &p, 10);
|
||||
if (p != NULL && *p == '\0') {
|
||||
if (adapter_index < 0) {
|
||||
cmdarg_err("The specified adapter index is a negative number");
|
||||
exit(1);
|
||||
}
|
||||
if (adapter_index > INT_MAX) {
|
||||
cmdarg_err("The specified adapter index is too large (greater than %d)",
|
||||
INT_MAX);
|
||||
exit(1);
|
||||
}
|
||||
if (adapter_index == 0) {
|
||||
cmdarg_err("there is no interface with that adapter index");
|
||||
exit(1);
|
||||
}
|
||||
if_list = get_interface_list(&err, err_str);
|
||||
if (if_list == NULL) {
|
||||
switch (err) {
|
||||
|
||||
case CANT_GET_INTERFACE_LIST:
|
||||
cant_get_if_list_errstr =
|
||||
cant_get_if_list_error_message(err_str);
|
||||
cmdarg_err("%s", cant_get_if_list_errstr);
|
||||
g_free(cant_get_if_list_errstr);
|
||||
break;
|
||||
|
||||
case NO_INTERFACES_FOUND:
|
||||
cmdarg_err("There are no interfaces on which a capture can be done");
|
||||
break;
|
||||
}
|
||||
exit(2);
|
||||
}
|
||||
if_info = g_list_nth_data(if_list, adapter_index - 1);
|
||||
if (if_info == NULL) {
|
||||
cmdarg_err("there is no interface with that adapter index");
|
||||
exit(1);
|
||||
}
|
||||
capture_opts->iface = g_strdup(if_info->name);
|
||||
free_interface_list(if_list);
|
||||
} else {
|
||||
capture_opts->iface = g_strdup(optarg);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg, gboolean *start_capture)
|
||||
{
|
||||
|
@ -317,7 +386,7 @@ capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg,
|
|||
capture_opts->show_info = FALSE;
|
||||
break;
|
||||
case 'i': /* Use interface xxx */
|
||||
capture_opts->iface = g_strdup(optarg);
|
||||
capture_opts_add_iface_opt(capture_opts, optarg);
|
||||
break;
|
||||
case 'k': /* Start capture immediately */
|
||||
*start_capture = TRUE;
|
||||
|
@ -369,13 +438,89 @@ capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg,
|
|||
}
|
||||
|
||||
|
||||
void capture_opts_trim(capture_options *capture_opts, int snaplen_min)
|
||||
void capture_opts_list_link_layer_types(capture_options *capture_opts)
|
||||
{
|
||||
gchar err_str[PCAP_ERRBUF_SIZE];
|
||||
GList *lt_list, *lt_entry;
|
||||
data_link_info_t *data_link_info;
|
||||
|
||||
/* Get the list of link-layer types for the capture device. */
|
||||
lt_list = get_pcap_linktype_list(capture_opts->iface, err_str);
|
||||
if (lt_list == NULL) {
|
||||
if (err_str[0] != '\0') {
|
||||
cmdarg_err("The list of data link types for the capture device could not be obtained (%s)."
|
||||
"Please check to make sure you have sufficient permissions, and that\n"
|
||||
"you have the proper interface or pipe specified.\n", err_str);
|
||||
} else
|
||||
cmdarg_err("The capture device has no data link types.");
|
||||
exit(2);
|
||||
}
|
||||
cmdarg_err_cont("Data link types (use option -y to set):");
|
||||
for (lt_entry = lt_list; lt_entry != NULL;
|
||||
lt_entry = g_list_next(lt_entry)) {
|
||||
data_link_info = lt_entry->data;
|
||||
cmdarg_err_cont(" %s", data_link_info->name);
|
||||
if (data_link_info->description != NULL)
|
||||
cmdarg_err_cont(" (%s)", data_link_info->description);
|
||||
else
|
||||
cmdarg_err_cont(" (not supported)");
|
||||
putchar('\n');
|
||||
}
|
||||
free_pcap_linktype_list(lt_list);
|
||||
}
|
||||
|
||||
|
||||
void capture_opts_list_interfaces()
|
||||
{
|
||||
GList *if_list;
|
||||
GList *if_entry;
|
||||
if_info_t *if_info;
|
||||
int err;
|
||||
gchar err_str[PCAP_ERRBUF_SIZE];
|
||||
gchar *cant_get_if_list_errstr;
|
||||
int i;
|
||||
|
||||
|
||||
if_list = get_interface_list(&err, err_str);
|
||||
if (if_list == NULL) {
|
||||
switch (err) {
|
||||
case CANT_GET_INTERFACE_LIST:
|
||||
cant_get_if_list_errstr = cant_get_if_list_error_message(err_str);
|
||||
cmdarg_err("%s", cant_get_if_list_errstr);
|
||||
g_free(cant_get_if_list_errstr);
|
||||
break;
|
||||
|
||||
case NO_INTERFACES_FOUND:
|
||||
cmdarg_err("There are no interfaces on which a capture can be done");
|
||||
break;
|
||||
}
|
||||
exit(2);
|
||||
}
|
||||
|
||||
i = 1; /* Interface id number */
|
||||
for (if_entry = g_list_first(if_list); if_entry != NULL;
|
||||
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);
|
||||
printf("\n");
|
||||
}
|
||||
free_interface_list(if_list);
|
||||
}
|
||||
|
||||
|
||||
void capture_opts_trim_snaplen(capture_options *capture_opts, int snaplen_min)
|
||||
{
|
||||
if (capture_opts->snaplen < 1)
|
||||
capture_opts->snaplen = WTAP_MAX_PACKET_SIZE;
|
||||
else if (capture_opts->snaplen < snaplen_min)
|
||||
capture_opts->snaplen = snaplen_min;
|
||||
}
|
||||
|
||||
|
||||
void capture_opts_trim_ring_num_files(capture_options *capture_opts)
|
||||
{
|
||||
/* Check the value range of the ring_num_files parameter */
|
||||
if (capture_opts->ring_num_files > RINGBUFFER_MAX_NUM_FILES)
|
||||
capture_opts->ring_num_files = RINGBUFFER_MAX_NUM_FILES;
|
||||
|
@ -385,4 +530,48 @@ void capture_opts_trim(capture_options *capture_opts, int snaplen_min)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
gboolean capture_opts_trim_iface(capture_options *capture_opts, const char *capture_device)
|
||||
{
|
||||
GList *if_list;
|
||||
if_info_t *if_info;
|
||||
int err;
|
||||
gchar err_str[PCAP_ERRBUF_SIZE];
|
||||
gchar *cant_get_if_list_errstr;
|
||||
|
||||
|
||||
/* Did the user specify an interface to use? */
|
||||
if (capture_opts->iface == NULL) {
|
||||
/* No - is a default specified in the preferences file? */
|
||||
if (capture_device != NULL) {
|
||||
/* Yes - use it. */
|
||||
capture_opts->iface = g_strdup(capture_device);
|
||||
} else {
|
||||
/* No - pick the first one from the list of interfaces. */
|
||||
if_list = get_interface_list(&err, err_str);
|
||||
if (if_list == NULL) {
|
||||
switch (err) {
|
||||
|
||||
case CANT_GET_INTERFACE_LIST:
|
||||
cant_get_if_list_errstr = cant_get_if_list_error_message(err_str);
|
||||
cmdarg_err("%s", cant_get_if_list_errstr);
|
||||
g_free(cant_get_if_list_errstr);
|
||||
break;
|
||||
|
||||
case NO_INTERFACES_FOUND:
|
||||
cmdarg_err("There are no interfaces on which a capture can be done");
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
if_info = if_list->data; /* first interface */
|
||||
capture_opts->iface = g_strdup(if_info->name);
|
||||
free_interface_list(if_list);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
#endif /* HAVE_LIBPCAP */
|
||||
|
|
|
@ -105,13 +105,28 @@ capture_opts_init(capture_options *capture_opts, void *cfile);
|
|||
extern void
|
||||
capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg, gboolean *start_capture);
|
||||
|
||||
/* trim values after command line finished */
|
||||
extern void
|
||||
capture_opts_trim(capture_options *capture_opts, int snaplen_min);
|
||||
|
||||
/* log content of capture_opts */
|
||||
extern void
|
||||
capture_opts_log(const char *log_domain, GLogLevelFlags log_level, capture_options *capture_opts);
|
||||
|
||||
/* list link layer types */
|
||||
extern void
|
||||
capture_opts_list_link_layer_types(capture_options *capture_opts);
|
||||
|
||||
/* list interfaces */
|
||||
extern void
|
||||
capture_opts_list_interfaces();
|
||||
|
||||
/* trim the snaplen entry */
|
||||
extern void
|
||||
capture_opts_trim_snaplen(capture_options *capture_opts, int snaplen_min);
|
||||
|
||||
/* trim the ring_num_files entry */
|
||||
extern void
|
||||
capture_opts_trim_ring_num_files(capture_options *capture_opts);
|
||||
|
||||
/* trim the interface entry */
|
||||
extern gboolean
|
||||
capture_opts_trim_iface(capture_options *capture_opts, const char *capture_device);
|
||||
|
||||
#endif /* capture_opts.h */
|
||||
|
|
114
dumpcap.c
114
dumpcap.c
|
@ -109,7 +109,7 @@ print_usage(gboolean print_ver) {
|
|||
fprintf(output, "\nUsage: dumpcap [option] ...\n");
|
||||
fprintf(output, "\n");
|
||||
fprintf(output, "Capture interface:\n");
|
||||
fprintf(output, " -i <interface> name of interface (def: first none loopback)\n");
|
||||
fprintf(output, " -i <interface> name or idx of interface (def: first none loopback)\n");
|
||||
fprintf(output, " -f <capture filter> packet filter in libpcap format\n");
|
||||
fprintf(output, " -s <snaplen> packet snapshot length (def: 65535)\n");
|
||||
fprintf(output, " -p don't capture in promiscuous mode\n");
|
||||
|
@ -133,6 +133,7 @@ print_usage(gboolean print_ver) {
|
|||
fprintf(output, "Miscellaneous:\n");
|
||||
fprintf(output, " -v print version information and exit\n");
|
||||
fprintf(output, " -h display this help and exit\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, "\n");
|
||||
fprintf(output, "Example: dumpcap -i eth0 -a duration:60 -w output.pcap\n");
|
||||
|
@ -241,8 +242,6 @@ main(int argc, char *argv[])
|
|||
gboolean start_capture = TRUE;
|
||||
GList *if_list;
|
||||
if_info_t *if_info;
|
||||
GList *lt_list, *lt_entry;
|
||||
data_link_info_t *data_link_info;
|
||||
gchar err_str[PCAP_ERRBUF_SIZE];
|
||||
gchar *cant_get_if_list_errstr;
|
||||
gboolean stats_known;
|
||||
|
@ -250,7 +249,7 @@ main(int argc, char *argv[])
|
|||
GLogLevelFlags log_flags;
|
||||
gboolean list_link_layer_types = FALSE;
|
||||
|
||||
#define OPTSTRING_INIT "a:b:c:f:Hhi:Lps:vW:w:y:"
|
||||
#define OPTSTRING_INIT "a:b:c:Df:hi:Lps:vw:y:"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define OPTSTRING_WIN32 "B:Z:"
|
||||
|
@ -345,7 +344,6 @@ main(int argc, char *argv[])
|
|||
case 'b': /* Ringbuffer option */
|
||||
case 'c': /* Capture xxx packets */
|
||||
case 'f': /* capture filter */
|
||||
case 'H': /* Hide capture info dialog box */
|
||||
case 'i': /* Use interface xxx */
|
||||
case 'p': /* Don't capture in promiscuous mode */
|
||||
case 's': /* Set the snapshot (capture) length */
|
||||
|
@ -358,14 +356,12 @@ main(int argc, char *argv[])
|
|||
#endif /* _WIN32 */
|
||||
capture_opts_add_opt(capture_opts, opt, optarg, &start_capture);
|
||||
break;
|
||||
/* This is a hidden option supporting Sync mode, so we don't set
|
||||
* the error flags for the user in the non-libpcap case.
|
||||
*/
|
||||
case 'W': /* Write to capture file FD xxx */
|
||||
capture_opts_add_opt(capture_opts, opt, optarg, &start_capture);
|
||||
break;
|
||||
|
||||
/*** all non capture option specific ***/
|
||||
case 'D': /* Print a list of capture devices and exit */
|
||||
capture_opts_list_interfaces();
|
||||
exit(0);
|
||||
break;
|
||||
case 'L': /* Print list of link-layer types and exit */
|
||||
list_link_layer_types = TRUE;
|
||||
break;
|
||||
|
@ -450,33 +446,12 @@ if (capture_opts->iface == NULL) {
|
|||
}
|
||||
|
||||
if (list_link_layer_types) {
|
||||
/* Get the list of link-layer types for the capture device. */
|
||||
lt_list = get_pcap_linktype_list(capture_opts->iface, err_str);
|
||||
if (lt_list == NULL) {
|
||||
if (err_str[0] != '\0') {
|
||||
cmdarg_err("The list of data link types for the capture device could not be obtained (%s)."
|
||||
"Please check to make sure you have sufficient permissions, and that\n"
|
||||
"you have the proper interface or pipe specified.\n", err_str);
|
||||
} else
|
||||
cmdarg_err("The capture device has no data link types.");
|
||||
exit_main(2);
|
||||
}
|
||||
g_warning("Data link types (use option -y to set):");
|
||||
for (lt_entry = lt_list; lt_entry != NULL;
|
||||
lt_entry = g_list_next(lt_entry)) {
|
||||
data_link_info = lt_entry->data;
|
||||
g_warning(" %s", data_link_info->name);
|
||||
if (data_link_info->description != NULL)
|
||||
g_warning(" (%s)", data_link_info->description);
|
||||
else
|
||||
g_warning(" (not supported)");
|
||||
putchar('\n');
|
||||
}
|
||||
free_pcap_linktype_list(lt_list);
|
||||
capture_opts_list_link_layer_types(capture_opts);
|
||||
exit_main(0);
|
||||
}
|
||||
|
||||
capture_opts_trim(capture_opts, MIN_PACKET_SIZE);
|
||||
capture_opts_trim_snaplen(capture_opts, MIN_PACKET_SIZE);
|
||||
capture_opts_trim_ring_num_files(capture_opts);
|
||||
|
||||
/* Now start the capture. */
|
||||
|
||||
|
@ -547,8 +522,9 @@ static void
|
|||
destroy_console(void)
|
||||
{
|
||||
if (has_console) {
|
||||
printf("\n\nPress any key to exit\n");
|
||||
_getch();
|
||||
/* XXX - doesn't make sense while we're linked as a console application */
|
||||
/* printf("\n\nPress any key to exit\n");
|
||||
_getch();*/
|
||||
FreeConsole();
|
||||
}
|
||||
}
|
||||
|
@ -637,6 +613,9 @@ pipe_write_block(int pipe, char indicator, int len, const char *msg)
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
int count = 0;
|
||||
|
||||
void
|
||||
sync_pipe_packet_count_to_parent(int packet_count)
|
||||
{
|
||||
|
@ -646,6 +625,9 @@ sync_pipe_packet_count_to_parent(int packet_count)
|
|||
|
||||
/*g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "sync_pipe_packet_count_to_parent: %s", tmp);*/
|
||||
|
||||
count += packet_count;
|
||||
fprintf(stderr, "\rpackets: %u", count);
|
||||
|
||||
pipe_write_block(1, SP_PACKET_COUNT, strlen(tmp)+1, tmp);
|
||||
}
|
||||
|
||||
|
@ -684,14 +666,6 @@ sync_pipe_drops_to_parent(int drops)
|
|||
/* simple_dialog "dummies" */
|
||||
|
||||
|
||||
static gpointer *
|
||||
display_simple_dialog(gint type, gint btn_mask, char *message)
|
||||
{
|
||||
printf("%s", message);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *simple_dialog_primary_start(void)
|
||||
{
|
||||
return "";
|
||||
|
@ -702,56 +676,6 @@ char *simple_dialog_primary_end(void)
|
|||
return "";
|
||||
}
|
||||
|
||||
/* Simple dialog function - Displays a dialog box with the supplied message
|
||||
* text.
|
||||
*
|
||||
* Args:
|
||||
* type : One of ESD_TYPE_*.
|
||||
* btn_mask : The value passed in determines which buttons are displayed.
|
||||
* msg_format : Sprintf-style format of the text displayed in the dialog.
|
||||
* ... : Argument list for msg_format
|
||||
*/
|
||||
|
||||
gpointer
|
||||
vsimple_dialog(ESD_TYPE_E type, gint btn_mask, const gchar *msg_format, va_list ap)
|
||||
{
|
||||
gchar *vmessage;
|
||||
gchar *message;
|
||||
gpointer *win;
|
||||
#if GTK_MAJOR_VERSION >= 2
|
||||
GdkWindowState state = 0;
|
||||
#endif
|
||||
|
||||
/* Format the message. */
|
||||
vmessage = g_strdup_vprintf(msg_format, ap);
|
||||
|
||||
#if GTK_MAJOR_VERSION >= 2
|
||||
/* convert character encoding from locale to UTF8 (using iconv) */
|
||||
message = g_locale_to_utf8(vmessage, -1, NULL, NULL, NULL);
|
||||
g_free(vmessage);
|
||||
#else
|
||||
message = vmessage;
|
||||
#endif
|
||||
|
||||
win = display_simple_dialog(type, btn_mask, message);
|
||||
|
||||
g_free(message);
|
||||
|
||||
return win;
|
||||
}
|
||||
|
||||
gpointer
|
||||
simple_dialog(ESD_TYPE_E type, gint btn_mask, const gchar *msg_format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
gpointer ret;
|
||||
|
||||
va_start(ap, msg_format);
|
||||
ret = vsimple_dialog(type, btn_mask, msg_format, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *
|
||||
simple_dialog_format_message(const char *msg)
|
||||
{
|
||||
|
|
90
gtk/main.c
90
gtk/main.c
|
@ -1089,7 +1089,7 @@ print_usage(gboolean print_ver) {
|
|||
output = stderr;
|
||||
}
|
||||
#ifdef HAVE_LIBPCAP
|
||||
fprintf(output, "\n%s [ -vh ] [ -klLnpQS ] [ -a <capture autostop condition> ] ...\n", PACKAGE);
|
||||
fprintf(output, "\n%s [ -vh ] [ -DklLnpQS ] [ -a <capture autostop condition> ] ...\n", PACKAGE);
|
||||
fprintf(output, "\t[ -b <capture ring buffer option> ] ...\n");
|
||||
#ifdef _WIN32
|
||||
fprintf(output, "\t[ -B <capture buffer size> ]\n");
|
||||
|
@ -1742,12 +1742,6 @@ main(int argc, char *argv[])
|
|||
int err;
|
||||
#ifdef HAVE_LIBPCAP
|
||||
gboolean start_capture = FALSE;
|
||||
GList *if_list;
|
||||
if_info_t *if_info;
|
||||
GList *lt_list, *lt_entry;
|
||||
data_link_info_t *data_link_info;
|
||||
gchar err_str[PCAP_ERRBUF_SIZE];
|
||||
gchar *cant_get_if_list_errstr;
|
||||
gboolean stats_known;
|
||||
struct pcap_stat stats;
|
||||
#else
|
||||
|
@ -1764,14 +1758,14 @@ main(int argc, char *argv[])
|
|||
guint go_to_packet = 0;
|
||||
int optind_initial;
|
||||
|
||||
#define OPTSTRING_INIT "a:b:c:f:g:Hhi:klLm:nN:o:pQr:R:Ss:t:vw:y:z:"
|
||||
#define OPTSTRING_INIT "a:b:c:Df:g:Hhi:klLm:nN:o:pQr:R:Ss:t:vw:y:z:"
|
||||
|
||||
#ifdef HAVE_LIBPCAP
|
||||
#ifdef _WIN32
|
||||
#define OPTSTRING_CHILD "W:Z:"
|
||||
#define OPTSTRING_CHILD "Z:"
|
||||
#define OPTSTRING_WIN32 "B:"
|
||||
#else
|
||||
#define OPTSTRING_CHILD "W:"
|
||||
#define OPTSTRING_CHILD ""
|
||||
#define OPTSTRING_WIN32 ""
|
||||
#endif /* _WIN32 */
|
||||
#else
|
||||
|
@ -1958,7 +1952,7 @@ main(int argc, char *argv[])
|
|||
#endif
|
||||
splash_win = splash_new("Loading Ethereal ...");
|
||||
|
||||
splash_update(splash_win, "Registering dissectors ...");
|
||||
splash_update(splash_win, "Init dissectors ...");
|
||||
|
||||
/* Register all dissectors; we must do this before checking for the
|
||||
"-G" flag, as the "-G" flag dumps information registered by the
|
||||
|
@ -1967,7 +1961,7 @@ main(int argc, char *argv[])
|
|||
epan_init(PLUGIN_DIR,register_all_protocols,register_all_protocol_handoffs,
|
||||
failure_alert_box,open_failure_alert_box,read_failure_alert_box);
|
||||
|
||||
splash_update(splash_win, "Registering tap listeners ...");
|
||||
splash_update(splash_win, "Init tap listeners ...");
|
||||
|
||||
/* Register all tap listeners; we do this before we parse the arguments,
|
||||
as the "-z" argument can specify a registered tap. */
|
||||
|
@ -2152,16 +2146,17 @@ main(int argc, char *argv[])
|
|||
arg_error = TRUE;
|
||||
#endif
|
||||
break;
|
||||
#ifdef HAVE_LIBPCAP
|
||||
/* This is a hidden option supporting Sync mode, so we don't set
|
||||
* the error flags for the user in the non-libpcap case.
|
||||
*/
|
||||
case 'W': /* Write to capture file FD xxx */
|
||||
capture_opts_add_opt(capture_opts, opt, optarg, &start_capture);
|
||||
break;
|
||||
#endif
|
||||
|
||||
/*** all non capture option specific ***/
|
||||
case 'D': /* Print a list of capture devices and exit */
|
||||
#ifdef HAVE_LIBPCAP
|
||||
capture_opts_list_interfaces();
|
||||
exit(0);
|
||||
#else
|
||||
capture_option_specified = TRUE;
|
||||
arg_error = TRUE;
|
||||
#endif
|
||||
break;
|
||||
case 'g': /* Go to packet */
|
||||
go_to_packet = get_positive_int(optarg, "go to packet");
|
||||
break;
|
||||
|
@ -2383,64 +2378,19 @@ main(int argc, char *argv[])
|
|||
|
||||
if (start_capture || list_link_layer_types) {
|
||||
/* Did the user specify an interface to use? */
|
||||
if (capture_opts->iface == NULL) {
|
||||
/* No - is a default specified in the preferences file? */
|
||||
if (prefs->capture_device != NULL) {
|
||||
/* Yes - use it. */
|
||||
capture_opts->iface = g_strdup(get_if_name(prefs->capture_device));
|
||||
} else {
|
||||
/* No - pick the first one from the list of interfaces. */
|
||||
if_list = get_interface_list(&err, err_str);
|
||||
if (if_list == NULL) {
|
||||
switch (err) {
|
||||
|
||||
case CANT_GET_INTERFACE_LIST:
|
||||
cant_get_if_list_errstr = cant_get_if_list_error_message(err_str);
|
||||
cmdarg_err("%s", cant_get_if_list_errstr);
|
||||
g_free(cant_get_if_list_errstr);
|
||||
break;
|
||||
|
||||
case NO_INTERFACES_FOUND:
|
||||
cmdarg_err("There are no interfaces on which a capture can be done");
|
||||
break;
|
||||
}
|
||||
if (!capture_opts_trim_iface(capture_opts,
|
||||
(prefs->capture_device) ? get_if_name(prefs->capture_device) : NULL)) {
|
||||
exit(2);
|
||||
}
|
||||
if_info = if_list->data; /* first interface */
|
||||
capture_opts->iface = g_strdup(if_info->name);
|
||||
free_interface_list(if_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (list_link_layer_types) {
|
||||
/* Get the list of link-layer types for the capture device. */
|
||||
lt_list = get_pcap_linktype_list(capture_opts->iface, err_str);
|
||||
if (lt_list == NULL) {
|
||||
if (err_str[0] != '\0') {
|
||||
cmdarg_err("The list of data link types for the capture device could not be obtained (%s)."
|
||||
"Please check to make sure you have sufficient permissions, and that\n"
|
||||
"you have the proper interface or pipe specified.\n", err_str);
|
||||
} else
|
||||
cmdarg_err("The capture device has no data link types.");
|
||||
exit(2);
|
||||
}
|
||||
g_warning("Data link types (use option -y to set):");
|
||||
for (lt_entry = lt_list; lt_entry != NULL;
|
||||
lt_entry = g_list_next(lt_entry)) {
|
||||
data_link_info = lt_entry->data;
|
||||
g_warning(" %s", data_link_info->name);
|
||||
if (data_link_info->description != NULL)
|
||||
g_warning(" (%s)", data_link_info->description);
|
||||
else
|
||||
g_warning(" (not supported)");
|
||||
putchar('\n');
|
||||
}
|
||||
free_pcap_linktype_list(lt_list);
|
||||
capture_opts_list_link_layer_types(capture_opts);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
capture_opts_trim(capture_opts, MIN_PACKET_SIZE);
|
||||
capture_opts_trim_snaplen(capture_opts, MIN_PACKET_SIZE);
|
||||
capture_opts_trim_ring_num_files(capture_opts);
|
||||
#endif /* HAVE_LIBPCAP */
|
||||
|
||||
/* Notify all registered modules that have had any of their preferences
|
||||
|
|
910
tethereal.c
910
tethereal.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue