forked from osmocom/wireshark
major capture engine rework: use two task model for EVERY capture mode
rework of the -b command line parameter (for Ethereal and Tethereal) svn path=/trunk/; revision=13949
This commit is contained in:
parent
cb859703ca
commit
7e78ef354e
30
capture.c
30
capture.c
|
@ -72,7 +72,7 @@
|
|||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
static gboolean normal_do_capture(capture_options *capture_opts, gboolean is_tempfile);
|
||||
/*static gboolean normal_do_capture(capture_options *capture_opts, gboolean is_tempfile);*/
|
||||
static void stop_capture_signal_handler(int signo);
|
||||
|
||||
|
||||
|
@ -92,8 +92,16 @@ capture_open_output(capture_options *capture_opts, gboolean *is_tempfile) {
|
|||
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,
|
||||
(capture_opts->has_ring_num_files) ? capture_opts->ring_num_files : 0);
|
||||
/* capture_opts->save_file_fd = ringbuf_init(capfile_name,
|
||||
(capture_opts->has_ring_num_files) ? capture_opts->ring_num_files : 0);*/
|
||||
/* XXX - this is a hack, we need to find a way to move this whole function to capture_loop.c */
|
||||
capture_opts->save_file_fd = -1;
|
||||
if(capture_opts->save_file != NULL) {
|
||||
g_free(capture_opts->save_file);
|
||||
}
|
||||
capture_opts->save_file = capfile_name;
|
||||
*is_tempfile = FALSE;
|
||||
return TRUE;
|
||||
} else {
|
||||
/* Try to open/create the specified file for use as a capture buffer. */
|
||||
capture_opts->save_file_fd = open(capfile_name, O_RDWR|O_BINARY|O_TRUNC|O_CREAT,
|
||||
|
@ -115,7 +123,7 @@ capture_open_output(capture_options *capture_opts, gboolean *is_tempfile) {
|
|||
"could not be opened: %s.", capfile_name, strerror(errno));
|
||||
} else {
|
||||
if (capture_opts->multi_files_on) {
|
||||
ringbuf_error_cleanup();
|
||||
/* ringbuf_error_cleanup();*/
|
||||
}
|
||||
open_failure_alert_box(capfile_name, errno, TRUE);
|
||||
}
|
||||
|
@ -134,17 +142,19 @@ capture_open_output(capture_options *capture_opts, gboolean *is_tempfile) {
|
|||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* 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();
|
||||
/* ringbuf_free();*/
|
||||
} else {
|
||||
g_free(capture_opts->save_file);
|
||||
}
|
||||
capture_opts->save_file = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Open a specified file, or create a temporary file, and start a capture
|
||||
|
@ -173,17 +183,19 @@ do_capture(capture_options *capture_opts)
|
|||
* 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) {
|
||||
/* 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 */
|
||||
cf_callback_invoke(cf_cb_live_capture_prepare, capture_opts);
|
||||
#if 0
|
||||
} else {
|
||||
/* normal mode: do the capture synchronously */
|
||||
cf_callback_invoke(cf_cb_live_capture_prepare, capture_opts);
|
||||
ret = normal_do_capture(capture_opts, is_tempfile);
|
||||
/* capture is finished here */
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -268,6 +280,7 @@ guint32 drops)
|
|||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* start a normal capture session */
|
||||
static gboolean
|
||||
normal_do_capture(capture_options *capture_opts, gboolean is_tempfile)
|
||||
|
@ -292,6 +305,7 @@ normal_do_capture(capture_options *capture_opts, gboolean is_tempfile)
|
|||
capture_close_output(capture_opts);
|
||||
return succeeded;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
|
@ -304,7 +318,7 @@ stop_capture_signal_handler(int signo _U_)
|
|||
int
|
||||
capture_child_start(capture_options *capture_opts, gboolean *stats_known, struct pcap_stat *stats)
|
||||
{
|
||||
gchar *err_msg;
|
||||
/* gchar *err_msg;*/
|
||||
|
||||
g_assert(capture_opts->capture_child);
|
||||
|
||||
|
@ -316,6 +330,7 @@ capture_child_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
signal(SIGUSR1, stop_capture_signal_handler);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* 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
|
||||
|
@ -325,6 +340,7 @@ capture_child_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
g_free(err_msg);
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return capture_loop_start(capture_opts, stats_known, stats);
|
||||
}
|
||||
|
|
|
@ -1027,6 +1027,26 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
/* We haven't yet gotten the capture statistics. */
|
||||
*stats_known = FALSE;
|
||||
|
||||
/*g_warning("capture_loop_start");
|
||||
capture_opts_info(capture_opts);*/
|
||||
|
||||
/*_asm {int 3};*/
|
||||
|
||||
if (capture_opts->multi_files_on) {
|
||||
/* ringbuffer is enabled */
|
||||
capture_opts->save_file_fd = ringbuf_init(capture_opts->save_file,
|
||||
(capture_opts->has_ring_num_files) ? capture_opts->ring_num_files : 0);
|
||||
if (capture_opts->save_file_fd == -1) {
|
||||
ringbuf_error_cleanup();
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* replace save_file by current ringbuffer filename */
|
||||
if(capture_opts->save_file) {
|
||||
g_free(capture_opts->save_file);
|
||||
}
|
||||
capture_opts->save_file = g_strdup(ringbuf_current_filename());
|
||||
}
|
||||
|
||||
/* open the "input file" from network interface or capture pipe */
|
||||
if (!capture_loop_open_input(capture_opts, &ld, errmsg, sizeof(errmsg))) {
|
||||
|
@ -1123,6 +1143,9 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
if (cnd_file_duration) {
|
||||
cnd_reset(cnd_file_duration);
|
||||
}
|
||||
if (capture_opts->capture_child) {
|
||||
sync_pipe_filename_to_parent(capture_opts->save_file);
|
||||
}
|
||||
} else {
|
||||
/* File switch failed: stop here */
|
||||
ld.go = FALSE;
|
||||
|
@ -1191,6 +1214,9 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
cnd_reset(cnd_file_duration);
|
||||
if(cnd_autostop_size)
|
||||
cnd_reset(cnd_autostop_size);
|
||||
if (capture_opts->capture_child) {
|
||||
sync_pipe_filename_to_parent(capture_opts->save_file);
|
||||
}
|
||||
} else {
|
||||
/* File switch failed: stop here */
|
||||
ld.go = FALSE;
|
||||
|
|
|
@ -85,6 +85,39 @@ capture_opts_init(capture_options *capture_opts, void *cfile)
|
|||
capture_opts->fork_child = -1; /* invalid process handle */
|
||||
}
|
||||
|
||||
|
||||
/* debug only: print content of capture_opts to console */
|
||||
void
|
||||
capture_opts_info(capture_options *capture_opts) {
|
||||
g_warning("CAPTURE OPTIONS :");
|
||||
g_warning("File : %s", capture_opts->cf);
|
||||
g_warning("Filter : %s", capture_opts->cfilter);
|
||||
g_warning("Interface : %s", capture_opts->iface);
|
||||
#ifdef _WIN32
|
||||
g_warning("BufferSize : %u (MB)", capture_opts->buffer_size);
|
||||
#endif
|
||||
g_warning("SnapLen (%u): %u", capture_opts->has_snaplen, capture_opts->snaplen);
|
||||
g_warning("Promisc : %u", capture_opts->promisc_mode);
|
||||
g_warning("LinkType : %d", capture_opts->linktype);
|
||||
g_warning("Child : %u", capture_opts->capture_child);
|
||||
g_warning("SaveFile : %s", capture_opts->save_file);
|
||||
g_warning("SaveFileFd : %d", capture_opts->save_file_fd);
|
||||
g_warning("SyncMode : %u", capture_opts->sync_mode);
|
||||
g_warning("ShowInfo : %u", capture_opts->show_info);
|
||||
g_warning("QuitAfterCap : %u", capture_opts->quit_after_cap);
|
||||
|
||||
g_warning("MultiFilesOn : %u", capture_opts->multi_files_on);
|
||||
g_warning("FileDuration (%u): %u", capture_opts->has_file_duration, capture_opts->file_duration);
|
||||
g_warning("RingNumFiles (%u): %u", capture_opts->has_ring_num_files, capture_opts->ring_num_files);
|
||||
|
||||
g_warning("AutostopFiles (%u): %u", capture_opts->has_autostop_files, capture_opts->autostop_files);
|
||||
g_warning("AutostopPackets (%u): %u", capture_opts->has_autostop_packets, capture_opts->autostop_packets);
|
||||
g_warning("AutostopFilesize(%u): %u", capture_opts->has_autostop_filesize, capture_opts->autostop_filesize);
|
||||
g_warning("AutostopDuration(%u): %u", capture_opts->has_autostop_duration, capture_opts->autostop_duration);
|
||||
|
||||
g_warning("ForkChild : %d", capture_opts->fork_child);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
@ -148,18 +181,12 @@ get_ring_arguments(capture_options *capture_opts, const char *appname, const cha
|
|||
gchar *p = NULL, *colonp;
|
||||
|
||||
colonp = strchr(arg, ':');
|
||||
|
||||
if (colonp != NULL) {
|
||||
p = colonp;
|
||||
*p++ = '\0';
|
||||
}
|
||||
|
||||
capture_opts->ring_num_files =
|
||||
get_natural_int(appname, arg, "number of ring buffer files");
|
||||
|
||||
if (colonp == NULL)
|
||||
return TRUE;
|
||||
|
||||
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
|
||||
|
@ -177,9 +204,16 @@ get_ring_arguments(capture_options *capture_opts, const char *appname, const cha
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (strcmp(arg,"files") == 0) {
|
||||
capture_opts->has_ring_num_files = TRUE;
|
||||
capture_opts->ring_num_files = get_natural_int(appname, p, "number of ring buffer files");
|
||||
} else if (strcmp(arg,"filesize") == 0) {
|
||||
capture_opts->has_autostop_filesize = TRUE;
|
||||
capture_opts->autostop_filesize = get_positive_int(appname, p, "ring buffer filesize");
|
||||
} else if (strcmp(arg,"duration") == 0) {
|
||||
capture_opts->has_file_duration = TRUE;
|
||||
capture_opts->file_duration = get_positive_int(appname, p,
|
||||
"ring buffer duration");
|
||||
capture_opts->file_duration = get_positive_int(appname, p, "ring buffer duration");
|
||||
}
|
||||
|
||||
*colonp = ':'; /* put the colon back */
|
||||
return TRUE;
|
||||
|
@ -202,7 +236,6 @@ capture_opts_add_opt(capture_options *capture_opts, const char *appname, int opt
|
|||
break;
|
||||
case 'b': /* Ringbuffer option */
|
||||
capture_opts->multi_files_on = TRUE;
|
||||
capture_opts->has_ring_num_files = TRUE;
|
||||
if (get_ring_arguments(capture_opts, appname, optarg) == FALSE) {
|
||||
fprintf(stderr, "%s: Invalid or unknown -b arg \"%s\"\n", appname, optarg);
|
||||
exit(1);
|
||||
|
|
|
@ -222,6 +222,10 @@ sync_pipe_do_capture(capture_options *capture_opts, gboolean is_tempfile) {
|
|||
int err;
|
||||
char ssnap[24];
|
||||
char scount[24]; /* need a constant for len of numbers */
|
||||
char sfilesize[24]; /* need a constant for len of numbers */
|
||||
char sfile_duration[24]; /* need a constant for len of numbers */
|
||||
char sring_num_files[24]; /* need a constant for len of numbers */
|
||||
char sautostop_files[24]; /* need a constant for len of numbers */
|
||||
char sautostop_filesize[24]; /* need a constant for len of numbers */
|
||||
char sautostop_duration[24]; /* need a constant for len of numbers */
|
||||
char save_file_fd_str[24];
|
||||
|
@ -239,6 +243,10 @@ sync_pipe_do_capture(capture_options *capture_opts, gboolean is_tempfile) {
|
|||
enum PIPES { PIPE_READ, PIPE_WRITE }; /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
|
||||
int sync_pipe[2]; /* pipes used to sync between instances */
|
||||
|
||||
|
||||
/*g_warning("sync_pipe_do_capture");
|
||||
capture_opts_info(capture_opts);*/
|
||||
|
||||
capture_opts->fork_child = -1;
|
||||
|
||||
/* Allocate the string pointer array with enough space for the
|
||||
|
@ -260,12 +268,6 @@ sync_pipe_do_capture(capture_options *capture_opts, gboolean is_tempfile) {
|
|||
sprintf(save_file_fd_str,"%d",capture_opts->save_file_fd); /* in lieu of itoa */
|
||||
argv = sync_pipe_add_arg(argv, &argc, save_file_fd_str);
|
||||
|
||||
if (capture_opts->has_autostop_packets) {
|
||||
argv = sync_pipe_add_arg(argv, &argc, "-c");
|
||||
sprintf(scount,"%d",capture_opts->autostop_packets);
|
||||
argv = sync_pipe_add_arg(argv, &argc, scount);
|
||||
}
|
||||
|
||||
if (capture_opts->has_snaplen) {
|
||||
argv = sync_pipe_add_arg(argv, &argc, "-s");
|
||||
sprintf(ssnap,"%d",capture_opts->snaplen);
|
||||
|
@ -283,11 +285,43 @@ sync_pipe_do_capture(capture_options *capture_opts, gboolean is_tempfile) {
|
|||
argv = sync_pipe_add_arg(argv, &argc, ssnap);
|
||||
}
|
||||
|
||||
if(capture_opts->multi_files_on) {
|
||||
if (capture_opts->has_autostop_filesize) {
|
||||
argv = sync_pipe_add_arg(argv, &argc, "-b");
|
||||
sprintf(sfilesize,"filesize:%d",capture_opts->autostop_filesize);
|
||||
argv = sync_pipe_add_arg(argv, &argc, sfilesize);
|
||||
}
|
||||
|
||||
if (capture_opts->has_file_duration) {
|
||||
argv = sync_pipe_add_arg(argv, &argc, "-b");
|
||||
sprintf(sfile_duration,"duration:%d",capture_opts->file_duration);
|
||||
argv = sync_pipe_add_arg(argv, &argc, sfile_duration);
|
||||
}
|
||||
|
||||
if (capture_opts->has_ring_num_files) {
|
||||
argv = sync_pipe_add_arg(argv, &argc, "-b");
|
||||
sprintf(sring_num_files,"files:%d",capture_opts->ring_num_files);
|
||||
argv = sync_pipe_add_arg(argv, &argc, sring_num_files);
|
||||
}
|
||||
|
||||
if (capture_opts->has_autostop_files) {
|
||||
argv = sync_pipe_add_arg(argv, &argc, "-a");
|
||||
sprintf(sautostop_files,"files:%d",capture_opts->autostop_files);
|
||||
argv = sync_pipe_add_arg(argv, &argc, sautostop_files);
|
||||
}
|
||||
} else {
|
||||
if (capture_opts->has_autostop_filesize) {
|
||||
argv = sync_pipe_add_arg(argv, &argc, "-a");
|
||||
sprintf(sautostop_filesize,"filesize:%d",capture_opts->autostop_filesize);
|
||||
argv = sync_pipe_add_arg(argv, &argc, sautostop_filesize);
|
||||
}
|
||||
}
|
||||
|
||||
if (capture_opts->has_autostop_packets) {
|
||||
argv = sync_pipe_add_arg(argv, &argc, "-c");
|
||||
sprintf(scount,"%d",capture_opts->autostop_packets);
|
||||
argv = sync_pipe_add_arg(argv, &argc, scount);
|
||||
}
|
||||
|
||||
if (capture_opts->has_autostop_duration) {
|
||||
argv = sync_pipe_add_arg(argv, &argc, "-a");
|
||||
|
@ -304,7 +338,6 @@ sync_pipe_do_capture(capture_options *capture_opts, gboolean is_tempfile) {
|
|||
|
||||
#ifdef _WIN32
|
||||
/* Create a pipe for the child process */
|
||||
|
||||
if(_pipe(sync_pipe, 512, O_BINARY) < 0) {
|
||||
/* Couldn't create the pipe between parent and child. */
|
||||
error = errno;
|
||||
|
@ -402,7 +435,9 @@ sync_pipe_do_capture(capture_options *capture_opts, gboolean is_tempfile) {
|
|||
|
||||
/* Close the save file FD, as we won't be using it - we'll be opening
|
||||
it and reading the save file through Wiretap. */
|
||||
if(capture_opts->save_file_fd != -1) {
|
||||
close(capture_opts->save_file_fd);
|
||||
}
|
||||
|
||||
if (capture_opts->fork_child == -1) {
|
||||
/* We couldn't even create the child process. */
|
||||
|
@ -676,10 +711,6 @@ sync_pipe_input_cb(gint source, gpointer user_data)
|
|||
}
|
||||
*r = '\0';
|
||||
|
||||
/* currently, both filenames must be equal */
|
||||
/* (this will change, when multiple files together with sync_mode are captured) */
|
||||
g_assert(strcmp(capture_opts->save_file, msg) == 0);
|
||||
|
||||
/* save the new filename */
|
||||
if(capture_opts->save_file != NULL) {
|
||||
g_free(capture_opts->save_file);
|
||||
|
|
|
@ -2070,12 +2070,12 @@ main(int argc, char *argv[])
|
|||
fprintf(stderr, "ethereal: Ring buffer requested, but capture isn't being saved to a permanent file.\n");
|
||||
capture_opts->multi_files_on = FALSE;
|
||||
}
|
||||
if (capture_opts->sync_mode) {
|
||||
/* if (capture_opts->sync_mode) {
|
||||
fprintf(stderr, "ethereal: Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.\n");
|
||||
capture_opts->multi_files_on = FALSE;
|
||||
}
|
||||
if (!capture_opts->has_autostop_filesize) {
|
||||
fprintf(stderr, "ethereal: Ring buffer requested, but no maximum capture file size was specified.\n");
|
||||
}*/
|
||||
if (!capture_opts->has_autostop_filesize && !capture_opts->has_file_duration) {
|
||||
fprintf(stderr, "ethereal: Ring buffer requested, but no maximum capture file size or duration were specified.\n");
|
||||
capture_opts->multi_files_on = FALSE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -232,6 +232,12 @@ ringbuf_init(const char *capfile_name, guint num_files)
|
|||
return rb_data.fd;
|
||||
}
|
||||
|
||||
|
||||
const gchar *ringbuf_current_filename(void)
|
||||
{
|
||||
return rb_data.files[rb_data.curr_file_num % rb_data.num_files].name;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calls wtap_dump_fdopen() for the current ringbuffer file
|
||||
*/
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#define RINGBUFFER_MAX_NUM_FILES 1024
|
||||
|
||||
int ringbuf_init(const char *capture_name, guint num_files);
|
||||
const gchar *ringbuf_current_filename(void);
|
||||
wtap_dumper* ringbuf_init_wtap_dump_fdopen(int filetype, int linktype,
|
||||
int snaplen, int *err);
|
||||
gboolean ringbuf_switch_file(wtap_dumper **pdh, gchar **save_file, int *save_file_fd, int *err);
|
||||
|
|
Loading…
Reference in New Issue