capture_opts_init(capture_options *capture_opts, void *cfile)
{
capture_opts->cf = cfile;
+ capture_opts->cfilter = g_strdup("");
+ capture_opts->iface = NULL;
#ifdef _WIN32
capture_opts->buffer_size = 1; /* 1 MB */
#endif
capture_opts->autostop_filesize = 1024 * 1024; /* 1 MB */
capture_opts->has_autostop_duration = FALSE;
capture_opts->autostop_duration = 60; /* 1 min */
+
+}
+
+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, "ethereal: The specified %s \"%s\" isn't a decimal number\n",
+ name, string);
+ exit(1);
+ }
+ if (number < 0) {
+ fprintf(stderr, "ethereal: The specified %s \"%s\" is a negative number\n",
+ name, string);
+ exit(1);
+ }
+ if (number > INT_MAX) {
+ fprintf(stderr, "ethereal: The specified %s \"%s\" is too large (greater than %d)\n",
+ name, string, 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, "ethereal: 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(capture_options *capture_opts, const char *autostoparg)
+{
+ gchar *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((guchar)*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(capture_options *capture_opts, const char *arg)
+{
+ gchar *p = NULL, *colonp;
+
+ colonp = strchr(arg, ':');
+
+ if (colonp != NULL) {
+ p = colonp;
+ *p++ = '\0';
+ }
+
+ capture_opts->ring_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((guchar)*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_file_duration = TRUE;
+ capture_opts->file_duration = get_positive_int(p,
+ "ring buffer duration");
+
+ *colonp = ':'; /* put the colon back */
+ return TRUE;
+}
+
+
+void
+capture_opt_add(capture_options *capture_opts, int opt, const char *optarg, gboolean *start_capture)
+{
+ int i;
+
+
+ switch(opt) {
+ case 'a': /* autostop criteria */
+ if (set_autostop_criterion(capture_opts, optarg) == FALSE) {
+ fprintf(stderr, "ethereal: Invalid or unknown -a flag \"%s\"\n", optarg);
+ exit(1);
+ }
+ break;
+ case 'b': /* Ringbuffer option */
+ capture_opts->multi_files_on = TRUE;
+ capture_opts->has_ring_num_files = TRUE;
+ if (get_ring_arguments(capture_opts, optarg) == FALSE) {
+ fprintf(stderr, "ethereal: Invalid or unknown -b arg \"%s\"\n", optarg);
+ exit(1);
+ }
+ break;
+ case 'c': /* Capture xxx packets */
+ capture_opts->has_autostop_packets = TRUE;
+ capture_opts->autostop_packets = get_positive_int(optarg, "packet count");
+ break;
+ case 'f': /* capture filter */
+ if (capture_opts->cfilter)
+ g_free(capture_opts->cfilter);
+ capture_opts->cfilter = g_strdup(optarg);
+ break;
+ case 'H': /* Hide capture info dialog box */
+ capture_opts->show_info = FALSE;
+ break;
+ case 'i': /* Use interface xxx */
+ capture_opts->iface = g_strdup(optarg);
+ break;
+ case 'k': /* Start capture immediately */
+ *start_capture = TRUE;
+ break;
+ /*case 'l':*/ /* Automatic scrolling in live capture mode */
+ case 'p': /* Don't capture in promiscuous mode */
+ capture_opts->promisc_mode = FALSE;
+ break;
+ case 'Q': /* Quit after capture (just capture to file) */
+ capture_opts->quit_after_cap = TRUE;
+ *start_capture = TRUE; /*** -Q implies -k !! ***/
+ break;
+ case 's': /* Set the snapshot (capture) length */
+ capture_opts->has_snaplen = TRUE;
+ capture_opts->snaplen = get_positive_int(optarg, "snapshot length");
+ break;
+ case 'S': /* "Sync" mode: used for following file ala tail -f */
+ capture_opts->sync_mode = TRUE;
+ break;
+ case 'w': /* Write to capture file xxx */
+ capture_opts->save_file = g_strdup(optarg);
+ break;
+ case 'W': /* Write to capture file FD xxx */
+ capture_opts->save_file_fd = atoi(optarg);
+ break;
+ case 'y': /* Set the pcap data link type */
+#ifdef HAVE_PCAP_DATALINK_NAME_TO_VAL
+ capture_opts->linktype = pcap_datalink_name_to_val(optarg);
+ if (capture_opts->linktype == -1) {
+ fprintf(stderr, "ethereal: 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 */
+ break;
+#ifdef _WIN32
+ /* Hidden option supporting Sync mode */
+ case 'Z': /* Write to pipe FD XXX */
+ /* associate stdout with pipe */
+ i = atoi(optarg);
+ if (dup2(i, 1) < 0) {
+ fprintf(stderr, "Unable to dup pipe handle\n");
+ exit(1);
+ }
+ break;
+#endif /* _WIN32 */
+ default:
+ /* the caller is responsible to send us only the right opt's */
+ g_assert_not_reached();
+ }
+}
+
/* open the output file (temporary/specified name/ringbuffer) and close the old one */
/* Returns TRUE if the file opened successfully, FALSE otherwise. */
static gboolean
-capture_open_output(capture_options *capture_opts, const char *save_file, gboolean *is_tempfile) {
+capture_open_output(capture_options *capture_opts, gboolean *is_tempfile) {
char tmpname[128+1];
gchar *capfile_name;
- if (save_file != NULL) {
+ if (capture_opts->save_file != NULL) {
/* If the Sync option is set, we return to the caller while the capture
* is in progress. Therefore we need to take a copy of save_file in
* case the caller destroys it after we return.
*/
- capfile_name = g_strdup(save_file);
+ capfile_name = g_strdup(capture_opts->save_file);
if (capture_opts->multi_files_on) {
/* ringbuffer is enabled */
capture_opts->save_file_fd = ringbuf_init(capfile_name,
to the file in question. */
/* Returns TRUE if the capture starts successfully, FALSE otherwise. */
gboolean
-do_capture(capture_options *capture_opts, const char *save_file)
+do_capture(capture_options *capture_opts)
{
gboolean is_tempfile;
gboolean ret;
gchar *title;
/* open the output file (temporary/specified name/ringbuffer) and close the old one */
- if(!capture_open_output(capture_opts, save_file, &is_tempfile)) {
+ if(!capture_open_output(capture_opts, &is_tempfile)) {
return FALSE;
}
title = g_strdup_printf("%s: Capturing - Ethereal",
- get_interface_descriptive_name(cf_get_iface(capture_opts->cf)));
+ get_interface_descriptive_name(capture_opts->iface));
if (capture_opts->sync_mode) {
/* sync mode: do the capture in a child process */
ret = sync_pipe_do_capture(capture_opts, is_tempfile);
typedef struct capture_options_tag {
/* general */
void *cf; /**< handle to cfile (note: untyped handle) */
+ gchar *cfilter; /**< Capture filter string */
+ gchar *iface; /**< the network interface to capture from */
+
#ifdef _WIN32
int buffer_size; /**< the capture buffer size (MB) */
#endif
int linktype; /**< Data link type to use, or -1 for
"use default" */
gboolean capture_child; /**< True if this is the child for "-S" */
- gchar *save_file; /**< File the capture was saved in */
+ gchar *save_file; /**< the capture file name */
int save_file_fd; /**< File descriptor for saved file */
/* GUI related */
extern void
capture_opts_init(capture_options *capture_opts, void *cfile);
+extern void
+capture_opt_add(capture_options *capture_opts, int opt, const char *optarg, gboolean *start_capture);
+
/**
* Open a specified file, or create a temporary file, and start a capture
* to the file in question.
*
* @param capture_opts the numerous capture options
- * @param save_file the name of the capture file, or NULL for a temporary file
* @return TRUE if the capture starts successfully, FALSE otherwise.
*/
-extern gboolean do_capture(capture_options *capture_opts, const char *save_file);
+extern gboolean do_capture(capture_options *capture_opts);
/** Do the low-level work of a capture (start the capture child). */
extern int capture_start(capture_options *capture_opts, gboolean *stats_known, struct pcap_stat *stats);
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->pcap_h = pcap_open_live(cf_get_iface(capture_opts->cf),
+ ld->pcap_h = pcap_open_live(capture_opts->iface,
capture_opts->has_snaplen ? capture_opts->snaplen :
WTAP_MAX_PACKET_SIZE,
capture_opts->promisc_mode, CAP_READ_TIMEOUT,
/* setting the data link type only works on real interfaces */
if (capture_opts->linktype != -1) {
- set_linktype_err_str = set_pcap_linktype(ld->pcap_h, cf_get_iface(capture_opts->cf),
+ set_linktype_err_str = set_pcap_linktype(ld->pcap_h, capture_opts->iface,
capture_opts->linktype);
if (set_linktype_err_str != NULL) {
g_snprintf(errmsg, errmsg_len, "Unable to set data link type (%s).",
} else
#endif
{
- pcap_encap = get_pcap_linktype(ld->pcap_h, cf_get_iface(capture_opts->cf));
+ pcap_encap = get_pcap_linktype(ld->pcap_h, capture_opts->iface);
file_snaplen = pcap_snapshot(ld->pcap_h);
}
}
/* init the input filter from the network interface (capture pipe will do nothing) */
- if (!capture_loop_init_filter(&ld, cf_get_iface(capture_opts->cf), cf_get_cfilter(capture_opts->cf), errmsg, sizeof(errmsg))) {
+ if (!capture_loop_init_filter(&ld, capture_opts->iface, capture_opts->cfilter, errmsg, sizeof(errmsg))) {
goto error;
}
if(show_info) {
capture_ui.callback_data = &ld;
capture_ui.counts = &ld.counts;
- capture_info_create(&capture_ui, cf_get_iface(capture_opts->cf));
+ capture_info_create(&capture_ui, capture_opts->iface);
}
/* init the time values */
argv = sync_pipe_add_arg(argv, &argc, CHILD_NAME);
argv = sync_pipe_add_arg(argv, &argc, "-i");
- argv = sync_pipe_add_arg(argv, &argc, cf_get_iface(capture_opts->cf));
+ argv = sync_pipe_add_arg(argv, &argc, capture_opts->iface);
argv = sync_pipe_add_arg(argv, &argc, "-w");
argv = sync_pipe_add_arg(argv, &argc, capture_opts->save_file);
/* Convert filter string to a quote delimited string and pass to child */
filterstring = NULL;
- if (cf_get_cfilter(capture_opts->cf) != NULL && strlen(cf_get_cfilter(capture_opts->cf)) != 0) {
+ if (capture_opts->cfilter != NULL && strlen(capture_opts->cfilter) != 0) {
argv = sync_pipe_add_arg(argv, &argc, "-f");
- filterstring = sync_pipe_quote_encapsulate(cf_get_cfilter(capture_opts->cf));
+ filterstring = sync_pipe_quote_encapsulate(capture_opts->cfilter);
argv = sync_pipe_add_arg(argv, &argc, filterstring);
}
/* The child process started a capture.
Attempt to open the capture file and set up to read it. */
- switch(cf_start_tail(capture_opts->cf, capture_opts->save_file, is_tempfile, &err)) {
+ switch(cf_start_tail(capture_opts->cf, capture_opts->save_file, capture_opts->iface, is_tempfile, &err)) {
case CF_OK:
/* We were able to open and set up to read the capture file;
arrange that our callback be called whenever it's possible
cf->rfcode = NULL;
cf->dfilter = NULL;
cf->dfcode = NULL;
-#ifdef HAVE_LIBPCAP
- cf->cfilter = g_strdup("");
-#endif
- cf->iface = NULL;
cf->has_snap = FALSE;
cf->snap = WTAP_MAX_PACKET_SIZE;
cf->count = 0;
guint32 eusec; /* Elapsed microseconds */
gboolean has_snap; /* TRUE if maximum capture packet length is known */
int snap; /* Maximum captured packet length */
- gchar *iface; /* Interface */
wtap *wth; /* Wiretap session */
- dfilter_t *rfcode; /* Compiled read filter program */
+ dfilter_t *rfcode; /* Compiled read (display) filter program */
gchar *dfilter; /* Display filter string */
dfilter_t *dfcode; /* Compiled display filter program */
-#ifdef HAVE_LIBPCAP
- gchar *cfilter; /* Capture filter string */
-#endif
gchar *sfilter; /* Search filter string */
gboolean sbackward; /* TRUE if search is backward, FALSE if forward */
gboolean hex; /* TRUE is raw data search is being performed */
#ifdef HAVE_LIBPCAP
cf_status_t
-cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
+cf_start_tail(capture_file *cf, const char *fname, const char *iface, gboolean is_tempfile, int *err)
{
gchar *capture_msg;
cf_status_t cf_status;
packets (yes, I know, we don't have any *yet*). */
set_menus_for_captured_packets(TRUE);
- capture_msg = g_strdup_printf(" %s: <live capture in progress>", get_interface_descriptive_name(cf->iface));
+ capture_msg = g_strdup_printf(" %s: <live capture in progress>", get_interface_descriptive_name(iface));
statusbar_push_file_msg(capture_msg);
return cf->count;
}
-/* XXX - use a macro instead? */
-/* XXX - move iface this to capture_opts? */
-gchar *
-cf_get_iface(capture_file *cf)
-{
- return cf->iface;
-}
-
/* XXX - use a macro instead? */
gboolean
cf_is_tempfile(capture_file *cf)
cf->rfcode = rfcode;
}
-gchar *cf_get_cfilter(capture_file *cf)
-{
- return cf->cfilter;
-}
-
typedef struct {
color_filter_t *colorf;
epan_dissect_t *edt;
* @param err the error code, if an error had occured
* @return one of cf_status_t
*/
-cf_status_t cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err);
+cf_status_t cf_start_tail(capture_file *cf, const char *fname, const char *iface, gboolean is_tempfile, int *err);
/**
* Read packets from the "end" of a capture file.
*/
gboolean cf_is_tempfile(capture_file *cf);
-/**
- * Get the interface name to capture from.
- *
- * @param cf the capture file
- * @return the interface name (don't have to be g_free'd)
- */
-gchar *cf_get_iface(capture_file *cf);
-
-/**
- * Get the capture filter of this capture file.
- *
- * @param cf the capture file
- * @return the capture filter (don't have to be g_free'd)
- */
-gchar *cf_get_cfilter(capture_file *cf);
-
/**
* Set flag, if the number of packet drops while capturing are known or not.
*
combo_list = build_capture_combo_list(if_list, TRUE);
if (combo_list != NULL)
gtk_combo_set_popdown_strings(GTK_COMBO(if_cb), combo_list);
- if (cfile.iface == NULL && prefs.capture_device != NULL) {
+ if (capture_opts->iface == NULL && prefs.capture_device != NULL) {
/* No interface was specified on the command line or in a previous
capture, but there is one specified in the preferences file;
make the one from the preferences file the default */
- cfile.iface = g_strdup(prefs.capture_device);
+ capture_opts->iface = g_strdup(prefs.capture_device);
}
- if (cfile.iface != NULL)
- gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), cfile.iface);
+ if (capture_opts->iface != NULL)
+ gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), capture_opts->iface);
else if (combo_list != NULL) {
gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry),
(char *)combo_list->data);
if (filter_list != NULL)
gtk_combo_set_popdown_strings(GTK_COMBO(filter_cm), filter_list);
- if (cfile.cfilter)
- gtk_entry_set_text(GTK_ENTRY(filter_te), cfile.cfilter);
+ if (capture_opts->cfilter)
+ gtk_entry_set_text(GTK_ENTRY(filter_te), capture_opts->cfilter);
gtk_tooltips_set_tip(tooltips, filter_te,
"Enter a capture filter to reduce the amount of packets to be captured. "
"See \"Capture Filters\" in the online help for further information how to use it.",
gchar *if_text;
gchar *if_name;
const gchar *filter_text;
- gchar *save_file;
const gchar *g_save_file;
gchar *cf_name;
gchar *dirname;
g_free(entry_text);
return;
}
- if (cfile.iface)
- g_free(cfile.iface);
- cfile.iface = g_strdup(if_name);
+ if (capture_opts->iface)
+ g_free(capture_opts->iface);
+ capture_opts->iface = g_strdup(if_name);
g_free(entry_text);
capture_opts->linktype =
no filter is set, which means no packets arrive as input on that
socket, which means Ethereal never sees any packets. */
filter_text = gtk_entry_get_text(GTK_ENTRY(filter_te));
- if (cfile.cfilter)
- g_free(cfile.cfilter);
+ if (capture_opts->cfilter)
+ g_free(capture_opts->cfilter);
g_assert(filter_text != NULL);
- cfile.cfilter = g_strdup(filter_text);
+ capture_opts->cfilter = g_strdup(filter_text);
g_save_file = gtk_entry_get_text(GTK_ENTRY(file_te));
if (g_save_file && g_save_file[0]) {
/* User specified a file to which the capture should be written. */
- save_file = g_strdup(g_save_file);
+ capture_opts->save_file = g_strdup(g_save_file);
/* Save the directory name for future file dialogs. */
cf_name = g_strdup(g_save_file);
dirname = get_dirname(cf_name); /* Overwrites cf_name */
g_free(cf_name);
} else {
/* User didn't specify a file; save to a temporary file. */
- save_file = NULL;
+ capture_opts->save_file = NULL;
}
capture_opts->has_autostop_packets =
}
/* test if the settings are ok for a ringbuffer */
- if (save_file == NULL) {
+ if (capture_opts->save_file == NULL) {
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
PRIMARY_TEXT_START "Multiple files: No capture file name given!\n\n" PRIMARY_TEXT_END
"You must specify a filename if you want to use multiple files.");
PRIMARY_TEXT_START "Multiple files: No file limit given!\n\n" PRIMARY_TEXT_END
"You must specify a file size at which is switched to the next capture file\n"
"if you want to use multiple files.");
- g_free(save_file);
+ g_free(capture_opts->save_file);
+ capture_opts->save_file = NULL;
return;
}
} else {
window_destroy(GTK_WIDGET(parent_w));
- if (do_capture(capture_opts, save_file)) {
+ if (do_capture(capture_opts)) {
/* The capture succeeded, which means the capture filter syntax is
valid; add this capture filter to the recent capture filter list. */
- cfilter_combo_add_recent(cfile.cfilter);
+ cfilter_combo_add_recent(capture_opts->cfilter);
}
- if (save_file != NULL)
- g_free(save_file);
}
static void
{
if_dlg_data_t *if_dlg_data = if_data;
- if (cfile.iface)
- g_free(cfile.iface);
+ if (capture_opts->iface)
+ g_free(capture_opts->iface);
- cfile.iface = g_strdup(if_dlg_data->device);
+ capture_opts->iface = g_strdup(if_dlg_data->device);
- do_capture(capture_opts, NULL /* save_file */);
+ if (capture_opts->save_file)
+ g_free(capture_opts->save_file);
+ capture_opts->save_file = NULL;
+
+ do_capture(capture_opts);
}
{
if_dlg_data_t *if_dlg_data = if_data;
- if (cfile.iface)
- g_free(cfile.iface);
+ if (capture_opts->iface)
+ g_free(capture_opts->iface);
- cfile.iface = g_strdup(if_dlg_data->device);
+ capture_opts->iface = g_strdup(if_dlg_data->device);
capture_prep_cb(NULL, NULL);
}
return number;
}
-#ifdef HAVE_LIBPCAP
-/*
- * 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)
-{
- gchar *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((guchar)*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)
-{
- gchar *p = NULL, *colonp;
-
- colonp = strchr(arg, ':');
-
- if (colonp != NULL) {
- p = colonp;
- *p++ = '\0';
- }
-
- capture_opts->ring_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((guchar)*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_file_duration = TRUE;
- capture_opts->file_duration = get_positive_int(p,
- "ring buffer duration");
-
- *colonp = ':'; /* put the colon back */
- return TRUE;
-}
-#endif
-
#if defined(_WIN32) || GTK_MAJOR_VERSION < 2 || ! defined USE_THREADS
/*
Once every 3 seconds we get a callback here which we use to update
int err;
#ifdef HAVE_LIBPCAP
gboolean start_capture = FALSE;
- gchar *save_file = NULL;
GList *if_list;
if_info_t *if_info;
GList *lt_list, *lt_entry;
}
#ifdef _WIN32
+ /* if the user wants a console to be always there, well, we should open one for him */
if (prefs->gui_console_open == console_open_always) {
create_console();
}
/* Now get our args */
while ((opt = getopt(argc, argv, optstring)) != -1) {
switch (opt) {
+ /*** capture option specific ***/
case 'a': /* autostop criteria */
+ case 'b': /* Ringbuffer option */
+ case 'c': /* Capture xxx packets */
+ case 'f': /* capture filter */
+ case 'k': /* Start capture immediately */
+ case 'H': /* Hide capture info dialog box */
+ case 'i': /* Use interface xxx */
+ case 'p': /* Don't capture in promiscuous mode */
+ case 'Q': /* Quit after capture (just capture to file) */
+ case 's': /* Set the snapshot (capture) length */
+ case 'S': /* "Sync" mode: used for following file ala tail -f */
+ case 'w': /* Write to capture file xxx */
+ case 'y': /* Set the pcap data link type */
+#ifdef _WIN32
+ /* Hidden option supporting Sync mode */
+ case 'Z': /* Write to pipe FD XXX */
+#endif /* _WIN32 */
#ifdef HAVE_LIBPCAP
- if (set_autostop_criterion(optarg) == FALSE) {
- fprintf(stderr, "ethereal: Invalid or unknown -a flag \"%s\"\n", optarg);
- exit(1);
- }
+ capture_opt_add(capture_opts, opt, optarg, &start_capture);
#else
capture_option_specified = TRUE;
arg_error = TRUE;
#endif
break;
- case 'b': /* Ringbuffer option */
#ifdef HAVE_LIBPCAP
- capture_opts->multi_files_on = TRUE;
- capture_opts->has_ring_num_files = TRUE;
- if (get_ring_arguments(optarg) == FALSE) {
- fprintf(stderr, "ethereal: Invalid or unknown -b arg \"%s\"\n", optarg);
- exit(1);
- }
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
+ /* This is a hidden option supporting Sync mode, so we don't set
+ * the error flags for the user in the non-libpcap case.
+ */
+ case 'W': /* Write to capture file FD xxx */
+ capture_opt_add(capture_opts, opt, optarg, &start_capture);
+ break;
#endif
- break;
+
+ /*** all non capture option specific ***/
case 'B': /* Byte view pane height */
bv_size = get_positive_int(optarg, "byte view pane height");
break;
- case 'c': /* Capture xxx packets */
-#ifdef HAVE_LIBPCAP
- capture_opts->has_autostop_packets = TRUE;
- capture_opts->autostop_packets = get_positive_int(optarg, "packet count");
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
- case 'f':
-#ifdef HAVE_LIBPCAP
- if (cfile.cfilter)
- g_free(cfile.cfilter);
- cfile.cfilter = g_strdup(optarg);
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
case 'h': /* Print help and exit */
print_usage(TRUE);
exit(0);
break;
- case 'i': /* Use interface xxx */
-#ifdef HAVE_LIBPCAP
- cfile.iface = g_strdup(optarg);
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
- case 'k': /* Start capture immediately */
-#ifdef HAVE_LIBPCAP
- start_capture = TRUE;
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
case 'l': /* Automatic scrolling in live capture mode */
#ifdef HAVE_LIBPCAP
auto_scroll_live = TRUE;
#else
capture_option_specified = TRUE;
arg_error = TRUE;
-#endif
- break;
- case 'H': /* Hide capture info dialog box */
-#ifdef HAVE_LIBPCAP
- capture_opts->show_info = FALSE;
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
#endif
break;
case 'L': /* Print list of link-layer types and exit */
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 'P': /* Packet list pane height */
pl_size = get_positive_int(optarg, "packet list pane height");
break;
- case 'Q': /* Quit after capture (just capture to file) */
-#ifdef HAVE_LIBPCAP
- capture_opts->quit_after_cap = TRUE;
- start_capture = TRUE; /*** -Q implies -k !! ***/
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
case 'r': /* Read capture file xxx */
/* We may set "last_open_dir" to "cf_name", and if we change
"last_open_dir" later, we free the old value, so we have to
case 'R': /* Read file filter */
rfilter = optarg;
break;
- case 's': /* Set the snapshot (capture) length */
-#ifdef HAVE_LIBPCAP
- capture_opts->has_snaplen = TRUE;
- capture_opts->snaplen = get_positive_int(optarg, "snapshot length");
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
- case 'S': /* "Sync" mode: used for following file ala tail -f */
-#ifdef HAVE_LIBPCAP
- capture_opts->sync_mode = TRUE;
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
case 't': /* Time stamp type */
if (strcmp(optarg, "r") == 0)
set_timestamp_setting(TS_RELATIVE);
#endif
exit(0);
break;
- case 'w': /* Write to capture file xxx */
-#ifdef HAVE_LIBPCAP
- save_file = g_strdup(optarg);
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- 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, "ethereal: 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 /* HAVE_LIBPCAP */
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif /* HAVE_LIBPCAP */
- break;
-#ifdef HAVE_LIBPCAP
- /* This is a hidden option supporting Sync mode, so we don't set
- * the error flags for the user in the non-libpcap case.
- */
- case 'W': /* Write to capture file FD xxx */
- capture_opts->save_file_fd = atoi(optarg);
- break;
-#endif
case 'z':
for(tli=tap_list;tli;tli=tli->next){
if(!strncmp(tli->cmd,optarg,strlen(tli->cmd))){
exit(1);
}
break;
-
-#ifdef _WIN32
-#ifdef HAVE_LIBPCAP
- /* Hidden option supporting Sync mode */
- case 'Z': /* Write to pipe FD XXX */
- /* associate stdout with pipe */
- i = atoi(optarg);
- if (dup2(i, 1) < 0) {
- fprintf(stderr, "Unable to dup pipe handle\n");
- exit(1);
- }
- break;
-#endif /* HAVE_LIBPCAP */
-#endif /* _WIN32 */
-
default:
case '?': /* Bad flag - print usage message */
arg_error = TRUE;
argv++;
}
+
+
if (argc != 0) {
/*
* Extra command line arguments were specified; complain.
sync_mode takes precedence;
c) it makes no sense to enable the ring buffer if the maximum
file size is set to "infinite". */
- if (save_file == NULL) {
+ if (capture_opts->save_file == NULL) {
fprintf(stderr, "ethereal: Ring buffer requested, but capture isn't being saved to a permanent file.\n");
capture_opts->multi_files_on = FALSE;
}
if (start_capture || list_link_layer_types) {
/* Did the user specify an interface to use? */
- if (cfile.iface == NULL) {
+ if (capture_opts->iface == NULL) {
/* No - is a default specified in the preferences file? */
if (prefs->capture_device != NULL) {
/* Yes - use it. */
- cfile.iface = g_strdup(prefs->capture_device);
+ capture_opts->iface = g_strdup(prefs->capture_device);
} else {
/* No - pick the first one from the list of interfaces. */
if_list = get_interface_list(&err, err_str);
exit(2);
}
if_info = if_list->data; /* first interface */
- cfile.iface = g_strdup(if_info->name);
+ capture_opts->iface = g_strdup(if_info->name);
free_interface_list(if_list);
}
}
if (list_link_layer_types) {
/* Get the list of link-layer types for the capture device. */
- lt_list = get_pcap_linktype_list(cfile.iface, err_str);
+ lt_list = get_pcap_linktype_list(capture_opts->iface, err_str);
if (lt_list == NULL) {
if (err_str[0] != '\0') {
fprintf(stderr, "ethereal: The list of data link types for the capture device could not be obtained (%s).\n"
else if (capture_opts->num_files < RINGBUFFER_MIN_NUM_FILES)
capture_opts->ring_num_files = RINGBUFFER_MIN_NUM_FILES;
#endif
-#endif
+#endif /* HAVE_LIBPCAP */
/* Notify all registered modules that have had any of their preferences
changed either from one of the preferences file or from the command
/* close the splash screen, as we are going to open the main window now */
splash_destroy(splash_win);
+
#ifdef HAVE_LIBPCAP
/* Is this a "child" ethereal, which is only supposed to pop up a
capture box to let us stop the capture, and run a capture
to a file that our parent will read? */
- if (!capture_opts->capture_child) {
+ if (capture_opts->capture_child) {
+ /* This is the child process for a sync mode or fork mode capture,
+ so just do the low-level work of a capture - don't create
+ a temporary file and fork off *another* child process (so don't
+ call "do_capture()"). */
+
+ /* Pop up any queued-up alert boxes. */
+ display_queued_messages();
+
+ /* XXX - hand these stats to the parent process */
+ capture_start(capture_opts, &stats_known, &stats);
+
+ /* The capture is done; there's nothing more for us to do. */
+ gtk_exit(0);
+ }
#endif
- /* No. Pop up the main window, and read in a capture file if
+
+ /***********************************************************************/
+ /* Everything is prepared now, preferences and command line was read in,
+ we are NOT a child window for a synced capture. */
+
+ /* Pop up the main window, and read in a capture file if
we were told to. */
create_main_window(pl_size, tv_size, bv_size, prefs);
}
#ifdef HAVE_LIBPCAP
if (start_capture) {
+ if (capture_opts->save_file != NULL) {
+ /* Save the directory name for future file dialogs. */
+ /* (get_dirname overwrites filename) */
+ s = get_dirname(g_strdup(capture_opts->save_file));
+ set_last_open_dir(s);
+ g_free(s);
+ }
/* "-k" was specified; start a capture. */
- if (do_capture(capture_opts, save_file)) {
+ if (do_capture(capture_opts)) {
/* The capture started. Open tap windows; we do so after creating
the main window, to avoid GTK warnings, and after starting the
capture, so we know we have something to tap. */
g_free(tap_opt);
}
}
- if (save_file != NULL) {
- /* Save the directory name for future file dialogs. */
- s = get_dirname(save_file); /* Overwrites save_file */
- set_last_open_dir(s);
- g_free(save_file);
- save_file = NULL;
- }
}
else {
set_menus_for_capture_in_progress(FALSE);
}
- } else {
- /* This is the child process for a sync mode or fork mode capture,
- so just do the low-level work of a capture - don't create
- a temporary file and fork off *another* child process (so don't
- call "do_capture()"). */
- /* Pop up any queued-up alert boxes. */
- display_queued_messages();
-
- /* XXX - hand these stats to the parent process */
- capture_start(capture_opts, &stats_known, &stats);
-
- /* The capture is done; there's nothing more for us to do. */
- gtk_exit(0);
- }
- if (!start_capture && (cfile.cfilter == NULL || strlen(cfile.cfilter) == 0)) {
- if (cfile.cfilter) {
- g_free(cfile.cfilter);
+ /* if the user didn't supplied a capture filter, use the one to filter out remote connections like SSH */
+ if (!start_capture && (capture_opts->cfilter == NULL || strlen(capture_opts->cfilter) == 0)) {
+ if (capture_opts->cfilter) {
+ g_free(capture_opts->cfilter);
}
- cfile.cfilter = g_strdup(get_conn_cfilter());
+ capture_opts->cfilter = g_strdup(get_conn_cfilter());
}
+
#else /* HAVE_LIBPCAP */
set_menus_for_capture_in_progress(FALSE);
#endif /* HAVE_LIBPCAP */
#include "globals.h"
#include "file.h"
+#ifdef HAVE_LIBPCAP
+#include "capture.h"
+#include "main.h"
+#endif
#include "summary.h"
#include "summary_dlg.h"
#include "dlg_utils.h"
/* initial computations */
summary_fill_in(&cfile, &summary);
+#ifdef HAVE_LIBPCAP
+ summary_fill_in_capture(capture_opts, &summary);
+#endif
seconds = summary.stop_time - summary.start_time;
disp_seconds = summary.filtered_stop - summary.filtered_start;
/* interface */
if (summary.iface) {
- g_snprintf(string_buff, SUM_STR_MAX, "%s", summary.iface);
+ g_snprintf(string_buff, SUM_STR_MAX, "%s", summary.iface_descr);
} else {
g_snprintf(string_buff, SUM_STR_MAX, "unknown");
}
#include <epan/packet.h>
#include "cfile.h"
#include "summary.h"
+#ifdef HAVE_LIBPCAP
+#include "capture_ui_utils.h"
+#endif
static double
st->packet_count = cf->count;
st->drops_known = cf->drops_known;
st->drops = cf->drops;
- st->iface = cf->iface;
st->dfilter = cf->dfilter;
-#ifdef HAVE_LIBPCAP
- st->cfilter = cf->cfilter;
-#else
+ /* capture related */
st->cfilter = NULL;
-#endif
+ st->iface = NULL;
+ st->iface_descr = NULL;
+}
+
+
+#ifdef HAVE_LIBPCAP
+void
+summary_fill_in_capture(capture_options *capture_opts, summary_tally *st)
+{
+ st->cfilter = capture_opts->cfilter;
+ st->iface = capture_opts->iface;
+ if(st->iface) {
+ st->iface_descr = get_interface_descriptive_name(st->iface);
+ } else {
+ st->iface_descr = NULL;
+ }
}
+#endif
#ifndef __SUMMARY_H__
#define __SUMMARY_H__
+#ifdef HAVE_LIBPCAP
+#include "capture.h"
+#endif
+
typedef struct _summary_tally {
guint32 bytes; /* total bytes */
double start_time; /* seconds, with msec resolution */
const char *iface; /* interface name */
const char *dfilter; /* display filter */
const char *cfilter; /* capture filter */
+ const char *iface_descr;/* descriptive interface name */
} summary_tally;
-void summary_fill_in(capture_file *cf, summary_tally *st);
+extern void
+summary_fill_in(capture_file *cf, summary_tally *st);
+
+#ifdef HAVE_LIBPCAP
+extern void
+summary_fill_in_capture(capture_options *capture_opts, summary_tally *st);
+#endif
#endif /* summary.h */
#ifdef HAVE_LIBPCAP
typedef struct {
gchar *save_file; /* File that user saved capture to */
+ 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 */
static capture_options capture_opts = {
"",
+ "",
+ NULL,
WTAP_MAX_PACKET_SIZE, /* snapshot length - default is
infinite, in effect */
TRUE, /* promiscuous mode is the default */
char badopt;
ethereal_tap_list *tli;
+
+ /* XXX - better use capture_opts_init instead */
+ capture_opts.cfilter = g_strdup("");
+
set_timestamp_setting(TS_RELATIVE);
/* Register all dissectors; we must do this before checking for the
case 'f':
#ifdef HAVE_LIBPCAP
capture_filter_specified = TRUE;
- if (cfile.cfilter)
- g_free(cfile.cfilter);
- cfile.cfilter = g_strdup(optarg);
+ if (capture_opts.cfilter)
+ g_free(capture_opts.cfilter);
+ capture_opts.cfilter = g_strdup(optarg);
#else
capture_option_specified = TRUE;
arg_error = TRUE;
fprintf(stderr, "tethereal: there is no interface with that adapter index\n");
exit(1);
}
- cfile.iface = g_strdup(if_info->name);
+ capture_opts.iface = g_strdup(if_info->name);
free_interface_list(if_list);
} else
- cfile.iface = g_strdup(optarg);
+ capture_opts.iface = g_strdup(optarg);
#else
capture_option_specified = TRUE;
arg_error = TRUE;
"tethereal: Capture filters were specified both with \"-f\" and with additional command-line arguments\n");
exit(2);
}
- cfile.cfilter = get_args_as_string(argc, argv, optind);
+ capture_opts.cfilter = get_args_as_string(argc, argv, optind);
#else
capture_option_specified = TRUE;
#endif
#endif
/* Yes; did the user specify an interface to use? */
- if (cfile.iface == NULL) {
+ 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) {
- cfile.iface = g_strdup(prefs->capture_device);
+ capture_opts.iface = g_strdup(prefs->capture_device);
} else {
- cfile.iface = g_strdup(if_text + 1); /* Skip over space */
+ capture_opts.iface = g_strdup(if_text + 1); /* Skip over space */
}
} else {
/* No - pick the first one from the list of interfaces. */
exit(2);
}
if_info = if_list->data; /* first interface */
- cfile.iface = g_strdup(if_info->name);
+ capture_opts.iface = g_strdup(if_info->name);
free_interface_list(if_list);
}
}
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(cfile.iface, err_str);
+ 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"
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(cfile.iface, capture_opts.snaplen,
+ 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, cfile.iface,
+ set_linktype_err_str = set_pcap_linktype(ld.pch, capture_opts.iface,
capture_opts.linktype);
if (set_linktype_err_str != NULL) {
snprintf(errmsg, sizeof errmsg, "Unable to set data link type (%s).",
setgid(getgid());
#endif
- if (cfile.cfilter && !ld.from_pipe) {
+ if (capture_opts.cfilter && !ld.from_pipe) {
/* A capture filter was specified; set it up. */
- if (pcap_lookupnet(cfile.iface, &netnum, &netmask, lookup_net_err_str) < 0) {
+ 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
"Warning: Couldn't obtain netmask info (%s).\n", lookup_net_err_str);
netmask = 0;
}
- if (pcap_compile(ld.pch, &fcode, cfile.cfilter, 1, netmask) < 0) {
- if (dfilter_compile(cfile.cfilter, &rfcode)) {
+ if (pcap_compile(ld.pch, &fcode, capture_opts.cfilter, 1, netmask) < 0) {
+ if (dfilter_compile(capture_opts.cfilter, &rfcode)) {
snprintf(errmsg, sizeof errmsg,
"Unable to parse capture filter string (%s).\n"
" Interestingly enough, this looks like a valid display filter\n"
} else
#endif
{
- pcap_encap = get_pcap_linktype(ld.pch, cfile.iface);
+ pcap_encap = get_pcap_linktype(ld.pch, capture_opts.iface);
file_snaplen = pcap_snapshot(ld.pch);
}
ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_encap);
#endif /* _WIN32 */
/* Let the user know what interface was chosen. */
- descr = get_interface_descriptive_name(cfile.iface);
+ descr = get_interface_descriptive_name(capture_opts.iface);
fprintf(stderr, "Capturing on %s\n", descr);
g_free(descr);
* the same time, sort of like an "Update list of packets
* in real time" capture in Ethereal.)
*/
- if (cf->iface != NULL)
+ if (capture_opts.iface != NULL)
continue;
column_len = strlen(cf->cinfo.col_data[i]);
if (column_len < 3)