* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-/* With MSVC and a libethereal.dll this file needs to import some variables
- in a special way. Therefore _NEED_VAR_IMPORT_ is defined. */
-#define _NEED_VAR_IMPORT_
-
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_LIBPCAP
#include <wiretap/wtap-capture.h>
#include <wiretap/libpcap.h>
-#endif
-
#ifdef _WIN32
#include "capture-wpcap.h"
#endif
+#include "capture.h"
+#endif
+
/*
* This is the template for the decode as option; it is shared between the
static guint32 firstsec, firstusec;
static guint32 prevsec, prevusec;
static GString *comp_info_str, *runtime_info_str;
-static gboolean quiet;
static gboolean print_packet_info; /* TRUE if we're to print packet information */
/*
static print_stream_t *print_stream;
#ifdef HAVE_LIBPCAP
+/*
+ * TRUE if we're to print packet counts to keep track of captured packets.
+ */
+static gboolean print_packet_counts;
+
typedef struct _loop_data {
gboolean go; /* TRUE as long as we're supposed to keep capturing */
gint linktype;
static loop_data ld;
#ifdef HAVE_LIBPCAP
-typedef struct {
- gchar *cfilter; /* Capture filter string */
- gchar *iface; /* the network interface to capture from */
- int snaplen; /* Maximum captured packet length */
- int promisc_mode; /* Capture in promiscuous mode */
- int autostop_count; /* Maximum packet count */
- gboolean has_autostop_duration; /* TRUE if maximum capture duration
- is specified */
- gint32 autostop_duration; /* Maximum capture duration */
- gboolean has_autostop_filesize; /* TRUE if maximum capture file size
- is specified */
- gint32 autostop_filesize; /* Maximum capture file size */
- gboolean ringbuffer_on; /* TRUE if ring buffer in use */
- guint32 ringbuffer_num_files; /* Number of ring buffer files */
- gboolean has_ring_duration; /* TRUE if ring duration specified */
- gint32 ringbuffer_duration; /* Switch file after n seconds */
- int linktype; /* Data link type to use, or -1 for
- "use default" */
-} capture_options;
-
-static capture_options capture_opts = {
- "", /* No capture filter string specified */
- NULL, /* Default is "pick the first interface" */
- WTAP_MAX_PACKET_SIZE, /* snapshot length - default is
- infinite, in effect */
- TRUE, /* promiscuous mode is the default */
- 0, /* max packet count - default is 0,
- meaning infinite */
- FALSE, /* maximum capture duration not
- specified by default */
- 0, /* maximum capture duration */
- FALSE, /* maximum capture file size not
- specified by default */
- 0, /* maximum capture file size */
- FALSE, /* ring buffer off by default */
- RINGBUFFER_MIN_NUM_FILES, /* default number of ring buffer files */
- FALSE, /* Switch ring file after some */
- 0, /* specified time is off by default */
- -1 /* Default to not change link type */
-};
+static capture_options capture_opts;
-static gboolean list_link_layer_types;
#ifdef SIGINFO
static gboolean infodelay; /* if TRUE, don't print capture info in SIGINFO handler */
fprintf(output, "\tdefault is libpcap\n");
}
-#ifdef HAVE_LIBPCAP
-static int
-get_natural_int(const char *string, const char *name)
-{
- long number;
- char *p;
-
- number = strtol(string, &p, 10);
- if (p == string || *p != '\0') {
- fprintf(stderr, "tethereal: The specified %s \"%s\" isn't a decimal number\n",
- name, string);
- exit(1);
- }
- if (number < 0) {
- fprintf(stderr, "tethereal: The specified %s is a negative number\n",
- name);
- exit(1);
- }
- if (number > INT_MAX) {
- fprintf(stderr, "tethereal: The specified %s is too large (greater than %d)\n",
- name, INT_MAX);
- exit(1);
- }
- return number;
-}
-
-static int
-get_positive_int(const char *string, const char *name)
-{
- long number;
-
- number = get_natural_int(string, name);
-
- if (number == 0) {
- fprintf(stderr, "tethereal: The specified %s is zero\n",
- name);
- exit(1);
- }
-
- return number;
-}
-
-/*
- * Given a string of the form "<autostop criterion>:<value>", as might appear
- * as an argument to a "-a" option, parse it and set the criterion in
- * question. Return an indication of whether it succeeded or failed
- * in some fashion.
- */
-static gboolean
-set_autostop_criterion(const char *autostoparg)
-{
- guchar *p, *colonp;
-
- colonp = strchr(autostoparg, ':');
- if (colonp == NULL)
- return FALSE;
-
- p = colonp;
- *p++ = '\0';
-
- /*
- * Skip over any white space (there probably won't be any, but
- * as we allow it in the preferences file, we might as well
- * allow it here).
- */
- while (isspace(*p))
- p++;
- if (*p == '\0') {
- /*
- * Put the colon back, so if our caller uses, in an
- * error message, the string they passed us, the message
- * looks correct.
- */
- *colonp = ':';
- return FALSE;
- }
- if (strcmp(autostoparg,"duration") == 0) {
- capture_opts.has_autostop_duration = TRUE;
- capture_opts.autostop_duration = get_positive_int(p,"autostop duration");
- } else if (strcmp(autostoparg,"filesize") == 0) {
- capture_opts.has_autostop_filesize = TRUE;
- capture_opts.autostop_filesize = get_positive_int(p,"autostop filesize");
- } else {
- return FALSE;
- }
- *colonp = ':'; /* put the colon back */
- return TRUE;
-}
-
-/*
- * Given a string of the form "<ring buffer file>:<duration>", as might appear
- * as an argument to a "-b" option, parse it and set the arguments in
- * question. Return an indication of whether it succeeded or failed
- * in some fashion.
- */
-static gboolean
-get_ring_arguments(const char *arg)
-{
- guchar *p = NULL, *colonp;
-
- colonp = strchr(arg, ':');
-
- if (colonp != NULL) {
- p = colonp;
- *p++ = '\0';
- }
-
- capture_opts.ringbuffer_num_files =
- get_natural_int(arg, "number of ring buffer files");
-
- if (colonp == NULL)
- return TRUE;
-
- /*
- * Skip over any white space (there probably won't be any, but
- * as we allow it in the preferences file, we might as well
- * allow it here).
- */
- while (isspace(*p))
- p++;
- if (*p == '\0') {
- /*
- * Put the colon back, so if our caller uses, in an
- * error message, the string they passed us, the message
- * looks correct.
- */
- *colonp = ':';
- return FALSE;
- }
-
- capture_opts.has_ring_duration = TRUE;
- capture_opts.ringbuffer_duration = get_positive_int(p,
- "ring buffer duration");
-
- *colonp = ':'; /* put the colon back */
- return TRUE;
-}
-#endif
-
/* structure to keep track of what tap listeners have been registered.
*/
typedef struct _ethereal_tap_list {
char *p;
gchar err_str[PCAP_ERRBUF_SIZE];
gchar *cant_get_if_list_errstr;
+ gboolean list_link_layer_types;
#else
gboolean capture_option_specified = FALSE;
#endif
+ gboolean quiet = FALSE;
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;
dfilter_t *rfcode = NULL;
e_prefs *prefs;
char badopt;
- ethereal_tap_list *tli;
-
+ ethereal_tap_list *tli = NULL;
+ gboolean got_tap = FALSE;
+
#ifdef HAVE_LIBPCAP
- /* XXX - better use capture_opts_init instead */
- capture_opts.cfilter = g_strdup("");
+ capture_opts_init(&capture_opts, NULL /* cfile */);
#endif
set_timestamp_setting(TS_RELATIVE);
while ((opt = getopt(argc, argv, "a:b:c:d:Df:F:hi:lLnN:o:pqr:R:s:St:T:vw:Vxy:z:")) != -1) {
switch (opt) {
case 'a': /* autostop criteria */
-#ifdef HAVE_LIBPCAP
- if (set_autostop_criterion(optarg) == FALSE) {
- fprintf(stderr, "tethereal: Invalid or unknown -a flag \"%s\"\n", optarg);
- exit(1);
- }
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
case 'b': /* Ringbuffer option */
-#ifdef HAVE_LIBPCAP
- capture_opts.ringbuffer_on = TRUE;
- if (get_ring_arguments(optarg) == FALSE) {
- fprintf(stderr, "tethereal: Invalid or unknown -b arg \"%s\"\n", optarg);
- exit(1);
- }
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
case 'c': /* Capture xxx packets */
+ case 'f': /* capture filter */
+ case 'p': /* Don't capture in promiscuous mode */
+ case 's': /* Set the snapshot (capture) length */
+ case 'y': /* Set the pcap data link type */
#ifdef HAVE_LIBPCAP
- capture_opts.autostop_count =
- get_positive_int(optarg, "packet count");
+ capture_opts_add_opt(&capture_opts, "tethereal", opt, optarg, &start_capture);
#else
capture_option_specified = TRUE;
arg_error = TRUE;
arg_error = TRUE;
#endif
break;
- case 'f':
-#ifdef HAVE_LIBPCAP
- capture_filter_specified = TRUE;
- if (capture_opts.cfilter)
- g_free(capture_opts.cfilter);
- capture_opts.cfilter = g_strdup(optarg);
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
case 'F':
out_file_type = wtap_short_string_to_file_type(optarg);
if (out_file_type < 0) {
break;
}
break;
- case 'p': /* Don't capture in promiscuous mode */
-#ifdef HAVE_LIBPCAP
- capture_opts.promisc_mode = FALSE;
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
case 'q': /* Quiet */
quiet = TRUE;
break;
case 'r': /* Read capture file xxx */
cf_name = g_strdup(optarg);
- quiet = TRUE; /* We're not capturing, so don't print packet counts */
break;
case 'R': /* Read file filter */
rfilter = optarg;
break;
- case 's': /* Set the snapshot (capture) length */
-#ifdef HAVE_LIBPCAP
- capture_opts.snaplen = get_positive_int(optarg, "snapshot length");
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
case 'S': /* show packets in real time */
print_packet_info = TRUE;
break;
case 'x': /* Print packet data in hex (and ASCII) */
print_hex = TRUE;
break;
- case 'y': /* Set the pcap data link type */
-#ifdef HAVE_LIBPCAP
-#ifdef HAVE_PCAP_DATALINK_NAME_TO_VAL
- capture_opts.linktype = pcap_datalink_name_to_val(optarg);
- if (capture_opts.linktype == -1) {
- fprintf(stderr, "tethereal: The specified data link type \"%s\" isn't valid\n",
- optarg);
- exit(1);
- }
-#else /* HAVE_PCAP_DATALINK_NAME_TO_VAL */
- /* XXX - just treat it as a number */
- capture_opts.linktype = get_natural_int(optarg, "data link type");
-#endif /* HAVE_PCAP_DATALINK_NAME_TO_VAL */
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
case 'z':
for(tli=tap_list;tli;tli=tli->next){
if(!strncmp(tli->cmd,optarg,strlen(tli->cmd))){
- (*tli->func)(optarg);
+ /* we won't call the init function for the tap this soon
+ as it would disallow mate's fields (which are registered
+ by the preferences set callback) from being used as
+ part of a tap filter */
+ got_tap = TRUE;
break;
}
}
exit(1);
}
/* No - did they specify a ring buffer option? */
- if (capture_opts.ringbuffer_on) {
+ if (capture_opts.multi_files_on) {
fprintf(stderr, "tethereal: Ring buffer requested, but a capture isn't being done.\n");
exit(1);
}
exit(1);
}
- if (capture_opts.ringbuffer_on) {
+ if (capture_opts.multi_files_on) {
/* Ring buffer works only under certain conditions:
a) ring buffer does not work if you're not saving the capture to
a file;
line that their preferences have changed. */
prefs_apply_all();
+ /* At this point mate will have registered its field array so we can
+ have a filter with one of mate's late registered fields as part
+ of the tap's filter */
+ if (got_tap)
+ (*tli->func)(optarg);
+
/* disabled protocols as per configuration file */
if (gdp_path == NULL && dp_path == NULL) {
set_disabled_protos_list();
else if (capture_opts.snaplen < MIN_PACKET_SIZE)
capture_opts.snaplen = MIN_PACKET_SIZE;
- /* Check the value range of the ringbuffer_num_files parameter */
- if (capture_opts.ringbuffer_num_files > RINGBUFFER_MAX_NUM_FILES)
- capture_opts.ringbuffer_num_files = RINGBUFFER_MAX_NUM_FILES;
+ /* 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;
#if RINGBUFFER_MIN_NUM_FILES > 0
- else if (capture_opts.ringbuffer_num_files < RINGBUFFER_MIN_NUM_FILES)
- capture_opts.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
+ else if (capture_opts.ring_num_files < RINGBUFFER_MIN_NUM_FILES)
+ capture_opts.ring_num_files = RINGBUFFER_MIN_NUM_FILES;
#endif
#endif
exit(0);
}
+ if (!quiet) {
+ /*
+ * The user didn't ask us not to print a count of packets as
+ * they arrive, so do so.
+ */
+ print_packet_counts = TRUE;
+ }
+
capture(save_file, out_file_type);
- if (capture_opts.ringbuffer_on) {
+ if (capture_opts.multi_files_on) {
ringbuf_free();
}
#else
goto error;
}
ld.save_file = save_file;
- if (capture_opts.ringbuffer_on) {
+ if (capture_opts.multi_files_on) {
save_file_fd = ringbuf_init(save_file,
- capture_opts.ringbuffer_num_files);
+ 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);
cnd_stop_timeout = cnd_new((const char*)CND_CLASS_TIMEOUT,
(gint32)capture_opts.autostop_duration);
- if (capture_opts.ringbuffer_on && capture_opts.has_ring_duration)
+ if (capture_opts.multi_files_on && capture_opts.has_file_duration)
cnd_ring_timeout = cnd_new(CND_CLASS_TIMEOUT,
- capture_opts.ringbuffer_duration);
+ capture_opts.file_duration);
if (!setjmp(ld.stopenv)) {
ld.go = TRUE;
reading the FIFO sees the packets immediately and doesn't get
any partial packet, forcing it to block in the middle of reading
that packet. */
- if (capture_opts.autostop_count == 0)
+ if (capture_opts.autostop_packets == 0)
pcap_cnt = -1;
else {
- if (ld.packet_count >= capture_opts.autostop_count) {
+ if (ld.packet_count >= capture_opts.autostop_packets) {
/* XXX do we need this test here? */
/* It appears there's nothing more to capture. */
break;
}
- pcap_cnt = capture_opts.autostop_count - ld.packet_count;
+ pcap_cnt = capture_opts.autostop_packets - ld.packet_count;
}
} else {
/* We need to check the capture file size or the timeout after
/* The specified capture time has elapsed; stop the capture. */
ld.go = FALSE;
} else if (inpkts > 0) {
- if (capture_opts.autostop_count != 0 &&
- ld.packet_count >= capture_opts.autostop_count) {
+ if (capture_opts.autostop_packets != 0 &&
+ ld.packet_count >= capture_opts.autostop_packets) {
/* The specified number of packets have been captured and have
passed both any capture filter in effect and any read filter
in effect. */
(guint32)wtap_get_bytes_dumped(ld.pdh))) {
/* We're saving the capture to a file, and the capture file reached
its maximum size. */
- if (capture_opts.ringbuffer_on) {
+ 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)) {
/* File switch succeeded: reset the condition */
if (cnd_ring_timeout != NULL)
cnd_delete(cnd_ring_timeout);
- if ((save_file != NULL) && !quiet) {
- /* We're saving to a file, which means we're printing packet counts
- to stderr if we are not running silent and deep.
+ if (print_packet_counts) {
+ /* We're printing packet counts to stderr.
Send a newline so that we move to the line after the packet count. */
fprintf(stderr, "\n");
}
if (save_file != NULL) {
/* We're saving to a file or files; close all files. */
- if (capture_opts.ringbuffer_on) {
+ if (capture_opts.multi_files_on) {
dump_ok = ringbuf_wtap_dump_close(&save_file, &err);
} else {
dump_ok = wtap_dump_close(ld.pdh, &err);
return TRUE;
error:
- if (capture_opts.ringbuffer_on) {
+ if (capture_opts.multi_files_on) {
ringbuf_error_cleanup();
}
g_free(save_file);
if (!process_packet(&cfile, ldat->pdh, 0, &whdr, &pseudo_header, pd, &err)) {
/* Error writing to a capture file */
- if (!quiet) {
- /* We're capturing packets, so (if -q not specified) we're printing
- a count of packets captured; move to the line after the count. */
+ 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);
signal(SIGINFO, report_counts_siginfo);
#endif /* SIGINFO */
- if (quiet || print_packet_info) {
+ if (!print_packet_counts) {
/* Report the count only if we aren't printing a packet count
as packets arrive. */
fprintf(stderr, "%u packets captured\n", ld.packet_count);
if (!wtap_dump(pdh, whdr, pseudo_header, pd, err))
return FALSE;
#ifdef HAVE_LIBPCAP
- /* Report packet capture count if not quiet */
- if (!quiet && !print_packet_info) {
- /* Don't print a packet count if we were asked not to with "-q"
- or if we're also printing packet info. */
+ if (print_packet_counts) {
+ /* We're printing packet counts. */
if (ld.packet_count != 0) {
fprintf(stderr, "\r%u ", ld.packet_count);
/* stderr could be line buffered */