In Tethereal, don't save to a temporary file if "-w" isn't specified,

even if doing a live capture; just print the packets without saving
them.

In dumpcap:

	default to the capturing the entire packet;

	don't do the "Press any key" stuff when debugging on UN*X;

	do console logging (to the standard error) even when we're
	running as the capture child (the sync pipe should only be the
	standard output, not the standard error).

svn path=/trunk/; revision=17786
This commit is contained in:
Guy Harris 2006-04-03 00:52:59 +00:00
parent 2376539aab
commit 2de9620eea
6 changed files with 137 additions and 121 deletions

View File

@ -300,6 +300,7 @@ cap_pipe_open_live(char *pipename, struct pcap_hdr *hdr, loop_data *ld,
hdr->snaplen = BSWAP32(hdr->snaplen);
hdr->network = BSWAP32(hdr->network);
}
ld->linktype = hdr->network;
if (hdr->version_major < 2) {
g_snprintf(errmsg, errmsgl, "Unable to read old libpcap format");
@ -540,11 +541,11 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
if (set_linktype_err_str != NULL) {
g_snprintf(errmsg, errmsg_len, "Unable to set data link type (%s).",
set_linktype_err_str);
g_snprintf(secondary_errmsg, secondary_errmsg_len,
"Please report this to the Ethereal developers");
g_snprintf(secondary_errmsg, secondary_errmsg_len, please_report);
return FALSE;
}
}
ld->linktype = get_pcap_linktype(ld->pcap_h, capture_opts->iface);
} else {
/* We couldn't open "iface" as a network device. */
#ifdef _WIN32
@ -725,27 +726,23 @@ initfilter_status_t capture_loop_init_filter(pcap_t *pcap_h, gboolean from_cap_p
/* set up to write to the already-opened capture output file/files */
gboolean capture_loop_init_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;
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_init_output");
/* get packet encapsulation type and snaplen */
/* get snaplen */
#ifndef _WIN32
if (ld->from_cap_pipe) {
pcap_encap = ld->cap_pipe_hdr.network;
file_snaplen = ld->cap_pipe_hdr.snaplen;
} else
#endif
{
pcap_encap = get_pcap_linktype(ld->pcap_h, capture_opts->iface);
file_snaplen = pcap_snapshot(ld->pcap_h);
}
/* Set up to write to the capture file. */
ld->linktype = pcap_encap;
if (capture_opts->multi_files_on) {
ld->pdh = ringbuf_init_libpcap_fdopen(ld->linktype, file_snaplen, &err);
} else {
@ -1118,7 +1115,7 @@ capture_loop_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, capture_loop_stop_signal_handler);
signal(SIGUSR1, capture_loop_stop_signal_handler);
#endif
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop starting ...");
@ -1149,17 +1146,19 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
goto error;
}
/* open the output file (temporary/specified name/ringbuffer) */
if (!capture_loop_open_output(capture_opts, &save_file_fd, errmsg, sizeof(errmsg))) {
*secondary_errmsg = '\0';
goto error;
}
/* If we're supposed to write to a capture file, open it for output
(temporary/specified name/ringbuffer) */
if (capture_opts->saving_to_file) {
if (!capture_loop_open_output(capture_opts, &save_file_fd, errmsg, sizeof(errmsg))) {
*secondary_errmsg = '\0';
goto error;
}
/* set up to write to the already-opened capture output file/files */
if (!capture_loop_init_output(capture_opts, save_file_fd, &ld, errmsg, sizeof(errmsg))) {
*secondary_errmsg = '\0';
goto error;
}
/* set up to write to the already-opened capture output file/files */
if (!capture_loop_init_output(capture_opts, save_file_fd, &ld, errmsg, sizeof(errmsg))) {
*secondary_errmsg = '\0';
goto error;
}
/* XXX - capture SIGTERM and close the capture, in case we're on a
Linux 2.0[.x] system and you have to explicitly close the capture
@ -1167,15 +1166,16 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
in other places as well - and I don't think that works all the
time in any case, due to libpcap bugs. */
/* Well, we should be able to start capturing.
/* Well, we should be able to start capturing.
Sync out the capture file, so the header makes it to the file system,
and send a "capture started successfully and capture file created"
message to our parent so that they'll open the capture file and
update its windows to indicate that we have a live capture in
progress. */
libpcap_dump_flush(ld.pdh, NULL);
sync_pipe_filename_to_parent(capture_opts->save_file);
Sync out the capture file, so the header makes it to the file system,
and send a "capture started successfully and capture file created"
message to our parent so that they'll open the capture file and
update its windows to indicate that we have a live capture in
progress. */
libpcap_dump_flush(ld.pdh, NULL);
sync_pipe_filename_to_parent(capture_opts->save_file);
}
/* initialize capture stop (and alike) conditions */
init_capture_stop_conditions();
@ -1220,18 +1220,20 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
inpkts_to_sync_pipe += inpkts;
/* check capture size condition */
if (cnd_autostop_size != NULL && cnd_eval(cnd_autostop_size,
(guint32)ld.bytes_written)){
if (cnd_autostop_size != NULL &&
cnd_eval(cnd_autostop_size, (guint32)ld.bytes_written)){
/* Capture size limit reached, do we have another file? */
if (capture_opts->multi_files_on) {
if (cnd_autostop_files != NULL && cnd_eval(cnd_autostop_files, ++autostop_files)) {
/* no files left: stop here */
if (cnd_autostop_files != NULL &&
cnd_eval(cnd_autostop_files, ++autostop_files)) {
/* no files left: stop here */
ld.go = FALSE;
continue;
}
/* Switch to the next ringbuffer file */
if (ringbuf_switch_file(&ld.pdh, &capture_opts->save_file, &save_file_fd, &ld.err)) {
if (ringbuf_switch_file(&ld.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) {
@ -1293,7 +1295,8 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
if (cnd_file_duration != NULL && cnd_eval(cnd_file_duration)) {
/* duration limit reached, do we have another file? */
if (capture_opts->multi_files_on) {
if (cnd_autostop_files != NULL && cnd_eval(cnd_autostop_files, ++autostop_files)) {
if (cnd_autostop_files != NULL &&
cnd_eval(cnd_autostop_files, ++autostop_files)) {
/* no files left: stop here */
ld.go = FALSE;
continue;
@ -1311,7 +1314,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
sync_pipe_filename_to_parent(capture_opts->save_file);
} else {
/* File switch failed: stop here */
ld.go = FALSE;
ld.go = FALSE;
continue;
}
} else {
@ -1357,8 +1360,11 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
write_ok = FALSE;
}
/* close the wiretap (output) file */
close_ok = capture_loop_close_output(capture_opts, &ld, &err_close);
if (capture_opts->saving_to_file) {
/* close the wiretap (output) file */
close_ok = capture_loop_close_output(capture_opts, &ld, &err_close);
} else
close_ok = TRUE;
/* there might be packets not yet notified to the parent */
/* (do this after closing the file, so all packets are already flushed) */

View File

@ -52,16 +52,17 @@ void
capture_opts_init(capture_options *capture_opts, void *cfile)
{
capture_opts->cf = cfile;
capture_opts->cfilter = g_strdup(""); /* No capture filter string specified */
capture_opts->cfilter = g_strdup(""); /* No capture filter string specified */
capture_opts->iface = NULL; /* Default is "pick the first interface" */
#ifdef _WIN32
capture_opts->buffer_size = 1; /* 1 MB */
#endif
capture_opts->has_snaplen = FALSE;
capture_opts->snaplen = WTAP_MAX_PACKET_SIZE; /* snapshot length - default is
infinite, in effect */
infinite, in effect */
capture_opts->promisc_mode = TRUE; /* promiscuous mode is the default */
capture_opts->linktype = -1; /* the default linktype */
capture_opts->saving_to_file = FALSE;
capture_opts->save_file = NULL;
capture_opts->real_time_mode = TRUE;
capture_opts->show_info = TRUE;
@ -106,6 +107,7 @@ capture_opts_log(const char *log_domain, GLogLevelFlags log_level, capture_optio
g_log(log_domain, log_level, "SnapLen (%u): %u", capture_opts->has_snaplen, capture_opts->snaplen);
g_log(log_domain, log_level, "Promisc : %u", capture_opts->promisc_mode);
g_log(log_domain, log_level, "LinkType : %d", capture_opts->linktype);
g_log(log_domain, log_level, "SavingToFile : %u", capture_opts->saving_to_file);
g_log(log_domain, log_level, "SaveFile : %s", (capture_opts->save_file) ? capture_opts->save_file : "");
g_log(log_domain, log_level, "RealTimeMode : %u", capture_opts->real_time_mode);
g_log(log_domain, log_level, "ShowInfo : %u", capture_opts->show_info);
@ -223,7 +225,7 @@ get_ring_arguments(capture_options *capture_opts, const char *arg)
capture_opts->file_duration = get_positive_int(p, "ring buffer duration");
}
*colonp = ':'; /* put the colon back */
*colonp = ':'; /* put the colon back */
return TRUE;
}
@ -355,6 +357,7 @@ capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg,
capture_opts->real_time_mode = TRUE;
break;
case 'w': /* Write to capture file x */
capture_opts->saving_to_file = TRUE;
#if defined _WIN32 && (GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 6))
/* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
capture_opts->save_file = g_locale_to_utf8(optarg, -1, NULL, NULL, NULL);
@ -363,7 +366,7 @@ capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg,
#endif
status = capture_opts_output_to_pipe(capture_opts->save_file, &capture_opts->output_to_pipe);
return status;
break;
break;
case 'y': /* Set the pcap data link type */
#ifdef HAVE_PCAP_DATALINK_NAME_TO_VAL
capture_opts->linktype = linktype_name_to_val(optarg);
@ -396,11 +399,11 @@ int capture_opts_list_link_layer_types(capture_options *capture_opts)
lt_list = get_pcap_linktype_list(capture_opts->iface, err_str);
if (lt_list == NULL) {
if (err_str[0] != '\0') {
cmdarg_err("The list of data link types for the capture device \"%s\" could not be obtained (%s)."
"Please check to make sure you have sufficient permissions, and that\n"
"you have the proper interface or pipe specified.\n", capture_opts->iface, err_str);
cmdarg_err("The list of data link types for the capture device \"%s\" could not be obtained (%s)."
"Please check to make sure you have sufficient permissions, and that\n"
"you have the proper interface or pipe specified.\n", capture_opts->iface, err_str);
} else
cmdarg_err("The capture device \"%s\" has no data link types.", capture_opts->iface);
cmdarg_err("The capture device \"%s\" has no data link types.", capture_opts->iface);
return 2;
}
cmdarg_err_cont("Data link types (use option -y to set):");
@ -409,9 +412,9 @@ int capture_opts_list_link_layer_types(capture_options *capture_opts)
data_link_info = lt_entry->data;
cmdarg_err_cont(" %s", data_link_info->name);
if (data_link_info->description != NULL)
cmdarg_err_cont(" (%s)", data_link_info->description);
cmdarg_err_cont(" (%s)", data_link_info->description);
else
cmdarg_err_cont(" (not supported)");
cmdarg_err_cont(" (not supported)");
putchar('\n');
}
free_pcap_linktype_list(lt_list);

View File

@ -35,9 +35,9 @@
/* Current state of capture engine. XXX - differentiate states */
typedef enum {
CAPTURE_STOPPED, /**< stopped */
CAPTURE_STOPPED, /**< stopped */
CAPTURE_PREPARING, /**< preparing, but still no response from capture child */
CAPTURE_RUNNING /**< capture child signalled ok, capture is running now */
CAPTURE_RUNNING /**< capture child signalled ok, capture is running now */
} capture_state;
@ -57,6 +57,7 @@ typedef struct capture_options_tag {
gboolean promisc_mode; /**< Capture in promiscuous mode */
int linktype; /**< Data link type to use, or -1 for
"use default" */
gboolean saving_to_file; /**< TRUE if capture is writing to a file */
gchar *save_file; /**< the capture file name */
/* GUI related */
@ -68,18 +69,18 @@ typedef struct capture_options_tag {
/* multiple files (and ringbuffer) */
gboolean multi_files_on; /**< TRUE if ring buffer in use */
gboolean has_file_duration; /**< TRUE if ring duration specified */
gboolean has_file_duration; /**< TRUE if ring duration specified */
gint32 file_duration; /* Switch file after n seconds */
gboolean has_ring_num_files;/**< TRUE if ring num_files specified */
guint32 ring_num_files; /**< Number of multiple buffer files */
/* autostop conditions */
gboolean has_autostop_files;/**< TRUE if maximum number of capture files
are specified */
are specified */
gint32 autostop_files; /**< Maximum number of capture files */
gboolean has_autostop_packets; /**< TRUE if maximum packet count is
specified */
gboolean has_autostop_packets; /**< TRUE if maximum packet count is
specified */
int autostop_packets; /**< Maximum packet count */
gboolean has_autostop_filesize; /**< TRUE if maximum capture file size
is specified */
@ -89,7 +90,7 @@ typedef struct capture_options_tag {
gint32 autostop_duration; /**< Maximum capture duration */
/* internally used (don't touch from outside) */
int fork_child; /**< If not -1, in parent, process ID of child */
int fork_child; /**< If not -1, in parent, process ID of child */
#ifdef _WIN32
int signal_pipe_write_fd; /**< the pipe to signal the child */
#endif

View File

@ -206,7 +206,6 @@ void exit_main(int status)
#ifdef _WIN32
/* Shutdown windows sockets */
WSACleanup();
#endif
/* can be helpful for debugging */
#ifdef DEBUG_DUMPCAP
@ -214,6 +213,8 @@ void exit_main(int status)
_getch();
#endif
#endif /* _WIN32 */
exit(status);
}
@ -303,7 +304,12 @@ main(int argc, char *argv[])
by the command line parameters. */
capture_opts_init(capture_opts, NULL);
capture_opts->snaplen = MIN_PACKET_SIZE;
/* Default to capturing the entire packet. */
capture_opts->snaplen = WTAP_MAX_PACKET_SIZE;
/* We always save to a file - if no file was specified, we save to a
temporary file. */
capture_opts->saving_to_file = TRUE;
capture_opts->has_ring_num_files = TRUE;
/* Now get our args */
@ -447,10 +453,6 @@ console_log_handler(const char *log_domain, GLogLevelFlags log_level,
const char *level;
if(capture_child) {
return;
}
/* ignore log message, if log_level isn't interesting */
if( !(log_level & G_LOG_LEVEL_MASK & ~(G_LOG_LEVEL_DEBUG|G_LOG_LEVEL_INFO))) {
#ifndef DEBUG_DUMPCAP
@ -462,44 +464,44 @@ console_log_handler(const char *log_domain, GLogLevelFlags log_level,
time(&curr);
today = localtime(&curr);
switch(log_level & G_LOG_LEVEL_MASK) {
case G_LOG_LEVEL_ERROR:
level = "Err ";
break;
case G_LOG_LEVEL_CRITICAL:
level = "Crit";
break;
case G_LOG_LEVEL_WARNING:
level = "Warn";
break;
case G_LOG_LEVEL_MESSAGE:
level = "Msg ";
break;
case G_LOG_LEVEL_INFO:
level = "Info";
break;
case G_LOG_LEVEL_DEBUG:
level = "Dbg ";
break;
default:
fprintf(stderr, "unknown log_level %u\n", log_level);
level = NULL;
g_assert_not_reached();
}
switch(log_level & G_LOG_LEVEL_MASK) {
case G_LOG_LEVEL_ERROR:
level = "Err ";
break;
case G_LOG_LEVEL_CRITICAL:
level = "Crit";
break;
case G_LOG_LEVEL_WARNING:
level = "Warn";
break;
case G_LOG_LEVEL_MESSAGE:
level = "Msg ";
break;
case G_LOG_LEVEL_INFO:
level = "Info";
break;
case G_LOG_LEVEL_DEBUG:
level = "Dbg ";
break;
default:
fprintf(stderr, "unknown log_level %u\n", log_level);
level = NULL;
g_assert_not_reached();
}
/* don't use printf (stdout), in child mode we're using stdout for the sync_pipe */
if(log_level & G_LOG_LEVEL_MESSAGE) {
/* normal user messages without additional infos */
fprintf(stderr, "%s\n", message);
fflush(stderr);
} else {
/* info/debug messages with additional infos */
fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
today->tm_hour, today->tm_min, today->tm_sec,
log_domain != NULL ? log_domain : "",
level, message);
fflush(stderr);
}
/* don't use printf (stdout), in child mode we're using stdout for the sync_pipe */
if(log_level & G_LOG_LEVEL_MESSAGE) {
/* normal user messages without additional infos */
fprintf(stderr, "%s\n", message);
fflush(stderr);
} else {
/* info/debug messages with additional infos */
fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
today->tm_hour, today->tm_min, today->tm_sec,
log_domain != NULL ? log_domain : "",
level, message);
fflush(stderr);
}
}

View File

@ -1398,6 +1398,8 @@ capture_dlg_prep(gpointer parent_w) {
g_assert(filter_text != NULL);
capture_opts->cfilter = g_strdup(filter_text);
/* Ethereal always saves to a capture file. */
capture_opts->save_file = TRUE;
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. */

View File

@ -1103,22 +1103,22 @@ main(int argc, char *argv[])
}
}
/* If we're not writing to a file and "-q" wasn't specified
we should print packet information */
if (capture_opts.save_file == NULL && !quiet)
print_packet_info = TRUE;
if (capture_opts.save_file != NULL &&
strcmp(capture_opts.save_file, "-") == 0
&& print_packet_info) {
/* If we're writing to the standard output.
and we'll also be writing dissected packets to the standard
output, reject the request. At best, we could redirect that
to the standard error; we *can't* write both to the standard
output and have either of them be useful. */
if (!capture_opts.saving_to_file) {
/* We're not saving the capture to a file; if "-q" wasn't specified,
we should print packet information */
if (!quiet)
print_packet_info = TRUE;
} else {
/* We're saving to a file; if we're writing to the standard output.
and we'll also be writing dissected packets to the standard
output, reject the request. At best, we could redirect that
to the standard error; we *can't* write both to the standard
output and have either of them be useful. */
if (strcmp(capture_opts.save_file, "-") == 0 && print_packet_info) {
cmdarg_err("You can't write both raw packet data and dissected packets"
" to the standard output.");
exit(1);
}
}
#ifndef HAVE_LIBPCAP
@ -1217,7 +1217,7 @@ main(int argc, char *argv[])
/*
* "-r" wasn't specified, so we're doing a live capture.
*/
if (capture_opts.save_file != NULL) {
if (capture_opts.saving_to_file) {
/* They specified a "-w" flag, so we'll be saving to a capture file. */
/* When capturing, we only support writing libpcap format. */
@ -1568,23 +1568,25 @@ capture(void)
goto error;
}
/* open the output file (temporary/specified name/ringbuffer/named pipe/stdout) */
if (!capture_loop_open_output(&capture_opts, &save_file_fd, errmsg, sizeof(errmsg))) {
*secondary_errmsg = '\0';
goto error;
}
if (capture_opts.saving_to_file) {
/* open the output file (temporary/specified name/ringbuffer/named pipe/stdout) */
if (!capture_loop_open_output(&capture_opts, &save_file_fd, errmsg, sizeof(errmsg))) {
*secondary_errmsg = '\0';
goto error;
}
/* set up to write to the already-opened capture output file/files */
if(!capture_loop_init_output(&capture_opts, save_file_fd, &ld, errmsg, sizeof errmsg)) {
*secondary_errmsg = '\0';
goto error;
/* set up to write to the already-opened capture output file/files */
if(!capture_loop_init_output(&capture_opts, save_file_fd, &ld, errmsg, sizeof errmsg)) {
*secondary_errmsg = '\0';
goto error;
}
/* Save the capture file name. */
ld.save_file = capture_opts.save_file;
}
ld.wtap_linktype = wtap_pcap_encap_to_wtap_encap(ld.linktype);
/* Save the capture file name. */
ld.save_file = capture_opts.save_file;
#ifdef _WIN32
/* Catch a CTRL+C event and, if we get it, clean up and exit. */
SetConsoleCtrlHandler(capture_cleanup, TRUE);