* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-/* With MSVC and a libethereal.dll this file needs to import some variables
- in a special way. Therefore _NEED_VAR_IMPORT_ is defined. */
-#define _NEED_VAR_IMPORT_
-
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
+#include <ctype.h>
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
static void stop_capture_signal_handler(int signo);
-void
-capture_opts_init(capture_options *capture_opts, void *cfile)
-{
- capture_opts->cf = cfile;
-#ifdef _WIN32
- capture_opts->buffer_size = 1; /* 1 MB */
-#endif
- capture_opts->has_snaplen = FALSE;
- capture_opts->snaplen = MIN_PACKET_SIZE;
- capture_opts->promisc_mode = TRUE;
- capture_opts->linktype = -1; /* the default linktype */
-/* capture_opts->capture_child = FALSE;*/
- capture_opts->save_file = NULL;
- capture_opts->save_file_fd = -1;
- capture_opts->sync_mode = TRUE;
- capture_opts->show_info = TRUE;
- capture_opts->quit_after_cap = FALSE;
-
- capture_opts->multi_files_on = FALSE;
- capture_opts->has_file_duration = FALSE;
- capture_opts->file_duration = 60; /* 1 min */
- capture_opts->has_ring_num_files = TRUE;
- capture_opts->ring_num_files = 2;
-
- capture_opts->has_autostop_files = FALSE;
- capture_opts->autostop_files = 1;
- capture_opts->has_autostop_packets = FALSE;
- capture_opts->autostop_packets = 1;
- capture_opts->has_autostop_filesize = FALSE;
- capture_opts->autostop_filesize = 1024 * 1024; /* 1 MB */
- capture_opts->has_autostop_duration = FALSE;
- capture_opts->autostop_duration = 60; /* 1 min */
-}
-
-
-/* open the output file (temporary/specified name/ringbuffer) and close the old one */
+/* open the output file (temporary/specified name/ringbuffer) */
/* 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,
/* did we fail to open the output file? */
if (capture_opts->save_file_fd == -1) {
- if (is_tempfile) {
+ if (*is_tempfile) {
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
- "The temporary file to which the capture would be saved (\"%s\")"
+ "The temporary file to which the capture would be saved (\"%s\") "
"could not be opened: %s.", capfile_name, strerror(errno));
} else {
if (capture_opts->multi_files_on) {
return FALSE;
}
- /* close the old file */
- cf_close(capture_opts->cf);
- g_assert(capture_opts->save_file == NULL);
+ if(capture_opts->save_file != NULL) {
+ g_free(capture_opts->save_file);
+ }
capture_opts->save_file = capfile_name;
/* capture_opts.save_file is "g_free"ed later, which is equivalent to
"g_free(capfile_name)". */
}
+/* close the output file (NOT the capture file) */
+static void
+capture_close_output(capture_options *capture_opts)
+{
+ if (capture_opts->multi_files_on) {
+ ringbuf_free();
+ } else {
+ g_free(capture_opts->save_file);
+ }
+ capture_opts->save_file = NULL;
+}
+
+
/* Open a specified file, or create a temporary file, and start a capture
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)) {
+
+ /* open the new output file (temporary/specified name/ringbuffer) */
+ 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)));
- if (capture_opts->sync_mode) {
+ /* close the currently loaded capture file */
+ cf_close(capture_opts->cf);
+
+ /* We could simply use TRUE for this expression now, this will work for all
+ * captures except for some of the multiple files options, as these capture
+ * options currently cannot be passed through the command line to the
+ * capture child.
+ *
+ * If this is fixed, we could always use the sync mode, throwing away the
+ * normal mode completely and doing some more cleanup. */
+/* if (TRUE) {*/
+ if (capture_opts->sync_mode) {
/* sync mode: do the capture in a child process */
ret = sync_pipe_do_capture(capture_opts, is_tempfile);
/* capture is still running */
- set_main_window_name(title);
+ cf_callback_invoke(cf_cb_live_capture_prepare, capture_opts);
} else {
/* normal mode: do the capture synchronously */
- set_main_window_name(title);
+ cf_callback_invoke(cf_cb_live_capture_prepare, capture_opts);
ret = normal_do_capture(capture_opts, is_tempfile);
/* capture is finished here */
}
- g_free(title);
return ret;
}
-/* start a normal capture session */
-static gboolean
-normal_do_capture(capture_options *capture_opts, gboolean is_tempfile)
+/* we've succeeded a capture, try to read it into a new capture file */
+gboolean
+capture_read(capture_options *capture_opts, gboolean is_tempfile, gboolean drops_known,
+guint32 drops)
{
- int capture_succeeded;
- gboolean stats_known;
- struct pcap_stat stats;
int err;
- /* Not sync mode. */
- capture_succeeded = capture_start(capture_opts, &stats_known, &stats);
- if (capture_opts->quit_after_cap) {
- /* DON'T unlink the save file. Presumably someone wants it. */
- main_window_exit();
- }
- if (!capture_succeeded) {
- /* We didn't succeed in doing the capture, so we don't have a save
- file. */
- if (capture_opts->multi_files_on) {
- ringbuf_free();
- } else {
- g_free(capture_opts->save_file);
- }
- capture_opts->save_file = NULL;
- return FALSE;
- }
+
/* Capture succeeded; attempt to read in the capture file. */
if (cf_open(capture_opts->cf, capture_opts->save_file, is_tempfile, &err) != CF_OK) {
/* We're not doing a capture any more, so we don't have a save
file. */
- if (capture_opts->multi_files_on) {
- ringbuf_free();
- } else {
- g_free(capture_opts->save_file);
- }
- capture_opts->save_file = NULL;
return FALSE;
}
/* Set the read filter to NULL. */
+ /* XXX - this is odd here, try to put it somewhere, where it fits better */
cf_set_rfcode(capture_opts->cf, NULL);
/* Get the packet-drop statistics.
we'll put them into the capture file that we write, and will
thus not have to set them here - "cf_read()" will get them from
the file and use them. */
- if (stats_known) {
+ if (drops_known) {
cf_set_drops_known(capture_opts->cf, TRUE);
/* XXX - on some systems, libpcap doesn't bother filling in
several statistics - perhaps including various interface
error statistics - and would tell us which of them it
supplies, allowing us to display only the ones it does. */
- cf_set_drops(capture_opts->cf, stats.ps_drop);
+ cf_set_drops(capture_opts->cf, drops);
}
switch (cf_read(capture_opts->cf)) {
return FALSE;
}
- /* We're not doing a capture any more, so we don't have a save
- file. */
- if (capture_opts->multi_files_on) {
- ringbuf_free();
- } else {
- g_free(capture_opts->save_file);
- }
- capture_opts->save_file = NULL;
-
/* if we didn't captured even a single packet, close the file again */
if(cf_packet_count(capture_opts->cf) == 0) {
simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
}
+/* start a normal capture session */
+static gboolean
+normal_do_capture(capture_options *capture_opts, gboolean is_tempfile)
+{
+ gboolean succeeded;
+ gboolean stats_known;
+ struct pcap_stat stats;
+
+
+ /* Not sync mode. */
+ succeeded = capture_loop_start(capture_opts, &stats_known, &stats);
+ if (capture_opts->quit_after_cap) {
+ /* DON'T unlink the save file. Presumably someone wants it. */
+ main_window_exit();
+ }
+ if (succeeded) {
+ /* We succeed in doing the capture, try to read it in. */
+ succeeded = capture_read(capture_opts, is_tempfile, stats_known, stats.ps_drop);
+ }
+
+ /* wether the capture suceeded or not, we have to close the output file here */
+ capture_close_output(capture_opts);
+ return succeeded;
+}
+
+
static void
stop_capture_signal_handler(int signo _U_)
{
int
-capture_start(capture_options *capture_opts, gboolean *stats_known, struct pcap_stat *stats)
+capture_child_start(capture_options *capture_opts, gboolean *stats_known, struct pcap_stat *stats)
{
+ gchar *err_msg;
+
+ g_assert(capture_opts->capture_child);
+
#ifndef _WIN32
/*
* Catch SIGUSR1, so that we exit cleanly if the parent process
* kills us with it due to the user selecting "Capture->Stop".
*/
- if (capture_opts->capture_child)
signal(SIGUSR1, stop_capture_signal_handler);
#endif
+ /* parent must have send us a file descriptor for the opened output file */
+ if (capture_opts->save_file_fd == -1) {
+ /* send this to the standard output as something our parent
+ should put in an error message box */
+ err_msg = g_strdup_printf("%s: \"-W\" flag not specified (internal error)\n", CHILD_NAME);
+ sync_pipe_errmsg_to_parent(err_msg);
+ g_free(err_msg);
+ return FALSE;
+ }
+
return capture_loop_start(capture_opts, stats_known, stats);
}
void
capture_stop(capture_options *capture_opts)
{
-
- if (capture_opts->sync_mode) {
+ /* stop the capture child, if we have one */
+ if (!capture_opts->capture_child) {
sync_pipe_stop(capture_opts);
}
-
+
+ /* stop the capture loop */
capture_loop_stop();
}
void
capture_kill_child(capture_options *capture_opts)
{
- if (capture_opts->sync_mode) {
+ /* kill the capture child, if we have one */
+ if (!capture_opts->capture_child) {
sync_pipe_kill(capture_opts);
}
}