From 0a9ef601d201f87ff3effb8aca62c61184fd6146 Mon Sep 17 00:00:00 2001 From: Guy Harris Date: Wed, 14 Jul 2021 22:16:30 -0700 Subject: [PATCH] Clean up handling of --capture-comment. Don't store the comments in a capture_options structure, because that's available only if we're being built with capture support, and --capture-comment can be used in TShark when reading a capture file and writing another capture file, with no live capture taking place. This means we don't handle that option in capture_opts_add_opt(); handle it in the programs that support it. Support writing multiple comments in dumpcap when capturing. These changes also fix builds without pcap, and makes --capture-comment work in Wireshark when a capture is started from the command line with -k. Update the help messages to indicate that --capture-comment adds a capture comment, it doesn't change any comment (much less "the" comment, as there isn't necessarily a single comment). Update the man pages: - not to presume that only pcapng files support file comments (even if that's true now, it might not be true in the future); - to note that multiple instances of --capture-comment are supported, and that multiple comments will be written, whether capturing or reading one file and writing another; - clarify that Wireshark doesn't *discard* SHB comments other than the first one, even though it only displays the first one; --- capture/capture_sync.c | 10 ++++--- capture/capture_sync.h | 6 +++- capture_opts.c | 11 ------- capture_opts.h | 10 ++----- doc/dumpcap.pod | 9 ++++-- doc/editcap.pod | 10 +++---- doc/tshark.pod | 10 +++---- doc/wireshark.pod | 7 ++++- dumpcap.c | 18 +++++++---- text2pcap.c | 7 +++-- tshark.c | 60 ++++++++++++++++++++----------------- ui/capture.c | 7 +++-- ui/capture.h | 6 +++- ui/commandline.c | 18 ++++++++++- ui/commandline.h | 7 +++++ ui/qt/main.cpp | 4 ++- ui/qt/main_window_slots.cpp | 3 +- writecap/pcapio.c | 21 +++++++++---- writecap/pcapio.h | 4 +-- 19 files changed, 142 insertions(+), 86 deletions(-) diff --git a/capture/capture_sync.c b/capture/capture_sync.c index ad7fbca89f..4352521fe3 100644 --- a/capture/capture_sync.c +++ b/capture/capture_sync.c @@ -204,7 +204,9 @@ init_pipe_args(int *argc) { #define ARGV_NUMBER_LEN 24 /* a new capture run: start a new dumpcap task and hand over parameters through command line */ gboolean -sync_pipe_start(capture_options *capture_opts, capture_session *cap_session, info_data_t* cap_data, void (*update_cb)(void)) +sync_pipe_start(capture_options *capture_opts, GPtrArray *capture_comments, + capture_session *cap_session, info_data_t* cap_data, + void (*update_cb)(void)) { #ifdef _WIN32 HANDLE sync_pipe_read; /* pipe used to send messages from child to parent */ @@ -257,10 +259,10 @@ sync_pipe_start(capture_options *capture_opts, capture_session *cap_session, inf else argv = sync_pipe_add_arg(argv, &argc, "-P"); - if (capture_opts->capture_comment) { - for (j = 0; j < capture_opts->capture_comment->len; j++) { + if (capture_comments != NULL) { + for (j = 0; j < capture_comments->len; j++) { argv = sync_pipe_add_arg(argv, &argc, "--capture-comment"); - argv = sync_pipe_add_arg(argv, &argc, (char*)g_ptr_array_index(capture_opts->capture_comment, j)); + argv = sync_pipe_add_arg(argv, &argc, (char*)g_ptr_array_index(capture_comments, j)); } } diff --git a/capture/capture_sync.h b/capture/capture_sync.h index b2c6751eff..2d7b8e116b 100644 --- a/capture/capture_sync.h +++ b/capture/capture_sync.h @@ -35,13 +35,17 @@ struct _info_data; * Most of the parameters are passed through the global capture_opts. * * @param capture_opts the options + * @param capture_comments if not NULL, a GPtrArray * to a set of comments + * to put in the capture file's Section Header Block if it's a pcapng file * @param cap_session a handle for the capture session * @param cap_data a struct with capture info data * @param update_cb update screen * @return TRUE if a capture could be started, FALSE if not */ extern gboolean -sync_pipe_start(capture_options *capture_opts, capture_session *cap_session, struct _info_data* cap_data, void(*update_cb)(void)); +sync_pipe_start(capture_options *capture_opts, GPtrArray *capture_comments, + capture_session *cap_session, struct _info_data* cap_data, + void(*update_cb)(void)); /** User wants to stop capturing, gracefully close the capture child */ extern void diff --git a/capture_opts.c b/capture_opts.c index e87bc9f653..504560caee 100644 --- a/capture_opts.c +++ b/capture_opts.c @@ -115,7 +115,6 @@ capture_opts_init(capture_options *capture_opts) capture_opts->autostop_filesize = 1000; /* 1 MB */ capture_opts->has_autostop_duration = FALSE; capture_opts->autostop_duration = 60.0; /* 1 min */ - capture_opts->capture_comment = NULL; capture_opts->output_to_pipe = FALSE; capture_opts->capture_child = FALSE; @@ -147,10 +146,6 @@ capture_opts_cleanup(capture_options *capture_opts) capture_opts->all_ifaces = NULL; } g_free(capture_opts->save_file); - if (capture_opts->capture_comment != NULL) { - g_ptr_array_free(capture_opts->capture_comment, TRUE); - capture_opts->capture_comment = NULL; - } } /* log content of capture_opts */ @@ -803,12 +798,6 @@ capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg_ int status, snaplen; switch(opt) { - case LONGOPT_CAPTURE_COMMENT: /* capture comment */ - if (!capture_opts->capture_comment) { - capture_opts->capture_comment = g_ptr_array_new_with_free_func(g_free); - } - g_ptr_array_add(capture_opts->capture_comment, g_strdup(optarg_str_p)); - break; case 'a': /* autostop criteria */ if (set_autostop_criterion(capture_opts, optarg_str_p) == FALSE) { cmdarg_err("Invalid or unknown -a flag \"%s\"", optarg_str_p); diff --git a/capture_opts.h b/capture_opts.h index 1452f30484..660a9746bd 100644 --- a/capture_opts.h +++ b/capture_opts.h @@ -44,10 +44,9 @@ extern "C" { * In short: we must not use 1 here, which is another reason to use * values outside the range of ASCII graphic characters. */ -#define LONGOPT_CAPTURE_COMMENT LONGOPT_BASE_CAPTURE+1 -#define LONGOPT_LIST_TSTAMP_TYPES LONGOPT_BASE_CAPTURE+2 -#define LONGOPT_SET_TSTAMP_TYPE LONGOPT_BASE_CAPTURE+3 -#define LONGOPT_COMPRESS_TYPE LONGOPT_BASE_CAPTURE+4 +#define LONGOPT_LIST_TSTAMP_TYPES LONGOPT_BASE_CAPTURE+1 +#define LONGOPT_SET_TSTAMP_TYPE LONGOPT_BASE_CAPTURE+2 +#define LONGOPT_COMPRESS_TYPE LONGOPT_BASE_CAPTURE+3 /* * Options for capturing common to all capturing programs. @@ -76,7 +75,6 @@ extern "C" { #endif #define LONGOPT_CAPTURE_COMMON \ - {"capture-comment", required_argument, NULL, LONGOPT_CAPTURE_COMMENT}, \ {"autostop", required_argument, NULL, 'a'}, \ {"ring-buffer", required_argument, NULL, 'b'}, \ LONGOPT_BUFFER_SIZE \ @@ -313,8 +311,6 @@ typedef struct capture_options_tag { is specified */ gdouble autostop_duration; /**< Maximum capture duration */ - GPtrArray *capture_comment; /** capture comment to write to the - output file */ gboolean print_file_names; /**< TRUE if printing names of completed files as we close them */ gchar *print_name_to; /**< output file name */ diff --git a/doc/dumpcap.pod b/doc/dumpcap.pod index 19d16c5dfd..c5f043f44c 100644 --- a/doc/dumpcap.pod +++ b/doc/dumpcap.pod @@ -419,11 +419,14 @@ the default capture link type is used if provided. =item --capture-comment EcommentE -Add a capture comment to the output file. +Add a capture comment to the output file, if supported by the output +file format. This option is only available if we output the captured packets to a -single file in pcapng format. Only one capture comment may be set per -output file. +single file. + +This option may be specified multiple times. Note that Wireshark +currently only displays the first comment of a capture file. =item --list-time-stamp-types diff --git a/doc/editcap.pod b/doc/editcap.pod index 1d7f520e1e..cf8bcb5f16 100644 --- a/doc/editcap.pod +++ b/doc/editcap.pod @@ -375,12 +375,12 @@ the same command line. =item --capture-comment EcommentE -Adds the given comment to the Section Header Block (SHB) of the pcapng -output file. New comments will be added I any comments present in the -input file unless B<--discard-capture-comment> is also specified. +Adds the given comment to the output file, if supported by the output +file format. New comments will be added I any comments present +in the input file unless B<--discard-capture-comment> is also specified. -This option may be specified multiple times. Note that Wireshark currently only -recognizes the first comment of a capture file. +This option may be specified multiple times. Note that Wireshark +currently only displays the first comment of a capture file. =item --discard-capture-comment diff --git a/doc/tshark.pod b/doc/tshark.pod index 5548b1a971..e0059d43cf 100644 --- a/doc/tshark.pod +++ b/doc/tshark.pod @@ -1728,13 +1728,11 @@ SMB packets exchanged by the host at IP address 1.2.3.4 . =item --capture-comment EcommentE -Add a capture comment to the output file. +Add a capture comment to the output file, if supported by the output +file format. -This option is only available if a new output file in pcapng format is -created. - -This option may be specified multiple times. Note that Wireshark currently only -recognizes the first comment of a capture file. +This option may be specified multiple times. Note that Wireshark +currently only displays the first comment of a capture file. =item --list-time-stamp-types diff --git a/doc/wireshark.pod b/doc/wireshark.pod index c94814901a..f9b91b19b3 100644 --- a/doc/wireshark.pod +++ b/doc/wireshark.pod @@ -319,7 +319,12 @@ Start with the given configuration profile. =item --capture-comment EcommentE -Set the capture file comment, if supported by the capture format. +When performing a capture file from the command line, with the B<-k> +flag, add a capture comment to the output file, if supported by the +capture format. + +This option may be specified multiple times. Note that Wireshark +currently only displays the first comment of a capture file. =item -d Elayer typeE==EselectorE,Edecode-as protocolE diff --git a/dumpcap.c b/dumpcap.c index e54725520a..e8e8323429 100644 --- a/dumpcap.c +++ b/dumpcap.c @@ -336,6 +336,7 @@ dumpcap_log_writer(const char *domain, enum ws_log_level level, /* capture related options */ static capture_options global_capture_opts; +static GPtrArray *capture_comments = NULL; static gboolean quiet = FALSE; static gboolean use_threads = FALSE; static guint64 start_time; @@ -3099,7 +3100,7 @@ capture_loop_init_pcapng_output(capture_options *capture_opts, loop_data *ld, get_cpu_info(cpu_info_str); successful = pcapng_write_section_header_block(ld->pdh, - (const char *)capture_opts->capture_comment, /* Comment */ + capture_comments, /* Comments */ cpu_info_str->str, /* HW */ os_info_str->str, /* OS */ get_appname_and_version(), @@ -4815,6 +4816,7 @@ get_dumpcap_runtime_info(GString *str) #define LONGOPT_IFNAME LONGOPT_BASE_APPLICATION+1 #define LONGOPT_IFDESCR LONGOPT_BASE_APPLICATION+2 +#define LONGOPT_CAPTURE_COMMENT LONGOPT_BASE_APPLICATION+3 /* And now our feature presentation... [ fade to music ] */ int @@ -4828,6 +4830,7 @@ main(int argc, char *argv[]) LONGOPT_CAPTURE_COMMON {"ifname", required_argument, NULL, LONGOPT_IFNAME}, {"ifdescr", required_argument, NULL, LONGOPT_IFDESCR}, + {"capture-comment", required_argument, NULL, LONGOPT_CAPTURE_COMMENT}, {0, 0, 0, 0 } }; @@ -5139,7 +5142,6 @@ main(int argc, char *argv[]) case 's': /* Set the snapshot (capture) length */ case 'w': /* Write to capture file x */ case 'y': /* Set the pcap data link type */ - case LONGOPT_CAPTURE_COMMENT: /* add a capture comment */ #ifdef HAVE_PCAP_REMOTE case 'u': /* Use UDP for data transfer */ case 'r': /* Capture own RPCAP traffic too */ @@ -5183,6 +5185,12 @@ main(int argc, char *argv[]) exit_main(1); } break; + case LONGOPT_CAPTURE_COMMENT: /* capture comment */ + if (capture_comments == NULL) { + capture_comments = g_ptr_array_new_with_free_func(g_free); + } + g_ptr_array_add(capture_comments, g_strdup(optarg)); + break; case 'Z': capture_child = TRUE; #ifdef _WIN32 @@ -5319,10 +5327,10 @@ main(int argc, char *argv[]) global_capture_opts.use_pcapng = TRUE; } - if (global_capture_opts.capture_comment && + if (capture_comments && (!global_capture_opts.use_pcapng || global_capture_opts.multi_files_on)) { - /* XXX - for ringbuffer, should we apply the comment to each file? */ - cmdarg_err("A capture comment can only be set if we capture into a single pcapng file."); + /* XXX - for ringbuffer, should we apply the comments to each file? */ + cmdarg_err("Capture comments can only be set if we capture into a single pcapng file."); exit_main(1); } diff --git a/text2pcap.c b/text2pcap.c index a706027a86..2b2471f079 100644 --- a/text2pcap.c +++ b/text2pcap.c @@ -883,17 +883,20 @@ write_file_header (void) if (use_pcapng) { char *comment; + GPtrArray *comments; comment = g_strdup_printf("Generated from input file %s.", input_filename); + comments = g_ptr_array_new_with_free_func(g_free); + g_ptr_array_add(comments, comment); success = pcapng_write_section_header_block(output_file, - comment, + comments, NULL, /* HW */ NULL, /* OS */ get_appname_and_version(), -1, /* section_length */ &bytes_written, &err); - g_free(comment); + g_ptr_array_free(comments, TRUE); if (success) { success = pcapng_write_interface_description_block(output_file, NULL, diff --git a/tshark.c b/tshark.c index 7da895d502..7b8071d54c 100644 --- a/tshark.c +++ b/tshark.c @@ -144,6 +144,7 @@ #define LONGOPT_NO_DUPLICATE_KEYS LONGOPT_BASE_APPLICATION+3 #define LONGOPT_ELASTIC_MAPPING_FILTER LONGOPT_BASE_APPLICATION+4 #define LONGOPT_EXPORT_TLS_SESSION_KEYS LONGOPT_BASE_APPLICATION+5 +#define LONGOPT_CAPTURE_COMMENT LONGOPT_BASE_APPLICATION+6 capture_file cfile; @@ -199,6 +200,9 @@ static json_dumper jdumper; /* The line separator used between packets, changeable via the -S option */ static const char *separator = ""; +/* Per-file comments to be added to the output file. */ +static GPtrArray *capture_comments = NULL; + static gboolean prefs_loaded = FALSE; #ifdef HAVE_LIBPCAP @@ -248,7 +252,7 @@ typedef enum { PROCESS_FILE_ERROR, PROCESS_FILE_INTERRUPTED } process_file_status_t; -static process_file_status_t process_cap_file(capture_file *, char *, int, gboolean, capture_options); +static process_file_status_t process_cap_file(capture_file *, char *, int, gboolean, int, gint64); static gboolean process_packet_single_pass(capture_file *cf, epan_dissect_t *edt, gint64 offset, wtap_rec *rec, Buffer *buf, @@ -425,7 +429,7 @@ print_usage(FILE *output) fprintf(output, " -w write packets to a pcapng-format file named \"outfile\"\n"); fprintf(output, " (or '-' for stdout)\n"); fprintf(output, " --capture-comment \n"); - fprintf(output, " set the capture file comment, if supported\n"); + fprintf(output, " add a capture file comment, if supported\n"); fprintf(output, " -C start with specified configuration profile\n"); fprintf(output, " -F set the output file type, default is pcapng\n"); fprintf(output, " an empty \"-F\" option will list the file types\n"); @@ -706,6 +710,7 @@ main(int argc, char *argv[]) {"color", no_argument, NULL, LONGOPT_COLOR}, {"no-duplicate-keys", no_argument, NULL, LONGOPT_NO_DUPLICATE_KEYS}, {"elastic-mapping-filter", required_argument, NULL, LONGOPT_ELASTIC_MAPPING_FILTER}, + {"capture-comment", required_argument, NULL, LONGOPT_CAPTURE_COMMENT}, {0, 0, 0, 0 } }; gboolean arg_error = FALSE; @@ -1100,7 +1105,6 @@ main(int argc, char *argv[]) #endif case 's': /* Set the snapshot (capture) length */ case 'y': /* Set the pcap data link type */ - case LONGOPT_CAPTURE_COMMENT: /* add a capture comment */ #ifdef CAN_SET_CAPTURE_BUFFER_SIZE case 'B': /* Buffer size */ #endif @@ -1476,6 +1480,12 @@ main(int argc, char *argv[]) no_duplicate_keys = TRUE; node_children_grouper = proto_node_group_children_by_json_key; break; + case LONGOPT_CAPTURE_COMMENT: /* capture comment */ + if (capture_comments == NULL) { + capture_comments = g_ptr_array_new_with_free_func(g_free); + } + g_ptr_array_add(capture_comments, g_strdup(optarg)); + break; default: case '?': /* Bad flag - print usage message */ switch(optopt) { @@ -1710,7 +1720,7 @@ main(int argc, char *argv[]) exit_status = INVALID_OPTION; goto clean_exit; } - if (global_capture_opts.capture_comment) { + if (capture_comments != NULL) { if (global_capture_opts.saving_to_file) { /* They specified a "-w" flag, so we'll be saving to a capture file. * This is fine if they're using pcapng. @@ -1767,8 +1777,8 @@ main(int argc, char *argv[]) exit_status = INVALID_OPTION; goto clean_exit; } - if (global_capture_opts.capture_comment && !use_pcapng) { - cmdarg_err("A capture comment can only be written to a pcapng file."); + if (capture_comments != NULL && !use_pcapng) { + cmdarg_err("Capture comments can only be written to a pcapng file."); exit_status = INVALID_OPTION; goto clean_exit; } @@ -1828,8 +1838,8 @@ main(int argc, char *argv[]) exit_status = INVALID_OPTION; goto clean_exit; } - if (global_capture_opts.capture_comment) { - cmdarg_err("A capture comment was specified, but " + if (capture_comments != NULL) { + cmdarg_err("Capture comments were specified, but " "the capture isn't being saved to a file."); exit_status = INVALID_OPTION; goto clean_exit; @@ -2090,13 +2100,14 @@ main(int argc, char *argv[]) /* Process the packets in the file */ ws_debug("tshark: invoking process_cap_file() to process the packets"); TRY { -#ifndef HAVE_LIBPCAP - global_capture_opts.has_autostop_packets = max_packet_count > 0; - global_capture_opts.autostop_packets = max_packet_count; - global_capture_opts.has_autostop_filesize = FALSE; - global_capture_opts.autostop_filesize = 0; + status = process_cap_file(&cfile, output_file_name, out_file_type, out_file_name_res, +#ifdef HAVE_LIBPCAP + global_capture_opts.has_autostop_packets ? global_capture_opts.autostop_packets : 0, + global_capture_opts.has_autostop_filesize ? global_capture_opts.autostop_filesize : 0); +#else + max_packet_count, + 0); #endif - status = process_cap_file(&cfile, output_file_name, out_file_type, out_file_name_res, global_capture_opts); } CATCH(OutOfMemoryError) { fprintf(stderr, @@ -2541,7 +2552,8 @@ capture(void) fflush(stderr); g_string_free(str, TRUE); - ret = sync_pipe_start(&global_capture_opts, &global_capture_session, &global_info_data, NULL); + ret = sync_pipe_start(&global_capture_opts, capture_comments, + &global_capture_session, &global_info_data, NULL); if (!ret) return FALSE; @@ -3535,7 +3547,7 @@ process_cap_file_single_pass(capture_file *cf, wtap_dumper *pdh, static process_file_status_t process_cap_file(capture_file *cf, char *save_file, int out_file_type, - gboolean out_file_name_res, capture_options capture_opts) + gboolean out_file_name_res, int max_packet_count, gint64 max_byte_count) { process_file_status_t status = PROCESS_FILE_SUCCEEDED; wtap_dumper *pdh; @@ -3548,13 +3560,6 @@ process_cap_file(capture_file *cf, char *save_file, int out_file_type, wtap_dump_params params = WTAP_DUMP_PARAMS_INIT; char *shb_user_appl; pass_status_t first_pass_status, second_pass_status; - int max_packet_count = 0; - int max_byte_count = 0; - - if (capture_opts.has_autostop_packets) - max_packet_count = capture_opts.autostop_packets; - if (capture_opts.has_autostop_filesize) - max_byte_count = capture_opts.autostop_filesize; if (save_file != NULL) { /* Set up to write to the capture file. */ @@ -3565,10 +3570,11 @@ process_cap_file(capture_file *cf, char *save_file, int out_file_type, /* this is free'd by wtap_block_unref() later */ wtap_block_add_string_option_format(g_array_index(params.shb_hdrs, wtap_block_t, 0), OPT_SHB_USERAPPL, "%s", get_appname_and_version()); } - if (capture_opts.capture_comment != NULL) { - guint i; - for (i = 0; i < capture_opts.capture_comment->len; i++) { - wtap_block_add_string_option_format(g_array_index(params.shb_hdrs, wtap_block_t, 0), OPT_COMMENT, "%s", (char*)g_ptr_array_index(capture_opts.capture_comment, i)); + if (capture_comments != NULL) { + for (guint i = 0; i < capture_comments->len; i++) { + wtap_block_add_string_option_format(g_array_index(params.shb_hdrs, wtap_block_t, 0), + OPT_COMMENT, "%s", + (char *)g_ptr_array_index(capture_comments, i)); } } diff --git a/ui/capture.c b/ui/capture.c index b88c86efdd..cff9d4ae6f 100644 --- a/ui/capture.c +++ b/ui/capture.c @@ -117,7 +117,9 @@ capture_callback_remove(capture_callback_t func, gpointer user_data) * @return TRUE if the capture starts successfully, FALSE otherwise. */ gboolean -capture_start(capture_options *capture_opts, capture_session *cap_session, info_data_t* cap_data, void(*update_cb)(void)) +capture_start(capture_options *capture_opts, GPtrArray *capture_comments, + capture_session *cap_session, info_data_t* cap_data, + void(*update_cb)(void)) { GString *source; @@ -128,7 +130,8 @@ capture_start(capture_options *capture_opts, capture_session *cap_session, info_ cf_set_tempfile_source((capture_file *)cap_session->cf, source->str); g_string_free(source, TRUE); /* try to start the capture child process */ - if (!sync_pipe_start(capture_opts, cap_session, cap_data, update_cb)) { + if (!sync_pipe_start(capture_opts, capture_comments, cap_session, + cap_data, update_cb)) { /* We failed to start the capture child. */ if(capture_opts->save_file != NULL) { g_free(capture_opts->save_file); diff --git a/ui/capture.h b/ui/capture.h index 6589dfc8e7..f02e18ed92 100644 --- a/ui/capture.h +++ b/ui/capture.h @@ -60,13 +60,17 @@ capture_input_init(capture_session *cap_session, capture_file *cf); * Start a capture session. * * @param capture_opts the numerous capture options + * @param capture_comments if not NULL, a GPtrArray * to a set of comments + * to put in the capture file's Section Header Block if it's a pcapng file * @param cap_session the handle for the capture session * @param cap_data a struct with capture info data * @param update_cb update screen * @return TRUE if the capture starts successfully, FALSE otherwise. */ extern gboolean -capture_start(capture_options *capture_opts, capture_session *cap_session, info_data_t* cap_data, void(*update_cb)(void)); +capture_start(capture_options *capture_opts, GPtrArray *capture_comments, + capture_session *cap_session, info_data_t* cap_data, + void(*update_cb)(void)); /** Stop a capture session (usually from a menu item). */ extern void diff --git a/ui/commandline.c b/ui/commandline.c index 66a82493ab..66f7ebe111 100644 --- a/ui/commandline.c +++ b/ui/commandline.c @@ -173,8 +173,10 @@ commandline_print_usage(gboolean for_help_option) { fprintf(output, "\n"); fprintf(output, "Output:\n"); fprintf(output, " -w set the output filename (or '-' for stdout)\n"); +#ifdef HAVE_LIBPCAP fprintf(output, " --capture-comment \n"); - fprintf(output, " set the capture file comment, if supported\n"); + fprintf(output, " add a capture file comment, if supported\n"); +#endif ws_log_print_usage(output); @@ -197,6 +199,7 @@ commandline_print_usage(gboolean for_help_option) { } #define LONGOPT_FULL_SCREEN LONGOPT_BASE_GUI+1 +#define LONGOPT_CAPTURE_COMMENT LONGOPT_BASE_GUI+2 #define OPTSTRING OPTSTRING_CAPTURE_COMMON OPTSTRING_DISSECT_COMMON "C:g:HhjJ:klm:o:P:r:R:Svw:X:Y:z:" static const struct option long_options[] = { @@ -206,6 +209,7 @@ static const struct option long_options[] = { {"display-filter", required_argument, NULL, 'Y' }, {"version", no_argument, NULL, 'v'}, {"fullscreen", no_argument, NULL, LONGOPT_FULL_SCREEN }, + {"capture-comment", required_argument, NULL, LONGOPT_CAPTURE_COMMENT}, LONGOPT_CAPTURE_COMMON LONGOPT_DISSECT_COMMON {0, 0, 0, 0 } @@ -407,6 +411,7 @@ void commandline_other_options(int argc, char *argv[], gboolean opt_reset) global_commandline_info.list_link_layer_types = FALSE; global_commandline_info.list_timestamp_types = FALSE; global_commandline_info.quit_after_cap = getenv("WIRESHARK_QUIT_AFTER_CAPTURE") ? TRUE : FALSE; + global_commandline_info.capture_comments = NULL; #endif global_commandline_info.full_screen = FALSE; @@ -587,6 +592,17 @@ void commandline_other_options(int argc, char *argv[], gboolean opt_reset) case LONGOPT_FULL_SCREEN: global_commandline_info.full_screen = TRUE; break; +#ifdef HAVE_LIBPCAP + case LONGOPT_CAPTURE_COMMENT: /* capture comment */ + if (global_commandline_info.capture_comments == NULL) { + global_commandline_info.capture_comments = g_ptr_array_new_with_free_func(g_free); + } + g_ptr_array_add(global_commandline_info.capture_comments, g_strdup(optarg)); +#else + capture_option_specified = TRUE; + arg_error = TRUE; +#endif + break; default: case '?': /* Bad flag - print usage message */ arg_error = TRUE; diff --git a/ui/commandline.h b/ui/commandline.h index de1ba65528..72eeefc4d7 100644 --- a/ui/commandline.h +++ b/ui/commandline.h @@ -27,6 +27,13 @@ typedef struct commandline_param_info gboolean list_timestamp_types; gboolean start_capture; gboolean quit_after_cap; + + /* + * We currently don't support this as a way to add file comments + * to an existing capture file in Wireshark; we only support it + * for adding comments to live captures. + */ + GPtrArray *capture_comments; #endif e_prefs *prefs_p; search_direction jump_backwards; diff --git a/ui/qt/main.cpp b/ui/qt/main.cpp index 975c0e21b5..efb55caad6 100644 --- a/ui/qt/main.cpp +++ b/ui/qt/main.cpp @@ -1034,7 +1034,9 @@ int main(int argc, char *qt_argv[]) if (global_capture_opts.ifaces->len == 0) collect_ifaces(&global_capture_opts); CaptureFile::globalCapFile()->window = main_w; - if (capture_start(&global_capture_opts, main_w->captureSession(), main_w->captureInfoData(), main_window_update)) { + if (capture_start(&global_capture_opts, global_commandline_info.capture_comments, + main_w->captureSession(), main_w->captureInfoData(), + main_window_update)) { /* The capture started. Open stat windows; we do so after creating the main window, to avoid GTK warnings, and after successfully opening the capture file, so we know we have something to compute diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index eed66d9ad9..0c18aece0d 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -868,7 +868,8 @@ void MainWindow::startCapture() { CaptureFile::globalCapFile()->window = this; info_data_.ui.ui = this; - if (capture_start(&global_capture_opts, &cap_session_, &info_data_, main_window_update)) { + if (capture_start(&global_capture_opts, NULL, &cap_session_, &info_data_, + main_window_update)) { capture_options *capture_opts = cap_session_.capture_opts; GString *interface_names; diff --git a/writecap/pcapio.c b/writecap/pcapio.c index 14e4d7f31b..124531de9c 100644 --- a/writecap/pcapio.c +++ b/writecap/pcapio.c @@ -307,7 +307,7 @@ pcapng_write_block(FILE* pfile, gboolean pcapng_write_section_header_block(FILE* pfile, - const char *comment, + GPtrArray *comments, const char *hw, const char *os, const char *appname, @@ -324,13 +324,17 @@ pcapng_write_section_header_block(FILE* pfile, block_total_length = sizeof(struct shb) + sizeof(guint32); options_length = 0; - options_length += pcapng_count_string_option(comment); + if (comments != NULL) { + for (guint i = 0; i < comments->len; i++) { + options_length += pcapng_count_string_option((char *)g_ptr_array_index(comments, i)); + } + } options_length += pcapng_count_string_option(hw); options_length += pcapng_count_string_option(os); options_length += pcapng_count_string_option(appname); /* If we have options add size of end-of-options */ if (options_length != 0) { - options_length += (guint32)sizeof(struct option); + options_length += (guint32)sizeof(struct option); } block_total_length += options_length; @@ -345,9 +349,14 @@ pcapng_write_section_header_block(FILE* pfile, if (!write_to_file(pfile, (const guint8*)&shb, sizeof(struct shb), bytes_written, err)) return FALSE; - if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment, - bytes_written, err)) - return FALSE; + if (comments != NULL) { + for (guint i = 0; i < comments->len; i++) { + if (!pcapng_write_string_option(pfile, OPT_COMMENT, + (char *)g_ptr_array_index(comments, i), + bytes_written, err)) + return FALSE; + } + } if (!pcapng_write_string_option(pfile, SHB_HARDWARE, hw, bytes_written, err)) return FALSE; diff --git a/writecap/pcapio.h b/writecap/pcapio.h index 065e04877b..72df645a76 100644 --- a/writecap/pcapio.h +++ b/writecap/pcapio.h @@ -44,8 +44,8 @@ pcapng_write_block(FILE* pfile, */ extern gboolean pcapng_write_section_header_block(FILE* pfile, /**< Write information */ - const char *comment, /**< Comment on the section, Optinon 1 opt_comment - * A UTF-8 string containing a comment that is associated to the current block. + GPtrArray *comments, /**< Comments on the section, Optinon 1 opt_comment + * UTF-8 strings containing comments that areassociated to the current block. */ const char *hw, /**< HW, Optinon 2 shb_hardware * An UTF-8 string containing the description of the hardware used to create this section.