#include <glib.h>
#include <epan/epan.h>
#include <epan/filesystem.h>
+#include <epan/privileges.h>
#include <wiretap/file_util.h>
#include "globals.h"
#include <epan/addr_resolv.h>
#include "util.h"
#include "clopts_common.h"
+#include "cmdarg_err.h"
#include "version_info.h"
#include <epan/conversation.h>
#include <epan/plugins.h>
#include <epan/tap.h>
#include <epan/stat_cmd_args.h>
#include <epan/timestamp.h>
+#include <epan/ex-opt.h>
#ifdef HAVE_LIBPCAP
#include <pcap.h>
#include <setjmp.h>
-#include "pcap-util.h"
+#include "capture-pcap-util.h"
+#include "pcapio.h"
#include <wiretap/wtap-capture.h>
-#include <wiretap/libpcap.h>
#ifdef _WIN32
#include "capture-wpcap.h"
#include "capture_errs.h"
#endif /* _WIN32 */
#include "capture.h"
+#include "capture_loop.h"
+#include "capture_sync.h"
#endif /* HAVE_LIBPCAP */
#include "epan/emem.h"
+#include "log.h"
+#include <epan/funnel.h>
/*
* This is the template for the decode as option; it is shared between the
static print_format_e print_format = PR_FMT_TEXT;
static print_stream_t *print_stream;
+/*
+ * Standard secondary message for unexpected errors.
+ */
+static const char please_report[] =
+ "Please report this to the Ethereal developers";
+
#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;
- 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;
#endif /* HAVE_LIBPCAP */
-static int capture(char *, int);
+static int capture(void);
static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *,
const u_char *);
static void report_counts(void);
#endif /* HAVE_LIBPCAP */
static int load_cap_file(capture_file *, char *, int);
-static gboolean process_packet(capture_file *cf, wtap_dumper *pdh, long offset,
+static gboolean process_packet(capture_file *cf, long offset,
const struct wtap_pkthdr *whdr, union wtap_pseudo_header *pseudo_header,
- const guchar *pd, int *err);
+ const guchar *pd);
static void show_capture_file_io_error(const char *, int, gboolean);
static void show_print_file_io_error(int err);
static gboolean write_preamble(capture_file *cf);
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);
capture_file cfile;
+static void list_capture_types(void) {
+ int i;
+
+ fprintf(stderr, "editcap: The available capture file types for \"F\":\n");
+ for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
+ if (wtap_dump_can_open(i))
+ fprintf(stderr, " %s - %s\n",
+ wtap_file_type_short_string(i), wtap_file_type_string(i));
+ }
+}
+
static void
print_usage(gboolean print_ver)
{
- int i;
FILE *output;
if (print_ver) {
output = stdout;
- fprintf(output, "This is t" PACKAGE " " VERSION "%s"
- "\n (C) 1998-2005 Gerald Combs <gerald@ethereal.com>"
- "\n%s\n%s\n",
-
- svnversion, comp_info_str->str, runtime_info_str->str);
+ fprintf(output,
+ "Tethereal " VERSION "%s\n"
+ "Dump and analyze network traffic.\n"
+ "See http://www.ethereal.com for more information.\n"
+ "\n"
+ "%s",
+ svnversion, get_copyright_info());
} else {
output = stderr;
}
+ fprintf(output, "\n");
+ fprintf(output, "Usage: tethereal [options] ...\n");
+ fprintf(output, "\n");
+
#ifdef HAVE_LIBPCAP
- fprintf(output, "\nt%s [ -vh ] [ -DlLnpqSVx ] [ -a <capture autostop condition> ] ...\n",
- PACKAGE);
- fprintf(output, "\t[ -b <capture ring buffer option> ] ... [ -c <capture packet count> ]\n");
- fprintf(output, "\t[ -d %s ] ...\n", decode_as_arg_template);
- fprintf(output, "\t[ -f <capture filter> ] [ -F <output file type> ]\n");
- fprintf(output, "\t[ -i <capture interface> ] [ -N <name resolving flags> ]\n");
- fprintf(output, "\t[ -o <preference setting> ] ... [ -r <infile> ]\n");
- fprintf(output, "\t[ -R <read (display) filter> ] [ -s <capture snaplen> ]\n");
- fprintf(output, "\t[ -t <time stamp format> ] [ -T pdml|ps|psml|text ]\n");
- fprintf(output, "\t[ -w <savefile> ] [ -y <capture link type> ] [ -z <statistics> ]\n");
-#else
- fprintf(output, "\nt%s [ -vh ] [ -lnVx ]\n", PACKAGE);
- fprintf(output, "\t[ -d %s ] ...\n", decode_as_arg_template);
- fprintf(output, "\t[ -F <output file type> ] [ -N <name resolving flags> ]\n");
- fprintf(output, "\t[ -o <preference setting> ] ... [ -r <infile> ]\n");
- fprintf(output, "\t[ -R <read (display) filter> ] \t[ -t <time stamp format> ]\n");
- fprintf(output, "\t[ -T pdml|ps|psml|text ] [ -w <savefile> ] [ -z <statistics ]\n");
+ fprintf(output, "Capture interface:\n");
+ fprintf(output, " -i <interface> name or idx of interface (def: first none loopback)\n");
+ fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
+ fprintf(output, " -s <snaplen> packet snapshot length (def: 65535)\n");
+ fprintf(output, " -p don't capture in promiscuous mode\n");
+#ifdef _WIN32
+ fprintf(output, " -B <buffer size> size of kernel buffer (def: 1MB)\n");
#endif
- fprintf(output, "Valid file type arguments to the \"-F\" flag:\n");
- for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
- if (wtap_dump_can_open(i))
- fprintf(output, "\t%s - %s\n",
- wtap_file_type_short_string(i), wtap_file_type_string(i));
- }
- fprintf(output, "\tdefault is libpcap\n");
+ fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
+ fprintf(output, " -D print list of interfaces and exit\n");
+ fprintf(output, " -L print list of link-layer types of iface and exit\n");
+ fprintf(output, "\n");
+ fprintf(output, "Capture stop conditions:\n");
+ fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
+ fprintf(output, " -a <autostop cond.> ... duration:NUM - stop after NUM seconds\n");
+ fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
+ fprintf(output, " files:NUM - stop after NUM files\n");
+ /*fprintf(output, "\n");*/
+ fprintf(output, "Capture output:\n");
+ fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
+ fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
+ fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
+#endif /* HAVE_LIBPCAP */
+
+ /*fprintf(output, "\n");*/
+ fprintf(output, "Input file:\n");
+ fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin!)\n");
+
+ fprintf(output, "\n");
+ fprintf(output, "Processing:\n");
+ fprintf(output, " -R <read filter> packet filter in Ethereal display filter syntax\n");
+ fprintf(output, " -n disable all name resolutions (def: all enabled)\n");
+ fprintf(output, " -N <name resolve flags> enable specific name resolution(s): \"mntC\"\n");
+ fprintf(output, " -d %s ...\n", decode_as_arg_template);
+ fprintf(output, " \"Decode As\", see the man page for details\n");
+ fprintf(output, " Example: tcp.port==8888,http\n");
+
+ /*fprintf(output, "\n");*/
+ fprintf(output, "Output:\n");
+ fprintf(stderr, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
+ fprintf(stderr, " -F <output file type> set the output file type, default is libpcap\n");
+ fprintf(stderr, " an empty \"-F\" option will list the file types\n");
+ fprintf(output, " -V add output of packet tree (Packet Details)\n");
+ fprintf(output, " -x add output of hex and ASCII dump (Packet Bytes)\n");
+ fprintf(output, " -T pdml|ps|psml|text output format of text output (def: text)\n");
+ fprintf(output, " -t ad|a|r|d output format of time stamps (def: r: rel. to first)\n");
+ fprintf(output, " -l flush output after each packet\n");
+ fprintf(output, " -q be more quiet on stdout (e.g. when using statistics)\n");
+ fprintf(output, " -X <key>:<value> eXtension options, see the man page for details\n");
+ fprintf(output, " -z <statistics> various statistics, see the man page for details\n");
+
+ fprintf(output, "\n");
+ fprintf(stderr, "Miscellaneous:\n");
+ fprintf(stderr, " -h display this help and exit\n");
+ fprintf(stderr, " -v display version info and exit\n");
+ fprintf(output, " -o <name>:<value> ... override preference setting\n");
}
/*
remaining_param = strchr(table_name, '=');
if (remaining_param == NULL) {
- fprintf(stderr, "tethereal: Parameter \"%s\" doesn't follow the template \"%s\"\n", cl_param, decode_as_arg_template);
+ cmdarg_err("Parameter \"%s\" doesn't follow the template \"%s\"", cl_param, decode_as_arg_template);
/* If the argument does not follow the template, carry on anyway to check
if the table name is at least correct. If remaining_param is NULL,
we'll exit anyway further down */
/* Look for the requested table */
if ( !(*(table_name)) ) { /* Is the table name empty, if so, don't even search for anything, display a message */
- fprintf(stderr, "tethereal: No layer type specified\n"); /* Note, we don't exit here, but table_matching will remain NULL, so we exit below */
+ cmdarg_err("No layer type specified"); /* Note, we don't exit here, but table_matching will remain NULL, so we exit below */
}
else {
table_matching = find_dissector_table(table_name);
if (!table_matching) {
- fprintf(stderr, "tethereal: Unknown layer type -- %s\n", table_name); /* Note, we don't exit here, but table_matching will remain NULL, so we exit below */
+ cmdarg_err("Unknown layer type -- %s", table_name); /* Note, we don't exit here, but table_matching will remain NULL, so we exit below */
}
}
if (!table_matching) {
/* Display a list of supported layer types to help the user, if the
specified layer type was not found */
- fprintf(stderr, "tethereal: Valid layer types are:\n");
+ cmdarg_err("Valid layer types are:");
fprint_all_layer_types(stderr);
}
if (remaining_param == NULL || !table_matching) {
}
if (*(remaining_param + 1) != '=') { /* Check for "==" and not only '=' */
- fprintf(stderr, "tethereal: WARNING: -d requires \"==\" instead of \"=\". Option will be treated as \"%s==%s\"\n", table_name, remaining_param + 1);
+ cmdarg_err("WARNING: -d requires \"==\" instead of \"=\". Option will be treated as \"%s==%s\"", table_name, remaining_param + 1);
}
else {
remaining_param++; /* Move to the second '=' */
remaining_param = strchr(selector_str, ',');
if (remaining_param == NULL) {
- fprintf(stderr, "tethereal: Parameter \"%s\" doesn't follow the template \"%s\"\n", cl_param, decode_as_arg_template);
+ cmdarg_err("Parameter \"%s\" doesn't follow the template \"%s\"", cl_param, decode_as_arg_template);
/* If the argument does not follow the template, carry on anyway to check
if the selector value is at least correct. If remaining_param is NULL,
we'll exit anyway further down */
There's no need to remove leading and trailing spaces from the
selector number string, because sscanf will do that for us. */
if ( sscanf(selector_str, "%u", &selector) != 1 ) {
- fprintf(stderr, "tethereal: Invalid selector number \"%s\"\n", selector_str);
+ cmdarg_err("Invalid selector number \"%s\"", selector_str);
g_free(decoded_param);
return FALSE;
}
if (remaining_param == NULL) {
/* Exit if no ',' separator was found (see above) */
- fprintf(stderr, "tethereal: Valid protocols for layer type \"%s\" are:\n", table_name);
+ cmdarg_err("Valid protocols for layer type \"%s\" are:", table_name);
fprint_all_protocols_for_layer_types(stderr, table_name);
g_free(decoded_param);
return FALSE;
/* We now have a pointer to the handle for the requested table inside the variable table_matching */
if ( ! (*dissector_str) ) { /* Is the dissector name empty, if so, don't even search for a matching dissector and display all dissectors found for the selected table */
- fprintf(stderr, "tethereal: No protocol name specified\n"); /* Note, we don't exit here, but dissector_matching will remain NULL, so we exit below */
+ cmdarg_err("No protocol name specified"); /* Note, we don't exit here, but dissector_matching will remain NULL, so we exit below */
}
else {
user_protocol_name.nb_match = 0;
if (user_protocol_name.nb_match != 0) {
dissector_matching = user_protocol_name.matched_handle;
if (user_protocol_name.nb_match > 1) {
- fprintf(stderr, "tethereal: WARNING: Protocol \"%s\" matched %u dissectors, first one will be used\n", dissector_str, user_protocol_name.nb_match);
+ cmdarg_err("WARNING: Protocol \"%s\" matched %u dissectors, first one will be used", dissector_str, user_protocol_name.nb_match);
}
}
else {
so we exit below */
if (proto_get_id_by_filter_name(dissector_str) == -1) {
/* No such protocol */
- fprintf(stderr, "tethereal: Unknown protocol -- \"%s\"\n", dissector_str);
+ cmdarg_err("Unknown protocol -- \"%s\"", dissector_str);
} else {
- fprintf(stderr, "tethereal: Protocol \"%s\" isn't valid for layer type \"%s\"\n",
+ cmdarg_err("Protocol \"%s\" isn't valid for layer type \"%s\"",
dissector_str, table_name);
}
}
}
if (!dissector_matching) {
- fprintf(stderr, "tethereal: Valid protocols for layer type \"%s\" are:\n", table_name);
+ cmdarg_err("Valid protocols for layer type \"%s\" are:", table_name);
fprint_all_protocols_for_layer_types(stderr, table_name);
g_free(decoded_param);
return FALSE;
return TRUE;
}
+static void
+log_func_ignore (const gchar *log_domain _U_, GLogLevelFlags log_level _U_,
+ const gchar *message _U_, gpointer user_data _U_)
+{
+}
+
+static char *
+output_file_description(const char *fname)
+{
+ char *save_file_string;
+
+ /* Get a string that describes what we're writing to */
+ if (strcmp(fname, "-") == 0) {
+ /* We're writing to the standard output */
+ save_file_string = g_strdup("standard output");
+ } else {
+ /* We're writing to a file with the name in save_file */
+ save_file_string = g_strdup_printf("file \"%s\"", fname);
+ }
+ return save_file_string;
+}
+
int
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
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;
-#endif
#ifdef HAVE_PCAP_OPEN_DEAD
struct bpf_program fcode;
#endif
dfilter_t *rfcode = NULL;
e_prefs *prefs;
char badopt;
+ GLogLevelFlags log_flags;
+ int status;
+
+#define OPTSTRING_INIT "a:b:c:d:Df:F:hi:lLnN:o:pqr:R:s:St:T:vVw:xX:y:z:"
+#ifdef HAVE_LIBPCAP
+#ifdef _WIN32
+#define OPTSTRING_WIN32 "B:"
+#else
+#define OPTSTRING_WIN32 ""
+#endif /* _WIN32 */
+#else
+#define OPTSTRING_WIN32 ""
+#endif /* HAVE_LIBPCAP */
+
+ static const char optstring[] = OPTSTRING_INIT OPTSTRING_WIN32;
+
+ /*
+ * Get credential information for later use.
+ */
+ get_credential_info();
+
+ /* 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 */);
+ g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
+ log_flags,
+ log_func_ignore, NULL /* user_data */);
/* initialize memory allocation subsystem */
ep_init_chunk();
se_init_chunk();
+ initialize_funnel_ops();
+
#ifdef HAVE_LIBPCAP
capture_opts_init(&capture_opts, NULL /* cfile */);
#endif
as the "-z" argument can specify a registered tap. */
/* we register the plugin taps before the other taps because
- stats_tree taps plugins will be registered as tap listeners
- by stats_tree_stat.c and need to registered before that */
+ stats_tree taps plugins will be registered as tap listeners
+ by stats_tree_stat.c and need to registered before that */
#ifdef HAVE_PLUGINS
register_all_plugin_tap_listeners();
#endif
for backwards compatibility we dump out a glossary of display
filter symbols.
- We do this here to mirror what happens in the GTK+ version, although
- it's not necessary here. */
- handle_dashG_option(argc, argv, "tethereal");
+ XXX - we do this here, for now, to support "-G" with no arguments.
+ If none of our build or other processes uses "-G" with no arguments,
+ we can just process it with the other arguments. */
+ if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
+ if (argc == 2)
+ proto_registrar_dump_fields(1);
+ else {
+ if (strcmp(argv[2], "fields") == 0)
+ proto_registrar_dump_fields(1);
+ else if (strcmp(argv[2], "fields2") == 0)
+ proto_registrar_dump_fields(2);
+ else if (strcmp(argv[2], "fields3") == 0)
+ proto_registrar_dump_fields(3);
+ else if (strcmp(argv[2], "protocols") == 0)
+ proto_registrar_dump_protocols();
+ else if (strcmp(argv[2], "values") == 0)
+ proto_registrar_dump_values();
+ else if (strcmp(argv[2], "decodes") == 0)
+ dissector_dump_decodes();
+ else if (strcmp(argv[2], "defaultprefs") == 0)
+ write_prefs(NULL);
+ else if (strcmp(argv[2], "currentprefs") == 0) {
+ read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
+ &pf_open_errno, &pf_read_errno, &pf_path);
+ write_prefs(NULL);
+ } else {
+ cmdarg_err("Invalid \"%s\" option for -G flag", argv[2]);
+ exit(1);
+ }
+ }
+ exit(0);
+ }
/* Set the C-language locale to the native environment. */
setlocale(LC_ALL, "");
&pf_open_errno, &pf_read_errno, &pf_path);
if (gpf_path != NULL) {
if (gpf_open_errno != 0) {
- fprintf(stderr, "Can't open global preferences file \"%s\": %s.\n",
+ cmdarg_err("Can't open global preferences file \"%s\": %s.",
pf_path, strerror(gpf_open_errno));
}
if (gpf_read_errno != 0) {
- fprintf(stderr, "I/O error reading global preferences file \"%s\": %s.\n",
+ cmdarg_err("I/O error reading global preferences file \"%s\": %s.",
pf_path, strerror(gpf_read_errno));
}
}
if (pf_path != NULL) {
if (pf_open_errno != 0) {
- fprintf(stderr, "Can't open your preferences file \"%s\": %s.\n", pf_path,
+ cmdarg_err("Can't open your preferences file \"%s\": %s.", pf_path,
strerror(pf_open_errno));
}
if (pf_read_errno != 0) {
- fprintf(stderr, "I/O error reading your preferences file \"%s\": %s.\n",
+ cmdarg_err("I/O error reading your preferences file \"%s\": %s.",
pf_path, strerror(pf_read_errno));
}
g_free(pf_path);
/* Read the disabled protocols file. */
read_disabled_protos_list(&gdp_path, &gdp_open_errno, &gdp_read_errno,
- &dp_path, &dp_open_errno, &dp_read_errno);
+ &dp_path, &dp_open_errno, &dp_read_errno);
if (gdp_path != NULL) {
if (gdp_open_errno != 0) {
- fprintf(stderr,
- "Could not open global disabled protocols file\n\"%s\": %s.\n",
- gdp_path, strerror(gdp_open_errno));
+ cmdarg_err("Could not open global disabled protocols file\n\"%s\": %s.",
+ gdp_path, strerror(gdp_open_errno));
}
if (gdp_read_errno != 0) {
- fprintf(stderr,
- "I/O error reading global disabled protocols file\n\"%s\": %s.\n",
- gdp_path, strerror(gdp_read_errno));
+ cmdarg_err("I/O error reading global disabled protocols file\n\"%s\": %s.",
+ gdp_path, strerror(gdp_read_errno));
}
g_free(gdp_path);
}
if (dp_path != NULL) {
if (dp_open_errno != 0) {
- fprintf(stderr,
- "Could not open your disabled protocols file\n\"%s\": %s.\n", dp_path,
+ cmdarg_err(
+ "Could not open your disabled protocols file\n\"%s\": %s.", dp_path,
strerror(dp_open_errno));
}
if (dp_read_errno != 0) {
- fprintf(stderr,
- "I/O error reading your disabled protocols file\n\"%s\": %s.\n", dp_path,
+ cmdarg_err(
+ "I/O error reading your disabled protocols file\n\"%s\": %s.", dp_path,
strerror(dp_read_errno));
}
g_free(dp_path);
print_format = PR_FMT_TEXT;
/* Now get our args */
- while ((opt = getopt(argc, argv, "a:b:c:d:Df:F:hi:lLnN:o:pqr:R:s:St:T:vw:Vxy:z:")) != -1) {
+ while ((opt = getopt(argc, argv, optstring)) != -1) {
switch (opt) {
case 'a': /* autostop criteria */
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 'w': /* Write to capture file xxx */
case 'y': /* Set the pcap data link type */
+#ifdef _WIN32
+ case 'B': /* Buffer size */
+#endif /* _WIN32 */
#ifdef HAVE_LIBPCAP
- capture_opts_add_opt(&capture_opts, "tethereal", opt, optarg, &start_capture);
+ status = capture_opts_add_opt(&capture_opts, opt, optarg, &start_capture);
+ if(status != 0) {
+ exit(status);
+ }
#else
capture_option_specified = TRUE;
arg_error = TRUE;
case 'd': /* Decode as rule */
if (!add_decode_as(optarg))
exit(1);
- break;
- case 'D': /* Print a list of capture devices */
+ break;
+ 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);
- fprintf(stderr, "tethereal: %s\n", cant_get_if_list_errstr);
- g_free(cant_get_if_list_errstr);
- break;
-
- case NO_INTERFACES_FOUND:
- fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
- 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);
- exit(0);
+ status = capture_opts_list_interfaces();
+ exit(status);
#else
capture_option_specified = TRUE;
arg_error = TRUE;
case 'F':
out_file_type = wtap_short_string_to_file_type(optarg);
if (out_file_type < 0) {
- fprintf(stderr, "tethereal: \"%s\" isn't a valid capture file type\n",
- optarg);
+ cmdarg_err("\"%s\" isn't a valid capture file type", optarg);
+ list_capture_types();
exit(1);
}
break;
case 'h': /* Print help and exit */
- 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) {
- fprintf(stderr,
- "tethereal: The specified adapter index is a negative number\n");
- exit(1);
- }
- if (adapter_index > INT_MAX) {
- fprintf(stderr,
- "tethereal: The specified adapter index is too large (greater than %d)\n",
- INT_MAX);
- exit(1);
- }
- if (adapter_index == 0) {
- fprintf(stderr, "tethereal: there is no interface with that adapter index\n");
- 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);
- fprintf(stderr, "tethereal: %s\n", cant_get_if_list_errstr);
- g_free(cant_get_if_list_errstr);
- break;
-
- case NO_INTERFACES_FOUND:
- fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
- break;
- }
- exit(2);
- }
- if_info = g_list_nth_data(if_list, adapter_index - 1);
- if (if_info == NULL) {
- fprintf(stderr, "tethereal: there is no interface with that adapter index\n");
- 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
+ print_usage(TRUE);
+ exit(0);
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
- each packet is printed; however, that should be good
- enough for all the purposes to which "-l" is put (and
- is probably actually better for "-V", as it does fewer
- writes).
-
- See the comment in "process_packet()" for an explanation of
- why we do that, and why we don't just use "setvbuf()" to
- make the standard output line-buffered (short version: in
- Windows, "line-buffered" is the same as "fully-buffered",
- and the output buffer is only flushed when it fills up). */
- line_buffered = TRUE;
- break;
+ /* This isn't line-buffering, strictly speaking, it's just
+ flushing the standard output after the information for
+ each packet is printed; however, that should be good
+ enough for all the purposes to which "-l" is put (and
+ is probably actually better for "-V", as it does fewer
+ writes).
+
+ See the comment in "process_packet()" for an explanation of
+ why we do that, and why we don't just use "setvbuf()" to
+ make the standard output line-buffered (short version: in
+ Windows, "line-buffered" is the same as "fully-buffered",
+ and the output buffer is only flushed when it fills up). */
+ line_buffered = TRUE;
+ break;
case 'L': /* Print list of link-layer types and exit */
#ifdef HAVE_LIBPCAP
list_link_layer_types = TRUE;
g_resolv_flags = RESOLV_NONE;
badopt = string_to_name_resolve(optarg, &g_resolv_flags);
if (badopt != '\0') {
- fprintf(stderr, "tethereal: -N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'\n",
- badopt);
+ cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
+ badopt);
exit(1);
}
break;
case 'o': /* Override preference from command line */
switch (prefs_set_pref(optarg)) {
- case PREFS_SET_SYNTAX_ERR:
- fprintf(stderr, "tethereal: Invalid -o flag \"%s\"\n", optarg);
+ case PREFS_SET_SYNTAX_ERR:
+ cmdarg_err("Invalid -o flag \"%s\"", optarg);
exit(1);
break;
case PREFS_SET_NO_SUCH_PREF:
case PREFS_SET_OBSOLETE:
- fprintf(stderr, "tethereal: -o flag \"%s\" specifies unknown preference\n",
- optarg);
+ cmdarg_err("-o flag \"%s\" specifies unknown preference", optarg);
exit(1);
break;
}
else if (strcmp(optarg, "d") == 0)
timestamp_set_type(TS_DELTA);
else {
- fprintf(stderr, "tethereal: Invalid time stamp type \"%s\"\n",
+ cmdarg_err("Invalid time stamp type \"%s\"",
optarg);
- fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
- fprintf(stderr, "\"ad\" for absolute with date, or \"d\" for delta.\n");
+ cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
+ cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
exit(1);
}
break;
case 'T': /* printing Type */
if (strcmp(optarg, "text") == 0) {
- output_action = WRITE_TEXT;
- print_format = PR_FMT_TEXT;
- } else if (strcmp(optarg, "ps") == 0) {
- output_action = WRITE_TEXT;
- print_format = PR_FMT_PS;
- } else if (strcmp(optarg, "pdml") == 0) {
- output_action = WRITE_XML;
- verbose = TRUE;
- } else if (strcmp(optarg, "psml") == 0) {
- output_action = WRITE_XML;
- verbose = FALSE;
- } else {
- fprintf(stderr, "tethereal: Invalid -T parameter.\n");
- fprintf(stderr, "It must be \"ps\", \"text\", \"pdml\", or \"psml\".\n");
- exit(1);
- }
- break;
+ output_action = WRITE_TEXT;
+ print_format = PR_FMT_TEXT;
+ } else if (strcmp(optarg, "ps") == 0) {
+ output_action = WRITE_TEXT;
+ print_format = PR_FMT_PS;
+ } else if (strcmp(optarg, "pdml") == 0) {
+ output_action = WRITE_XML;
+ verbose = TRUE;
+ } else if (strcmp(optarg, "psml") == 0) {
+ output_action = WRITE_XML;
+ verbose = FALSE;
+ } else {
+ cmdarg_err("Invalid -T parameter.");
+ cmdarg_err_cont("It must be \"ps\", \"text\", \"pdml\", or \"psml\".");
+ exit(1);
+ }
+ break;
case 'v': /* Show version and exit */
- printf("t" PACKAGE " " VERSION "%s\n%s\n%s\n",
- svnversion, comp_info_str->str, runtime_info_str->str);
+ printf("Tethereal " VERSION "%s\n"
+ "\n"
+ "%s"
+ "\n"
+ "%s"
+ "\n"
+ "%s",
+ svnversion, get_copyright_info(), comp_info_str->str,
+ runtime_info_str->str);
exit(0);
break;
- case 'w': /* Write to capture file xxx */
- save_file = g_strdup(optarg);
- break;
case 'V': /* Verbose */
verbose = TRUE;
break;
case 'x': /* Print packet data in hex (and ASCII) */
- print_hex = TRUE;
- break;
+ print_hex = TRUE;
+ break;
+ case 'X':
+ ex_opt_add(optarg);
+ break;
case 'z':
/* We won't call the init function for the stat this soon
as it would disallow MATE's fields (which are registered
part of a tap filter. Instead, we just add the argument
to a list of stat arguments. */
if (!process_stat_cmd_arg(optarg)) {
- fprintf(stderr,"tethereal: invalid -z argument.\n");
- fprintf(stderr," -z argument must be one of :\n");
- list_stat_cmd_args();
- exit(1);
- }
+ cmdarg_err("invalid -z argument.");
+ cmdarg_err_cont(" -z argument must be one of :");
+ list_stat_cmd_args();
+ exit(1);
+ }
break;
default:
case '?': /* Bad flag - print usage message */
- arg_error = TRUE;
+ switch(optopt) {
+ case'F':
+ list_capture_types();
+ break;
+ default:
+ print_usage(TRUE);
+ }
+ exit(1);
break;
}
}
if (optind < argc) {
if (cf_name != NULL) {
if (rfilter != NULL) {
- fprintf(stderr,
-"tethereal: Read filters were specified both with \"-R\" and with additional command-line arguments\n");
- exit(2);
+ cmdarg_err("Read filters were specified both with \"-R\" "
+ "and with additional command-line arguments");
+ exit(1);
}
rfilter = get_args_as_string(argc, argv, optind);
} else {
#ifdef HAVE_LIBPCAP
if (capture_filter_specified) {
- fprintf(stderr,
-"tethereal: Capture filters were specified both with \"-f\" and with additional command-line arguments\n");
- exit(2);
+ cmdarg_err("Capture filters were specified both with \"-f\""
+ " and with additional command-line arguments");
+ exit(1);
}
capture_opts.cfilter = get_args_as_string(argc, argv, optind);
#else
}
}
- /* See if we're writing a capture file and the file is a pipe */
-#ifdef HAVE_LIBPCAP
- ld.output_to_pipe = FALSE;
-#endif
- if (save_file != NULL) {
- /* We're writing to a capture file. */
- if (strcmp(save_file, "-") == 0) {
- /* Write to the standard output. */
- g_free(save_file);
- save_file = g_strdup("");
-#ifdef HAVE_LIBPCAP
- /* XXX - should we check whether it's a pipe? It's arguably
- silly to do "-w - >output_file" rather than "-w output_file",
- but by not checking we might be violating the Principle Of
- Least Astonishment. */
- ld.output_to_pipe = TRUE;
-#endif
- }
-#ifdef HAVE_LIBPCAP
- else {
- err = test_for_fifo(save_file);
- switch (err) {
-
- case ENOENT: /* it doesn't exist, so we'll be creating it,
- and it won't be a FIFO */
- case 0: /* found it, but it's not a FIFO */
- break;
-
- case ESPIPE: /* it is a FIFO */
- ld.output_to_pipe = TRUE;
- break;
-
- default: /* couldn't stat it */
- fprintf(stderr,
- "tethereal: Error testing whether capture file is a pipe: %s\n",
- strerror(errno));
- exit(2);
- }
- }
-#endif
- } else {
- /* We're not writing to a file, so we should print packet information
- unless "-q" was specified. */
+ if (!capture_opts.saving_to_file) {
+ /* We're not saving the capture to a file; if "-q" wasn't specified,
+ we should print packet information */
if (!quiet)
print_packet_info = TRUE;
+ } else {
+ /* We're saving to a file; if we're writing to the standard output.
+ and we'll also be writing dissected packets to the standard
+ output, reject the request. At best, we could redirect that
+ to the standard error; we *can't* write both to the standard
+ output and have either of them be useful. */
+ if (strcmp(capture_opts.save_file, "-") == 0 && print_packet_info) {
+ cmdarg_err("You can't write both raw packet data and dissected packets"
+ " to the standard output.");
+ exit(1);
+ }
}
#ifndef HAVE_LIBPCAP
if (capture_option_specified)
- fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
+ cmdarg_err("This version of Tethereal was not built with support for capturing packets.");
#endif
if (arg_error) {
print_usage(FALSE);
#ifdef HAVE_LIBPCAP
if (cf_name != NULL) {
if (capture_filter_specified) {
- fprintf(stderr,
-"tethereal: Only read filters, not capture filters, can be specified when reading a capture file.\n");
- exit(2);
+ cmdarg_err("Only read filters, not capture filters, "
+ "can be specified when reading a capture file.");
+ exit(1);
}
}
#endif
if (print_hex) {
if (output_action != WRITE_TEXT) {
- fprintf(stderr, "tethereal: Raw packet hex data can only be printed as text or PostScript\n");
+ cmdarg_err("Raw packet hex data can only be printed as text or PostScript");
exit(1);
}
}
did the user also specify a capture file to be read? */
if (cf_name) {
/* Yes - that's bogus. */
- fprintf(stderr, "tethereal: You can't specify -L and a capture file to be read.\n");
+ cmdarg_err("You can't specify -L and a capture file to be read.");
exit(1);
}
/* No - did they specify a ring buffer option? */
if (capture_opts.multi_files_on) {
- fprintf(stderr, "tethereal: Ring buffer requested, but a capture isn't being done.\n");
+ cmdarg_err("Ring buffer requested, but a capture isn't being done.");
exit(1);
}
} else {
/* If they didn't specify a "-w" flag, but specified a maximum capture
file size, tell them that this doesn't work, and exit. */
- if (capture_opts.has_autostop_filesize && save_file == NULL) {
- fprintf(stderr, "tethereal: Maximum capture file size specified, but "
- "capture isn't being saved to a file.\n");
+ if (capture_opts.has_autostop_filesize && capture_opts.save_file == NULL) {
+ cmdarg_err("Maximum capture file size specified, but "
+ "capture isn't being saved to a file.");
exit(1);
}
- 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;
- b) ring buffer only works if you're saving in libpcap format;
- c) it makes no sense to enable the ring buffer if the maximum
- file size is set to "infinite";
- d) file must not be a pipe. */
- if (save_file == NULL) {
- fprintf(stderr, "tethereal: Ring buffer requested, but "
- "capture isn't being saved to a file.\n");
- exit(1);
+ if (cf_name) {
+ /*
+ * "-r" was specified, so we're reading a capture file.
+ * Capture options don't apply here.
+ */
+ if (capture_opts.multi_files_on) {
+ cmdarg_err("Multiple capture files requested, but "
+ "a capture isn't being done.");
+ exit(1);
+ }
+ if (capture_opts.has_file_duration) {
+ cmdarg_err("Switching capture files after a time interval was specified, but "
+ "a capture isn't being done.");
+ exit(1);
+ }
+ if (capture_opts.has_ring_num_files) {
+ cmdarg_err("A ring buffer of capture files was specified, but "
+ "a capture isn't being done.");
+ exit(1);
+ }
+ if (capture_opts.has_autostop_files) {
+ cmdarg_err("A maximum number of capture files was specified, but "
+ "a capture isn't being done.");
+ exit(1);
+ }
+ if (capture_opts.has_autostop_packets) {
+ cmdarg_err("A maximum number of captured packets was specified, but "
+ "a capture isn't being done.");
+ exit(1);
}
- if (out_file_type != WTAP_FILE_PCAP) {
- fprintf(stderr, "tethereal: Ring buffer requested, but "
- "capture isn't being saved in libpcap format.\n");
- exit(2);
+ if (capture_opts.has_autostop_filesize) {
+ cmdarg_err("A maximum capture file size was specified, but "
+ "a capture isn't being done.");
+ exit(1);
}
- if (!capture_opts.has_autostop_filesize) {
- fprintf(stderr, "tethereal: Ring buffer requested, but "
- "no maximum capture file size was specified.\n");
- exit(2);
+ if (capture_opts.has_autostop_duration) {
+ cmdarg_err("A maximum capture time was specified, but "
+ "a capture isn't being done.");
+ exit(1);
}
- if (ld.output_to_pipe) {
- fprintf(stderr, "tethereal: Ring buffer requested, but "
- "capture file is a pipe.\n");
- exit(2);
+ } else {
+ /*
+ * "-r" wasn't specified, so we're doing a live capture.
+ */
+ if (capture_opts.saving_to_file) {
+ /* They specified a "-w" flag, so we'll be saving to a capture file. */
+
+ /* When capturing, we only support writing libpcap format. */
+ if (out_file_type != WTAP_FILE_PCAP) {
+ cmdarg_err("Live captures can only be saved in libpcap format.");
+ exit(1);
+ }
+ if (capture_opts.multi_files_on) {
+ /* Multiple-file mode works only under certain conditions:
+ a) it doesn't work if you're writing to the standard output;
+ b) it doesn't work if you're writing to a pipe;
+ c) it makes no sense if the maximum file size is set to "infinite"
+ (XXX - shouldn't that be "if there is no stop criterion",
+ as you might want to switch files based on a packet count
+ or a time). */
+ if (strcmp(capture_opts.save_file, "-") == 0) {
+ cmdarg_err("Multiple capture files requested, but "
+ "the capture is being written to the standard output.");
+ exit(1);
+ }
+ if (capture_opts.output_to_pipe) {
+ cmdarg_err("Multiple capture files requested, but "
+ "the capture file is a pipe.");
+ exit(1);
+ }
+ if (!capture_opts.has_autostop_filesize) {
+ cmdarg_err("Multiple capture files requested, but "
+ "no maximum capture file size was specified.");
+ exit(1);
+ }
+ }
+ } else {
+ /* They didn't specify a "-w" flag, so we won't be saving to a
+ capture file. Check for options that only make sense if
+ we're saving to a file. */
+ if (capture_opts.has_autostop_filesize) {
+ cmdarg_err("Maximum capture file size specified, but "
+ "capture isn't being saved to a file.");
+ exit(1);
+ }
+ if (capture_opts.multi_files_on) {
+ cmdarg_err("Multiple capture files requested, but "
+ "the capture isn't being saved to a file.");
+ exit(1);
+ }
}
}
}
#ifdef _WIN32
/* Start windows sockets */
WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
-#endif /* _WIN32 */
+#endif /* _WIN32 */
/* Notify all registered modules that have had any of their preferences
changed either from one of the preferences file or from the command
}
#ifdef HAVE_LIBPCAP
- if (capture_opts.snaplen < 1)
- capture_opts.snaplen = WTAP_MAX_PACKET_SIZE;
- else if (capture_opts.snaplen < MIN_PACKET_SIZE)
- capture_opts.snaplen = MIN_PACKET_SIZE;
-
- /* 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.ring_num_files < RINGBUFFER_MIN_NUM_FILES)
- capture_opts.ring_num_files = RINGBUFFER_MIN_NUM_FILES;
-#endif
+ capture_opts_trim_snaplen(&capture_opts, MIN_PACKET_SIZE);
+ capture_opts_trim_ring_num_files(&capture_opts);
#endif
if (rfilter != NULL) {
if (!dfilter_compile(rfilter, &rfcode)) {
- fprintf(stderr, "tethereal: %s\n", dfilter_error_msg);
+ cmdarg_err("%s", dfilter_error_msg);
epan_cleanup();
#ifdef HAVE_PCAP_OPEN_DEAD
{
pc = pcap_open_dead(DLT_EN10MB, MIN_PACKET_SIZE);
if (pc != NULL) {
if (pcap_compile(pc, &fcode, rfilter, 0, 0) != -1) {
- fprintf(stderr,
- " Note: That display filter code looks like a valid capture filter;\n"
- " maybe you mixed them up?\n");
+ cmdarg_err_cont(
+ " Note: That display filter code looks like a valid capture filter;");
+ cmdarg_err_cont(
+ " maybe you mixed them up?");
}
pcap_close(pc);
}
/* We have to dissect each packet if:
- we're printing information about each packet;
+ we're printing information about each packet;
- we're using a read filter on the packets;
+ we're using a read filter on the packets;
- we're using any taps. */
+ we're using any taps. */
do_dissection = print_packet_info || rfcode || have_tap_listeners();
if (cf_name) {
* We're reading a capture file.
*/
-#ifndef _WIN32
/*
- * Immediately relinquish any set-UID or set-GID privileges we have;
- * we must not be allowed to read any capture files the user running
- * Tethereal can't open.
+ * Immediately relinquish any special privileges we have; we must not
+ * be allowed to read any capture files the user running Tethereal
+ * can't open.
*/
- setuid(getuid());
- setgid(getgid());
-#endif
+ relinquish_special_privs_perm();
if (cf_open(&cfile, cf_name, FALSE, &err) != CF_OK) {
epan_cleanup();
}
/* Process the packets in the file */
- err = load_cap_file(&cfile, save_file, out_file_type);
+ err = load_cap_file(&cfile, capture_opts.save_file, out_file_type);
if (err != 0) {
epan_cleanup();
exit(2);
if (!has_wpcap) {
char *detailed_err;
- fprintf(stderr, "tethereal: WinPcap couldn't be found.\n");
+ cmdarg_err("WinPcap couldn't be found.");
detailed_err = cant_load_winpcap_err("Tethereal");
- fprintf(stderr, "%s\n", detailed_err);
+ cmdarg_err_cont("%s", detailed_err);
g_free(detailed_err);
exit(2);
}
#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);
- fprintf(stderr, "tethereal: %s\n", cant_get_if_list_errstr);
- g_free(cant_get_if_list_errstr);
- break;
-
- case NO_INTERFACES_FOUND:
- fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
- 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') {
- fprintf(stderr, "tethereal: 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.\n", err_str);
- } else
- fprintf(stderr, "tethereal: The capture device has no data link types.\n");
- exit(2);
- }
- fprintf(stderr, "Data link types (use option -y to set):\n");
- for (lt_entry = lt_list; lt_entry != NULL;
- lt_entry = g_list_next(lt_entry)) {
- data_link_info = lt_entry->data;
- fprintf(stderr, " %s", data_link_info->name);
- if (data_link_info->description != NULL)
- fprintf(stderr, " (%s)", data_link_info->description);
- else
- fprintf(stderr, " (not supported)");
- putchar('\n');
- }
- free_pcap_linktype_list(lt_list);
- exit(0);
+ status = capture_opts_list_link_layer_types(&capture_opts);
+ exit(status);
}
- if (!quiet) {
+ if (!print_packet_info && !quiet) {
/*
- * The user didn't ask us not to print a count of packets as
- * they arrive, so do so.
+ * We're not printing information for each packet, and the user
+ * didn't ask us not to print a count of packets as they arrive,
+ * so print that count so the user knows that packets are arriving.
+ *
+ * XXX - what if the user wants to do a live capture, doesn't want
+ * to save it to a file, doesn't want information printed for each
+ * packet, does want some "-z" statistic, and wants packet counts
+ * so they know whether they're seeing any packets?
*/
print_packet_counts = TRUE;
}
/* For now, assume libpcap gives microsecond precision. */
timestamp_set_precision(TS_PREC_AUTO_USEC);
- capture(save_file, out_file_type);
+ capture();
if (capture_opts.multi_files_on) {
ringbuf_free();
}
#else
/* No - complain. */
- fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
+ cmdarg_err("This version of Tethereal was not built with support for capturing packets.");
exit(2);
#endif
}
draw_tap_listeners(TRUE);
+ funnel_dump_all_text_windows();
epan_cleanup();
return 0;
/* 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)
+capture(void)
{
- 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;
- dfilter_t *rfcode = NULL;
+ gboolean write_ok;
+ gboolean close_ok;
+ gboolean cfilter_error = FALSE;
+ char errmsg[1024+1];
+ char secondary_errmsg[4096+1];
int save_file_fd;
/* Initialize all data structures used for dissection. */
init_dissection();
- ld.linktype = WTAP_ENCAP_UNKNOWN;
+ ld.wtap_linktype = WTAP_ENCAP_UNKNOWN;
ld.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) {
- /* 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 (%s).\n"
-"Please check that you have the proper interface specified.\n"
-"\n"
-"Help can be found at: http://wiki.ethereal.com/CaptureSetup\n"
-"\n"
-"WinPcap does not support 64-bit Windows, so you will not be able to capture\n"
-"traffic with Tethereal on 64-bit Windows. You will have to use some other\n"
-"tool to capture traffic, such as netcap; see\n"
-"\n"
-" http://support.microsoft.com/?id=310875\n"
-"\n"
-"for information about netcap.\n"
-"\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).\n",
- open_err_str);
+
+ /* open the "input file" from network interface or capture pipe */
+ if (!capture_loop_open_input(&capture_opts, &ld, errmsg, sizeof(errmsg),
+ secondary_errmsg, sizeof(secondary_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
/*
- * We've opened the capture device, so, if we're set-UID or set-GID,
- * relinquish those privileges.
+ * We've opened the capture device, so we shouldn't need any special
+ * privileges any more; relinquish those privileges.
*
* XXX - if we have saved set-user-ID support, we should give up those
* privileges immediately, and then reclaim them long enough to get
* a list of network interfaces and to open one, and then give them
* up again, so that stuff we do while processing the argument list,
- * reading the user's preferences, etc. is done as the real user and
- * group, not the effective user and group.
+ * reading the user's preferences, loading and starting plugins
+ * (especially *user* plugins), etc. is done with the user's privileges,
+ * not special privileges.
*/
- setuid(getuid());
- setgid(getgid());
-#endif
+ relinquish_special_privs_perm();
- 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.
- */
- fprintf(stderr,
- "Warning: Couldn't obtain netmask info (%s).\n", 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
- }
+ /* init the input filter from the network interface (capture pipe will do nothing) */
+ switch (capture_loop_init_filter(ld.pcap_h, ld.from_cap_pipe, capture_opts.iface, capture_opts.cfilter)) {
- /* Set up to write to the capture file. */
-#ifndef _WIN32
- if (ld.from_pipe) {
- pcap_encap = hdr.network;
- file_snaplen = hdr.snaplen;
- } else
-#endif
- {
- pcap_encap = get_pcap_linktype(ld.pch, capture_opts.iface);
- file_snaplen = pcap_snapshot(ld.pch);
+ case INITFILTER_NO_ERROR:
+ break;
+
+ case INITFILTER_BAD_FILTER:
+ cfilter_error = TRUE;
+ g_snprintf(errmsg, sizeof(errmsg), "%s", pcap_geterr(ld.pcap_h));
+ *secondary_errmsg = '\0';
+ goto error;
+
+ case INITFILTER_OTHER_ERROR:
+ g_snprintf(errmsg, sizeof(errmsg), "Can't install filter (%s).",
+ pcap_geterr(ld.pcap_h));
+ g_snprintf(secondary_errmsg, sizeof(secondary_errmsg), "%s", please_report);
+ goto error;
}
- 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 (capture_opts.saving_to_file) {
+ /* open the output file (temporary/specified name/ringbuffer/named pipe/stdout) */
+ if (!capture_loop_open_output(&capture_opts, &save_file_fd, errmsg, sizeof(errmsg))) {
+ *secondary_errmsg = '\0';
+ goto error;
}
- 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);
+ /* set up to write to the already-opened capture output file/files */
+ if(!capture_loop_init_output(&capture_opts, save_file_fd, &ld, errmsg, sizeof errmsg)) {
+ *secondary_errmsg = '\0';
goto error;
}
+
+ /* Save the capture file name. */
+ ld.save_file = capture_opts.save_file;
}
- /* 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')
- fprintf(stderr, "tethereal: WARNING: %s.\n", open_err_str);
+ ld.wtap_linktype = wtap_pcap_encap_to_wtap_encap(ld.linktype);
#ifdef _WIN32
/* Catch a CTRL+C event and, if we get it, clean up and exit. */
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,
- capture_opts.file_duration);
+ cnd_file_duration = cnd_new(CND_CLASS_TIMEOUT, capture_opts.file_duration);
if (!setjmp(ld.stopenv)) {
ld.go = TRUE;
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
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
pcap_cnt = 1;
}
#ifndef _WIN32
- if (ld.from_pipe) {
- inpkts = pipe_dispatch(pipe_fd, &ld, &hdr, &rechdr, pcap_data,
- errmsg, sizeof errmsg);
+ if (ld.from_cap_pipe) {
+ inpkts = cap_pipe_dispatch(&ld, 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, ld.packet_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) {
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)ld.bytes_written)) {
/* 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.pdh, &capture_opts.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 */
volatile_err = loop_err;
ld.go = FALSE;
}
}
- if (ld.output_to_pipe) {
+ if (capture_opts.output_to_pipe) {
if (ld.packet_count > packet_count_prev) {
- wtap_dump_flush(ld.pdh);
+ libpcap_dump_flush(ld.pdh, NULL);
packet_count_prev = ld.packet_count;
}
}
} /* 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.
/* If we got an error while capturing, report it. */
if (inpkts < 0) {
#ifndef _WIN32
- if (ld.from_pipe) {
- if (ld.pipe_err == PIPERR) {
- fprintf(stderr, "tethereal: Error while capturing packets: %s\n",
- errmsg);
+ if (ld.from_cap_pipe) {
+ if (ld.cap_pipe_err == PIPERR) {
+ cmdarg_err("Error while capturing packets: %s", errmsg);
}
} else
#endif
{
- fprintf(stderr, "tethereal: Error while capturing packets: %s\n",
- pcap_geterr(ld.pch));
+ cmdarg_err("Error while capturing packets: %s", 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;
+ show_capture_file_io_error(capture_opts.save_file, volatile_err, FALSE);
+ write_ok = FALSE;
}
- if (save_file != NULL) {
+ if (capture_opts.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)
- show_capture_file_io_error(save_file, err, TRUE);
+ if (!close_ok && write_ok)
+ show_capture_file_io_error(capture_opts.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 {
- fprintf(stderr, "tethereal: Can't get packet-drop statistics: %s\n",
- pcap_geterr(ld.pch));
+ cmdarg_err("Can't get packet-drop statistics: %s", 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
if (capture_opts.multi_files_on) {
ringbuf_error_cleanup();
}
- g_free(save_file);
- save_file = NULL;
- fprintf(stderr, "tethereal: %s\n", errmsg);
+ g_free(capture_opts.save_file);
+ capture_opts.save_file = NULL;
+ if (cfilter_error) {
+ dfilter_t *rfcode = NULL;
+ if (dfilter_compile(capture_opts.cfilter, &rfcode) && rfcode != NULL) {
+ cmdarg_err(
+ "Invalid capture filter: \"%s\"!\n"
+ "\n"
+ "That string looks like a valid display filter; however, it isn't a valid\n"
+ "capture filter (%s).\n"
+ "\n"
+ "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 User's Guide for a description of the capture filter syntax.",
+ capture_opts.cfilter, errmsg);
+ dfilter_free(rfcode);
+ } else {
+ cmdarg_err(
+ "Invalid capture filter: \"%s\"!\n"
+ "\n"
+ "That string isn't a valid capture filter (%s).\n"
+ "See the User's Guide for a description of the capture filter syntax.",
+ capture_opts.cfilter, errmsg);
+ }
+ } else {
+ cmdarg_err("%s", errmsg);
+ if (*secondary_errmsg != '\0') {
+ fprintf(stderr, "\n");
+ cmdarg_err_cont("%s", secondary_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;
{
struct wtap_pkthdr whdr;
union wtap_pseudo_header pseudo_header;
- loop_data *ldat = (loop_data *) user;
+ const guchar *wtap_pd;
+ loop_data *ld = (loop_data *) user;
int loop_err;
int err;
int save_file_fd;
-
- /* 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,
- &whdr, &err);
- if (pd == NULL)
- return;
+ gboolean packet_accepted;
#ifdef SIGINFO
/*
* 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->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)) {
- /* Error writing to a capture file */
+ if (do_dissection) {
+ /* We're goint to print packet information, run a read filter, or
+ process taps. Use process_packet() to handle that; in order
+ to do that, we need to convert from libpcap to Wiretap format.
+ If that fails, ignore the packet (wtap_process_pcap_packet has
+ written an error message). */
+ wtap_pd = wtap_process_pcap_packet(ld->wtap_linktype, phdr, pd,
+ &pseudo_header, &whdr, &err);
+ if (wtap_pd == NULL)
+ return;
+
+ packet_accepted = process_packet(&cfile, 0, &whdr, &pseudo_header, wtap_pd);
+ } else {
+ /* We're just writing out packets. */
+ packet_accepted = TRUE;
+ }
+
+ if (packet_accepted) {
+ /* Count this packet. */
+#ifdef HAVE_LIBPCAP
+ ld->packet_count++;
+#endif
+
+ if (ld->pdh != NULL) {
+ if (!libpcap_write_packet(ld->pdh, phdr, pd, &ld->bytes_written, &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(ld->save_file, err, FALSE);
+ pcap_close(ld->pcap_h);
+ libpcap_dump_close(ld->pdh, &err);
+ exit(2);
+ }
+ }
if (print_packet_counts) {
- /* We're printing counts of packets captured; move to the line after
- the count. */
- fprintf(stderr, "\n");
+ /* We're printing packet counts. */
+ if (ld->packet_count != 0) {
+ fprintf(stderr, "\r%u ", ld->packet_count);
+ /* stderr could be line buffered */
+ fflush(stderr);
+ }
}
- show_capture_file_io_error(ldat->save_file, err, FALSE);
- pcap_close(ldat->pch);
- wtap_dump_close(ldat->pdh, &err);
- exit(2);
}
#ifdef SIGINFO
fprintf(stderr, "%u packets captured\n", ld.packet_count);
}
#ifdef SIGINFO
- infoprint = FALSE; /* we just reported it */
+ infoprint = FALSE; /* we just reported it */
#endif /* SIGINFO */
}
int err;
gchar *err_info;
long data_offset;
+ char *save_file_string = NULL;
linktype = wtap_file_encap(cf->wth);
if (save_file != NULL) {
+ /* Get a string that describes what we're writing to */
+ save_file_string = output_file_description(save_file);
+
/* Set up to write to the capture file. */
snapshot_length = wtap_snapshot_length(cf->wth);
if (snapshot_length == 0) {
/* Snapshot length of input file not known. */
snapshot_length = WTAP_MAX_PACKET_SIZE;
}
- pdh = wtap_dump_open(save_file, out_file_type,
- linktype, snapshot_length, FALSE /* compressed */, &err);
+ pdh = wtap_dump_open(save_file, out_file_type, linktype, snapshot_length,
+ FALSE /* compressed */, &err);
if (pdh == NULL) {
/* We couldn't set up to write to the capture file. */
switch (err) {
case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
- fprintf(stderr,
- "tethereal: Capture files can't be written in that format.\n");
+ cmdarg_err("Capture files can't be written in that format.");
break;
case WTAP_ERR_UNSUPPORTED_ENCAP:
case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
- fprintf(stderr,
- "tethereal: The capture file being read can't be written in "
- "that format.\n");
+ cmdarg_err("The capture file being read can't be written in "
+ "that format.");
break;
case WTAP_ERR_CANT_OPEN:
- fprintf(stderr,
- "tethereal: The file \"%s\" couldn't be created for some "
- "unknown reason.\n",
- *save_file == '\0' ? "stdout" : save_file);
+ cmdarg_err("The %s couldn't be created for some "
+ "unknown reason.", save_file_string);
break;
case WTAP_ERR_SHORT_WRITE:
- fprintf(stderr,
- "tethereal: A full header couldn't be written to the file \"%s\".\n",
- *save_file == '\0' ? "stdout" : save_file);
+ cmdarg_err("A full header couldn't be written to the %s.",
+ save_file_string);
break;
default:
- fprintf(stderr,
- "tethereal: The file \"%s\" could not be created: %s\n.",
- *save_file == '\0' ? "stdout" : save_file,
- wtap_strerror(err));
+ cmdarg_err("The %s could not be created: %s.", save_file_string,
+ wtap_strerror(err));
break;
}
goto out;
pdh = NULL;
}
while (wtap_read(cf->wth, &err, &err_info, &data_offset)) {
- if (!process_packet(cf, pdh, data_offset, wtap_phdr(cf->wth),
- wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth),
- &err)) {
- /* Error writing to a capture file */
- show_capture_file_io_error(save_file, err, FALSE);
- wtap_dump_close(pdh, &err);
- exit(2);
+ if (process_packet(cf, data_offset, wtap_phdr(cf->wth),
+ wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth))) {
+ /* Either there's no read filtering or this packet passed the
+ filter, so, if we're writing to a capture file, write
+ this packet out. */
+ if (pdh != NULL) {
+ if (!wtap_dump(pdh, wtap_phdr(cf->wth),
+ wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth),
+ &err)) {
+ /* Error writing to a capture file */
+ show_capture_file_io_error(save_file, err, FALSE);
+ wtap_dump_close(pdh, &err);
+ exit(2);
+ }
+ }
}
}
if (err != 0) {
switch (err) {
case WTAP_ERR_UNSUPPORTED_ENCAP:
- fprintf(stderr,
-"tethereal: \"%s\" has a packet with a network type that Tethereal doesn't support.\n(%s)\n",
- cf->filename, err_info);
+ cmdarg_err("\"%s\" has a packet with a network type that Tethereal doesn't support.\n(%s)",
+ cf->filename, err_info);
break;
case WTAP_ERR_CANT_READ:
- fprintf(stderr,
-"tethereal: An attempt to read from \"%s\" failed for some unknown reason.\n",
- cf->filename);
+ cmdarg_err("An attempt to read from \"%s\" failed for some unknown reason.",
+ cf->filename);
break;
case WTAP_ERR_SHORT_READ:
- fprintf(stderr,
-"tethereal: \"%s\" appears to have been cut short in the middle of a packet.\n",
- cf->filename);
+ cmdarg_err("\"%s\" appears to have been cut short in the middle of a packet.",
+ cf->filename);
break;
case WTAP_ERR_BAD_RECORD:
- fprintf(stderr,
-"tethereal: \"%s\" appears to be damaged or corrupt.\n(%s)\n",
- cf->filename, err_info);
+ cmdarg_err("\"%s\" appears to be damaged or corrupt.\n(%s)",
+ cf->filename, err_info);
break;
default:
- fprintf(stderr,
-"tethereal: An error occurred while reading \"%s\": %s.\n",
- cf->filename, wtap_strerror(err));
+ cmdarg_err("An error occurred while reading \"%s\": %s.",
+ cf->filename, wtap_strerror(err));
break;
}
if (save_file != NULL) {
wtap_close(cf->wth);
cf->wth = NULL;
+ if (save_file_string != NULL)
+ g_free(save_file_string);
+
return err;
}
static void
fill_in_fdata(frame_data *fdata, capture_file *cf,
- const struct wtap_pkthdr *phdr, long offset)
+ const struct wtap_pkthdr *phdr, long offset)
{
fdata->next = NULL;
fdata->prev = NULL;
fdata->flags.visited = 0;
fdata->flags.marked = 0;
fdata->flags.ref_time = 0;
+ fdata->color_filter = NULL;
/* If we don't have the time stamp of the first packet in the
capture, it's because this is the first packet. Save the time
}
static gboolean
-process_packet(capture_file *cf, wtap_dumper *pdh, long offset,
- const struct wtap_pkthdr *whdr,
- union wtap_pseudo_header *pseudo_header, const guchar *pd,
- int *err)
+process_packet(capture_file *cf, long offset, const struct wtap_pkthdr *whdr,
+ union wtap_pseudo_header *pseudo_header, const guchar *pd)
{
frame_data fdata;
gboolean create_proto_tree;
}
if (passed) {
- /* Count this packet. */
-#ifdef HAVE_LIBPCAP
- ld.packet_count++;
-#endif
-
/* Process this packet. */
- if (pdh != NULL) {
- /* We're writing to a capture file; write this packet. */
- if (!wtap_dump(pdh, whdr, pseudo_header, pd, err))
- return FALSE;
-#ifdef HAVE_LIBPCAP
- 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 */
- fflush(stderr);
- }
- }
-#endif
- }
if (print_packet_info) {
/* We're printing packet information; print the information for
this packet. */
epan_dissect_free(edt);
clear_fdata(&fdata);
}
- return TRUE;
+ return passed;
}
static void
show_capture_file_io_error(const char *fname, int err, gboolean is_close)
{
- if (*fname == '\0')
- fname = "stdout";
+ char *save_file_string;
+
+ save_file_string = output_file_description(fname);
switch (err) {
case ENOSPC:
- fprintf(stderr,
-"tethereal: Not all the packets could be written to \"%s\" because there is "
-"no space left on the file system.\n",
- fname);
+ cmdarg_err("Not all the packets could be written to the %s because there is "
+ "no space left on the file system.",
+ save_file_string);
break;
#ifdef EDQUOT
case EDQUOT:
- fprintf(stderr,
-"tethereal: Not all the packets could be written to \"%s\" because you are "
-"too close to, or over your disk quota.\n",
- fname);
+ cmdarg_err("Not all the packets could be written to the %s because you are "
+ "too close to, or over your disk quota.",
+ save_file_string);
break;
#endif
case WTAP_ERR_CANT_CLOSE:
- fprintf(stderr,
-"tethereal: \"%s\" couldn't be closed for some unknown reason.\n",
- fname);
+ cmdarg_err("The %s couldn't be closed for some unknown reason.",
+ save_file_string);
break;
case WTAP_ERR_SHORT_WRITE:
- fprintf(stderr,
-"tethereal: Not all the packets could be written to \"%s\".\n",
- fname);
+ cmdarg_err("Not all the packets could be written to the %s.",
+ save_file_string);
break;
default:
if (is_close) {
- fprintf(stderr,
-"tethereal: \"%s\" could not be closed: %s.\n",
- fname, wtap_strerror(err));
+ cmdarg_err("The %s could not be closed: %s.", save_file_string,
+ wtap_strerror(err));
} else {
- fprintf(stderr,
-"tethereal: An error occurred while writing to \"%s\": %s.\n",
- fname, wtap_strerror(err));
+ cmdarg_err("An error occurred while writing to the %s: %s.",
+ save_file_string, wtap_strerror(err));
}
break;
}
+ g_free(save_file_string);
}
static gboolean
case COL_CLS_TIME:
case COL_REL_TIME:
case COL_ABS_TIME:
- case COL_ABS_DATE_TIME: /* XXX - wider */
+ case COL_ABS_DATE_TIME: /* XXX - wider */
column_len = strlen(cf->cinfo.col_data[i]);
if (column_len < 10)
column_len = 10;
switch (err) {
case ENOSPC:
- fprintf(stderr,
-"tethereal: Not all the packets could be printed because there is "
-"no space left on the file system.\n");
+ cmdarg_err("Not all the packets could be printed because there is "
+"no space left on the file system.");
break;
#ifdef EDQUOT
case EDQUOT:
- fprintf(stderr,
-"tethereal: Not all the packets could be printed because you are "
-"too close to, or over your disk quota.\n");
+ cmdarg_err("Not all the packets could be printed because you are "
+"too close to, or over your disk quota.");
break;
#endif
default:
- fprintf(stderr,
-"tethereal: An error occurred while printing packets: %s.\n",
+ cmdarg_err("An error occurred while printing packets: %s.",
strerror(err));
break;
}
case WTAP_ERR_CANT_WRITE_TO_PIPE:
/* Seen only when opening a capture file for writing. */
g_snprintf(errmsg_errno, sizeof(errmsg_errno),
- "The file \"%%s\" is a pipe, and %s capture files can't be "
- "written to a pipe.", wtap_file_type_string(file_type));
+ "The file \"%%s\" is a pipe, and %s capture files can't be "
+ "written to a pipe.", wtap_file_type_string(file_type));
errmsg = errmsg_errno;
break;
default:
g_snprintf(errmsg_errno, sizeof(errmsg_errno),
- "The file \"%%s\" could not be %s: %s.",
- for_writing ? "created" : "opened",
- wtap_strerror(err));
+ "The file \"%%s\" could not be %s: %s.",
+ for_writing ? "created" : "opened",
+ wtap_strerror(err));
errmsg = errmsg_errno;
break;
}
init_dissection();
cf->wth = wth;
- cf->f_datalen = 0; /* not used, but set it anyway */
+ cf->f_datalen = 0; /* not used, but set it anyway */
/* Set the file name because we need it to set the follow stream filter.
XXX - is that still true? We need it for other reasons, though,
fail:
g_snprintf(err_msg, sizeof err_msg,
- cf_open_error_message(*err, err_info, FALSE, 0), fname);
- fprintf(stderr, "tethereal: %s\n", err_msg);
+ cf_open_error_message(*err, err_info, FALSE, cf->cd_t), fname);
+ cmdarg_err("%s", err_msg);
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) */
+
+/*
+ * General errors are reported with an console message in Tethereal.
+ */
static void
-adjust_header(loop_data *ldat, struct pcap_hdr *hdr, struct pcaprec_hdr *rechdr)
+failure_message(const char *msg_format, va_list ap)
{
- 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;
- }
+ fprintf(stderr, "tethereal: ");
+ vfprintf(stderr, msg_format, ap);
+ fprintf(stderr, "\n");
}
-/* 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)
+/*
+ * Read errors are reported with an console message in Tethereal.
+ */
+static void
+read_failure_message(const char *filename, int err)
{
- struct stat pipe_stat;
- int fd;
- guint32 magic;
- int b;
- unsigned int bytes_read;
+ cmdarg_err("An error occurred while reading from the file \"%s\": %s.",
+ filename, strerror(err));
+}
- /*
- * 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;
- }
- }
+/*
+ * Report an error in command-line arguments.
+ */
+void
+cmdarg_err(const char *fmt, ...)
+{
+ va_list ap;
- ldat->from_pipe = TRUE;
+ va_start(ap, fmt);
+ fprintf(stderr, "tethereal: ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+}
- /* 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;
- }
+/*
+ * Report additional information for an error in command-line arguments.
+ */
+void
+cmdarg_err_cont(const char *fmt, ...)
+{
+ va_list ap;
- 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;
- }
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+}
- /* 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);
- }
+/****************************************************************************************************************/
+/* indication report "dummies", needed for capture_loop.c */
- if (hdr->version_major < 2) {
- g_snprintf(errmsg, errmsgl, "Unable to read old libpcap format");
- goto error;
- }
+#ifdef HAVE_LIBPCAP
- ldat->pipe_state = STATE_EXPECT_REC_HDR;
- ldat->pipe_err = PIPOK;
- return fd;
+/** Report a new capture file having been opened. */
+void
+report_new_capture_file(const char *filename)
+{
+ /* shouldn't happen */
+ g_assert_not_reached();
+}
-error:
- ldat->pipe_err = PIPERR;
- eth_close(fd);
- return -1;
+/** Report a number of new packets captured. */
+void
+report_packet_count(int packet_count)
+{
+ /* shouldn't happen */
+ g_assert_not_reached();
+}
+/** Report the packet drops once the capture finishes. */
+void
+report_packet_drops(int drops)
+{
+ /* shouldn't happen */
+ g_assert_not_reached();
}
-/* 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)
+/** Report an error in the capture. */
+void
+report_capture_error(const char *errmsg, const char *secondary_error_msg)
{
- 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;
+ cmdarg_err(errmsg);
+ cmdarg_err_cont(secondary_error_msg);
+}
- case STATE_EXPECT_DATA:
- ldat->bytes_read = 0;
- ldat->pipe_state = STATE_READ_DATA;
- /* Fall through */
+/** Report an error with a capture filter. */
+void
+report_cfilter_error(const char *cfilter, const char *errmsg)
+{
- 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;
+ cmdarg_err(
+ "Invalid capture filter: \"%s\"!\n"
+ "\n"
+ "That string isn't a valid capture filter (%s).\n"
+ "See the User's Guide for a description of the capture filter syntax.",
+ cfilter, errmsg);
+}
- default:
- g_snprintf(errmsg, errmsgl, "pipe_dispatch: invalid state");
- result = PD_ERR;
+#endif /* HAVE_LIBPCAP */
- } /* 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;
- }
+/****************************************************************************************************************/
+/* signal pipe "dummies", needed for capture_loop.c */
- ldat->pipe_err = PIPERR;
- /* Return here rather than inside the switch to prevent GCC warning */
- return -1;
-}
-#endif /* _WIN32 */
-#endif /* HAVE_LIBPCAP */
+#ifdef HAVE_LIBPCAP
-/*
- * General errors are reported with an console message in Tethereal.
- */
-static void
-failure_message(const char *msg_format, va_list ap)
+#ifdef _WIN32
+gboolean
+signal_pipe_check_running(void)
{
- fprintf(stderr, "tethereal: ");
- vfprintf(stderr, msg_format, ap);
- fprintf(stderr, "\n");
+ /* currently, no check required */
+ return TRUE;
}
+#endif /* _WIN32 */
-/*
- * Read errors are reported with an console message in Tethereal.
- */
-static void
-read_failure_message(const char *filename, int err)
-{
- fprintf(stderr, "tethereal: An error occurred while reading from the file \"%s\": %s.\n",
- filename, strerror(err));
-}
+#endif /* HAVE_LIBPCAP */