summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.common1
-rw-r--r--capture_loop.c206
-rw-r--r--capture_loop.h110
-rw-r--r--capture_opts.c193
-rw-r--r--capture_opts.h23
-rw-r--r--dumpcap.c116
-rw-r--r--gtk/main.c92
-rw-r--r--tethereal.c918
8 files changed, 631 insertions, 1028 deletions
diff --git a/Makefile.common b/Makefile.common
index 4e4b3abce7..a6f5c7954c 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -178,6 +178,7 @@ tethereal_SOURCES = \
$(ETHEREAL_COMMON_SRC) \
$(TETHEREAL_TAP_SRC) \
capture_opts.c \
+ capture_loop.c \
tethereal-tap-register.c \
tethereal.c
diff --git a/capture_loop.c b/capture_loop.c
index 31c0283d73..db0664e454 100644
--- a/capture_loop.c
+++ b/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;
}
-
- 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;
}
diff --git a/capture_loop.h b/capture_loop.h
index 1a89d90f5a..4336927c4c 100644
--- a/capture_loop.h
+++ b/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 */
diff --git a/capture_opts.c b/capture_opts.c
index 85b175ee23..b108b59e5a 100644
--- a/capture_opts.c
+++ b/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)
{
@@ -283,6 +288,70 @@ get_pipe_arguments(capture_options *capture_opts, const char *arg)
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)
{
switch(opt) {
@@ -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 */
diff --git a/capture_opts.h b/capture_opts.h
index e75535afd1..193866d583 100644
--- a/capture_opts.h
+++ b/capture_opts.h
@@ -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 */
diff --git a/dumpcap.c b/dumpcap.c
index 1a764a514f..8cc0c13e7d 100644
--- a/dumpcap.c
+++ b/dumpcap.c
@@ -74,7 +74,7 @@ GString *comp_info_str, *runtime_info_str;
gchar *ethereal_path = NULL;
#ifdef _WIN32
-static gboolean has_console = TRUE; /* TRUE if app has console */
+static gboolean has_console = TRUE; /* TRUE if app has console */
static void create_console(void);
static void destroy_console(void);
#endif
@@ -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)
{
diff --git a/gtk/main.c b/gtk/main.c
index e39144ab28..d075d5373d 100644
--- a/gtk/main.c
+++ b/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;
- }
- exit(2);
- }
- if_info = if_list->data; /* first interface */
- capture_opts->iface = g_strdup(if_info->name);
- free_interface_list(if_list);
- }
+ if (!capture_opts_trim_iface(capture_opts,
+ (prefs->capture_device) ? get_if_name(prefs->capture_device) : NULL)) {
+ exit(2);
}
}
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
diff --git a/tethereal.c b/tethereal.c
index 05b8016fed..37571e1ce3 100644
--- a/tethereal.c
+++ b/tethereal.c
@@ -100,6 +100,7 @@
#include "capture_errs.h"
#endif /* _WIN32 */
#include "capture.h"
+#include "capture_loop.h"
#endif /* HAVE_LIBPCAP */
#include "epan/emem.h"
@@ -137,27 +138,6 @@ static print_stream_t *print_stream;
*/
static gboolean print_packet_counts;
-typedef struct _loop_data {
- gboolean go; /* TRUE as long as we're supposed to keep capturing */
- gint linktype;
- gboolean from_pipe; /* TRUE if we are capturing data from a pipe */
- pcap_t *pch;
- char *save_file; /* Name of file to which we're writing */
- wtap_dumper *pdh;
- jmp_buf stopenv;
- gboolean output_to_pipe;
- int packet_count;
-#ifndef _WIN32
- gboolean modified; /* TRUE if data in the pipe uses modified pcap headers */
- gboolean byte_swapped; /* TRUE if data in the pipe is byte swapped */
- unsigned int bytes_to_read, bytes_read; /* Used by pipe_dispatch */
- enum {
- STATE_EXPECT_REC_HDR, STATE_READ_REC_HDR,
- STATE_EXPECT_DATA, STATE_READ_DATA
- } pipe_state;
- enum { PIPOK, PIPEOF, PIPERR, PIPNEXIST } pipe_err;
-#endif
-} loop_data;
static loop_data ld;
@@ -197,14 +177,6 @@ static gboolean print_packet(capture_file *cf, epan_dissect_t *edt);
static gboolean write_finale(void);
static const char *cf_open_error_message(int err, gchar *err_info,
gboolean for_writing, int file_type);
-#ifdef HAVE_LIBPCAP
-#ifndef _WIN32
-static void adjust_header(loop_data *, struct pcap_hdr *, struct pcaprec_hdr *);
-static int pipe_open_live(char *, struct pcap_hdr *, loop_data *, char *, int);
-static int pipe_dispatch(int, loop_data *, struct pcap_hdr *, \
- struct pcaprec_modified_hdr *, guchar *, char *, int);
-#endif /* _WIN32 */
-#endif
static void open_failure_message(const char *filename, int err,
gboolean for_writing);
@@ -609,6 +581,10 @@ add_decode_as(const gchar *cl_param)
return TRUE;
}
+void log_func_ignore (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
+{
+}
+
int
main(int argc, char *argv[])
{
@@ -629,13 +605,8 @@ main(int argc, char *argv[])
int err;
#ifdef HAVE_LIBPCAP
gboolean capture_filter_specified = FALSE;
- GList *if_list, *if_entry;
- if_info_t *if_info;
- long adapter_index;
- char *p;
- gchar err_str[PCAP_ERRBUF_SIZE];
- gchar *cant_get_if_list_errstr;
gboolean list_link_layer_types = FALSE;
+ gboolean start_capture = FALSE;
#else
gboolean capture_option_specified = FALSE;
#endif
@@ -643,18 +614,13 @@ main(int argc, char *argv[])
gchar *save_file = NULL;
int out_file_type = WTAP_FILE_PCAP;
gchar *cf_name = NULL, *rfilter = NULL;
-#ifdef HAVE_LIBPCAP
- gboolean start_capture = FALSE;
- gchar *if_text;
- GList *lt_list, *lt_entry;
- data_link_info_t *data_link_info;
-#endif
#ifdef HAVE_PCAP_OPEN_DEAD
struct bpf_program fcode;
#endif
dfilter_t *rfcode = NULL;
e_prefs *prefs;
char badopt;
+ GLogLevelFlags log_flags;
#define OPTSTRING_INIT "a:b:c:d:Df:F:hi:lLnN:o:pqr:R:s:St:T:vVw:xy:z:"
#ifdef HAVE_LIBPCAP
@@ -669,6 +635,20 @@ main(int argc, char *argv[])
static const char optstring[] = OPTSTRING_INIT OPTSTRING_WIN32;
+ /* nothing more than the standard GLib handler, but without a warning */
+ log_flags =
+ G_LOG_LEVEL_ERROR|
+ G_LOG_LEVEL_CRITICAL|
+ G_LOG_LEVEL_WARNING|
+ G_LOG_LEVEL_MESSAGE|
+ G_LOG_LEVEL_INFO|
+ G_LOG_LEVEL_DEBUG|
+ G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
+
+ g_log_set_handler(NULL,
+ log_flags,
+ log_func_ignore, NULL /* user_data */);
+
/* initialize memory allocation subsystem */
ep_init_chunk();
se_init_chunk();
@@ -826,6 +806,7 @@ main(int argc, char *argv[])
case 'b': /* Ringbuffer option */
case 'c': /* Capture xxx packets */
case 'f': /* capture filter */
+ case 'i': /* Use interface xxx */
case 'p': /* Don't capture in promiscuous mode */
case 's': /* Set the snapshot (capture) length */
case 'y': /* Set the pcap data link type */
@@ -843,35 +824,9 @@ main(int argc, char *argv[])
if (!add_decode_as(optarg))
exit(1);
break;
- case 'D': /* Print a list of capture devices */
+ case 'D': /* Print a list of capture devices and exit */
#ifdef HAVE_LIBPCAP
- 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);
+ capture_opts_list_interfaces();
exit(0);
#else
capture_option_specified = TRUE;
@@ -890,62 +845,6 @@ main(int argc, char *argv[])
print_usage(TRUE);
exit(0);
break;
- case 'i': /* Use interface xxx */
-#ifdef HAVE_LIBPCAP
- /*
- * 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);
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
case 'l': /* "Line-buffer" standard output */
/* This isn't line-buffering, strictly speaking, it's just
flushing the standard output after the information for
@@ -1287,7 +1186,8 @@ main(int argc, char *argv[])
}
#ifdef HAVE_LIBPCAP
- 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
if (rfilter != NULL) {
@@ -1414,64 +1314,16 @@ main(int argc, char *argv[])
}
#endif
- /* Yes; 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. */
- if_text = strrchr(prefs->capture_device, ' ');
- if (if_text == NULL) {
- capture_opts.iface = g_strdup(prefs->capture_device);
- } else {
- capture_opts.iface = g_strdup(if_text + 1); /* Skip over space */
- }
- } 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;
- }
- exit(2);
- }
- if_info = if_list->data; /* first interface */
- capture_opts.iface = g_strdup(if_info->name);
- free_interface_list(if_list);
- }
+ /* trim the interface name and exit if that failed */
+ if (!capture_opts_trim_iface(&capture_opts,
+ (prefs->capture_device) ? get_if_name(prefs->capture_device) : NULL)) {
+ exit(2);
}
+ /* if requested, list the link layer types and exit */
if (list_link_layer_types) {
- /* We were asked to list the link-layer types for an interface.
- 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).\n"
- "Please check to make sure you have sufficient permissions, and that\n"
- "you have the proper interface or pipe specified.", 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 (%s)",
- data_link_info->name,
- (data_link_info->description != NULL) ? data_link_info->description : "not supported");
- }
- free_pcap_linktype_list(lt_list);
- exit(0);
+ capture_opts_list_link_layer_types(&capture_opts);
+ exit(0);
}
if (!quiet) {
@@ -1507,160 +1359,41 @@ main(int argc, char *argv[])
/* Do the low-level work of a capture.
Returns TRUE if it succeeds, FALSE otherwise. */
-static condition *volatile cnd_ring_timeout = NULL; /* this must be visible in process_packet */
+static condition *volatile cnd_file_duration = NULL; /* this must be visible in process_packet */
static int
capture(char *save_file, int out_file_type)
{
- int pcap_encap;
- int file_snaplen;
- gchar open_err_str[PCAP_ERRBUF_SIZE];
- gchar lookup_net_err_str[PCAP_ERRBUF_SIZE];
- bpf_u_int32 netnum, netmask;
- struct bpf_program fcode;
- const char *set_linktype_err_str;
int err = 0;
int volatile volatile_err = 0;
int volatile inpkts = 0;
int pcap_cnt;
char errmsg[1024+1];
- condition *volatile cnd_stop_capturesize = NULL;
- condition *volatile cnd_stop_timeout = NULL;
+ condition *volatile cnd_autostop_size = NULL;
+ condition *volatile cnd_autostop_duration = NULL;
char *descr;
#ifndef _WIN32
void (*oldhandler)(int);
- static const char ppamsg[] = "can't find PPA for ";
- const char *libpcap_warn;
- volatile int pipe_fd = -1;
- struct pcap_hdr hdr;
- struct pcaprec_modified_hdr rechdr;
guchar pcap_data[WTAP_MAX_PACKET_SIZE];
#endif
struct pcap_stat stats;
- gboolean write_err;
- gboolean dump_ok;
+ gboolean write_ok;
+ gboolean close_ok;
dfilter_t *rfcode = NULL;
int save_file_fd;
/* Initialize all data structures used for dissection. */
init_dissection();
- ld.linktype = WTAP_ENCAP_UNKNOWN;
- ld.pdh = NULL;
+ ld.wtap_linktype = WTAP_ENCAP_UNKNOWN;
+ ld.wtap_pdh = NULL;
+ ld.packet_cb = capture_pcap_cb;
- /* Open the network interface to capture from it.
- Some versions of libpcap may put warnings into the error buffer
- if they succeed; to tell if that's happened, we have to clear
- the error buffer, and check if it's still a null string. */
- open_err_str[0] = '\0';
- ld.pch = pcap_open_live(capture_opts.iface, capture_opts.snaplen,
- capture_opts.promisc_mode, 1000, open_err_str);
- if (ld.pch != NULL) {
- /* we've opened "iface" as a network device */
-#ifdef _WIN32
- /* try to set the capture buffer size */
- if (pcap_setbuff(ld.pch, capture_opts.buffer_size * 1024 * 1024) != 0) {
- cmdarg_err("Couldn't set the capture buffer size!\n"
- "\n"
- "The capture buffer size of %luMB seems to be too high for your machine,\n"
- "the default of 1MB will be used.\n"
- "\n"
- "Nonetheless, the capture is started.",
- capture_opts.buffer_size);
- }
-#endif
-
- /* setting the data link type only works on real interfaces */
- if (capture_opts.linktype != -1) {
- set_linktype_err_str = set_pcap_linktype(ld.pch, capture_opts.iface,
- capture_opts.linktype);
- if (set_linktype_err_str != NULL) {
- g_snprintf(errmsg, sizeof errmsg, "Unable to set data link type (%s).",
- set_linktype_err_str);
- goto error;
- }
- }
- } else {
- /* We couldn't open "cfile.iface" as a network device. */
-#ifdef _WIN32
- /* On Windows, we don't support capturing on pipes, so we give up. */
-
- /* On Win32 OSes, the capture devices are probably available to all
- users; don't warn about permissions problems.
-
- Do, however, warn about the lack of 64-bit support, and warn that
- WAN devices aren't supported. */
- g_snprintf(errmsg, sizeof errmsg,
-"The capture session could not be initiated!\n"
-"\n"
-"(%s)\n"
-"\n"
-"Please check that you have the proper interface specified.\n"
-"\n"
-"\n"
-"Help can be found at:\n"
-"\n"
-" http://wiki.ethereal.com/CaptureSetup\n"
-"\n"
-"64-bit Windows:\n"
-"WinPcap does not support 64-bit Windows, you will have to use some other\n"
-"tool to capture traffic, such as netcap.\n"
-"For netcap details see: http://support.microsoft.com/?id=310875\n"
-"\n"
-"Modem (PPP/WAN):\n"
-"Note that version 3.0 of WinPcap, and earlier versions of WinPcap, don't\n"
-"support capturing on PPP/WAN interfaces on Windows NT 4.0 / 2000 / XP /\n"
-"Server 2003.\n"
-"WinPcap 3.1 has support for it on Windows 2000 / XP / Server 2003, but has no\n"
-"support for it on Windows NT 4.0 or Windows Vista (Beta 1).",
- open_err_str);
+ /* open the "input file" from network interface or capture pipe */
+ if (!capture_loop_open_input(&capture_opts, &ld, errmsg, sizeof(errmsg)))
+ {
goto error;
-#else
- /* try to open cfile.iface as a pipe */
- pipe_fd = pipe_open_live(capture_opts.iface, &hdr, &ld, errmsg,
- sizeof errmsg);
-
- if (pipe_fd == -1) {
-
- if (ld.pipe_err == PIPNEXIST) {
- /* 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 Tethereal 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 Tethereal with a version of the libpcap library\n"
- "that doesn't handle HP-UX network devices well; this means that\n"
- "Tethereal 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"
- "packaged binary form from the Software Porting And Archive Centre\n"
- "for HP-UX; the Centre is at http://hpux.connect.org.uk/ - the page\n"
- "at the URL lists a number of mirror sites.";
- else
- libpcap_warn = "";
- g_snprintf(errmsg, sizeof errmsg,
- "The capture session could not be initiated (%s).\n"
- "Please check to make sure you have sufficient permissions, and that\n"
- "you have the proper interface or pipe specified.%s", open_err_str,
- libpcap_warn);
- }
- /*
- * Else pipe (or file) does exist and pipe_open_live() has
- * filled in errmsg
- */
- goto error;
- } else
- /* pipe_open_live() succeeded; don't want
- error message from pcap_open_live() */
- open_err_str[0] = '\0';
-#endif
}
#ifndef _WIN32
@@ -1679,92 +1412,26 @@ capture(char *save_file, int out_file_type)
setgid(getgid());
#endif
- if (capture_opts.cfilter && !ld.from_pipe) {
- /* A capture filter was specified; set it up. */
- if (pcap_lookupnet(capture_opts.iface, &netnum, &netmask, lookup_net_err_str) < 0) {
- /*
- * Well, we can't get the netmask for this interface; it's used
- * only for filters that check for broadcast IP addresses, so
- * we just warn the user, and punt and use 0.
- */
- cmdarg_err(
- "Warning: Couldn't obtain netmask info (%s).", lookup_net_err_str);
- netmask = 0;
- }
- if (pcap_compile(ld.pch, &fcode, capture_opts.cfilter, 1, netmask) < 0) {
- if (dfilter_compile(capture_opts.cfilter, &rfcode)) {
- g_snprintf(errmsg, sizeof errmsg,
- "Unable to parse capture filter string (%s).\n"
- " Interestingly enough, this looks like a valid display filter\n"
- " Are you sure you didn't mix them up?",
- pcap_geterr(ld.pch));
- } else {
- g_snprintf(errmsg, sizeof errmsg,
- "Unable to parse capture filter string (%s).",
- pcap_geterr(ld.pch));
- }
- goto error;
- }
- if (pcap_setfilter(ld.pch, &fcode) < 0) {
- g_snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
- pcap_geterr(ld.pch));
-#ifdef HAVE_PCAP_FREECODE
- pcap_freecode(&fcode);
-#endif
- goto error;
- }
-#ifdef HAVE_PCAP_FREECODE
- pcap_freecode(&fcode);
-#endif
+ capture_opts.save_file = save_file;
+
+ /* open the output file (temporary/specified name/ringbuffer) */
+ if (!capture_loop_open_output(&capture_opts, &save_file_fd, errmsg, sizeof(errmsg))) {
+ goto error;
}
- /* Set up to write to the capture file. */
-#ifndef _WIN32
- if (ld.from_pipe) {
- pcap_encap = hdr.network;
- file_snaplen = hdr.snaplen;
- } else
-#endif
+ /* init the input filter from the network interface (capture pipe will do nothing) */
+ if(!capture_loop_init_filter(ld.pcap_h, ld.from_cap_pipe,
+ capture_opts.iface, capture_opts.cfilter, errmsg, sizeof errmsg))
{
- pcap_encap = get_pcap_linktype(ld.pch, capture_opts.iface);
- file_snaplen = pcap_snapshot(ld.pch);
- }
- ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_encap);
- if (save_file != NULL) {
- /* Set up to write to the capture file. */
- if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
- strcpy(errmsg, "The network you're capturing from is of a type"
- " that Tethereal doesn't support.");
goto error;
- }
- ld.save_file = save_file;
- if (capture_opts.multi_files_on) {
- save_file_fd = ringbuf_init(save_file,
- capture_opts.ring_num_files);
- if (save_file_fd != -1) {
- ld.pdh = ringbuf_init_wtap_dump_fdopen(out_file_type, ld.linktype,
- file_snaplen, &err);
- } else {
- err = errno; /* "ringbuf_init()" failed */
- ld.pdh = NULL;
- }
- } else {
- ld.pdh = wtap_dump_open(save_file, out_file_type,
- ld.linktype, file_snaplen, FALSE /* compress */, &err);
- }
+ }
- if (ld.pdh == NULL) {
- g_snprintf(errmsg, sizeof errmsg,
- cf_open_error_message(err, NULL, TRUE, out_file_type),
- *save_file == '\0' ? "stdout" : save_file);
+ /* open the wiretap part of the output file (the output file is already open) */
+ if(!capture_loop_init_wiretap_output(&capture_opts, save_file_fd, &ld, errmsg, sizeof errmsg))
+ {
goto error;
- }
}
- /* 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')
- cmdarg_err("WARNING: %s.", open_err_str);
#ifdef _WIN32
/* Catch a CTRL+C event and, if we get it, clean up and exit. */
@@ -1795,14 +1462,14 @@ capture(char *save_file, int out_file_type)
init_capture_stop_conditions();
/* create stop conditions */
if (capture_opts.has_autostop_filesize)
- cnd_stop_capturesize = cnd_new((const char*)CND_CLASS_CAPTURESIZE,
+ cnd_autostop_size = cnd_new((const char*)CND_CLASS_CAPTURESIZE,
(long)capture_opts.autostop_filesize * 1024);
if (capture_opts.has_autostop_duration)
- cnd_stop_timeout = cnd_new((const char*)CND_CLASS_TIMEOUT,
+ cnd_autostop_duration = cnd_new((const char*)CND_CLASS_TIMEOUT,
(gint32)capture_opts.autostop_duration);
if (capture_opts.multi_files_on && capture_opts.has_file_duration)
- cnd_ring_timeout = cnd_new(CND_CLASS_TIMEOUT,
+ cnd_file_duration = cnd_new(CND_CLASS_TIMEOUT,
capture_opts.file_duration);
if (!setjmp(ld.stopenv)) {
@@ -1810,6 +1477,7 @@ capture(char *save_file, int out_file_type)
ld.packet_count = 0;
} else
ld.go = FALSE;
+
while (ld.go) {
/* We need to be careful with automatic variables defined in the
outer scope which are changed inside the loop. Most compilers
@@ -1838,7 +1506,7 @@ capture(char *save_file, int out_file_type)
int loop_err = 0;
int packet_count_prev = 0;
- if (cnd_stop_capturesize == NULL && cnd_stop_timeout == NULL) {
+ if (cnd_autostop_size == NULL && cnd_autostop_duration == NULL) {
/* We're not stopping at a particular capture file size, and we're
not stopping after some particular amount of time has expired,
so either we have no stop condition or the only stop condition
@@ -1870,17 +1538,17 @@ capture(char *save_file, int out_file_type)
pcap_cnt = 1;
}
#ifndef _WIN32
- if (ld.from_pipe) {
- inpkts = pipe_dispatch(pipe_fd, &ld, &hdr, &rechdr, pcap_data,
+ if (ld.from_cap_pipe) {
+ inpkts = cap_pipe_dispatch(ld.cap_pipe_fd, &ld, &ld.cap_pipe_hdr, &ld.cap_pipe_rechdr, pcap_data,
errmsg, sizeof errmsg);
} else
#endif
- inpkts = pcap_dispatch(ld.pch, pcap_cnt, capture_pcap_cb, (u_char *) &ld);
+ inpkts = pcap_dispatch(ld.pcap_h, pcap_cnt, capture_pcap_cb, (u_char *) &ld);
if (inpkts < 0) {
/* Error from "pcap_dispatch()", or error or "no more packets" from
- "pipe_dispatch(). */
+ "cap_pipe_dispatch(). */
ld.go = FALSE;
- } else if (cnd_stop_timeout != NULL && cnd_eval(cnd_stop_timeout)) {
+ } else if (cnd_autostop_duration != NULL && cnd_eval(cnd_autostop_duration)) {
/* The specified capture time has elapsed; stop the capture. */
ld.go = FALSE;
} else if (inpkts > 0) {
@@ -1890,18 +1558,18 @@ capture(char *save_file, int out_file_type)
passed both any capture filter in effect and any read filter
in effect. */
ld.go = FALSE;
- } else if (cnd_stop_capturesize != NULL &&
- cnd_eval(cnd_stop_capturesize,
- (guint32)wtap_get_bytes_dumped(ld.pdh))) {
+ } else if (cnd_autostop_size != NULL &&
+ cnd_eval(cnd_autostop_size,
+ (guint32)wtap_get_bytes_dumped(ld.wtap_pdh))) {
/* We're saving the capture to a file, and the capture file reached
its maximum size. */
if (capture_opts.multi_files_on) {
/* Switch to the next ringbuffer file */
- if (ringbuf_switch_file(&ld.pdh, &save_file, &save_file_fd, &loop_err)) {
+ if (ringbuf_switch_file(&ld.wtap_pdh, &save_file, &save_file_fd, &loop_err)) {
/* File switch succeeded: reset the condition */
- cnd_reset(cnd_stop_capturesize);
- if (cnd_ring_timeout) {
- cnd_reset(cnd_ring_timeout);
+ cnd_reset(cnd_autostop_size);
+ if (cnd_file_duration) {
+ cnd_reset(cnd_file_duration);
}
} else {
/* File switch failed: stop here */
@@ -1915,7 +1583,7 @@ capture(char *save_file, int out_file_type)
}
if (ld.output_to_pipe) {
if (ld.packet_count > packet_count_prev) {
- wtap_dump_flush(ld.pdh);
+ wtap_dump_flush(ld.wtap_pdh);
packet_count_prev = ld.packet_count;
}
}
@@ -1923,12 +1591,12 @@ capture(char *save_file, int out_file_type)
} /* while (ld.go) */
/* delete stop conditions */
- if (cnd_stop_capturesize != NULL)
- cnd_delete(cnd_stop_capturesize);
- if (cnd_stop_timeout != NULL)
- cnd_delete(cnd_stop_timeout);
- if (cnd_ring_timeout != NULL)
- cnd_delete(cnd_ring_timeout);
+ if (cnd_autostop_size != NULL)
+ cnd_delete(cnd_autostop_size);
+ if (cnd_autostop_duration != NULL)
+ cnd_delete(cnd_autostop_duration);
+ if (cnd_file_duration != NULL)
+ cnd_delete(cnd_file_duration);
if (print_packet_counts) {
/* We're printing packet counts to stderr.
@@ -1939,8 +1607,8 @@ capture(char *save_file, int out_file_type)
/* If we got an error while capturing, report it. */
if (inpkts < 0) {
#ifndef _WIN32
- if (ld.from_pipe) {
- if (ld.pipe_err == PIPERR) {
+ if (ld.from_cap_pipe) {
+ if (ld.cap_pipe_err == PIPERR) {
cmdarg_err("Error while capturing packets: %s",
errmsg);
}
@@ -1948,47 +1616,44 @@ capture(char *save_file, int out_file_type)
#endif
{
cmdarg_err("Error while capturing packets: %s",
- pcap_geterr(ld.pch));
+ pcap_geterr(ld.pcap_h));
}
}
if (volatile_err == 0)
- write_err = FALSE;
+ write_ok = TRUE;
else {
show_capture_file_io_error(save_file, volatile_err, FALSE);
- write_err = TRUE;
+ write_ok = FALSE;
}
if (save_file != NULL) {
/* We're saving to a file or files; close all files. */
- if (capture_opts.multi_files_on) {
- dump_ok = ringbuf_wtap_dump_close(&save_file, &err);
- } else {
- dump_ok = wtap_dump_close(ld.pdh, &err);
- }
+ close_ok = capture_loop_close_output(&capture_opts, &ld, &err);
+
/* If we've displayed a message about a write error, there's no point
in displaying another message about an error on close. */
- if (!dump_ok && !write_err)
+ if (!close_ok && write_ok)
show_capture_file_io_error(save_file, err, TRUE);
}
#ifndef _WIN32
- if (ld.from_pipe && pipe_fd >= 0)
- eth_close(pipe_fd);
+ if (ld.from_cap_pipe && ld.cap_pipe_fd >= 0)
+ eth_close(ld.cap_pipe_fd);
else
#endif
{
/* Get the capture statistics, and, if any packets were dropped, report
that. */
- if (pcap_stats(ld.pch, &stats) >= 0) {
+ if (pcap_stats(ld.pcap_h, &stats) >= 0) {
if (stats.ps_drop != 0) {
fprintf(stderr, "%u packets dropped\n", stats.ps_drop);
}
} else {
cmdarg_err("Can't get packet-drop statistics: %s",
- pcap_geterr(ld.pch));
+ pcap_geterr(ld.pcap_h));
}
- pcap_close(ld.pch);
+ pcap_close(ld.pcap_h);
}
/* Report the number of captured packets if not reported during capture
@@ -2005,14 +1670,14 @@ error:
save_file = NULL;
cmdarg_err("%s", errmsg);
#ifndef _WIN32
- if (ld.from_pipe) {
- if (pipe_fd >= 0)
- eth_close(pipe_fd);
+ if (ld.from_cap_pipe) {
+ if (ld.cap_pipe_fd >= 0)
+ eth_close(ld.cap_pipe_fd);
} else
#endif
{
- if (ld.pch != NULL)
- pcap_close(ld.pch);
+ if (ld.pcap_h != NULL)
+ pcap_close(ld.pcap_h);
}
return FALSE;
@@ -2024,7 +1689,7 @@ capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
{
struct wtap_pkthdr whdr;
union wtap_pseudo_header pseudo_header;
- loop_data *ldat = (loop_data *) user;
+ loop_data *ld = (loop_data *) user;
int loop_err;
int err;
int save_file_fd;
@@ -2032,7 +1697,7 @@ capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
/* Convert from libpcap to Wiretap format.
If that fails, ignore the packet (wtap_process_pcap_packet has
written an error message). */
- pd = wtap_process_pcap_packet(ldat->linktype, phdr, pd, &pseudo_header,
+ pd = wtap_process_pcap_packet(ld->wtap_linktype, phdr, pd, &pseudo_header,
&whdr, &err);
if (pd == NULL)
return;
@@ -2051,28 +1716,28 @@ capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
* the first packet of a new series of events as the last
* [or only] packet in the file, switch before writing!
*/
- if (cnd_ring_timeout != NULL && cnd_eval(cnd_ring_timeout)) {
+ if (cnd_file_duration != NULL && cnd_eval(cnd_file_duration)) {
/* time elapsed for this ring file, switch to the next */
- if (ringbuf_switch_file(&ldat->pdh, &ldat->save_file, &save_file_fd, &loop_err)) {
+ if (ringbuf_switch_file(&ld->wtap_pdh, &ld->save_file, &save_file_fd, &loop_err)) {
/* File switch succeeded: reset the condition */
- cnd_reset(cnd_ring_timeout);
+ cnd_reset(cnd_file_duration);
} else {
/* File switch failed: stop here */
/* XXX - we should do something with "loop_err" */
- ldat->go = FALSE;
+ ld->go = FALSE;
}
}
- if (!process_packet(&cfile, ldat->pdh, 0, &whdr, &pseudo_header, pd, &err)) {
+ if (!process_packet(&cfile, ld->wtap_pdh, 0, &whdr, &pseudo_header, pd, &err)) {
/* Error writing to a capture file */
if (print_packet_counts) {
/* We're printing counts of packets captured; move to the line after
the count. */
fprintf(stderr, "\n");
}
- show_capture_file_io_error(ldat->save_file, err, FALSE);
- pcap_close(ldat->pch);
- wtap_dump_close(ldat->pdh, &err);
+ show_capture_file_io_error(ld->save_file, err, FALSE);
+ pcap_close(ld->pcap_h);
+ wtap_dump_close(ld->wtap_pdh, &err);
exit(2);
}
@@ -3078,293 +2743,6 @@ fail:
return CF_ERROR;
}
-#ifdef HAVE_LIBPCAP
-#ifndef _WIN32
-/* Take care of byte order in the libpcap headers read from pipes.
- * (function taken from wiretap/libpcap.c) */
-static void
-adjust_header(loop_data *ldat, struct pcap_hdr *hdr, struct pcaprec_hdr *rechdr)
-{
- if (ldat->byte_swapped) {
- /* Byte-swap the record header fields. */
- rechdr->ts_sec = BSWAP32(rechdr->ts_sec);
- rechdr->ts_usec = BSWAP32(rechdr->ts_usec);
- rechdr->incl_len = BSWAP32(rechdr->incl_len);
- rechdr->orig_len = BSWAP32(rechdr->orig_len);
- }
-
- /* In file format version 2.3, the "incl_len" and "orig_len" fields were
- swapped, in order to match the BPF header layout.
-
- Unfortunately, some files were, according to a comment in the "libpcap"
- source, written with version 2.3 in their headers but without the
- interchanged fields, so if "incl_len" is greater than "orig_len" - which
- would make no sense - we assume that we need to swap them. */
- if (hdr->version_major == 2 &&
- (hdr->version_minor < 3 ||
- (hdr->version_minor == 3 && rechdr->incl_len > rechdr->orig_len))) {
- guint32 temp;
-
- temp = rechdr->orig_len;
- rechdr->orig_len = rechdr->incl_len;
- rechdr->incl_len = temp;
- }
-}
-
-/* Mimic pcap_open_live() for pipe captures
- * We check if "pipename" is "-" (stdin) or a FIFO, open it, and read the
- * 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
-pipe_open_live(char *pipename, struct pcap_hdr *hdr, loop_data *ldat,
- char *errmsg, int errmsgl)
-{
- struct stat pipe_stat;
- int fd;
- guint32 magic;
- int b;
- unsigned int bytes_read;
-
- /*
- * XXX Tethereal blocks until we return
- */
- if (strcmp(pipename, "-") == 0)
- fd = 0; /* read from stdin */
- else {
- if (eth_stat(pipename, &pipe_stat) < 0) {
- if (errno == ENOENT || errno == ENOTDIR)
- ldat->pipe_err = PIPNEXIST;
- else {
- g_snprintf(errmsg, errmsgl,
- "The capture session could not be initiated "
- "due to error on pipe: %s", strerror(errno));
- ldat->pipe_err = PIPERR;
- }
- return -1;
- }
- if (! S_ISFIFO(pipe_stat.st_mode)) {
- if (S_ISCHR(pipe_stat.st_mode)) {
- /*
- * Assume the user specified an interface on a system where
- * interfaces are in /dev. Pretend we haven't seen it.
- */
- ldat->pipe_err = PIPNEXIST;
- } else {
- g_snprintf(errmsg, errmsgl,
- "The capture session could not be initiated because\n"
- "\"%s\" is neither an interface nor a pipe", pipename);
- ldat->pipe_err = PIPERR;
- }
- return -1;
- }
- fd = eth_open(pipename, O_RDONLY, 0000 /* no creation so don't matter */);
- if (fd == -1) {
- g_snprintf(errmsg, errmsgl,
- "The capture session could not be initiated "
- "due to error on pipe open: %s", strerror(errno));
- ldat->pipe_err = PIPERR;
- return -1;
- }
- }
-
- ldat->from_pipe = TRUE;
-
- /* read the pcap header */
- bytes_read = 0;
- while (bytes_read < sizeof magic) {
- b = read(fd, ((char *)&magic)+bytes_read, sizeof magic-bytes_read);
- if (b <= 0) {
- if (b == 0)
- g_snprintf(errmsg, errmsgl, "End of file on pipe during open");
- else
- g_snprintf(errmsg, errmsgl, "Error on pipe during open: %s",
- strerror(errno));
- goto error;
- }
- bytes_read += b;
- }
-
- switch (magic) {
- case PCAP_MAGIC:
- /* Host that wrote it has our byte order, and was running
- a program using either standard or ss990417 libpcap. */
- ldat->byte_swapped = FALSE;
- ldat->modified = FALSE;
- break;
- case PCAP_MODIFIED_MAGIC:
- /* Host that wrote it has our byte order, but was running
- a program using either ss990915 or ss991029 libpcap. */
- ldat->byte_swapped = FALSE;
- ldat->modified = TRUE;
- break;
- case PCAP_SWAPPED_MAGIC:
- /* Host that wrote it has a byte order opposite to ours,
- and was running a program using either standard or
- ss990417 libpcap. */
- ldat->byte_swapped = TRUE;
- ldat->modified = FALSE;
- break;
- case PCAP_SWAPPED_MODIFIED_MAGIC:
- /* Host that wrote it out has a byte order opposite to
- ours, and was running a program using either ss990915
- or ss991029 libpcap. */
- ldat->byte_swapped = TRUE;
- ldat->modified = TRUE;
- break;
- default:
- /* Not a "libpcap" type we know about. */
- g_snprintf(errmsg, errmsgl, "Unrecognized libpcap format");
- goto error;
- }
-
- /* Read the rest of the header */
- bytes_read = 0;
- while (bytes_read < sizeof(struct pcap_hdr)) {
- b = read(fd, ((char *)hdr)+bytes_read,
- sizeof(struct pcap_hdr) - bytes_read);
- if (b <= 0) {
- if (b == 0)
- g_snprintf(errmsg, errmsgl, "End of file on pipe during open");
- else
- g_snprintf(errmsg, errmsgl, "Error on pipe during open: %s",
- strerror(errno));
- goto error;
- }
- bytes_read += b;
- }
-
- if (ldat->byte_swapped) {
- /* Byte-swap the header fields about which we care. */
- hdr->version_major = BSWAP16(hdr->version_major);
- hdr->version_minor = BSWAP16(hdr->version_minor);
- hdr->snaplen = BSWAP32(hdr->snaplen);
- hdr->network = BSWAP32(hdr->network);
- }
-
- if (hdr->version_major < 2) {
- g_snprintf(errmsg, errmsgl, "Unable to read old libpcap format");
- goto error;
- }
-
- ldat->pipe_state = STATE_EXPECT_REC_HDR;
- ldat->pipe_err = PIPOK;
- return fd;
-
-error:
- ldat->pipe_err = PIPERR;
- eth_close(fd);
- return -1;
-
-}
-/* We read one record from the pipe, take care of byte order in the record
- * header, write the record in the capture file, and update capture statistics. */
-
-static int
-pipe_dispatch(int fd, loop_data *ldat, struct pcap_hdr *hdr,
- struct pcaprec_modified_hdr *rechdr, guchar *data,
- char *errmsg, int errmsgl)
-{
- struct pcap_pkthdr phdr;
- int b;
- enum { PD_REC_HDR_READ, PD_DATA_READ, PD_PIPE_EOF, PD_PIPE_ERR,
- PD_ERR } result;
-
- switch (ldat->pipe_state) {
-
- case STATE_EXPECT_REC_HDR:
- ldat->bytes_to_read = ldat->modified ?
- sizeof(struct pcaprec_modified_hdr) : sizeof(struct pcaprec_hdr);
- ldat->bytes_read = 0;
- ldat->pipe_state = STATE_READ_REC_HDR;
- /* Fall through */
-
- case STATE_READ_REC_HDR:
- b = read(fd, ((char *)rechdr)+ldat->bytes_read,
- ldat->bytes_to_read - ldat->bytes_read);
- if (b <= 0) {
- if (b == 0)
- result = PD_PIPE_EOF;
- else
- result = PD_PIPE_ERR;
- break;
- }
- if ((ldat->bytes_read += b) < ldat->bytes_to_read)
- return 0;
- result = PD_REC_HDR_READ;
- break;
-
- case STATE_EXPECT_DATA:
- ldat->bytes_read = 0;
- ldat->pipe_state = STATE_READ_DATA;
- /* Fall through */
-
- case STATE_READ_DATA:
- b = read(fd, data+ldat->bytes_read, rechdr->hdr.incl_len - ldat->bytes_read);
- if (b <= 0) {
- if (b == 0)
- result = PD_PIPE_EOF;
- else
- result = PD_PIPE_ERR;
- break;
- }
- if ((ldat->bytes_read += b) < rechdr->hdr.incl_len)
- return 0;
- result = PD_DATA_READ;
- break;
-
- default:
- g_snprintf(errmsg, errmsgl, "pipe_dispatch: invalid state");
- result = PD_ERR;
-
- } /* switch (ldat->pipe_state) */
-
- /*
- * We've now read as much data as we were expecting, so process it.
- */
- switch (result) {
-
- case PD_REC_HDR_READ:
- /* We've read the header. Take care of byte order. */
- adjust_header(ldat, hdr, &rechdr->hdr);
- if (rechdr->hdr.incl_len > WTAP_MAX_PACKET_SIZE) {
- g_snprintf(errmsg, errmsgl, "Frame %u too long (%d bytes)",
- ldat->packet_count+1, rechdr->hdr.incl_len);
- break;
- }
- ldat->pipe_state = STATE_EXPECT_DATA;
- return 0;
-
- case PD_DATA_READ:
- /* Fill in a "struct pcap_pkthdr", and process the packet. */
- phdr.ts.tv_sec = rechdr->hdr.ts_sec;
- phdr.ts.tv_usec = rechdr->hdr.ts_usec;
- phdr.caplen = rechdr->hdr.incl_len;
- phdr.len = rechdr->hdr.orig_len;
-
- capture_pcap_cb((u_char *)ldat, &phdr, data);
-
- ldat->pipe_state = STATE_EXPECT_REC_HDR;
- return 1;
-
- case PD_PIPE_EOF:
- ldat->pipe_err = PIPEOF;
- return -1;
-
- case PD_PIPE_ERR:
- g_snprintf(errmsg, errmsgl, "Error reading from pipe: %s",
- strerror(errno));
- /* Fall through */
- case PD_ERR:
- break;
- }
-
- ldat->pipe_err = PIPERR;
- /* Return here rather than inside the switch to prevent GCC warning */
- return -1;
-}
-#endif /* _WIN32 */
-#endif /* HAVE_LIBPCAP */
/*
* General errors are reported with an console message in Tethereal.
@@ -3415,3 +2793,83 @@ cmdarg_err_cont(const char *fmt, ...)
fprintf(stderr, "\n");
va_end(ap);
}
+
+
+/****************************************************************************************************************/
+/* sync pipe "dummies", needed for capture_loop.c */
+
+#ifdef HAVE_LIBPCAP
+
+/** the child has opened a new capture file, notify the parent */
+void
+sync_pipe_filename_to_parent(const char *filename)
+{
+ /* shouldn't happen */
+ g_assert(0);
+}
+
+/** the child captured some new packets, notify the parent */
+void
+sync_pipe_packet_count_to_parent(int packet_count)
+{
+ /* shouldn't happen */
+ g_assert(0);
+}
+
+/** the child stopped capturing, notify the parent */
+void
+sync_pipe_drops_to_parent(int drops)
+{
+ /* shouldn't happen */
+ g_assert(0);
+}
+
+/** the child encountered an error, notify the parent */
+void
+sync_pipe_errmsg_to_parent(const char *errmsg)
+{
+ cmdarg_err(errmsg);
+}
+
+#endif /* HAVE_LIBPCAP */
+
+
+/****************************************************************************************************************/
+/* simple_dialog "dummies", needed for capture_loop.c */
+
+
+#ifdef HAVE_LIBPCAP
+
+char *simple_dialog_primary_start(void)
+{
+ return "";
+}
+
+char *simple_dialog_primary_end(void)
+{
+ return "";
+}
+
+
+/* XXX - do we need to convert the string for the console? */
+char *
+simple_dialog_format_message(const char *msg)
+{
+ char *str;
+
+
+ if (msg) {
+#if GTK_MAJOR_VERSION < 2
+ str = g_strdup(msg);
+#else
+ str = xml_escape(msg);
+#endif
+ } else {
+ str = NULL;
+ }
+ return str;
+}
+
+#endif /* HAVE_LIBPCAP */
+
+