diff --git a/capture_loop.c b/capture_loop.c index 445a6f7a74..8394e5ac96 100644 --- a/capture_loop.c +++ b/capture_loop.c @@ -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) */ diff --git a/capture_opts.c b/capture_opts.c index ad7d1c1b9f..3f0c27cb33 100644 --- a/capture_opts.c +++ b/capture_opts.c @@ -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); diff --git a/capture_opts.h b/capture_opts.h index 8c3b85eff4..8bf3d14a33 100644 --- a/capture_opts.h +++ b/capture_opts.h @@ -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 diff --git a/dumpcap.c b/dumpcap.c index 9d30e8d727..9e1fcbaa81 100644 --- a/dumpcap.c +++ b/dumpcap.c @@ -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); + } } diff --git a/gtk/capture_dlg.c b/gtk/capture_dlg.c index 708c85bf16..7622752c8b 100644 --- a/gtk/capture_dlg.c +++ b/gtk/capture_dlg.c @@ -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. */ diff --git a/tethereal.c b/tethereal.c index 9b763d1a59..f27718d1bc 100644 --- a/tethereal.c +++ b/tethereal.c @@ -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);