2 * Reports capture file information including # of packets, duration, others
4 * Copyright 2004 Ian Schorr
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
16 * New capinfos features
18 * Continue processing additional files after
19 * a wiretap open failure. The new -C option
20 * reverts to capinfos' original behavior which
21 * is to cancel any further file processing at
22 * first file open failure.
24 * Change the behavior of how the default display
25 * of all infos is initiated. This gets rid of a
26 * special post getopt() argument count test.
28 * Add new table output format (with related options)
29 * This feature allows outputting the various infos
30 * into a tab delimited text file, or to a comma
31 * separated variables file (*.csv) instead of the
32 * original "long" format.
35 * behaviour changed: Upon exit capinfos will return
36 * an error status if an error occurred at any
37 * point during "continuous" file processing.
38 * (Previously a success status was always
39 * returned if the -C option was not used).
45 #define WS_LOG_DOMAIN LOG_DOMAIN_MAIN
53 #include <ws_exit_codes.h>
54 #include <wsutil/ws_getopt.h>
58 #include <wiretap/wtap.h>
60 #include <wsutil/cmdarg_err.h>
61 #include <wsutil/filesystem.h>
62 #include <wsutil/privileges.h>
64 #include <wsutil/version_info.h>
65 #include <wiretap/wtap_opttypes.h>
68 #include <wsutil/plugins.h>
71 #include <wsutil/report_message.h>
72 #include <wsutil/str_util.h>
73 #include <wsutil/to_str.h>
74 #include <wsutil/file_util.h>
75 #include <wsutil/ws_assert.h>
76 #include <wsutil/wslog.h>
80 #include "ui/failure_message.h"
83 * By default capinfos now continues processing
84 * the next filename if and when wiretap detects
85 * a problem opening or reading a file.
86 * Use the '-C' option to revert back to original
87 * capinfos behavior which is to abort any
88 * additional file processing at the first file
89 * open or read failure.
92 static gboolean stop_after_failure
;
95 * table report variables
98 static gboolean long_report
= TRUE
; /* By default generate long report */
99 static gchar table_report_header
= TRUE
; /* Generate column header by default */
100 static gchar field_separator
= '\t'; /* Use TAB as field separator by default */
101 static gchar quote_char
= '\0'; /* Do NOT quote fields by default */
102 static gboolean machine_readable
; /* Display machine-readable numbers */
105 * capinfos has the ability to report on a number of
106 * various characteristics ("infos") for each input file.
108 * By default reporting of all info fields is enabled.
110 * Optionally the reporting of any specific info field
111 * or combination of info fields can be enabled with
112 * individual options.
115 static gboolean report_all_infos
= TRUE
; /* Report all infos */
117 static gboolean cap_file_type
= TRUE
; /* Report capture type */
118 static gboolean cap_file_encap
= TRUE
; /* Report encapsulation */
119 static gboolean cap_snaplen
= TRUE
; /* Packet size limit (snaplen)*/
120 static gboolean cap_packet_count
= TRUE
; /* Report packet count */
121 static gboolean cap_file_size
= TRUE
; /* Report file size */
122 static gboolean cap_comment
= TRUE
; /* Display the capture comment */
123 static gboolean cap_file_more_info
= TRUE
; /* Report more file info */
124 static gboolean cap_file_idb
= TRUE
; /* Report Interface info */
125 static gboolean cap_file_nrb
= TRUE
; /* Report Name Resolution Block info */
126 static gboolean cap_file_dsb
= TRUE
; /* Report Decryption Secrets Block info */
128 static gboolean cap_data_size
= TRUE
; /* Report packet byte size */
129 static gboolean cap_duration
= TRUE
; /* Report capture duration */
130 static gboolean cap_start_time
= TRUE
; /* Report capture start time */
131 static gboolean cap_end_time
= TRUE
; /* Report capture end time */
132 static gboolean time_as_secs
; /* Report time values as raw seconds */
134 static gboolean cap_data_rate_byte
= TRUE
; /* Report data rate bytes/sec */
135 static gboolean cap_data_rate_bit
= TRUE
; /* Report data rate bites/sec */
136 static gboolean cap_packet_size
= TRUE
; /* Report average packet size */
137 static gboolean cap_packet_rate
= TRUE
; /* Report average packet rate */
138 static gboolean cap_order
= TRUE
; /* Report if packets are in chronological order (True/False) */
139 static gboolean pkt_comments
= TRUE
; /* Report individual packet comments */
141 static gboolean cap_file_hashes
= TRUE
; /* Calculate file hashes */
143 // Strongest to weakest
144 #define HASH_SIZE_SHA256 32
145 #define HASH_SIZE_SHA1 20
147 #define HASH_STR_SIZE (65) /* Max hash size * 2 + '\0' */
148 #define HASH_BUF_SIZE (1024 * 1024)
151 static gchar file_sha256
[HASH_STR_SIZE
];
152 static gchar file_sha1
[HASH_STR_SIZE
];
154 static char *hash_buf
;
155 static gcry_md_hd_t hd
;
157 static guint num_ipv4_addresses
;
158 static guint num_ipv6_addresses
;
159 static guint num_decryption_secrets
;
162 * If we have at least two packets with time stamps, and they're not in
163 * order - i.e., the later packet has a time stamp older than the earlier
164 * packet - the time stamps are known not to be in order.
166 * If every packet has a time stamp, and they're all in order, the time
167 * stamp is known to be in order.
169 * Otherwise, we have no idea.
177 typedef struct _pkt_cmt
{
180 struct _pkt_cmt
*next
;
183 typedef struct _capture_info
{
184 const char *filename
;
186 wtap_compression_type compression_type
;
191 guint64 packet_bytes
;
192 gboolean times_known
;
194 int start_time_tsprec
;
196 int stop_time_tsprec
;
197 guint32 packet_count
;
198 gboolean snap_set
; /* If set in capture file header */
199 guint32 snaplen
; /* value from the capture file header */
200 guint32 snaplen_min_inferred
; /* If caplen < len for 1 or more rcds */
201 guint32 snaplen_max_inferred
; /* ... */
202 gboolean drops_known
;
209 double data_rate
; /* in bytes/s */
213 int *encap_counts
; /* array of per_packet encap counts; array has one entry per wtap_encap type */
214 pkt_cmt
*pkt_cmts
; /* list of packet comments */
216 guint num_interfaces
; /* number of IDBs, and thus size of interface_packet_counts array */
217 GArray
*interface_packet_counts
; /* array of per_packet interface_id counts; one entry per file IDB */
218 guint32 pkt_interface_id_unknown
; /* counts if packet interface_id didn't match a known one */
219 GArray
*idb_info_strings
; /* array of IDB info strings */
222 static char *decimal_point
;
225 enable_all_infos(void)
227 report_all_infos
= TRUE
;
229 cap_file_type
= TRUE
;
230 cap_file_encap
= TRUE
;
232 cap_packet_count
= TRUE
;
233 cap_file_size
= TRUE
;
236 cap_file_more_info
= TRUE
;
241 cap_data_size
= TRUE
;
243 cap_start_time
= TRUE
;
247 cap_data_rate_byte
= TRUE
;
248 cap_data_rate_bit
= TRUE
;
249 cap_packet_size
= TRUE
;
250 cap_packet_rate
= TRUE
;
252 cap_file_hashes
= TRUE
;
256 disable_all_infos(void)
258 report_all_infos
= FALSE
;
260 cap_file_type
= FALSE
;
261 cap_file_encap
= FALSE
;
263 cap_packet_count
= FALSE
;
264 cap_file_size
= FALSE
;
266 pkt_comments
= FALSE
;
267 cap_file_more_info
= FALSE
;
268 cap_file_idb
= FALSE
;
269 cap_file_nrb
= FALSE
;
270 cap_file_dsb
= FALSE
;
272 cap_data_size
= FALSE
;
273 cap_duration
= FALSE
;
274 cap_start_time
= FALSE
;
275 cap_end_time
= FALSE
;
278 cap_data_rate_byte
= FALSE
;
279 cap_data_rate_bit
= FALSE
;
280 cap_packet_size
= FALSE
;
281 cap_packet_rate
= FALSE
;
283 cap_file_hashes
= FALSE
;
287 order_string(order_t order
)
301 return "???"; /* "cannot happen" (the next step is "Profit!") */
306 absolute_time_string(nstime_t
*timer
, int tsprecision
, capture_info
*cf_info
)
309 * https://web.archive.org/web/20120513133703/http://www.idrbt.ac.in/publications/workingpapers/Working%20Paper%20No.%209.pdf
313 * A 64-bit Unix time would be safe for the indefinite future, as
314 * this variable would not overflow until 2**63 or
315 * 9,223,372,036,854,775,808 (over nine quintillion) seconds
316 * after the beginning of the Unix epoch - corresponding to
317 * GMT 15:30:08, Sunday, 4th December, 292,277,026,596.
319 * So, if we're displaying the time as YYYY-MM-DD HH:MM:SS.SSSSSSSSS,
320 * we'll have the buffer be large enough for a date of the format
321 * 292277026596-MM-DD HH:MM:SS.SSSSSSSSS, which is the biggest value
322 * you'll get with a 64-bit time_t and a nanosecond-resolution
323 * fraction-of-a-second.
325 * That's 12+1+2+1+2+1+2+1+2+2+2+1+9+1, including the terminating
328 * If we're displaying the time as epoch time, and the time is
329 * unsigned, 2^64-1 is 18446744073709551615, so the buffer has
330 * to be big enough for 18446744073709551615.999999999. That's
331 * 20+1+9+1, including the terminating '\0', or 31. If it's
332 * signed, 2^63 is 9223372036854775808, so the buffer has to
333 * be big enough for -9223372036854775808.999999999, which is
334 * again 20+1+9+1, or 31.
338 static gchar time_string_buf
[39];
340 if (cf_info
->times_known
&& cf_info
->packet_count
> 0) {
342 display_epoch_time(time_string_buf
, sizeof time_string_buf
, timer
, tsprecision
);
344 format_nstime_as_iso8601(time_string_buf
, sizeof time_string_buf
, timer
, decimal_point
, TRUE
, tsprecision
);
347 snprintf(time_string_buf
, sizeof time_string_buf
, "n/a");
349 return time_string_buf
;
353 relative_time_string(nstime_t
*timer
, int tsprecision
, capture_info
*cf_info
, gboolean want_seconds
)
355 const gchar
*second
= want_seconds
? " second" : "";
356 const gchar
*plural
= want_seconds
? "s" : "";
358 * If we're displaying the time as epoch time, and the time is
359 * unsigned, 2^64-1 is 18446744073709551615, so the buffer has
360 * to be big enough for "18446744073709551615.999999999 seconds".
361 * That's 20+1+9+1+7+1, including the terminating '\0', or 39.
362 * If it'ssigned, 2^63 is 9223372036854775808, so the buffer has to
363 * be big enough for "-9223372036854775808.999999999 seconds",
364 * which is again 20+1+9+1+7+1, or 39.
366 static gchar time_string_buf
[39];
368 if (cf_info
->times_known
&& cf_info
->packet_count
> 0) {
373 ptr
= time_string_buf
;
374 remaining
= sizeof time_string_buf
;
375 num_bytes
= snprintf(ptr
, remaining
,
377 (gint64
)timer
->secs
);
381 * Not much else we can do.
383 snprintf(ptr
, remaining
, "snprintf() failed");
384 return time_string_buf
;
386 if ((unsigned int)num_bytes
>= remaining
) {
388 * That filled up or would have overflowed the buffer.
389 * Nothing more we can do.
391 return time_string_buf
;
394 remaining
-= num_bytes
;
396 if (tsprecision
!= 0) {
398 * Append the fractional part.
400 num_bytes
= format_fractional_part_nsecs(ptr
, remaining
, timer
->nsecs
, decimal_point
, tsprecision
);
401 if ((unsigned int)num_bytes
>= remaining
) {
403 * That filled up or would have overflowed the buffer.
404 * Nothing more we can do.
406 return time_string_buf
;
409 remaining
-= num_bytes
;
415 snprintf(ptr
, remaining
, "%s%s",
417 timer
->secs
== 1 ? "" : plural
);
419 return time_string_buf
;
422 snprintf(time_string_buf
, sizeof time_string_buf
, "n/a");
423 return time_string_buf
;
426 static void print_value(const gchar
*text_p1
, gint width
, const gchar
*text_p2
, double value
)
429 printf("%s%.*f%s\n", text_p1
, width
, value
, text_p2
);
431 printf("%sn/a\n", text_p1
);
434 /* multi-line comments would conflict with the formatting that capinfos uses
435 we replace linefeeds with spaces */
437 string_replace_newlines(gchar
*str
)
454 show_option_string(const char *prefix
, const char *option_str
)
458 if (option_str
!= NULL
&& option_str
[0] != '\0') {
459 str
= g_strdup(option_str
);
460 string_replace_newlines(str
);
461 printf("%s%s\n", prefix
, str
);
467 print_stats(const gchar
*filename
, capture_info
*cf_info
)
469 const gchar
*file_type_string
, *file_encap_string
;
473 /* Build printable strings for various stats */
474 if (machine_readable
) {
475 file_type_string
= wtap_file_type_subtype_name(cf_info
->file_type
);
476 file_encap_string
= wtap_encap_name(cf_info
->file_encap
);
479 file_type_string
= wtap_file_type_subtype_description(cf_info
->file_type
);
480 file_encap_string
= wtap_encap_description(cf_info
->file_encap
);
483 if (filename
) printf ("File name: %s\n", filename
);
485 const char *compression_type_description
;
486 compression_type_description
= wtap_compression_type_description(cf_info
->compression_type
);
487 if (compression_type_description
== NULL
)
488 printf ("File type: %s\n",
491 printf ("File type: %s (%s)\n",
492 file_type_string
, compression_type_description
);
494 if (cap_file_encap
) {
495 printf ("File encapsulation: %s\n", file_encap_string
);
496 if (cf_info
->file_encap
== WTAP_ENCAP_PER_PACKET
) {
498 printf ("Encapsulation in use by packets (# of pkts):\n");
499 for (i
=0; i
<WTAP_NUM_ENCAP_TYPES
; i
++) {
500 if (cf_info
->encap_counts
[i
] > 0)
502 wtap_encap_description(i
), cf_info
->encap_counts
[i
]);
506 if (cap_file_more_info
) {
507 printf ("File timestamp precision: %s (%d)\n",
508 wtap_tsprec_string(cf_info
->file_tsprec
), cf_info
->file_tsprec
);
511 if (cap_snaplen
&& cf_info
->snap_set
)
512 printf ("Packet size limit: file hdr: %u bytes\n", cf_info
->snaplen
);
513 else if (cap_snaplen
&& !cf_info
->snap_set
)
514 printf ("Packet size limit: file hdr: (not set)\n");
515 if (cf_info
->snaplen_max_inferred
> 0) {
516 if (cf_info
->snaplen_min_inferred
== cf_info
->snaplen_max_inferred
)
517 printf ("Packet size limit: inferred: %u bytes\n", cf_info
->snaplen_min_inferred
);
519 printf ("Packet size limit: inferred: %u bytes - %u bytes (range)\n",
520 cf_info
->snaplen_min_inferred
, cf_info
->snaplen_max_inferred
);
522 if (cap_packet_count
) {
523 printf ("Number of packets: ");
524 if (machine_readable
) {
525 printf ("%u\n", cf_info
->packet_count
);
527 size_string
= format_size(cf_info
->packet_count
, FORMAT_SIZE_UNIT_NONE
, 0);
528 printf ("%s\n", size_string
);
533 printf ("File size: ");
534 if (machine_readable
) {
535 printf ("%" PRId64
" bytes\n", cf_info
->filesize
);
537 size_string
= format_size(cf_info
->filesize
, FORMAT_SIZE_UNIT_BYTES
, 0);
538 printf ("%s\n", size_string
);
543 printf ("Data size: ");
544 if (machine_readable
) {
545 printf ("%" PRIu64
" bytes\n", cf_info
->packet_bytes
);
547 size_string
= format_size(cf_info
->packet_bytes
, FORMAT_SIZE_UNIT_BYTES
, 0);
548 printf ("%s\n", size_string
);
552 if (cf_info
->times_known
) {
553 if (cap_duration
) /* XXX - shorten to hh:mm:ss */
554 printf("Capture duration: %s\n", relative_time_string(&cf_info
->duration
, cf_info
->duration_tsprec
, cf_info
, TRUE
));
556 printf("First packet time: %s\n", absolute_time_string(&cf_info
->start_time
, cf_info
->start_time_tsprec
, cf_info
));
558 printf("Last packet time: %s\n", absolute_time_string(&cf_info
->stop_time
, cf_info
->stop_time_tsprec
, cf_info
));
559 if (cap_data_rate_byte
) {
560 printf("Data byte rate: ");
561 if (machine_readable
) {
562 print_value("", 2, " bytes/sec", cf_info
->data_rate
);
564 size_string
= format_size((int64_t)cf_info
->data_rate
, FORMAT_SIZE_UNIT_BYTES_S
, 0);
565 printf ("%s\n", size_string
);
569 if (cap_data_rate_bit
) {
570 printf("Data bit rate: ");
571 if (machine_readable
) {
572 print_value("", 2, " bits/sec", cf_info
->data_rate
*8);
574 size_string
= format_size((int64_t)(cf_info
->data_rate
*8), FORMAT_SIZE_UNIT_BITS_S
, 0);
575 printf ("%s\n", size_string
);
580 if (cap_packet_size
) printf("Average packet size: %.2f bytes\n", cf_info
->packet_size
);
581 if (cf_info
->times_known
) {
582 if (cap_packet_rate
) {
583 printf("Average packet rate: ");
584 if (machine_readable
) {
585 print_value("", 2, " packets/sec", cf_info
->packet_rate
);
587 size_string
= format_size((int64_t)cf_info
->packet_rate
, FORMAT_SIZE_UNIT_PACKETS_S
, 0);
588 printf ("%s\n", size_string
);
593 if (cap_file_hashes
) {
594 printf ("SHA256: %s\n", file_sha256
);
595 printf ("SHA1: %s\n", file_sha1
);
597 if (cap_order
) printf ("Strict time order: %s\n", order_string(cf_info
->order
));
599 gboolean has_multiple_sections
= (wtap_file_get_num_shbs(cf_info
->wth
) > 1);
601 for (guint section_number
= 0;
602 section_number
< wtap_file_get_num_shbs(cf_info
->wth
);
606 // If we have more than one section, add headers for each section.
607 if (has_multiple_sections
)
608 printf("Section %u:\n\n", section_number
);
610 shb
= wtap_file_get_shb(cf_info
->wth
, section_number
);
612 if (cap_file_more_info
) {
615 if (wtap_block_get_string_option_value(shb
, OPT_SHB_HARDWARE
, &str
) == WTAP_OPTTYPE_SUCCESS
)
616 show_option_string("Capture hardware: ", str
);
617 if (wtap_block_get_string_option_value(shb
, OPT_SHB_OS
, &str
) == WTAP_OPTTYPE_SUCCESS
)
618 show_option_string("Capture oper-sys: ", str
);
619 if (wtap_block_get_string_option_value(shb
, OPT_SHB_USERAPPL
, &str
) == WTAP_OPTTYPE_SUCCESS
)
620 show_option_string("Capture application: ", str
);
626 for (i
= 0; wtap_block_get_nth_string_option_value(shb
, OPT_COMMENT
, i
, &str
) == WTAP_OPTTYPE_SUCCESS
; i
++) {
627 show_option_string("Capture comment: ", str
);
631 if (pkt_comments
&& cf_info
->pkt_cmts
!= NULL
) {
632 for (p
= cf_info
->pkt_cmts
; p
!= NULL
; prev
= p
, p
= p
->next
, g_free(prev
)) {
633 if (machine_readable
){
634 printf("Packet %d Comment: %s\n", p
->recno
, g_strescape(p
->cmt
, NULL
));
636 printf("Packet %d Comment: %s\n", p
->recno
, p
->cmt
);
642 if (cap_file_idb
&& cf_info
->num_interfaces
!= 0) {
644 ws_assert(cf_info
->num_interfaces
== cf_info
->idb_info_strings
->len
);
645 printf ("Number of interfaces in file: %u\n", cf_info
->num_interfaces
);
646 for (i
= 0; i
< cf_info
->idb_info_strings
->len
; i
++) {
647 gchar
*s
= g_array_index(cf_info
->idb_info_strings
, gchar
*, i
);
648 guint32 packet_count
= 0;
649 if (i
< cf_info
->interface_packet_counts
->len
)
650 packet_count
= g_array_index(cf_info
->interface_packet_counts
, guint32
, i
);
651 printf ("Interface #%u info:\n", i
);
653 printf (" Number of packets = %u\n", packet_count
);
659 if (num_ipv4_addresses
!= 0)
660 printf ("Number of resolved IPv4 addresses in file: %u\n", num_ipv4_addresses
);
661 if (num_ipv6_addresses
!= 0)
662 printf ("Number of resolved IPv6 addresses in file: %u\n", num_ipv6_addresses
);
665 if (num_decryption_secrets
!= 0)
666 printf ("Number of decryption secrets in file: %u\n", num_decryption_secrets
);
674 if (field_separator
) putchar(field_separator
);
680 if (quote_char
) putchar(quote_char
);
684 print_stats_table_header_label(const gchar
*label
)
693 print_stats_table_header(capture_info
*cf_info
)
702 if (cap_file_type
) print_stats_table_header_label("File type");
703 if (cap_file_encap
) print_stats_table_header_label("File encapsulation");
704 if (cap_file_more_info
) print_stats_table_header_label("File time precision");
706 print_stats_table_header_label("Packet size limit");
707 print_stats_table_header_label("Packet size limit min (inferred)");
708 print_stats_table_header_label("Packet size limit max (inferred)");
710 if (cap_packet_count
) print_stats_table_header_label("Number of packets");
711 if (cap_file_size
) print_stats_table_header_label("File size (bytes)");
712 if (cap_data_size
) print_stats_table_header_label("Data size (bytes)");
713 if (cap_duration
) print_stats_table_header_label("Capture duration (seconds)");
714 if (cap_start_time
) print_stats_table_header_label("Start time");
715 if (cap_end_time
) print_stats_table_header_label("End time");
716 if (cap_data_rate_byte
) print_stats_table_header_label("Data byte rate (bytes/sec)");
717 if (cap_data_rate_bit
) print_stats_table_header_label("Data bit rate (bits/sec)");
718 if (cap_packet_size
) print_stats_table_header_label("Average packet size (bytes)");
719 if (cap_packet_rate
) print_stats_table_header_label("Average packet rate (packets/sec)");
720 if (cap_file_hashes
) {
721 print_stats_table_header_label("SHA256");
722 print_stats_table_header_label("SHA1");
724 if (cap_order
) print_stats_table_header_label("Strict time order");
725 if (cap_file_more_info
) {
726 print_stats_table_header_label("Capture hardware");
727 print_stats_table_header_label("Capture oper-sys");
728 print_stats_table_header_label("Capture application");
730 if (cap_comment
) print_stats_table_header_label("Capture comment");
732 if (pkt_comments
&& cf_info
->pkt_cmts
!= NULL
) {
733 /* Packet 2^64 Comment" + NULL */
734 buf
= (char *)g_malloc0(strlen("Packet 18446744073709551616 Comment") + 1);
736 for (p
= cf_info
->pkt_cmts
; p
!= NULL
; p
= p
->next
) {
737 snprintf(buf
, strlen(buf
), "Packet %d Comment", p
->recno
);
738 print_stats_table_header_label(buf
);
746 print_stats_table(const gchar
*filename
, capture_info
*cf_info
)
748 const gchar
*file_type_string
, *file_encap_string
;
751 /* Build printable strings for various stats */
752 file_type_string
= wtap_file_type_subtype_name(cf_info
->file_type
);
753 file_encap_string
= wtap_encap_name(cf_info
->file_encap
);
757 printf("%s", filename
);
764 printf("%s", file_type_string
);
768 /* ToDo: If WTAP_ENCAP_PER_PACKET, show the list of encapsulations encountered;
769 * Output a line for each different encap with all fields repeated except
770 * the encapsulation field which has "Per Packet: ..." for each
771 * encapsulation type seen ?
773 if (cap_file_encap
) {
776 printf("%s", file_encap_string
);
780 if (cap_file_more_info
) {
783 printf("%s", wtap_tsprec_string(cf_info
->file_tsprec
));
790 if (cf_info
->snap_set
)
791 printf("%u", cf_info
->snaplen
);
795 if (cf_info
->snaplen_max_inferred
> 0) {
798 printf("%u", cf_info
->snaplen_min_inferred
);
802 printf("%u", cf_info
->snaplen_max_inferred
);
817 if (cap_packet_count
) {
820 printf("%u", cf_info
->packet_count
);
827 printf("%" PRId64
, cf_info
->filesize
);
834 printf("%" PRIu64
, cf_info
->packet_bytes
);
841 printf("%s", relative_time_string(&cf_info
->duration
, cf_info
->duration_tsprec
, cf_info
, FALSE
));
845 if (cap_start_time
) {
848 printf("%s", absolute_time_string(&cf_info
->start_time
, cf_info
->start_time_tsprec
, cf_info
));
855 printf("%s", absolute_time_string(&cf_info
->stop_time
, cf_info
->stop_time_tsprec
, cf_info
));
859 if (cap_data_rate_byte
) {
862 if (cf_info
->times_known
)
863 printf("%.2f", cf_info
->data_rate
);
869 if (cap_data_rate_bit
) {
872 if (cf_info
->times_known
)
873 printf("%.2f", cf_info
->data_rate
*8);
879 if (cap_packet_size
) {
882 printf("%.2f", cf_info
->packet_size
);
886 if (cap_packet_rate
) {
889 if (cf_info
->times_known
)
890 printf("%.2f", cf_info
->packet_rate
);
896 if (cap_file_hashes
) {
899 printf("%s", file_sha256
);
904 printf("%s", file_sha1
);
911 printf("%s", order_string(cf_info
->order
));
915 for (guint section_number
= 0;
916 section_number
< wtap_file_get_num_shbs(cf_info
->wth
);
920 shb
= wtap_file_get_shb(cf_info
->wth
, section_number
);
921 if (cap_file_more_info
) {
926 if (wtap_block_get_string_option_value(shb
, OPT_SHB_HARDWARE
, &str
) == WTAP_OPTTYPE_SUCCESS
) {
933 if (wtap_block_get_string_option_value(shb
, OPT_SHB_OS
, &str
) == WTAP_OPTTYPE_SUCCESS
) {
940 if (wtap_block_get_string_option_value(shb
, OPT_SHB_USERAPPL
, &str
) == WTAP_OPTTYPE_SUCCESS
) {
947 * One might argue that the following is silly to put into a table format,
948 * but oh well note that there may be *more than one* of each of these types
949 * of options. To mitigate some of the potential silliness the if(cap_comment)
950 * block is moved AFTER the if(cap_file_more_info) block. This will make any
951 * comments the last item(s) in each row. We now have a new -K option to
952 * disable cap_comment to more easily manage the potential silliness.
953 * Potential silliness includes multiple comments (therefore resulting in
954 * more than one additional column and/or comments with embedded newlines
955 * and/or possible delimiters).
957 * To mitigate embedded newlines and other special characters, use -M
962 gboolean have_cap
= FALSE
;
964 for (i
= 0; wtap_block_get_nth_string_option_value(shb
, OPT_COMMENT
, i
, &opt_comment
) == WTAP_OPTTYPE_SUCCESS
; i
++) {
968 if (machine_readable
){
969 printf("%s", g_strescape(opt_comment
, NULL
));
971 printf("%s", opt_comment
);
976 /* Maintain column alignment when we have no OPT_COMMENT */
985 if (pkt_comments
&& cf_info
->pkt_cmts
!= NULL
) {
986 for(p
= cf_info
->pkt_cmts
; p
!= NULL
; prev
= p
, p
= p
->next
, g_free(prev
)) {
989 if (machine_readable
) {
990 printf("%s", g_strescape(p
->cmt
, NULL
));
992 printf("%s", p
->cmt
);
1003 cleanup_capture_info(capture_info
*cf_info
)
1006 ws_assert(cf_info
!= NULL
);
1008 g_free(cf_info
->encap_counts
);
1009 cf_info
->encap_counts
= NULL
;
1011 g_array_free(cf_info
->interface_packet_counts
, TRUE
);
1012 cf_info
->interface_packet_counts
= NULL
;
1014 if (cf_info
->idb_info_strings
) {
1015 for (i
= 0; i
< cf_info
->idb_info_strings
->len
; i
++) {
1016 gchar
*s
= g_array_index(cf_info
->idb_info_strings
, gchar
*, i
);
1019 g_array_free(cf_info
->idb_info_strings
, TRUE
);
1021 cf_info
->idb_info_strings
= NULL
;
1025 count_ipv4_address(const guint addr _U_
, const gchar
*name _U_
, const bool static_entry _U_
)
1027 num_ipv4_addresses
++;
1031 count_ipv6_address(const void *addrp _U_
, const gchar
*name _U_
, const bool static_entry _U_
)
1033 num_ipv6_addresses
++;
1037 count_decryption_secret(guint32 secrets_type _U_
, const void *secrets _U_
, guint size _U_
)
1039 /* XXX - count them based on the secrets type (which is an opaque code,
1040 not a small integer)? */
1041 num_decryption_secrets
++;
1045 hash_to_str(const unsigned char *hash
, size_t length
, char *str
)
1049 for (i
= 0; i
< (int) length
; i
++) {
1050 snprintf(str
+(i
*2), 3, "%02x", hash
[i
]);
1055 calculate_hashes(const char *filename
)
1060 (void) g_strlcpy(file_sha256
, "<unknown>", HASH_STR_SIZE
);
1061 (void) g_strlcpy(file_sha1
, "<unknown>", HASH_STR_SIZE
);
1063 if (cap_file_hashes
) {
1064 fh
= ws_fopen(filename
, "rb");
1066 while((hash_bytes
= fread(hash_buf
, 1, HASH_BUF_SIZE
, fh
)) > 0) {
1067 gcry_md_write(hd
, hash_buf
, hash_bytes
);
1070 hash_to_str(gcry_md_read(hd
, GCRY_MD_SHA256
), HASH_SIZE_SHA256
, file_sha256
);
1071 hash_to_str(gcry_md_read(hd
, GCRY_MD_SHA1
), HASH_SIZE_SHA1
, file_sha1
);
1074 if (hd
) gcry_md_reset(hd
);
1079 process_cap_file(const char *filename
, gboolean need_separator
)
1089 guint32 snaplen_min_inferred
= 0xffffffff;
1090 guint32 snaplen_max_inferred
= 0;
1093 capture_info cf_info
;
1094 gboolean have_times
= TRUE
;
1095 nstime_t start_time
;
1096 int start_time_tsprec
;
1098 int stop_time_tsprec
;
1101 gboolean know_order
= FALSE
;
1102 order_t order
= IN_ORDER
;
1104 wtapng_iface_descriptions_t
*idb_info
;
1106 pkt_cmt
*pc
= NULL
, *prev
= NULL
;
1108 cf_info
.wth
= wtap_open_offline(filename
, WTAP_TYPE_AUTO
, &err
, &err_info
, FALSE
);
1110 cfile_open_failure_message(filename
, err
, err_info
);
1115 * Calculate the checksums. Do this after wtap_open_offline, so we don't
1116 * bother calculating them for files that are not known capture types
1117 * where we wouldn't print them anyway.
1119 calculate_hashes(filename
);
1121 if (need_separator
&& long_report
) {
1125 nstime_set_zero(&start_time
);
1126 start_time_tsprec
= WTAP_TSPREC_UNKNOWN
;
1127 nstime_set_zero(&stop_time
);
1128 stop_time_tsprec
= WTAP_TSPREC_UNKNOWN
;
1129 nstime_set_zero(&cur_time
);
1130 nstime_set_zero(&prev_time
);
1132 cf_info
.encap_counts
= g_new0(int,WTAP_NUM_ENCAP_TYPES
);
1134 idb_info
= wtap_file_get_idb_info(cf_info
.wth
);
1136 ws_assert(idb_info
->interface_data
!= NULL
);
1138 cf_info
.pkt_cmts
= NULL
;
1139 cf_info
.num_interfaces
= idb_info
->interface_data
->len
;
1140 cf_info
.interface_packet_counts
= g_array_sized_new(FALSE
, TRUE
, sizeof(guint32
), cf_info
.num_interfaces
);
1141 g_array_set_size(cf_info
.interface_packet_counts
, cf_info
.num_interfaces
);
1142 cf_info
.pkt_interface_id_unknown
= 0;
1147 /* Zero out the counters for the callbacks. */
1148 num_ipv4_addresses
= 0;
1149 num_ipv6_addresses
= 0;
1150 num_decryption_secrets
= 0;
1152 /* Register callbacks for new name<->address maps from the file and
1153 decryption secrets from the file. */
1154 wtap_set_cb_new_ipv4(cf_info
.wth
, count_ipv4_address
);
1155 wtap_set_cb_new_ipv6(cf_info
.wth
, count_ipv6_address
);
1156 wtap_set_cb_new_secrets(cf_info
.wth
, count_decryption_secret
);
1158 /* Tally up data that we need to parse through the file to find */
1159 wtap_rec_init(&rec
);
1160 ws_buffer_init(&buf
, 1514);
1161 while (wtap_read(cf_info
.wth
, &rec
, &buf
, &err
, &err_info
, &data_offset
)) {
1162 if (rec
.presence_flags
& WTAP_HAS_TS
) {
1163 prev_time
= cur_time
;
1166 start_time
= rec
.ts
;
1167 start_time_tsprec
= rec
.tsprec
;
1169 stop_time_tsprec
= rec
.tsprec
;
1172 if (nstime_cmp(&cur_time
, &prev_time
) < 0) {
1173 order
= NOT_IN_ORDER
;
1175 if (nstime_cmp(&cur_time
, &start_time
) < 0) {
1176 start_time
= cur_time
;
1177 start_time_tsprec
= rec
.tsprec
;
1179 if (nstime_cmp(&cur_time
, &stop_time
) > 0) {
1180 stop_time
= cur_time
;
1181 stop_time_tsprec
= rec
.tsprec
;
1184 have_times
= FALSE
; /* at least one packet has no time stamp */
1185 if (order
!= NOT_IN_ORDER
)
1186 order
= ORDER_UNKNOWN
;
1189 if (rec
.rec_type
== REC_TYPE_PACKET
) {
1190 bytes
+= rec
.rec_header
.packet_header
.len
;
1192 /* packet comments */
1193 if (pkt_comments
&& wtap_block_count_option(rec
.block
, OPT_COMMENT
) > 0) {
1195 for (i
= 0; wtap_block_get_nth_string_option_value(rec
.block
, OPT_COMMENT
, i
, &cmt_buff
) == WTAP_OPTTYPE_SUCCESS
; i
++) {
1196 pc
= g_new0(pkt_cmt
, 1);
1199 pc
->cmt
= g_strdup(cmt_buff
);
1203 cf_info
.pkt_cmts
= pc
;
1211 /* If caplen < len for a rcd, then presumably */
1212 /* 'Limit packet capture length' was done for this rcd. */
1213 /* Keep track as to the min/max actual snapshot lengths */
1214 /* seen for this file. */
1215 if (rec
.rec_header
.packet_header
.caplen
< rec
.rec_header
.packet_header
.len
) {
1216 if (rec
.rec_header
.packet_header
.caplen
< snaplen_min_inferred
)
1217 snaplen_min_inferred
= rec
.rec_header
.packet_header
.caplen
;
1218 if (rec
.rec_header
.packet_header
.caplen
> snaplen_max_inferred
)
1219 snaplen_max_inferred
= rec
.rec_header
.packet_header
.caplen
;
1222 if ((rec
.rec_header
.packet_header
.pkt_encap
> 0) &&
1223 (rec
.rec_header
.packet_header
.pkt_encap
< WTAP_NUM_ENCAP_TYPES
)) {
1224 cf_info
.encap_counts
[rec
.rec_header
.packet_header
.pkt_encap
] += 1;
1226 fprintf(stderr
, "capinfos: Unknown packet encapsulation %d in frame %u of file \"%s\"\n",
1227 rec
.rec_header
.packet_header
.pkt_encap
, packet
, filename
);
1230 /* Packet interface_id info */
1231 if (rec
.presence_flags
& WTAP_HAS_INTERFACE_ID
) {
1232 /* cf_info.num_interfaces is size, not index, so it's one more than max index */
1233 if (rec
.rec_header
.packet_header
.interface_id
>= cf_info
.num_interfaces
) {
1235 * OK, re-fetch the number of interfaces, as there might have
1236 * been an interface that was in the middle of packets, and
1237 * grow the array to be big enough for the new number of
1240 idb_info
= wtap_file_get_idb_info(cf_info
.wth
);
1242 cf_info
.num_interfaces
= idb_info
->interface_data
->len
;
1243 g_array_set_size(cf_info
.interface_packet_counts
, cf_info
.num_interfaces
);
1248 if (rec
.rec_header
.packet_header
.interface_id
< cf_info
.num_interfaces
) {
1249 g_array_index(cf_info
.interface_packet_counts
, guint32
,
1250 rec
.rec_header
.packet_header
.interface_id
) += 1;
1253 cf_info
.pkt_interface_id_unknown
+= 1;
1257 /* it's for interface_id 0 */
1258 if (cf_info
.num_interfaces
!= 0) {
1259 g_array_index(cf_info
.interface_packet_counts
, guint32
, 0) += 1;
1262 cf_info
.pkt_interface_id_unknown
+= 1;
1267 wtap_rec_reset(&rec
);
1269 wtap_rec_cleanup(&rec
);
1270 ws_buffer_free(&buf
);
1273 * Get IDB info strings.
1274 * We do this at the end, so we can get information for all IDBs in
1275 * the file, even those that come after packet records, and so that
1276 * we get, for example, a count of the number of statistics entries
1277 * for each interface as of the *end* of the file.
1279 idb_info
= wtap_file_get_idb_info(cf_info
.wth
);
1281 cf_info
.idb_info_strings
= g_array_sized_new(FALSE
, FALSE
, sizeof(gchar
*), cf_info
.num_interfaces
);
1282 cf_info
.num_interfaces
= idb_info
->interface_data
->len
;
1283 for (i
= 0; i
< cf_info
.num_interfaces
; i
++) {
1284 const wtap_block_t if_descr
= g_array_index(idb_info
->interface_data
, wtap_block_t
, i
);
1285 gchar
*s
= wtap_get_debug_if_descr(if_descr
, 21, "\n");
1286 g_array_append_val(cf_info
.idb_info_strings
, s
);
1294 "capinfos: An error occurred after reading %u packets from \"%s\".\n",
1296 cfile_read_failure_message(filename
, err
, err_info
);
1297 if (err
== WTAP_ERR_SHORT_READ
) {
1298 /* Don't give up completely with this one. */
1301 " (will continue anyway, checksums might be incorrect)\n");
1303 cleanup_capture_info(&cf_info
);
1304 wtap_close(cf_info
.wth
);
1310 size
= wtap_file_size(cf_info
.wth
, &err
);
1313 "capinfos: Can't get size of \"%s\": %s.\n",
1314 filename
, g_strerror(err
));
1315 cleanup_capture_info(&cf_info
);
1316 wtap_close(cf_info
.wth
);
1320 cf_info
.filesize
= size
;
1323 cf_info
.file_type
= wtap_file_type_subtype(cf_info
.wth
);
1324 cf_info
.compression_type
= wtap_get_compression_type(cf_info
.wth
);
1326 /* File Encapsulation */
1327 cf_info
.file_encap
= wtap_file_encap(cf_info
.wth
);
1329 cf_info
.file_tsprec
= wtap_file_tsprec(cf_info
.wth
);
1331 /* Packet size limit (snaplen) */
1332 cf_info
.snaplen
= wtap_snapshot_length(cf_info
.wth
);
1333 if (cf_info
.snaplen
> 0)
1334 cf_info
.snap_set
= TRUE
;
1336 cf_info
.snap_set
= FALSE
;
1338 cf_info
.snaplen_min_inferred
= snaplen_min_inferred
;
1339 cf_info
.snaplen_max_inferred
= snaplen_max_inferred
;
1342 cf_info
.packet_count
= packet
;
1345 cf_info
.times_known
= have_times
;
1346 cf_info
.start_time
= start_time
;
1347 cf_info
.start_time_tsprec
= start_time_tsprec
;
1348 cf_info
.stop_time
= stop_time
;
1349 cf_info
.stop_time_tsprec
= stop_time_tsprec
;
1350 nstime_delta(&cf_info
.duration
, &stop_time
, &start_time
);
1351 /* Duration precision is the higher of the start and stop time precisions. */
1352 if (cf_info
.stop_time_tsprec
> cf_info
.start_time_tsprec
)
1353 cf_info
.duration_tsprec
= cf_info
.stop_time_tsprec
;
1355 cf_info
.duration_tsprec
= cf_info
.start_time_tsprec
;
1356 cf_info
.know_order
= know_order
;
1357 cf_info
.order
= order
;
1359 /* Number of packet bytes */
1360 cf_info
.packet_bytes
= bytes
;
1362 cf_info
.data_rate
= 0.0;
1363 cf_info
.packet_rate
= 0.0;
1364 cf_info
.packet_size
= 0.0;
1367 double delta_time
= nstime_to_sec(&stop_time
) - nstime_to_sec(&start_time
);
1368 if (delta_time
> 0.0) {
1369 cf_info
.data_rate
= (double)bytes
/ delta_time
; /* Data rate per second */
1370 cf_info
.packet_rate
= (double)packet
/ delta_time
; /* packet rate per second */
1372 cf_info
.packet_size
= (double)bytes
/ packet
; /* Avg packet size */
1375 if (!long_report
&& table_report_header
) {
1376 print_stats_table_header(&cf_info
);
1380 print_stats(filename
, &cf_info
);
1382 print_stats_table(filename
, &cf_info
);
1385 cleanup_capture_info(&cf_info
);
1386 wtap_close(cf_info
.wth
);
1392 print_usage(FILE *output
)
1394 fprintf(output
, "\n");
1395 fprintf(output
, "Usage: capinfos [options] <infile> ...\n");
1396 fprintf(output
, "\n");
1397 fprintf(output
, "General infos:\n");
1398 fprintf(output
, " -t display the capture file type\n");
1399 fprintf(output
, " -E display the capture file encapsulation\n");
1400 fprintf(output
, " -I display the capture file interface information\n");
1401 fprintf(output
, " -F display additional capture file information\n");
1402 fprintf(output
, " -H display the SHA256 and SHA1 hashes of the file\n");
1403 fprintf(output
, " -k display the capture comment\n");
1404 fprintf(output
, " -p display individual packet comments\n");
1405 fprintf(output
, "\n");
1406 fprintf(output
, "Size infos:\n");
1407 fprintf(output
, " -c display the number of packets\n");
1408 fprintf(output
, " -s display the size of the file (in bytes)\n");
1409 fprintf(output
, " -d display the total length of all packets (in bytes)\n");
1410 fprintf(output
, " -l display the packet size limit (snapshot length)\n");
1411 fprintf(output
, "\n");
1412 fprintf(output
, "Time infos:\n");
1413 fprintf(output
, " -u display the capture duration (in seconds)\n");
1414 fprintf(output
, " -a display the capture start time\n");
1415 fprintf(output
, " -e display the capture end time\n");
1416 fprintf(output
, " -o display the capture file chronological status (True/False)\n");
1417 fprintf(output
, " -S display start and end times as seconds\n");
1418 fprintf(output
, "\n");
1419 fprintf(output
, "Statistic infos:\n");
1420 fprintf(output
, " -y display average data rate (in bytes/sec)\n");
1421 fprintf(output
, " -i display average data rate (in bits/sec)\n");
1422 fprintf(output
, " -z display average packet size (in bytes)\n");
1423 fprintf(output
, " -x display average packet rate (in packets/sec)\n");
1424 fprintf(output
, "\n");
1425 fprintf(output
, "Metadata infos:\n");
1426 fprintf(output
, " -n display number of resolved IPv4 and IPv6 addresses\n");
1427 fprintf(output
, " -D display number of decryption secrets\n");
1428 fprintf(output
, "\n");
1429 fprintf(output
, "Output format:\n");
1430 fprintf(output
, " -L generate long report (default)\n");
1431 fprintf(output
, " -T generate table report\n");
1432 fprintf(output
, " -M display machine-readable values in long reports\n");
1433 fprintf(output
, "\n");
1434 fprintf(output
, "Table report options:\n");
1435 fprintf(output
, " -R generate header record (default)\n");
1436 fprintf(output
, " -r do not generate header record\n");
1437 fprintf(output
, "\n");
1438 fprintf(output
, " -B separate infos with TAB character (default)\n");
1439 fprintf(output
, " -m separate infos with comma (,) character\n");
1440 fprintf(output
, " -b separate infos with SPACE character\n");
1441 fprintf(output
, "\n");
1442 fprintf(output
, " -N do not quote infos (default)\n");
1443 fprintf(output
, " -q quote infos with single quotes (')\n");
1444 fprintf(output
, " -Q quote infos with double quotes (\")\n");
1445 fprintf(output
, "\n");
1446 fprintf(output
, "Miscellaneous:\n");
1447 fprintf(output
, " -h, --help display this help and exit\n");
1448 fprintf(output
, " -v, --version display version info and exit\n");
1449 fprintf(output
, " -C cancel processing if file open fails (default is to continue)\n");
1450 fprintf(output
, " -A generate all infos (default)\n");
1451 fprintf(output
, " -K disable displaying the capture comment\n");
1452 fprintf(output
, " -P disable displaying individual packet comments\n");
1453 fprintf(output
, "\n");
1454 fprintf(output
, "Options are processed from left to right order with later options superseding\n");
1455 fprintf(output
, "or adding to earlier options.\n");
1456 fprintf(output
, "\n");
1457 fprintf(output
, "If no options are given the default is to display all infos in long report\n");
1458 fprintf(output
, "output format.\n");
1462 * Report an error in command-line arguments.
1465 capinfos_cmdarg_err(const char *msg_format
, va_list ap
)
1467 fprintf(stderr
, "capinfos: ");
1468 vfprintf(stderr
, msg_format
, ap
);
1469 fprintf(stderr
, "\n");
1473 * Report additional information for an error in command-line arguments.
1476 capinfos_cmdarg_err_cont(const char *msg_format
, va_list ap
)
1478 vfprintf(stderr
, msg_format
, ap
);
1479 fprintf(stderr
, "\n");
1483 main(int argc
, char *argv
[])
1485 char *configuration_init_error
;
1486 static const struct report_message_routines capinfos_report_routines
= {
1489 open_failure_message
,
1490 read_failure_message
,
1491 write_failure_message
,
1492 cfile_open_failure_message
,
1493 cfile_dump_open_failure_message
,
1494 cfile_read_failure_message
,
1495 cfile_write_failure_message
,
1496 cfile_close_failure_message
1498 gboolean need_separator
= FALSE
;
1500 int overall_error_status
= EXIT_SUCCESS
;
1501 static const struct ws_option long_options
[] = {
1502 {"help", ws_no_argument
, NULL
, 'h'},
1503 {"version", ws_no_argument
, NULL
, 'v'},
1510 * Set the C-language locale to the native environment and set the
1511 * code page to UTF-8 on Windows.
1514 setlocale(LC_ALL
, ".UTF-8");
1516 setlocale(LC_ALL
, "");
1519 cmdarg_err_init(capinfos_cmdarg_err
, capinfos_cmdarg_err_cont
);
1521 /* Initialize log handler early so we can have proper logging during startup. */
1522 ws_log_init("capinfos", vcmdarg_err
);
1524 /* Early logging command-line initialization. */
1525 ws_log_parse_args(&argc
, argv
, vcmdarg_err
, WS_EXIT_INVALID_OPTION
);
1527 ws_noisy("Finished log init and parsing command line log arguments");
1529 /* Get the decimal point. */
1530 decimal_point
= g_strdup(localeconv()->decimal_point
);
1532 /* Initialize the version information. */
1533 ws_init_version_info("Capinfos", NULL
, NULL
);
1536 create_app_running_mutex();
1540 * Get credential information for later use.
1542 init_process_policies();
1545 * Attempt to get the pathname of the directory containing the
1548 configuration_init_error
= configuration_init(argv
[0], NULL
);
1549 if (configuration_init_error
!= NULL
) {
1551 "capinfos: Can't get pathname of directory containing the capinfos program: %s.\n",
1552 configuration_init_error
);
1553 g_free(configuration_init_error
);
1556 init_report_message("capinfos", &capinfos_report_routines
);
1560 /* Process the options */
1561 while ((opt
= ws_getopt_long(argc
, argv
, "abcdehiklmnopqrstuvxyzABCDEFHIKLMNPQRST", long_options
, NULL
)) !=-1) {
1566 if (report_all_infos
) disable_all_infos();
1567 cap_file_type
= TRUE
;
1571 if (report_all_infos
) disable_all_infos();
1572 cap_file_encap
= TRUE
;
1576 if (report_all_infos
) disable_all_infos();
1581 if (report_all_infos
) disable_all_infos();
1582 cap_packet_count
= TRUE
;
1586 if (report_all_infos
) disable_all_infos();
1587 cap_file_size
= TRUE
;
1591 if (report_all_infos
) disable_all_infos();
1592 cap_data_size
= TRUE
;
1596 if (report_all_infos
) disable_all_infos();
1597 cap_duration
= TRUE
;
1601 if (report_all_infos
) disable_all_infos();
1602 cap_start_time
= TRUE
;
1606 if (report_all_infos
) disable_all_infos();
1607 cap_end_time
= TRUE
;
1611 time_as_secs
= TRUE
;
1615 if (report_all_infos
) disable_all_infos();
1616 cap_data_rate_byte
= TRUE
;
1620 if (report_all_infos
) disable_all_infos();
1621 cap_data_rate_bit
= TRUE
;
1625 if (report_all_infos
) disable_all_infos();
1626 cap_packet_size
= TRUE
;
1630 if (report_all_infos
) disable_all_infos();
1631 cap_packet_rate
= TRUE
;
1635 if (report_all_infos
) disable_all_infos();
1636 cap_file_hashes
= TRUE
;
1640 if (report_all_infos
) disable_all_infos();
1645 if (report_all_infos
) disable_all_infos();
1650 if (report_all_infos
) disable_all_infos();
1651 pkt_comments
= TRUE
;
1655 cap_comment
= FALSE
;
1659 pkt_comments
= FALSE
;
1663 if (report_all_infos
) disable_all_infos();
1664 cap_file_more_info
= TRUE
;
1668 if (report_all_infos
) disable_all_infos();
1669 cap_file_idb
= TRUE
;
1673 if (report_all_infos
) disable_all_infos();
1674 cap_file_nrb
= TRUE
;
1678 if (report_all_infos
) disable_all_infos();
1679 cap_file_dsb
= TRUE
;
1683 stop_after_failure
= TRUE
;
1695 long_report
= FALSE
;
1699 machine_readable
= TRUE
;
1703 table_report_header
= TRUE
;
1707 table_report_header
= FALSE
;
1723 field_separator
= '\t';
1727 field_separator
= ',';
1731 field_separator
= ' ';
1735 show_help_header("Print various information (infos) about capture files.");
1736 print_usage(stdout
);
1745 case '?': /* Bad flag - print usage message */
1746 print_usage(stderr
);
1747 overall_error_status
= WS_EXIT_INVALID_OPTION
;
1753 if ((argc
- ws_optind
) < 1) {
1754 print_usage(stderr
);
1755 overall_error_status
= WS_EXIT_INVALID_OPTION
;
1759 if (cap_file_hashes
) {
1760 gcry_check_version(NULL
);
1761 gcry_md_open(&hd
, GCRY_MD_SHA256
, 0);
1763 gcry_md_enable(hd
, GCRY_MD_SHA1
);
1765 hash_buf
= (char *)g_malloc(HASH_BUF_SIZE
);
1768 overall_error_status
= 0;
1770 for (opt
= ws_optind
; opt
< argc
; opt
++) {
1772 status
= process_cap_file(argv
[opt
], need_separator
);
1774 /* Something failed. It's been reported; remember that processing
1775 one file failed and, if -C was specified, stop. */
1776 overall_error_status
= status
;
1777 if (stop_after_failure
)
1781 /* Either it succeeded or it got a "short read" but printed
1782 information anyway. Note that we need a blank line before
1783 the next file's information, to separate it from the
1785 need_separator
= TRUE
;
1794 return overall_error_status
;