forked from osmocom/wireshark
a lot more capture engine code cleanup
most notably: - moved opening of safe_file to the capture child (capture_loop.c) - removed save_file_fd from capture_opts (no longer need to have it global) svn path=/trunk/; revision=13953
This commit is contained in:
parent
d11694e340
commit
daa67c79ba
288
capture.c
288
capture.c
|
@ -67,143 +67,41 @@
|
|||
#include "ui_util.h"
|
||||
|
||||
|
||||
/* Win32 needs the O_BINARY flag for open() */
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
/*static gboolean normal_do_capture(capture_options *capture_opts, gboolean is_tempfile);*/
|
||||
static void stop_capture_signal_handler(int signo);
|
||||
|
||||
|
||||
/* 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, gboolean *is_tempfile) {
|
||||
char tmpname[128+1];
|
||||
gchar *capfile_name;
|
||||
|
||||
|
||||
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(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);*/
|
||||
/* 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,
|
||||
0600);
|
||||
}
|
||||
*is_tempfile = FALSE;
|
||||
} else {
|
||||
/* Choose a random name for the temporary capture buffer */
|
||||
capture_opts->save_file_fd = create_tempfile(tmpname, sizeof tmpname, "ether");
|
||||
capfile_name = g_strdup(tmpname);
|
||||
*is_tempfile = TRUE;
|
||||
}
|
||||
|
||||
/* did we fail to open the output file? */
|
||||
if (capture_opts->save_file_fd == -1) {
|
||||
if (*is_tempfile) {
|
||||
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
|
||||
"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) {
|
||||
/* ringbuf_error_cleanup();*/
|
||||
}
|
||||
open_failure_alert_box(capfile_name, errno, TRUE);
|
||||
}
|
||||
g_free(capfile_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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)". */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
#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();*/
|
||||
} 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
|
||||
to the file in question. */
|
||||
/* start a capture */
|
||||
/* Returns TRUE if the capture starts successfully, FALSE otherwise. */
|
||||
gboolean
|
||||
do_capture(capture_options *capture_opts)
|
||||
{
|
||||
gboolean is_tempfile;
|
||||
gboolean ret;
|
||||
|
||||
|
||||
/* open the new output file (temporary/specified name/ringbuffer) */
|
||||
if(!capture_open_output(capture_opts, &is_tempfile)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
cf_callback_invoke(cf_cb_live_capture_prepare, capture_opts);
|
||||
#if 0
|
||||
/* try to start the capture child process */
|
||||
ret = sync_pipe_do_capture(capture_opts, capture_opts->save_file == NULL);
|
||||
|
||||
if(ret) {
|
||||
/* tell callbacks (menu, ...) that capture is running now */
|
||||
cf_callback_invoke(cf_cb_live_capture_prepare, capture_opts);
|
||||
} 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 */
|
||||
if(capture_opts->save_file != NULL) {
|
||||
g_free(capture_opts->save_file);
|
||||
capture_opts->save_file = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* 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,
|
||||
static gboolean
|
||||
capture_input_read_all(capture_options *capture_opts, gboolean is_tempfile, gboolean drops_known,
|
||||
guint32 drops)
|
||||
{
|
||||
int err;
|
||||
|
@ -280,46 +178,142 @@ guint32 drops)
|
|||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* start a normal capture session */
|
||||
static gboolean
|
||||
normal_do_capture(capture_options *capture_opts, gboolean is_tempfile)
|
||||
/* capture child tells us, we have a new (or the first) capture file */
|
||||
gboolean
|
||||
capture_input_new_file(capture_options *capture_opts, gchar *new_file)
|
||||
{
|
||||
gboolean succeeded;
|
||||
gboolean stats_known;
|
||||
struct pcap_stat stats;
|
||||
gboolean is_tempfile;
|
||||
int err;
|
||||
|
||||
|
||||
/* 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);
|
||||
/*g_warning("New capture file: %s", new_file);*/
|
||||
|
||||
/* save the new filename */
|
||||
if(capture_opts->save_file != NULL) {
|
||||
/* we start a new capture file, simply close the old one */
|
||||
/* XXX - is it enough to call cf_close here? */
|
||||
/* XXX - is it safe to call cf_close even if the file is close before? */
|
||||
cf_close(capture_opts->cf);
|
||||
g_free(capture_opts->save_file);
|
||||
is_tempfile = FALSE;
|
||||
} else {
|
||||
/* we didn't had a save_file before, must be a tempfile */
|
||||
is_tempfile = TRUE;
|
||||
cf_set_tempfile(capture_opts->cf, TRUE);
|
||||
}
|
||||
capture_opts->save_file = g_strdup(new_file);
|
||||
|
||||
/* if we are in sync mode, open the new file */
|
||||
if(capture_opts->sync_mode) {
|
||||
/* 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)) {
|
||||
case CF_OK:
|
||||
break;
|
||||
case CF_ERROR:
|
||||
/* Don't unlink the save file - leave it around, for debugging
|
||||
purposes. */
|
||||
g_free(capture_opts->save_file);
|
||||
capture_opts->save_file = NULL;
|
||||
return FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* wether the capture suceeded or not, we have to close the output file here */
|
||||
capture_close_output(capture_opts);
|
||||
return succeeded;
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* capture child tells us, we have new packets to read */
|
||||
void
|
||||
capture_input_new_packets(capture_options *capture_opts, int to_read)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
||||
if(capture_opts->sync_mode) {
|
||||
/* Read from the capture file the number of records the child told us
|
||||
it added.
|
||||
XXX - do something if this fails? */
|
||||
switch (cf_continue_tail(capture_opts->cf, to_read, &err)) {
|
||||
|
||||
case CF_READ_OK:
|
||||
case CF_READ_ERROR:
|
||||
/* Just because we got an error, that doesn't mean we were unable
|
||||
to read any of the file; we handle what we could get from the
|
||||
file.
|
||||
|
||||
XXX - abort on a read error? */
|
||||
break;
|
||||
|
||||
case CF_READ_ABORTED:
|
||||
/* Kill the child capture process; the user wants to exit, and we
|
||||
shouldn't just leave it running. */
|
||||
capture_kill_child(capture_opts);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* capture child closed it's side ot the pipe, do the required cleanup */
|
||||
void
|
||||
capture_input_closed(capture_options *capture_opts)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
||||
if(capture_opts->sync_mode) {
|
||||
/* Read what remains of the capture file, and finish the capture.
|
||||
XXX - do something if this fails? */
|
||||
switch (cf_finish_tail(capture_opts->cf, &err)) {
|
||||
|
||||
case CF_READ_OK:
|
||||
if(cf_packet_count(capture_opts->cf) == 0) {
|
||||
simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
|
||||
"%sNo packets captured!%s\n\n"
|
||||
"As no data was captured, closing the %scapture file!",
|
||||
simple_dialog_primary_start(), simple_dialog_primary_end(),
|
||||
cf_is_tempfile(capture_opts->cf) ? "temporary " : "");
|
||||
cf_close(capture_opts->cf);
|
||||
}
|
||||
break;
|
||||
case CF_READ_ERROR:
|
||||
/* Just because we got an error, that doesn't mean we were unable
|
||||
to read any of the file; we handle what we could get from the
|
||||
file. */
|
||||
break;
|
||||
|
||||
case CF_READ_ABORTED:
|
||||
/* Exit by leaving the main loop, so that any quit functions
|
||||
we registered get called. */
|
||||
main_window_quit();
|
||||
}
|
||||
} else {
|
||||
/* this is a normal mode capture, read in the capture file data */
|
||||
capture_input_read_all(capture_opts, cf_is_tempfile(capture_opts->cf),
|
||||
cf_get_drops_known(capture_opts->cf), cf_get_drops(capture_opts->cf));
|
||||
}
|
||||
|
||||
/* We're not doing a capture any more, so we don't have a save file. */
|
||||
g_assert(capture_opts->save_file);
|
||||
g_free(capture_opts->save_file);
|
||||
capture_opts->save_file = NULL;
|
||||
}
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
static void
|
||||
stop_capture_signal_handler(int signo _U_)
|
||||
capture_child_stop_signal_handler(int signo _U_)
|
||||
{
|
||||
capture_loop_stop();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
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
|
||||
|
@ -327,19 +321,7 @@ capture_child_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
* Catch SIGUSR1, so that we exit cleanly if the parent process
|
||||
* kills us with it due to the user selecting "Capture->Stop".
|
||||
*/
|
||||
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
|
||||
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;
|
||||
}
|
||||
signal(SIGUSR1, capture_child_stop_signal_handler);
|
||||
#endif
|
||||
|
||||
return capture_loop_start(capture_opts, stats_known, stats);
|
||||
|
@ -361,9 +343,7 @@ void
|
|||
capture_kill_child(capture_options *capture_opts)
|
||||
{
|
||||
/* kill the capture child, if we have one */
|
||||
if (!capture_opts->capture_child) {
|
||||
sync_pipe_kill(capture_opts);
|
||||
}
|
||||
sync_pipe_kill(capture_opts);
|
||||
}
|
||||
|
||||
|
||||
|
|
16
capture.h
16
capture.h
|
@ -52,7 +52,6 @@ typedef struct capture_options_tag {
|
|||
"use default" */
|
||||
gboolean capture_child; /**< True if this is the child for "-S" */
|
||||
gchar *save_file; /**< the capture file name */
|
||||
int save_file_fd; /**< File descriptor for saved file */
|
||||
|
||||
/* GUI related */
|
||||
gboolean sync_mode; /**< Fork a child to do the capture,
|
||||
|
@ -105,10 +104,19 @@ capture_opts_add_opt(capture_options *capture_opts, const char *appname, int opt
|
|||
extern gboolean do_capture(capture_options *capture_opts);
|
||||
|
||||
/**
|
||||
* Read in the newly captured data into the capture_file.
|
||||
* Capture child told us, we have a new (or the first) capture file.
|
||||
*/
|
||||
extern gboolean capture_read(capture_options *capture_opts, gboolean is_tempfile, gboolean drops_known,
|
||||
guint32 drops);
|
||||
extern gboolean capture_input_new_file(capture_options *capture_opts, gchar *new_file);
|
||||
|
||||
/**
|
||||
* Capture child told us, we have new packets to read.
|
||||
*/
|
||||
extern void capture_input_new_packets(capture_options *capture_opts, int to_read);
|
||||
|
||||
/**
|
||||
* Capture child closed it's side ot the pipe, do the required cleanup.
|
||||
*/
|
||||
extern void capture_input_closed(capture_options *capture_opts);
|
||||
|
||||
/** Do the low-level work of a capture (start the capture child).
|
||||
* Returns TRUE if it succeeds, FALSE otherwise. */
|
||||
|
|
|
@ -84,6 +84,8 @@
|
|||
/* XXX - try to remove this later */
|
||||
#include "ui_util.h"
|
||||
/* XXX - try to remove this later */
|
||||
#include "util.h"
|
||||
#include "alert_box.h"
|
||||
|
||||
|
||||
#include <epan/dissectors/packet-ap1394.h>
|
||||
|
@ -779,7 +781,7 @@ static int capture_loop_init_filter(loop_data *ld, const gchar * iface, gchar *
|
|||
|
||||
|
||||
/* open the wiretap part of the capture output file */
|
||||
static int capture_loop_open_wiretap_output(capture_options *capture_opts, loop_data *ld, char *errmsg, int errmsg_len) {
|
||||
static int capture_loop_open_wiretap_output(capture_options *capture_opts, int save_file_fd, loop_data *ld, char *errmsg, int errmsg_len) {
|
||||
int pcap_encap;
|
||||
int file_snaplen;
|
||||
int err;
|
||||
|
@ -809,7 +811,7 @@ static int capture_loop_open_wiretap_output(capture_options *capture_opts, loop_
|
|||
ld->wtap_pdh = ringbuf_init_wtap_dump_fdopen(WTAP_FILE_PCAP, ld->wtap_linktype,
|
||||
file_snaplen, &err);
|
||||
} else {
|
||||
ld->wtap_pdh = wtap_dump_fdopen(capture_opts->save_file_fd, WTAP_FILE_PCAP,
|
||||
ld->wtap_pdh = wtap_dump_fdopen(save_file_fd, WTAP_FILE_PCAP,
|
||||
ld->wtap_linktype, file_snaplen, &err);
|
||||
}
|
||||
|
||||
|
@ -966,6 +968,70 @@ capture_loop_dispatch(capture_options *capture_opts, loop_data *ld,
|
|||
}
|
||||
|
||||
|
||||
/* open the output file (temporary/specified name/ringbuffer) */
|
||||
/* Returns TRUE if the file opened successfully, FALSE otherwise. */
|
||||
static gboolean
|
||||
capture_loop_open_output(capture_options *capture_opts, int *save_file_fd) {
|
||||
char tmpname[128+1];
|
||||
gchar *capfile_name;
|
||||
gboolean is_tempfile;
|
||||
|
||||
|
||||
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(capture_opts->save_file);
|
||||
if (capture_opts->multi_files_on) {
|
||||
/* ringbuffer is enabled */
|
||||
*save_file_fd = ringbuf_init(capfile_name,
|
||||
(capture_opts->has_ring_num_files) ? capture_opts->ring_num_files : 0);
|
||||
|
||||
/* we need the ringbuf name */
|
||||
g_free(capfile_name);
|
||||
capfile_name = g_strdup(ringbuf_current_filename());
|
||||
} else {
|
||||
/* Try to open/create the specified file for use as a capture buffer. */
|
||||
*save_file_fd = open(capfile_name, O_RDWR|O_BINARY|O_TRUNC|O_CREAT,
|
||||
0600);
|
||||
}
|
||||
is_tempfile = FALSE;
|
||||
} else {
|
||||
/* Choose a random name for the temporary capture buffer */
|
||||
*save_file_fd = create_tempfile(tmpname, sizeof tmpname, "ether");
|
||||
capfile_name = g_strdup(tmpname);
|
||||
is_tempfile = TRUE;
|
||||
}
|
||||
|
||||
/* did we fail to open the output file? */
|
||||
if (*save_file_fd == -1) {
|
||||
if (is_tempfile) {
|
||||
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
|
||||
"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) {
|
||||
ringbuf_error_cleanup();
|
||||
}
|
||||
open_failure_alert_box(capfile_name, errno, TRUE);
|
||||
}
|
||||
g_free(capfile_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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)". */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* This needs to be static, so that the SIGUSR1 handler can clear the "go"
|
||||
* flag.
|
||||
|
@ -989,6 +1055,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
gboolean close_ok;
|
||||
capture_info capture_ui;
|
||||
char errmsg[4096+1];
|
||||
int save_file_fd;
|
||||
|
||||
gboolean show_info = capture_opts->show_info || !capture_opts->sync_mode;
|
||||
|
||||
|
@ -1030,22 +1097,10 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
/*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 output file (temporary/specified name/ringbuffer) */
|
||||
if (!capture_loop_open_output(capture_opts, &save_file_fd)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* open the "input file" from network interface or capture pipe */
|
||||
|
@ -1059,7 +1114,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
}
|
||||
|
||||
/* open the wiretap part of the output file (the output file is already open) */
|
||||
if (!capture_loop_open_wiretap_output(capture_opts, &ld, errmsg, sizeof(errmsg))) {
|
||||
if (!capture_loop_open_wiretap_output(capture_opts, save_file_fd, &ld, errmsg, sizeof(errmsg))) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -1137,7 +1192,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
}
|
||||
|
||||
/* Switch to the next ringbuffer file */
|
||||
if (ringbuf_switch_file(&ld.wtap_pdh, &capture_opts->save_file, &capture_opts->save_file_fd, &ld.err)) {
|
||||
if (ringbuf_switch_file(&ld.wtap_pdh, &capture_opts->save_file, &save_file_fd, &ld.err)) {
|
||||
/* File switch succeeded: reset the conditions */
|
||||
cnd_reset(cnd_autostop_size);
|
||||
if (cnd_file_duration) {
|
||||
|
@ -1209,7 +1264,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
}
|
||||
|
||||
/* Switch to the next ringbuffer file */
|
||||
if (ringbuf_switch_file(&ld.wtap_pdh, &capture_opts->save_file, &capture_opts->save_file_fd, &ld.err)) {
|
||||
if (ringbuf_switch_file(&ld.wtap_pdh, &capture_opts->save_file, &save_file_fd, &ld.err)) {
|
||||
/* file switch succeeded: reset the conditions */
|
||||
cnd_reset(cnd_file_duration);
|
||||
if(cnd_autostop_size)
|
||||
|
@ -1320,7 +1375,7 @@ error:
|
|||
} else {
|
||||
/* We can't use the save file, and we have no wtap_dump stream
|
||||
to close in order to close it, so close the FD directly. */
|
||||
close(capture_opts->save_file_fd);
|
||||
close(save_file_fd);
|
||||
|
||||
/* We couldn't even start the capture, so get rid of the capture
|
||||
file. */
|
||||
|
|
|
@ -61,7 +61,6 @@ capture_opts_init(capture_options *capture_opts, void *cfile)
|
|||
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;
|
||||
|
@ -101,7 +100,6 @@ capture_opts_info(capture_options *capture_opts) {
|
|||
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);
|
||||
|
@ -277,9 +275,6 @@ capture_opts_add_opt(capture_options *capture_opts, const char *appname, int opt
|
|||
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);
|
||||
|
|
181
capture_sync.c
181
capture_sync.c
|
@ -219,7 +219,6 @@ sync_pipe_do_capture(capture_options *capture_opts, gboolean is_tempfile) {
|
|||
int i;
|
||||
guchar c;
|
||||
char *msg;
|
||||
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 */
|
||||
|
@ -228,11 +227,9 @@ sync_pipe_do_capture(capture_options *capture_opts, gboolean is_tempfile) {
|
|||
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];
|
||||
#ifndef _WIN32
|
||||
char errmsg[1024+1];
|
||||
#endif
|
||||
int error;
|
||||
int argc;
|
||||
char **argv;
|
||||
#ifdef _WIN32
|
||||
|
@ -261,12 +258,10 @@ sync_pipe_do_capture(capture_options *capture_opts, gboolean is_tempfile) {
|
|||
argv = sync_pipe_add_arg(argv, &argc, "-i");
|
||||
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);
|
||||
|
||||
argv = sync_pipe_add_arg(argv, &argc, "-W");
|
||||
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->save_file) {
|
||||
argv = sync_pipe_add_arg(argv, &argc, "-w");
|
||||
argv = sync_pipe_add_arg(argv, &argc, capture_opts->save_file);
|
||||
}
|
||||
|
||||
if (capture_opts->has_snaplen) {
|
||||
argv = sync_pipe_add_arg(argv, &argc, "-s");
|
||||
|
@ -340,12 +335,8 @@ sync_pipe_do_capture(capture_options *capture_opts, gboolean is_tempfile) {
|
|||
/* 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;
|
||||
unlink(capture_opts->save_file);
|
||||
g_free(capture_opts->save_file);
|
||||
capture_opts->save_file = NULL;
|
||||
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
|
||||
strerror(error));
|
||||
strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -376,12 +367,8 @@ sync_pipe_do_capture(capture_options *capture_opts, gboolean is_tempfile) {
|
|||
#else
|
||||
if (pipe(sync_pipe) < 0) {
|
||||
/* Couldn't create the pipe between parent and child. */
|
||||
error = errno;
|
||||
unlink(capture_opts->save_file);
|
||||
g_free(capture_opts->save_file);
|
||||
capture_opts->save_file = NULL;
|
||||
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
|
||||
strerror(error));
|
||||
strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -433,21 +420,11 @@ sync_pipe_do_capture(capture_options *capture_opts, gboolean is_tempfile) {
|
|||
or by exiting abnormally). */
|
||||
close(sync_pipe[PIPE_WRITE]);
|
||||
|
||||
/* 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. */
|
||||
error = errno;
|
||||
close(sync_pipe[PIPE_READ]);
|
||||
unlink(capture_opts->save_file);
|
||||
g_free(capture_opts->save_file);
|
||||
capture_opts->save_file = NULL;
|
||||
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
|
||||
"Couldn't create child process: %s", strerror(error));
|
||||
"Couldn't create child process: %s", strerror(errno));
|
||||
close(sync_pipe[PIPE_READ]);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -464,12 +441,11 @@ sync_pipe_do_capture(capture_options *capture_opts, gboolean is_tempfile) {
|
|||
Close the read side of the sync pipe, remove the capture file,
|
||||
and report the failure. */
|
||||
close(sync_pipe[PIPE_READ]);
|
||||
unlink(capture_opts->save_file);
|
||||
g_free(capture_opts->save_file);
|
||||
capture_opts->save_file = NULL;
|
||||
sync_pipe_wait_for_child(capture_opts, TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* the first message should be the capture start or an error message */
|
||||
if (c == SP_CAPSTART || c == SP_ERROR_MSG)
|
||||
break;
|
||||
if (!isdigit(c)) {
|
||||
|
@ -477,9 +453,6 @@ sync_pipe_do_capture(capture_options *capture_opts, gboolean is_tempfile) {
|
|||
Close the read side of the sync pipe, remove the capture file,
|
||||
and report the failure. */
|
||||
close(sync_pipe[PIPE_READ]);
|
||||
unlink(capture_opts->save_file);
|
||||
g_free(capture_opts->save_file);
|
||||
capture_opts->save_file = NULL;
|
||||
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
|
||||
"Capture child process sent us a bad message");
|
||||
return FALSE;
|
||||
|
@ -516,97 +489,20 @@ sync_pipe_do_capture(capture_options *capture_opts, gboolean is_tempfile) {
|
|||
|
||||
/* Close the sync pipe. */
|
||||
close(sync_pipe[PIPE_READ]);
|
||||
|
||||
/* Get rid of the save file - the capture never started. */
|
||||
unlink(capture_opts->save_file);
|
||||
g_free(capture_opts->save_file);
|
||||
capture_opts->save_file = NULL;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(capture_opts->sync_mode) {
|
||||
/* 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)) {
|
||||
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
|
||||
to read from the sync pipe, so that it's called when
|
||||
the child process wants to tell us something. */
|
||||
pipe_input_set_handler(sync_pipe[PIPE_READ], (gpointer) capture_opts, &capture_opts->fork_child, sync_pipe_input_cb);
|
||||
/* We were able to set up to read the capture file;
|
||||
arrange that our callback be called whenever it's possible
|
||||
to read from the sync pipe, so that it's called when
|
||||
the child process wants to tell us something. */
|
||||
|
||||
return TRUE;
|
||||
break;
|
||||
case CF_ERROR:
|
||||
/* We weren't able to open the capture file; user has been
|
||||
alerted. Close the sync pipe. */
|
||||
/* we have a running capture, now wait for the real capture filename */
|
||||
pipe_input_set_handler(sync_pipe[PIPE_READ], (gpointer) capture_opts,
|
||||
&capture_opts->fork_child, sync_pipe_input_cb);
|
||||
|
||||
close(sync_pipe[PIPE_READ]);
|
||||
|
||||
/* Don't unlink the save file - leave it around, for debugging
|
||||
purposes. */
|
||||
g_free(capture_opts->save_file);
|
||||
capture_opts->save_file = NULL;
|
||||
return FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
g_assert_not_reached();
|
||||
return FALSE;
|
||||
} else {
|
||||
pipe_input_set_handler(sync_pipe[PIPE_READ], (gpointer) capture_opts, &capture_opts->fork_child, sync_pipe_input_cb);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sync_pipe_closed(capture_options *capture_opts)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
||||
/* The child has closed the sync pipe, meaning it's not going to be
|
||||
capturing any more packets. Pick up its exit status, and
|
||||
complain if it did anything other than exit with status 0. */
|
||||
sync_pipe_wait_for_child(capture_opts, FALSE);
|
||||
|
||||
if(capture_opts->sync_mode) {
|
||||
/* Read what remains of the capture file, and finish the capture.
|
||||
XXX - do something if this fails? */
|
||||
switch (cf_finish_tail(capture_opts->cf, &err)) {
|
||||
|
||||
case CF_READ_OK:
|
||||
if(cf_packet_count(capture_opts->cf) == 0) {
|
||||
simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
|
||||
"%sNo packets captured!%s\n\n"
|
||||
"As no data was captured, closing the %scapture file!",
|
||||
simple_dialog_primary_start(), simple_dialog_primary_end(),
|
||||
cf_is_tempfile(capture_opts->cf) ? "temporary " : "");
|
||||
cf_close(capture_opts->cf);
|
||||
}
|
||||
break;
|
||||
case CF_READ_ERROR:
|
||||
/* Just because we got an error, that doesn't mean we were unable
|
||||
to read any of the file; we handle what we could get from the
|
||||
file. */
|
||||
break;
|
||||
|
||||
case CF_READ_ABORTED:
|
||||
/* Exit by leaving the main loop, so that any quit functions
|
||||
we registered get called. */
|
||||
main_window_quit();
|
||||
}
|
||||
|
||||
/* We're not doing a capture any more, so we don't have a save
|
||||
file. */
|
||||
g_free(capture_opts->save_file);
|
||||
capture_opts->save_file = NULL;
|
||||
} else {
|
||||
/* this is a normal mode capture, read in the capture file data */
|
||||
capture_read(capture_opts, cf_is_tempfile(capture_opts->cf), cf_get_drops_known(capture_opts->cf), cf_get_drops(capture_opts->cf));
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -621,7 +517,6 @@ sync_pipe_input_cb(gint source, gpointer user_data)
|
|||
char buffer[BUFSIZE+1], *p = buffer, *q = buffer, *msg, *r;
|
||||
int nread, msglen, chars_to_copy;
|
||||
int to_read = 0;
|
||||
int err;
|
||||
|
||||
|
||||
/* we are a capture parent */
|
||||
|
@ -631,7 +526,8 @@ sync_pipe_input_cb(gint source, gpointer user_data)
|
|||
/* The child has closed the sync pipe, meaning it's not going to be
|
||||
capturing any more packets. Pick up its exit status, and
|
||||
complain if it did anything other than exit with status 0. */
|
||||
sync_pipe_closed(capture_opts);
|
||||
sync_pipe_wait_for_child(capture_opts, FALSE);
|
||||
capture_input_closed(capture_opts);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -711,12 +607,18 @@ sync_pipe_input_cb(gint source, gpointer user_data)
|
|||
}
|
||||
*r = '\0';
|
||||
|
||||
/* save the new filename */
|
||||
if(capture_opts->save_file != NULL) {
|
||||
g_free(capture_opts->save_file);
|
||||
if(!capture_input_new_file(capture_opts, msg)) {
|
||||
/* We weren't able to open the new capture file; user has been
|
||||
alerted. Close the sync pipe. */
|
||||
/* close(sync_pipe[PIPE_READ]);*/
|
||||
|
||||
/* XXX - how to kill things here ? */
|
||||
/* XXX - is it safe to close the pipe inside this callback? */
|
||||
close(source);
|
||||
}
|
||||
capture_opts->save_file = g_strdup(msg);
|
||||
|
||||
g_free(msg);
|
||||
|
||||
break;
|
||||
default :
|
||||
q++;
|
||||
|
@ -725,28 +627,7 @@ sync_pipe_input_cb(gint source, gpointer user_data)
|
|||
}
|
||||
}
|
||||
|
||||
if(capture_opts->sync_mode) {
|
||||
/* Read from the capture file the number of records the child told us
|
||||
it added.
|
||||
XXX - do something if this fails? */
|
||||
switch (cf_continue_tail(capture_opts->cf, to_read, &err)) {
|
||||
|
||||
case CF_READ_OK:
|
||||
case CF_READ_ERROR:
|
||||
/* Just because we got an error, that doesn't mean we were unable
|
||||
to read any of the file; we handle what we could get from the
|
||||
file.
|
||||
|
||||
XXX - abort on a read error? */
|
||||
break;
|
||||
|
||||
case CF_READ_ABORTED:
|
||||
/* Kill the child capture process; the user wants to exit, and we
|
||||
shouldn't just leave it running. */
|
||||
capture_kill_child(capture_opts);
|
||||
break;
|
||||
}
|
||||
}
|
||||
capture_input_new_packets(capture_opts, to_read);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
6
file.c
6
file.c
|
@ -659,6 +659,12 @@ cf_is_tempfile(capture_file *cf)
|
|||
return cf->is_tempfile;
|
||||
}
|
||||
|
||||
void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
|
||||
{
|
||||
cf->is_tempfile = is_tempfile;
|
||||
}
|
||||
|
||||
|
||||
/* XXX - use a macro instead? */
|
||||
void cf_set_drops_known(capture_file *cf, gboolean drops_known)
|
||||
{
|
||||
|
|
5
file.h
5
file.h
|
@ -182,6 +182,11 @@ int cf_packet_count(capture_file *cf);
|
|||
*/
|
||||
gboolean cf_is_tempfile(capture_file *cf);
|
||||
|
||||
/**
|
||||
* Set flag, that this file is a tempfile.
|
||||
*/
|
||||
void cf_set_tempfile(capture_file *cf, gboolean is_tempfile);
|
||||
|
||||
/**
|
||||
* Set flag, if the number of packet drops while capturing are known or not.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue