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;
This commit is contained in:
Guy Harris 2021-07-14 22:16:30 -07:00 committed by Wireshark GitLab Utility
parent 94ac641efa
commit 0a9ef601d2
19 changed files with 142 additions and 86 deletions

View File

@ -204,7 +204,9 @@ init_pipe_args(int *argc) {
#define ARGV_NUMBER_LEN 24 #define ARGV_NUMBER_LEN 24
/* a new capture run: start a new dumpcap task and hand over parameters through command line */ /* a new capture run: start a new dumpcap task and hand over parameters through command line */
gboolean 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 #ifdef _WIN32
HANDLE sync_pipe_read; /* pipe used to send messages from child to parent */ 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 else
argv = sync_pipe_add_arg(argv, &argc, "-P"); argv = sync_pipe_add_arg(argv, &argc, "-P");
if (capture_opts->capture_comment) { if (capture_comments != NULL) {
for (j = 0; j < capture_opts->capture_comment->len; j++) { for (j = 0; j < capture_comments->len; j++) {
argv = sync_pipe_add_arg(argv, &argc, "--capture-comment"); 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));
} }
} }

View File

@ -35,13 +35,17 @@ struct _info_data;
* Most of the parameters are passed through the global capture_opts. * Most of the parameters are passed through the global capture_opts.
* *
* @param capture_opts the options * @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_session a handle for the capture session
* @param cap_data a struct with capture info data * @param cap_data a struct with capture info data
* @param update_cb update screen * @param update_cb update screen
* @return TRUE if a capture could be started, FALSE if not * @return TRUE if a capture could be started, FALSE if not
*/ */
extern gboolean 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 */ /** User wants to stop capturing, gracefully close the capture child */
extern void extern void

View File

@ -115,7 +115,6 @@ capture_opts_init(capture_options *capture_opts)
capture_opts->autostop_filesize = 1000; /* 1 MB */ capture_opts->autostop_filesize = 1000; /* 1 MB */
capture_opts->has_autostop_duration = FALSE; capture_opts->has_autostop_duration = FALSE;
capture_opts->autostop_duration = 60.0; /* 1 min */ capture_opts->autostop_duration = 60.0; /* 1 min */
capture_opts->capture_comment = NULL;
capture_opts->output_to_pipe = FALSE; capture_opts->output_to_pipe = FALSE;
capture_opts->capture_child = FALSE; capture_opts->capture_child = FALSE;
@ -147,10 +146,6 @@ capture_opts_cleanup(capture_options *capture_opts)
capture_opts->all_ifaces = NULL; capture_opts->all_ifaces = NULL;
} }
g_free(capture_opts->save_file); 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 */ /* 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; int status, snaplen;
switch(opt) { 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 */ case 'a': /* autostop criteria */
if (set_autostop_criterion(capture_opts, optarg_str_p) == FALSE) { if (set_autostop_criterion(capture_opts, optarg_str_p) == FALSE) {
cmdarg_err("Invalid or unknown -a flag \"%s\"", optarg_str_p); cmdarg_err("Invalid or unknown -a flag \"%s\"", optarg_str_p);

View File

@ -44,10 +44,9 @@ extern "C" {
* In short: we must not use 1 here, which is another reason to use * In short: we must not use 1 here, which is another reason to use
* values outside the range of ASCII graphic characters. * values outside the range of ASCII graphic characters.
*/ */
#define LONGOPT_CAPTURE_COMMENT LONGOPT_BASE_CAPTURE+1 #define LONGOPT_LIST_TSTAMP_TYPES LONGOPT_BASE_CAPTURE+1
#define LONGOPT_LIST_TSTAMP_TYPES LONGOPT_BASE_CAPTURE+2 #define LONGOPT_SET_TSTAMP_TYPE LONGOPT_BASE_CAPTURE+2
#define LONGOPT_SET_TSTAMP_TYPE LONGOPT_BASE_CAPTURE+3 #define LONGOPT_COMPRESS_TYPE LONGOPT_BASE_CAPTURE+3
#define LONGOPT_COMPRESS_TYPE LONGOPT_BASE_CAPTURE+4
/* /*
* Options for capturing common to all capturing programs. * Options for capturing common to all capturing programs.
@ -76,7 +75,6 @@ extern "C" {
#endif #endif
#define LONGOPT_CAPTURE_COMMON \ #define LONGOPT_CAPTURE_COMMON \
{"capture-comment", required_argument, NULL, LONGOPT_CAPTURE_COMMENT}, \
{"autostop", required_argument, NULL, 'a'}, \ {"autostop", required_argument, NULL, 'a'}, \
{"ring-buffer", required_argument, NULL, 'b'}, \ {"ring-buffer", required_argument, NULL, 'b'}, \
LONGOPT_BUFFER_SIZE \ LONGOPT_BUFFER_SIZE \
@ -313,8 +311,6 @@ typedef struct capture_options_tag {
is specified */ is specified */
gdouble autostop_duration; /**< Maximum capture duration */ 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 gboolean print_file_names; /**< TRUE if printing names of completed
files as we close them */ files as we close them */
gchar *print_name_to; /**< output file name */ gchar *print_name_to; /**< output file name */

View File

@ -419,11 +419,14 @@ the default capture link type is used if provided.
=item --capture-comment E<lt>commentE<gt> =item --capture-comment E<lt>commentE<gt>
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 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 single file.
output 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 =item --list-time-stamp-types

View File

@ -375,12 +375,12 @@ the same command line.
=item --capture-comment E<lt>commentE<gt> =item --capture-comment E<lt>commentE<gt>
Adds the given comment to the Section Header Block (SHB) of the pcapng Adds the given comment to the output file, if supported by the output
output file. New comments will be added I<after> any comments present in the file format. New comments will be added I<after> any comments present
input file unless B<--discard-capture-comment> is also specified. in the input file unless B<--discard-capture-comment> is also specified.
This option may be specified multiple times. Note that Wireshark currently only This option may be specified multiple times. Note that Wireshark
recognizes the first comment of a capture file. currently only displays the first comment of a capture file.
=item --discard-capture-comment =item --discard-capture-comment

View File

@ -1728,13 +1728,11 @@ SMB packets exchanged by the host at IP address 1.2.3.4 .
=item --capture-comment E<lt>commentE<gt> =item --capture-comment E<lt>commentE<gt>
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 This option may be specified multiple times. Note that Wireshark
created. currently only displays the first comment of a capture file.
This option may be specified multiple times. Note that Wireshark currently only
recognizes the first comment of a capture file.
=item --list-time-stamp-types =item --list-time-stamp-types

View File

@ -319,7 +319,12 @@ Start with the given configuration profile.
=item --capture-comment E<lt>commentE<gt> =item --capture-comment E<lt>commentE<gt>
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 E<lt>layer typeE<gt>==E<lt>selectorE<gt>,E<lt>decode-as protocolE<gt> =item -d E<lt>layer typeE<gt>==E<lt>selectorE<gt>,E<lt>decode-as protocolE<gt>

View File

@ -336,6 +336,7 @@ dumpcap_log_writer(const char *domain, enum ws_log_level level,
/* capture related options */ /* capture related options */
static capture_options global_capture_opts; static capture_options global_capture_opts;
static GPtrArray *capture_comments = NULL;
static gboolean quiet = FALSE; static gboolean quiet = FALSE;
static gboolean use_threads = FALSE; static gboolean use_threads = FALSE;
static guint64 start_time; 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); get_cpu_info(cpu_info_str);
successful = pcapng_write_section_header_block(ld->pdh, successful = pcapng_write_section_header_block(ld->pdh,
(const char *)capture_opts->capture_comment, /* Comment */ capture_comments, /* Comments */
cpu_info_str->str, /* HW */ cpu_info_str->str, /* HW */
os_info_str->str, /* OS */ os_info_str->str, /* OS */
get_appname_and_version(), get_appname_and_version(),
@ -4815,6 +4816,7 @@ get_dumpcap_runtime_info(GString *str)
#define LONGOPT_IFNAME LONGOPT_BASE_APPLICATION+1 #define LONGOPT_IFNAME LONGOPT_BASE_APPLICATION+1
#define LONGOPT_IFDESCR LONGOPT_BASE_APPLICATION+2 #define LONGOPT_IFDESCR LONGOPT_BASE_APPLICATION+2
#define LONGOPT_CAPTURE_COMMENT LONGOPT_BASE_APPLICATION+3
/* And now our feature presentation... [ fade to music ] */ /* And now our feature presentation... [ fade to music ] */
int int
@ -4828,6 +4830,7 @@ main(int argc, char *argv[])
LONGOPT_CAPTURE_COMMON LONGOPT_CAPTURE_COMMON
{"ifname", required_argument, NULL, LONGOPT_IFNAME}, {"ifname", required_argument, NULL, LONGOPT_IFNAME},
{"ifdescr", required_argument, NULL, LONGOPT_IFDESCR}, {"ifdescr", required_argument, NULL, LONGOPT_IFDESCR},
{"capture-comment", required_argument, NULL, LONGOPT_CAPTURE_COMMENT},
{0, 0, 0, 0 } {0, 0, 0, 0 }
}; };
@ -5139,7 +5142,6 @@ main(int argc, char *argv[])
case 's': /* Set the snapshot (capture) length */ case 's': /* Set the snapshot (capture) length */
case 'w': /* Write to capture file x */ case 'w': /* Write to capture file x */
case 'y': /* Set the pcap data link type */ case 'y': /* Set the pcap data link type */
case LONGOPT_CAPTURE_COMMENT: /* add a capture comment */
#ifdef HAVE_PCAP_REMOTE #ifdef HAVE_PCAP_REMOTE
case 'u': /* Use UDP for data transfer */ case 'u': /* Use UDP for data transfer */
case 'r': /* Capture own RPCAP traffic too */ case 'r': /* Capture own RPCAP traffic too */
@ -5183,6 +5185,12 @@ main(int argc, char *argv[])
exit_main(1); exit_main(1);
} }
break; 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': case 'Z':
capture_child = TRUE; capture_child = TRUE;
#ifdef _WIN32 #ifdef _WIN32
@ -5319,10 +5327,10 @@ main(int argc, char *argv[])
global_capture_opts.use_pcapng = TRUE; 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)) { (!global_capture_opts.use_pcapng || global_capture_opts.multi_files_on)) {
/* XXX - for ringbuffer, should we apply the comment to each file? */ /* XXX - for ringbuffer, should we apply the comments to each file? */
cmdarg_err("A capture comment can only be set if we capture into a single pcapng file."); cmdarg_err("Capture comments can only be set if we capture into a single pcapng file.");
exit_main(1); exit_main(1);
} }

View File

@ -883,17 +883,20 @@ write_file_header (void)
if (use_pcapng) { if (use_pcapng) {
char *comment; char *comment;
GPtrArray *comments;
comment = g_strdup_printf("Generated from input file %s.", input_filename); 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, success = pcapng_write_section_header_block(output_file,
comment, comments,
NULL, /* HW */ NULL, /* HW */
NULL, /* OS */ NULL, /* OS */
get_appname_and_version(), get_appname_and_version(),
-1, /* section_length */ -1, /* section_length */
&bytes_written, &bytes_written,
&err); &err);
g_free(comment); g_ptr_array_free(comments, TRUE);
if (success) { if (success) {
success = pcapng_write_interface_description_block(output_file, success = pcapng_write_interface_description_block(output_file,
NULL, NULL,

View File

@ -144,6 +144,7 @@
#define LONGOPT_NO_DUPLICATE_KEYS LONGOPT_BASE_APPLICATION+3 #define LONGOPT_NO_DUPLICATE_KEYS LONGOPT_BASE_APPLICATION+3
#define LONGOPT_ELASTIC_MAPPING_FILTER LONGOPT_BASE_APPLICATION+4 #define LONGOPT_ELASTIC_MAPPING_FILTER LONGOPT_BASE_APPLICATION+4
#define LONGOPT_EXPORT_TLS_SESSION_KEYS LONGOPT_BASE_APPLICATION+5 #define LONGOPT_EXPORT_TLS_SESSION_KEYS LONGOPT_BASE_APPLICATION+5
#define LONGOPT_CAPTURE_COMMENT LONGOPT_BASE_APPLICATION+6
capture_file cfile; capture_file cfile;
@ -199,6 +200,9 @@ static json_dumper jdumper;
/* The line separator used between packets, changeable via the -S option */ /* The line separator used between packets, changeable via the -S option */
static const char *separator = ""; static const char *separator = "";
/* Per-file comments to be added to the output file. */
static GPtrArray *capture_comments = NULL;
static gboolean prefs_loaded = FALSE; static gboolean prefs_loaded = FALSE;
#ifdef HAVE_LIBPCAP #ifdef HAVE_LIBPCAP
@ -248,7 +252,7 @@ typedef enum {
PROCESS_FILE_ERROR, PROCESS_FILE_ERROR,
PROCESS_FILE_INTERRUPTED PROCESS_FILE_INTERRUPTED
} process_file_status_t; } 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, static gboolean process_packet_single_pass(capture_file *cf,
epan_dissect_t *edt, gint64 offset, wtap_rec *rec, Buffer *buf, epan_dissect_t *edt, gint64 offset, wtap_rec *rec, Buffer *buf,
@ -425,7 +429,7 @@ print_usage(FILE *output)
fprintf(output, " -w <outfile|-> write packets to a pcapng-format file named \"outfile\"\n"); fprintf(output, " -w <outfile|-> write packets to a pcapng-format file named \"outfile\"\n");
fprintf(output, " (or '-' for stdout)\n"); fprintf(output, " (or '-' for stdout)\n");
fprintf(output, " --capture-comment <comment>\n"); fprintf(output, " --capture-comment <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 <config profile> start with specified configuration profile\n"); fprintf(output, " -C <config profile> start with specified configuration profile\n");
fprintf(output, " -F <output file type> set the output file type, default is pcapng\n"); fprintf(output, " -F <output file type> set the output file type, default is pcapng\n");
fprintf(output, " an empty \"-F\" option will list the file types\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}, {"color", no_argument, NULL, LONGOPT_COLOR},
{"no-duplicate-keys", no_argument, NULL, LONGOPT_NO_DUPLICATE_KEYS}, {"no-duplicate-keys", no_argument, NULL, LONGOPT_NO_DUPLICATE_KEYS},
{"elastic-mapping-filter", required_argument, NULL, LONGOPT_ELASTIC_MAPPING_FILTER}, {"elastic-mapping-filter", required_argument, NULL, LONGOPT_ELASTIC_MAPPING_FILTER},
{"capture-comment", required_argument, NULL, LONGOPT_CAPTURE_COMMENT},
{0, 0, 0, 0 } {0, 0, 0, 0 }
}; };
gboolean arg_error = FALSE; gboolean arg_error = FALSE;
@ -1100,7 +1105,6 @@ main(int argc, char *argv[])
#endif #endif
case 's': /* Set the snapshot (capture) length */ case 's': /* Set the snapshot (capture) length */
case 'y': /* Set the pcap data link type */ case 'y': /* Set the pcap data link type */
case LONGOPT_CAPTURE_COMMENT: /* add a capture comment */
#ifdef CAN_SET_CAPTURE_BUFFER_SIZE #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
case 'B': /* Buffer size */ case 'B': /* Buffer size */
#endif #endif
@ -1476,6 +1480,12 @@ main(int argc, char *argv[])
no_duplicate_keys = TRUE; no_duplicate_keys = TRUE;
node_children_grouper = proto_node_group_children_by_json_key; node_children_grouper = proto_node_group_children_by_json_key;
break; 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: default:
case '?': /* Bad flag - print usage message */ case '?': /* Bad flag - print usage message */
switch(optopt) { switch(optopt) {
@ -1710,7 +1720,7 @@ main(int argc, char *argv[])
exit_status = INVALID_OPTION; exit_status = INVALID_OPTION;
goto clean_exit; goto clean_exit;
} }
if (global_capture_opts.capture_comment) { if (capture_comments != NULL) {
if (global_capture_opts.saving_to_file) { if (global_capture_opts.saving_to_file) {
/* They specified a "-w" flag, so we'll be saving to a capture file. /* They specified a "-w" flag, so we'll be saving to a capture file.
* This is fine if they're using pcapng. * This is fine if they're using pcapng.
@ -1767,8 +1777,8 @@ main(int argc, char *argv[])
exit_status = INVALID_OPTION; exit_status = INVALID_OPTION;
goto clean_exit; goto clean_exit;
} }
if (global_capture_opts.capture_comment && !use_pcapng) { if (capture_comments != NULL && !use_pcapng) {
cmdarg_err("A capture comment can only be written to a pcapng file."); cmdarg_err("Capture comments can only be written to a pcapng file.");
exit_status = INVALID_OPTION; exit_status = INVALID_OPTION;
goto clean_exit; goto clean_exit;
} }
@ -1828,8 +1838,8 @@ main(int argc, char *argv[])
exit_status = INVALID_OPTION; exit_status = INVALID_OPTION;
goto clean_exit; goto clean_exit;
} }
if (global_capture_opts.capture_comment) { if (capture_comments != NULL) {
cmdarg_err("A capture comment was specified, but " cmdarg_err("Capture comments were specified, but "
"the capture isn't being saved to a file."); "the capture isn't being saved to a file.");
exit_status = INVALID_OPTION; exit_status = INVALID_OPTION;
goto clean_exit; goto clean_exit;
@ -2090,13 +2100,14 @@ main(int argc, char *argv[])
/* Process the packets in the file */ /* Process the packets in the file */
ws_debug("tshark: invoking process_cap_file() to process the packets"); ws_debug("tshark: invoking process_cap_file() to process the packets");
TRY { TRY {
#ifndef HAVE_LIBPCAP status = process_cap_file(&cfile, output_file_name, out_file_type, out_file_name_res,
global_capture_opts.has_autostop_packets = max_packet_count > 0; #ifdef HAVE_LIBPCAP
global_capture_opts.autostop_packets = max_packet_count; global_capture_opts.has_autostop_packets ? global_capture_opts.autostop_packets : 0,
global_capture_opts.has_autostop_filesize = FALSE; global_capture_opts.has_autostop_filesize ? global_capture_opts.autostop_filesize : 0);
global_capture_opts.autostop_filesize = 0; #else
max_packet_count,
0);
#endif #endif
status = process_cap_file(&cfile, output_file_name, out_file_type, out_file_name_res, global_capture_opts);
} }
CATCH(OutOfMemoryError) { CATCH(OutOfMemoryError) {
fprintf(stderr, fprintf(stderr,
@ -2541,7 +2552,8 @@ capture(void)
fflush(stderr); fflush(stderr);
g_string_free(str, TRUE); 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) if (!ret)
return FALSE; return FALSE;
@ -3535,7 +3547,7 @@ process_cap_file_single_pass(capture_file *cf, wtap_dumper *pdh,
static process_file_status_t static process_file_status_t
process_cap_file(capture_file *cf, char *save_file, int out_file_type, 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; process_file_status_t status = PROCESS_FILE_SUCCEEDED;
wtap_dumper *pdh; 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; wtap_dump_params params = WTAP_DUMP_PARAMS_INIT;
char *shb_user_appl; char *shb_user_appl;
pass_status_t first_pass_status, second_pass_status; 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) { if (save_file != NULL) {
/* Set up to write to the capture file. */ /* 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 */ /* 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()); 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) { if (capture_comments != NULL) {
guint i; for (guint i = 0; i < capture_comments->len; 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),
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)); OPT_COMMENT, "%s",
(char *)g_ptr_array_index(capture_comments, i));
} }
} }

View File

@ -117,7 +117,9 @@ capture_callback_remove(capture_callback_t func, gpointer user_data)
* @return TRUE if the capture starts successfully, FALSE otherwise. * @return TRUE if the capture starts successfully, FALSE otherwise.
*/ */
gboolean 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; 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); cf_set_tempfile_source((capture_file *)cap_session->cf, source->str);
g_string_free(source, TRUE); g_string_free(source, TRUE);
/* try to start the capture child process */ /* 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. */ /* We failed to start the capture child. */
if(capture_opts->save_file != NULL) { if(capture_opts->save_file != NULL) {
g_free(capture_opts->save_file); g_free(capture_opts->save_file);

View File

@ -60,13 +60,17 @@ capture_input_init(capture_session *cap_session, capture_file *cf);
* Start a capture session. * Start a capture session.
* *
* @param capture_opts the numerous capture options * @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_session the handle for the capture session
* @param cap_data a struct with capture info data * @param cap_data a struct with capture info data
* @param update_cb update screen * @param update_cb update screen
* @return TRUE if the capture starts successfully, FALSE otherwise. * @return TRUE if the capture starts successfully, FALSE otherwise.
*/ */
extern gboolean 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). */ /** Stop a capture session (usually from a menu item). */
extern void extern void

View File

@ -173,8 +173,10 @@ commandline_print_usage(gboolean for_help_option) {
fprintf(output, "\n"); fprintf(output, "\n");
fprintf(output, "Output:\n"); fprintf(output, "Output:\n");
fprintf(output, " -w <outfile|-> set the output filename (or '-' for stdout)\n"); fprintf(output, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
#ifdef HAVE_LIBPCAP
fprintf(output, " --capture-comment <comment>\n"); fprintf(output, " --capture-comment <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); 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_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:" #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[] = { static const struct option long_options[] = {
@ -206,6 +209,7 @@ static const struct option long_options[] = {
{"display-filter", required_argument, NULL, 'Y' }, {"display-filter", required_argument, NULL, 'Y' },
{"version", no_argument, NULL, 'v'}, {"version", no_argument, NULL, 'v'},
{"fullscreen", no_argument, NULL, LONGOPT_FULL_SCREEN }, {"fullscreen", no_argument, NULL, LONGOPT_FULL_SCREEN },
{"capture-comment", required_argument, NULL, LONGOPT_CAPTURE_COMMENT},
LONGOPT_CAPTURE_COMMON LONGOPT_CAPTURE_COMMON
LONGOPT_DISSECT_COMMON LONGOPT_DISSECT_COMMON
{0, 0, 0, 0 } {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_link_layer_types = FALSE;
global_commandline_info.list_timestamp_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.quit_after_cap = getenv("WIRESHARK_QUIT_AFTER_CAPTURE") ? TRUE : FALSE;
global_commandline_info.capture_comments = NULL;
#endif #endif
global_commandline_info.full_screen = FALSE; 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: case LONGOPT_FULL_SCREEN:
global_commandline_info.full_screen = TRUE; global_commandline_info.full_screen = TRUE;
break; 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: default:
case '?': /* Bad flag - print usage message */ case '?': /* Bad flag - print usage message */
arg_error = TRUE; arg_error = TRUE;

View File

@ -27,6 +27,13 @@ typedef struct commandline_param_info
gboolean list_timestamp_types; gboolean list_timestamp_types;
gboolean start_capture; gboolean start_capture;
gboolean quit_after_cap; 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 #endif
e_prefs *prefs_p; e_prefs *prefs_p;
search_direction jump_backwards; search_direction jump_backwards;

View File

@ -1034,7 +1034,9 @@ int main(int argc, char *qt_argv[])
if (global_capture_opts.ifaces->len == 0) if (global_capture_opts.ifaces->len == 0)
collect_ifaces(&global_capture_opts); collect_ifaces(&global_capture_opts);
CaptureFile::globalCapFile()->window = main_w; 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 capture started. Open stat windows; we do so after creating
the main window, to avoid GTK warnings, and after successfully the main window, to avoid GTK warnings, and after successfully
opening the capture file, so we know we have something to compute opening the capture file, so we know we have something to compute

View File

@ -868,7 +868,8 @@ void MainWindow::startCapture() {
CaptureFile::globalCapFile()->window = this; CaptureFile::globalCapFile()->window = this;
info_data_.ui.ui = 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; capture_options *capture_opts = cap_session_.capture_opts;
GString *interface_names; GString *interface_names;

View File

@ -307,7 +307,7 @@ pcapng_write_block(FILE* pfile,
gboolean gboolean
pcapng_write_section_header_block(FILE* pfile, pcapng_write_section_header_block(FILE* pfile,
const char *comment, GPtrArray *comments,
const char *hw, const char *hw,
const char *os, const char *os,
const char *appname, const char *appname,
@ -324,7 +324,11 @@ pcapng_write_section_header_block(FILE* pfile,
block_total_length = sizeof(struct shb) + block_total_length = sizeof(struct shb) +
sizeof(guint32); sizeof(guint32);
options_length = 0; 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(hw);
options_length += pcapng_count_string_option(os); options_length += pcapng_count_string_option(os);
options_length += pcapng_count_string_option(appname); options_length += pcapng_count_string_option(appname);
@ -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)) if (!write_to_file(pfile, (const guint8*)&shb, sizeof(struct shb), bytes_written, err))
return FALSE; return FALSE;
if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment, 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)) bytes_written, err))
return FALSE; return FALSE;
}
}
if (!pcapng_write_string_option(pfile, SHB_HARDWARE, hw, if (!pcapng_write_string_option(pfile, SHB_HARDWARE, hw,
bytes_written, err)) bytes_written, err))
return FALSE; return FALSE;

View File

@ -44,8 +44,8 @@ pcapng_write_block(FILE* pfile,
*/ */
extern gboolean extern gboolean
pcapng_write_section_header_block(FILE* pfile, /**< Write information */ pcapng_write_section_header_block(FILE* pfile, /**< Write information */
const char *comment, /**< Comment on the section, Optinon 1 opt_comment GPtrArray *comments, /**< Comments on the section, Optinon 1 opt_comment
* A UTF-8 string containing a comment that is associated to the current block. * UTF-8 strings containing comments that areassociated to the current block.
*/ */
const char *hw, /**< HW, Optinon 2 shb_hardware const char *hw, /**< HW, Optinon 2 shb_hardware
* An UTF-8 string containing the description of the hardware used to create this section. * An UTF-8 string containing the description of the hardware used to create this section.