Bug Summary

File:capinfos.c
Warning:line 1068, column 33
Read function called when stream is in EOF state. Function has no effect

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name capinfos.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-21/lib/clang/21 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -I /builds/wireshark/wireshark/wiretap -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-truncation -Wno-format-nonliteral -Wno-pointer-sign -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2025-11-07-100324-3624-1 -x c /builds/wireshark/wireshark/capinfos.c
1/* capinfos.c
2 * Reports capture file information including # of packets, duration, others
3 *
4 * Copyright 2004 Ian Schorr
5 *
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 */
12
13/*
14 * 2009-09-19: jyoung
15 *
16 * New capinfos features
17 *
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.
23 *
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.
27 *
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.
33 *
34 * 2011-04-05: wmeier
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).
40 *
41 */
42
43
44#include <config.h>
45#define WS_LOG_DOMAIN"Main" LOG_DOMAIN_MAIN"Main"
46
47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50#include <stdarg.h>
51#include <locale.h>
52
53#include <ws_exit_codes.h>
54#include <wsutil/clopts_common.h>
55#include <wsutil/ws_getopt.h>
56
57#include <glib.h>
58
59#include <wiretap/wtap.h>
60
61#include <wsutil/cmdarg_err.h>
62#include <wsutil/filesystem.h>
63#include <wsutil/application_flavor.h>
64#include <wsutil/file_compressed.h>
65#include <wsutil/privileges.h>
66#include <cli_main.h>
67#include <wsutil/version_info.h>
68#include <wsutil/report_message.h>
69#include <wiretap/wtap_opttypes.h>
70
71#ifdef HAVE_PLUGINS1
72#include <wsutil/plugins.h>
73#endif
74
75#include <wsutil/str_util.h>
76#include <wsutil/to_str.h>
77#include <wsutil/file_util.h>
78#include <wsutil/ws_assert.h>
79#include <wsutil/wslog.h>
80
81#include <gcrypt.h>
82
83#include "ui/failure_message.h"
84
85/*
86 * By default capinfos now continues processing
87 * the next filename if and when wiretap detects
88 * a problem opening or reading a file.
89 * Use the '-C' option to revert back to original
90 * capinfos behavior which is to abort any
91 * additional file processing at the first file
92 * open or read failure.
93 */
94
95static bool_Bool stop_after_failure;
96
97/*
98 * table report variables
99 */
100
101static bool_Bool long_report = true1; /* By default generate long report */
102static bool_Bool table_report_header = true1; /* Generate column header by default */
103static char field_separator = '\t'; /* Use TAB as field separator by default */
104static char quote_char = '\0'; /* Do NOT quote fields by default */
105static bool_Bool machine_readable; /* Display machine-readable numbers */
106
107/*
108 * capinfos has the ability to report on a number of
109 * various characteristics ("infos") for each input file.
110 *
111 * By default reporting of all info fields is enabled.
112 *
113 * Optionally the reporting of any specific info field
114 * or combination of info fields can be enabled with
115 * individual options.
116 */
117
118static bool_Bool report_all_infos = true1; /* Report all infos */
119
120static bool_Bool cap_file_type = true1; /* Report capture type */
121static bool_Bool cap_file_encap = true1; /* Report encapsulation */
122static bool_Bool cap_snaplen = true1; /* Packet size limit (snaplen)*/
123static bool_Bool cap_packet_count = true1; /* Report packet count */
124static bool_Bool cap_file_size = true1; /* Report file size */
125static bool_Bool cap_comment = true1; /* Display the capture comment */
126static bool_Bool cap_file_more_info = true1; /* Report more file info */
127static bool_Bool cap_file_idb = true1; /* Report Interface info */
128static bool_Bool cap_file_nrb = true1; /* Report Name Resolution Block info */
129static bool_Bool cap_file_dsb = true1; /* Report Decryption Secrets Block info */
130
131static bool_Bool cap_data_size = true1; /* Report packet byte size */
132static bool_Bool cap_duration = true1; /* Report capture duration */
133static bool_Bool cap_earliest_packet_time = true1; /* Report timestamp of earliest packet */
134static bool_Bool cap_latest_packet_time = true1; /* Report timestamp of latest packet */
135static bool_Bool time_as_secs; /* Report time values as raw seconds */
136
137static bool_Bool cap_data_rate_byte = true1; /* Report data rate bytes/sec */
138static bool_Bool cap_data_rate_bit = true1; /* Report data rate bites/sec */
139static bool_Bool cap_packet_size = true1; /* Report average packet size */
140static bool_Bool cap_packet_rate = true1; /* Report average packet rate */
141static bool_Bool cap_order = true1; /* Report if packets are in chronological order (True/False) */
142static bool_Bool pkt_comments = true1; /* Report individual packet comments */
143
144static bool_Bool cap_file_hashes = true1; /* Calculate file hashes */
145
146// Strongest to weakest
147#define HASH_SIZE_SHA25632 32
148#define HASH_SIZE_SHA120 20
149
150#define HASH_STR_SIZE(65) (65) /* Max hash size * 2 + '\0' */
151#define HASH_BUF_SIZE(1024 * 1024) (1024 * 1024)
152
153
154static char file_sha256[HASH_STR_SIZE(65)];
155static char file_sha1[HASH_STR_SIZE(65)];
156
157static char *hash_buf;
158static gcry_md_hd_t hd;
159
160static unsigned int num_ipv4_addresses;
161static unsigned int num_ipv6_addresses;
162static unsigned int num_decryption_secrets;
163
164/*
165 * If we have at least two packets with time stamps, and they're not in
166 * order - i.e., the later packet has a time stamp older than the earlier
167 * packet - the time stamps are known not to be in order.
168 *
169 * If every packet has a time stamp, and they're all in order, the time
170 * stamp is known to be in order.
171 *
172 * Otherwise, we have no idea.
173 */
174typedef enum {
175 IN_ORDER,
176 NOT_IN_ORDER,
177 ORDER_UNKNOWN
178} order_t;
179
180typedef struct _pkt_cmt {
181 uint32_t recno;
182 char *cmt;
183 struct _pkt_cmt *next;
184} pkt_cmt;
185
186typedef struct _capture_info {
187 const char *filename;
188 uint16_t file_type;
189 ws_compression_type compression_type;
190 int file_encap;
191 int file_tsprec;
192 wtap *wth;
193 int64_t filesize;
194 uint64_t packet_bytes;
195 bool_Bool times_known;
196 nstime_t earliest_packet_time;
197 int earliest_packet_time_tsprec;
198 nstime_t latest_packet_time;
199 int latest_packet_time_tsprec;
200 uint32_t packet_count;
201 bool_Bool snap_set; /* If set in capture file header */
202 uint32_t snaplen; /* value from the capture file header */
203 uint32_t snaplen_min_inferred; /* If caplen < len for 1 or more rcds */
204 uint32_t snaplen_max_inferred; /* ... */
205 bool_Bool drops_known;
206 uint32_t drop_count;
207
208 nstime_t duration;
209 int duration_tsprec;
210 double packet_rate;
211 double packet_size;
212 double data_rate; /* in bytes/s */
213 bool_Bool know_order;
214 order_t order;
215
216 int *encap_counts; /* array of per_packet encap counts; array has one entry per wtap_encap type */
217 pkt_cmt *pkt_cmts; /* list of packet comments */
218
219 unsigned int num_interfaces; /* number of IDBs, and thus size of interface_packet_counts array */
220 GArray *interface_packet_counts; /* array of per_packet interface_id counts; one entry per file IDB */
221 uint32_t pkt_interface_id_unknown; /* counts if packet interface_id didn't match a known one */
222 GArray *idb_info_strings; /* array of IDB info strings */
223} capture_info;
224
225static char *decimal_point;
226
227static void
228enable_all_infos(void)
229{
230 report_all_infos = true1;
231
232 cap_file_type = true1;
233 cap_file_encap = true1;
234 cap_snaplen = true1;
235 cap_packet_count = true1;
236 cap_file_size = true1;
237 cap_comment = true1;
238 pkt_comments = true1;
239 cap_file_more_info = true1;
240 cap_file_idb = true1;
241 cap_file_nrb = true1;
242 cap_file_dsb = true1;
243
244 cap_data_size = true1;
245 cap_duration = true1;
246 cap_earliest_packet_time = true1;
247 cap_latest_packet_time = true1;
248 cap_order = true1;
249
250 cap_data_rate_byte = true1;
251 cap_data_rate_bit = true1;
252 cap_packet_size = true1;
253 cap_packet_rate = true1;
254
255 cap_file_hashes = true1;
256}
257
258static void
259disable_all_infos(void)
260{
261 report_all_infos = false0;
262
263 cap_file_type = false0;
264 cap_file_encap = false0;
265 cap_snaplen = false0;
266 cap_packet_count = false0;
267 cap_file_size = false0;
268 cap_comment = false0;
269 pkt_comments = false0;
270 cap_file_more_info = false0;
271 cap_file_idb = false0;
272 cap_file_nrb = false0;
273 cap_file_dsb = false0;
274
275 cap_data_size = false0;
276 cap_duration = false0;
277 cap_earliest_packet_time = false0;
278 cap_latest_packet_time = false0;
279 cap_order = false0;
280
281 cap_data_rate_byte = false0;
282 cap_data_rate_bit = false0;
283 cap_packet_size = false0;
284 cap_packet_rate = false0;
285
286 cap_file_hashes = false0;
287}
288
289static const char *
290order_string(order_t order)
291{
292 switch (order) {
293
294 case IN_ORDER:
295 return "True";
296
297 case NOT_IN_ORDER:
298 return "False";
299
300 case ORDER_UNKNOWN:
301 return "Unknown";
302
303 default:
304 return "???"; /* "cannot happen" (the next step is "Profit!") */
305 }
306}
307
308static char *
309absolute_time_string(nstime_t *timer, int tsprecision, capture_info *cf_info)
310{
311 /*
312 * https://web.archive.org/web/20120513133703/http://www.idrbt.ac.in/publications/workingpapers/Working%20Paper%20No.%209.pdf
313 *
314 * says:
315 *
316 * A 64-bit Unix time would be safe for the indefinite future, as
317 * this variable would not overflow until 2**63 or
318 * 9,223,372,036,854,775,808 (over nine quintillion) seconds
319 * after the beginning of the Unix epoch - corresponding to
320 * GMT 15:30:08, Sunday, 4th December, 292,277,026,596.
321 *
322 * So, if we're displaying the time as YYYY-MM-DD HH:MM:SS.SSSSSSSSS,
323 * we'll have the buffer be large enough for a date of the format
324 * 292277026596-MM-DD HH:MM:SS.SSSSSSSSS, which is the biggest value
325 * you'll get with a 64-bit time_t and a nanosecond-resolution
326 * fraction-of-a-second.
327 *
328 * That's 12+1+2+1+2+1+2+1+2+2+2+1+9+1, including the terminating
329 * \0, or 39.
330 *
331 * If we're displaying the time as epoch time, and the time is
332 * unsigned, 2^64-1 is 18446744073709551615, so the buffer has
333 * to be big enough for 18446744073709551615.999999999. That's
334 * 20+1+9+1, including the terminating '\0', or 31. If it's
335 * signed, 2^63 is 9223372036854775808, so the buffer has to
336 * be big enough for -9223372036854775808.999999999, which is
337 * again 20+1+9+1, or 31.
338 *
339 * So we go with 39.
340 */
341 static char time_string_buf[39];
342
343 if (cf_info->times_known && cf_info->packet_count > 0) {
344 if (time_as_secs) {
345 display_epoch_time(time_string_buf, sizeof time_string_buf, timer, tsprecision);
346 } else {
347 format_nstime_as_iso8601(time_string_buf, sizeof time_string_buf, timer, decimal_point, true1, tsprecision);
348 }
349 } else {
350 snprintf(time_string_buf, sizeof time_string_buf, "n/a");
351 }
352 return time_string_buf;
353}
354
355static char *
356relative_time_string(nstime_t *timer, int tsprecision, capture_info *cf_info, bool_Bool want_seconds)
357{
358 const char *second = want_seconds ? " second" : "";
359 const char *plural = want_seconds ? "s" : "";
360 /*
361 * If we're displaying the time as epoch time, and the time is
362 * unsigned, 2^64-1 is 18446744073709551615, so the buffer has
363 * to be big enough for "18446744073709551615.999999999 seconds".
364 * That's 20+1+9+1+7+1, including the terminating '\0', or 39.
365 * If it'ssigned, 2^63 is 9223372036854775808, so the buffer has to
366 * be big enough for "-9223372036854775808.999999999 seconds",
367 * which is again 20+1+9+1+7+1, or 39.
368 */
369 static char time_string_buf[39];
370
371 if (cf_info->times_known && cf_info->packet_count > 0) {
372 char *ptr;
373 size_t remaining;
374 int num_bytes;
375
376 ptr = time_string_buf;
377 remaining = sizeof time_string_buf;
378 num_bytes = snprintf(ptr, remaining,
379 "%"PRId64"l" "d",
380 (int64_t)timer->secs);
381 if (num_bytes < 0) {
382 /*
383 * That got an error.
384 * Not much else we can do.
385 */
386 snprintf(ptr, remaining, "snprintf() failed");
387 return time_string_buf;
388 }
389 if ((unsigned int)num_bytes >= remaining) {
390 /*
391 * That filled up or would have overflowed the buffer.
392 * Nothing more we can do.
393 */
394 return time_string_buf;
395 }
396 ptr += num_bytes;
397 remaining -= num_bytes;
398
399 if (tsprecision != 0) {
400 /*
401 * Append the fractional part.
402 */
403 num_bytes = format_fractional_part_nsecs(ptr, remaining, timer->nsecs, decimal_point, tsprecision);
404 if ((unsigned int)num_bytes >= remaining) {
405 /*
406 * That filled up or would have overflowed the buffer.
407 * Nothing more we can do.
408 */
409 return time_string_buf;
410 }
411 ptr += num_bytes;
412 remaining -= num_bytes;
413 }
414
415 /*
416 * Append the units.
417 */
418 snprintf(ptr, remaining, "%s%s",
419 second,
420 timer->secs == 1 ? "" : plural);
421
422 return time_string_buf;
423 }
424
425 snprintf(time_string_buf, sizeof time_string_buf, "n/a");
426 return time_string_buf;
427}
428
429static void print_value(const char *text_p1, int width, const char *text_p2, double value)
430{
431 if (value > 0.0)
432 printf("%s%.*f%s\n", text_p1, width, value, text_p2);
433 else
434 printf("%sn/a\n", text_p1);
435}
436
437/* multi-line comments would conflict with the formatting that capinfos uses
438 we replace linefeeds with spaces */
439static void
440string_replace_newlines(char *str)
441{
442 char *p;
443
444 if (str) {
445 p = str;
446 while (*p != '\0') {
447 if (*p == '\n')
448 *p = ' ';
449 if (*p == '\r')
450 *p = ' ';
451 p++;
452 }
453 }
454}
455
456static void
457show_option_string(const char *prefix, const char *option_str)
458{
459 char *str;
460
461 if (option_str != NULL((void*)0) && option_str[0] != '\0') {
462 str = g_strdup(option_str)g_strdup_inline (option_str);
463 string_replace_newlines(str);
464 printf("%s%s\n", prefix, str);
465 g_free(str);
466 }
467}
468
469static void
470print_stats(const char *filename, capture_info *cf_info)
471{
472 const char *file_type_string, *file_encap_string;
473 char *size_string;
474 pkt_cmt *p, *prev;
475
476 /* Build printable strings for various stats */
477 if (machine_readable) {
478 file_type_string = wtap_file_type_subtype_name(cf_info->file_type);
479 file_encap_string = wtap_encap_name(cf_info->file_encap);
480 }
481 else {
482 file_type_string = wtap_file_type_subtype_description(cf_info->file_type);
483 file_encap_string = wtap_encap_description(cf_info->file_encap);
484 }
485
486 if (filename) printf ("File name: %s\n", filename);
487 if (cap_file_type) {
488 const char *compression_type_description;
489 compression_type_description = ws_compression_type_description(cf_info->compression_type);
490 if (compression_type_description == NULL((void*)0))
491 printf ("File type: %s\n",
492 file_type_string);
493 else
494 printf ("File type: %s (%s)\n",
495 file_type_string, compression_type_description);
496 }
497 if (cap_file_encap) {
498 printf ("File encapsulation: %s\n", file_encap_string);
499 if (cf_info->file_encap == WTAP_ENCAP_PER_PACKET-1) {
500 int i;
501 printf ("Encapsulation in use by packets (# of pkts):\n");
502 for (i=0; i<WTAP_NUM_ENCAP_TYPESwtap_get_num_encap_types(); i++) {
503 if (cf_info->encap_counts[i] > 0)
504 printf(" %s (%d)\n",
505 wtap_encap_description(i), cf_info->encap_counts[i]);
506 }
507 }
508 }
509 if (cap_file_more_info) {
510 printf ("File timestamp precision: %s (%d)\n",
511 wtap_tsprec_string(cf_info->file_tsprec), cf_info->file_tsprec);
512 }
513
514 if (cap_snaplen && cf_info->snap_set)
515 printf ("Packet size limit: file hdr: %u bytes\n", cf_info->snaplen);
516 else if (cap_snaplen && !cf_info->snap_set)
517 printf ("Packet size limit: file hdr: (not set)\n");
518 if (cf_info->snaplen_max_inferred > 0) {
519 if (cf_info->snaplen_min_inferred == cf_info->snaplen_max_inferred)
520 printf ("Packet size limit: inferred: %u bytes\n", cf_info->snaplen_min_inferred);
521 else
522 printf ("Packet size limit: inferred: %u bytes - %u bytes (range)\n",
523 cf_info->snaplen_min_inferred, cf_info->snaplen_max_inferred);
524 }
525 if (cap_packet_count) {
526 printf ("Number of packets: ");
527 if (machine_readable) {
528 printf ("%u\n", cf_info->packet_count);
529 } else {
530 size_string = format_size(cf_info->packet_count, FORMAT_SIZE_UNIT_NONE, 0)format_size_wmem(((void*)0), cf_info->packet_count, FORMAT_SIZE_UNIT_NONE
, 0)
;
531 printf ("%s\n", size_string);
532 g_free(size_string);
533 }
534 }
535 if (cap_file_size) {
536 printf ("File size: ");
537 if (machine_readable) {
538 printf ("%" PRId64"l" "d" " bytes\n", cf_info->filesize);
539 } else {
540 size_string = format_size(cf_info->filesize, FORMAT_SIZE_UNIT_BYTES, 0)format_size_wmem(((void*)0), cf_info->filesize, FORMAT_SIZE_UNIT_BYTES
, 0)
;
541 printf ("%s\n", size_string);
542 g_free(size_string);
543 }
544 }
545 if (cap_data_size) {
546 printf ("Data size: ");
547 if (machine_readable) {
548 printf ("%" PRIu64"l" "u" " bytes\n", cf_info->packet_bytes);
549 } else {
550 size_string = format_size(cf_info->packet_bytes, FORMAT_SIZE_UNIT_BYTES, 0)format_size_wmem(((void*)0), cf_info->packet_bytes, FORMAT_SIZE_UNIT_BYTES
, 0)
;
551 printf ("%s\n", size_string);
552 g_free(size_string);
553 }
554 }
555 if (cf_info->times_known) {
556 if (cap_duration) /* XXX - shorten to hh:mm:ss */
557 printf("Capture duration: %s\n", relative_time_string(&cf_info->duration, cf_info->duration_tsprec, cf_info, true1));
558 if (cap_earliest_packet_time)
559 printf("Earliest packet time: %s\n", absolute_time_string(&cf_info->earliest_packet_time, cf_info->earliest_packet_time_tsprec, cf_info));
560 if (cap_latest_packet_time)
561 printf("Latest packet time: %s\n", absolute_time_string(&cf_info->latest_packet_time, cf_info->latest_packet_time_tsprec, cf_info));
562 if (cap_data_rate_byte) {
563 printf("Data byte rate: ");
564 if (machine_readable) {
565 print_value("", 2, " bytes/sec", cf_info->data_rate);
566 } else {
567 size_string = format_size((int64_t)cf_info->data_rate, FORMAT_SIZE_UNIT_BYTES_S, 0)format_size_wmem(((void*)0), (int64_t)cf_info->data_rate, FORMAT_SIZE_UNIT_BYTES_S
, 0)
;
568 printf ("%s\n", size_string);
569 g_free(size_string);
570 }
571 }
572 if (cap_data_rate_bit) {
573 printf("Data bit rate: ");
574 if (machine_readable) {
575 print_value("", 2, " bits/sec", cf_info->data_rate*8);
576 } else {
577 size_string = format_size((int64_t)(cf_info->data_rate*8), FORMAT_SIZE_UNIT_BITS_S, 0)format_size_wmem(((void*)0), (int64_t)(cf_info->data_rate*
8), FORMAT_SIZE_UNIT_BITS_S, 0)
;
578 printf ("%s\n", size_string);
579 g_free(size_string);
580 }
581 }
582 }
583 if (cap_packet_size) printf("Average packet size: %.2f bytes\n", cf_info->packet_size);
584 if (cf_info->times_known) {
585 if (cap_packet_rate) {
586 printf("Average packet rate: ");
587 if (machine_readable) {
588 print_value("", 2, " packets/sec", cf_info->packet_rate);
589 } else {
590 size_string = format_size((int64_t)cf_info->packet_rate, FORMAT_SIZE_UNIT_PACKETS_S, 0)format_size_wmem(((void*)0), (int64_t)cf_info->packet_rate
, FORMAT_SIZE_UNIT_PACKETS_S, 0)
;
591 printf ("%s\n", size_string);
592 g_free(size_string);
593 }
594 }
595 }
596 if (cap_file_hashes) {
597 printf ("SHA256: %s\n", file_sha256);
598 printf ("SHA1: %s\n", file_sha1);
599 }
600 if (cap_order) printf ("Strict time order: %s\n", order_string(cf_info->order));
601
602 bool_Bool has_multiple_sections = (wtap_file_get_num_shbs(cf_info->wth) > 1);
603
604 for (unsigned int section_number = 0;
605 section_number < wtap_file_get_num_shbs(cf_info->wth);
606 section_number++) {
607 wtap_block_t shb;
608
609 // If we have more than one section, add headers for each section.
610 if (has_multiple_sections)
611 printf("Section %u:\n\n", section_number);
612
613 shb = wtap_file_get_shb(cf_info->wth, section_number);
614 if (shb != NULL((void*)0)) {
615 if (cap_file_more_info) {
616 char *str;
617
618 if (wtap_block_get_string_option_value(shb, OPT_SHB_HARDWARE2, &str) == WTAP_OPTTYPE_SUCCESS)
619 show_option_string("Capture hardware: ", str);
620 if (wtap_block_get_string_option_value(shb, OPT_SHB_OS3, &str) == WTAP_OPTTYPE_SUCCESS)
621 show_option_string("Capture oper-sys: ", str);
622 if (wtap_block_get_string_option_value(shb, OPT_SHB_USERAPPL4, &str) == WTAP_OPTTYPE_SUCCESS)
623 show_option_string("Capture application: ", str);
624 }
625 if (cap_comment) {
626 unsigned int i;
627 char *str;
628
629 for (i = 0; wtap_block_get_nth_string_option_value(shb, OPT_COMMENT1, i, &str) == WTAP_OPTTYPE_SUCCESS; i++) {
630 show_option_string("Capture comment: ", str);
631 }
632 }
633 }
634 }
635
636 if (pkt_comments && cf_info->pkt_cmts != NULL((void*)0)) {
637 for (p = cf_info->pkt_cmts; p != NULL((void*)0); prev = p, p = p->next, g_free(prev)) {
638 if (machine_readable){
639 printf("Packet %u Comment: %s\n", p->recno, g_strescape(p->cmt, NULL((void*)0)));
640 } else {
641 printf("Packet %u Comment: %s\n", p->recno, p->cmt);
642 }
643 g_free(p->cmt);
644 }
645 }
646
647 if (cap_file_idb && cf_info->num_interfaces != 0) {
648 unsigned int i;
649 ws_assert(cf_info->num_interfaces == cf_info->idb_info_strings->len)do { if ((1) && !(cf_info->num_interfaces == cf_info
->idb_info_strings->len)) ws_log_fatal_full("Main", LOG_LEVEL_ERROR
, "capinfos.c", 649, __func__, "assertion failed: %s", "cf_info->num_interfaces == cf_info->idb_info_strings->len"
); } while (0)
;
650 printf ("Number of interfaces in file: %u\n", cf_info->num_interfaces);
651 for (i = 0; i < cf_info->idb_info_strings->len; i++) {
652 char *s = g_array_index(cf_info->idb_info_strings, char*, i)(((char**) (void *) (cf_info->idb_info_strings)->data) [
(i)])
;
653 uint32_t packet_count = 0;
654 if (i < cf_info->interface_packet_counts->len)
655 packet_count = g_array_index(cf_info->interface_packet_counts, uint32_t, i)(((uint32_t*) (void *) (cf_info->interface_packet_counts)->
data) [(i)])
;
656 printf ("Interface #%u info:\n", i);
657 printf ("%s", s);
658 printf (" Number of packets = %u\n", packet_count);
659 }
660 }
661
662 if (cap_file_nrb) {
663 if (num_ipv4_addresses != 0)
664 printf ("Number of resolved IPv4 addresses in file: %u\n", num_ipv4_addresses);
665 if (num_ipv6_addresses != 0)
666 printf ("Number of resolved IPv6 addresses in file: %u\n", num_ipv6_addresses);
667 }
668 if (cap_file_dsb) {
669 if (num_decryption_secrets != 0)
670 printf ("Number of decryption secrets in file: %u\n", num_decryption_secrets);
671 }
672}
673
674static void
675putsep(void)
676{
677 if (field_separator) putchar(field_separator);
678}
679
680static void
681putquote(void)
682{
683 if (quote_char) putchar(quote_char);
684}
685
686static void G_GNUC_PRINTF(1, 2)__attribute__((__format__ (__printf__, 1, 2)))
687print_stats_table_header_label(const char *fmt, ...)
688{
689 va_list ap;
690
691 putsep();
692 putquote();
693 va_start(ap, fmt)__builtin_va_start(ap, fmt);
694 vprintf(fmt, ap);
695 va_end(ap)__builtin_va_end(ap);
696 putquote();
697}
698
699static void
700print_stats_table_header(capture_info *cf_info)
701{
702 pkt_cmt *p;
703
704 putquote();
705 printf("File name");
706 putquote();
707
708 if (cap_file_type) print_stats_table_header_label("File type");
709 if (cap_file_encap) print_stats_table_header_label("File encapsulation");
710 if (cap_file_more_info) print_stats_table_header_label("File time precision");
711 if (cap_snaplen) {
712 print_stats_table_header_label("Packet size limit");
713 print_stats_table_header_label("Packet size limit min (inferred)");
714 print_stats_table_header_label("Packet size limit max (inferred)");
715 }
716 if (cap_packet_count) print_stats_table_header_label("Number of packets");
717 if (cap_file_size) print_stats_table_header_label("File size (bytes)");
718 if (cap_data_size) print_stats_table_header_label("Data size (bytes)");
719 if (cap_duration) print_stats_table_header_label("Capture duration (seconds)");
720 if (cap_earliest_packet_time) print_stats_table_header_label("Start time");
721 if (cap_latest_packet_time) print_stats_table_header_label("End time");
722 if (cap_data_rate_byte) print_stats_table_header_label("Data byte rate (bytes/sec)");
723 if (cap_data_rate_bit) print_stats_table_header_label("Data bit rate (bits/sec)");
724 if (cap_packet_size) print_stats_table_header_label("Average packet size (bytes)");
725 if (cap_packet_rate) print_stats_table_header_label("Average packet rate (packets/sec)");
726 if (cap_file_hashes) {
727 print_stats_table_header_label("SHA256");
728 print_stats_table_header_label("SHA1");
729 }
730 if (cap_order) print_stats_table_header_label("Strict time order");
731 if (cap_file_more_info) {
732 print_stats_table_header_label("Capture hardware");
733 print_stats_table_header_label("Capture oper-sys");
734 print_stats_table_header_label("Capture application");
735 }
736 if (cap_comment) print_stats_table_header_label("Capture comment");
737
738 if (pkt_comments && cf_info->pkt_cmts != NULL((void*)0)) {
739 for (p = cf_info->pkt_cmts; p != NULL((void*)0); p = p->next) {
740 print_stats_table_header_label("Packet %u Comment", p->recno);
741 }
742 }
743
744 printf("\n");
745}
746
747static void
748print_stats_table(const char *filename, capture_info *cf_info)
749{
750 const char *file_type_string, *file_encap_string;
751 pkt_cmt *p, *prev;
752
753 /* Build printable strings for various stats */
754 file_type_string = wtap_file_type_subtype_name(cf_info->file_type);
755 file_encap_string = wtap_encap_name(cf_info->file_encap);
756
757 if (filename) {
758 putquote();
759 printf("%s", filename);
760 putquote();
761 }
762
763 if (cap_file_type) {
764 putsep();
765 putquote();
766 printf("%s", file_type_string);
767 putquote();
768 }
769
770 /* ToDo: If WTAP_ENCAP_PER_PACKET, show the list of encapsulations encountered;
771 * Output a line for each different encap with all fields repeated except
772 * the encapsulation field which has "Per Packet: ..." for each
773 * encapsulation type seen ?
774 */
775 if (cap_file_encap) {
776 putsep();
777 putquote();
778 printf("%s", file_encap_string);
779 putquote();
780 }
781
782 if (cap_file_more_info) {
783 putsep();
784 putquote();
785 printf("%s", wtap_tsprec_string(cf_info->file_tsprec));
786 putquote();
787 }
788
789 if (cap_snaplen) {
790 putsep();
791 putquote();
792 if (cf_info->snap_set)
793 printf("%u", cf_info->snaplen);
794 else
795 printf("(not set)");
796 putquote();
797 if (cf_info->snaplen_max_inferred > 0) {
798 putsep();
799 putquote();
800 printf("%u", cf_info->snaplen_min_inferred);
801 putquote();
802 putsep();
803 putquote();
804 printf("%u", cf_info->snaplen_max_inferred);
805 putquote();
806 }
807 else {
808 putsep();
809 putquote();
810 printf("n/a");
811 putquote();
812 putsep();
813 putquote();
814 printf("n/a");
815 putquote();
816 }
817 }
818
819 if (cap_packet_count) {
820 putsep();
821 putquote();
822 printf("%u", cf_info->packet_count);
823 putquote();
824 }
825
826 if (cap_file_size) {
827 putsep();
828 putquote();
829 printf("%" PRId64"l" "d", cf_info->filesize);
830 putquote();
831 }
832
833 if (cap_data_size) {
834 putsep();
835 putquote();
836 printf("%" PRIu64"l" "u", cf_info->packet_bytes);
837 putquote();
838 }
839
840 if (cap_duration) {
841 putsep();
842 putquote();
843 printf("%s", relative_time_string(&cf_info->duration, cf_info->duration_tsprec, cf_info, false0));
844 putquote();
845 }
846
847 if (cap_earliest_packet_time) {
848 putsep();
849 putquote();
850 printf("%s", absolute_time_string(&cf_info->earliest_packet_time, cf_info->earliest_packet_time_tsprec, cf_info));
851 putquote();
852 }
853
854 if (cap_latest_packet_time) {
855 putsep();
856 putquote();
857 printf("%s", absolute_time_string(&cf_info->latest_packet_time, cf_info->latest_packet_time_tsprec, cf_info));
858 putquote();
859 }
860
861 if (cap_data_rate_byte) {
862 putsep();
863 putquote();
864 if (cf_info->times_known)
865 printf("%.2f", cf_info->data_rate);
866 else
867 printf("n/a");
868 putquote();
869 }
870
871 if (cap_data_rate_bit) {
872 putsep();
873 putquote();
874 if (cf_info->times_known)
875 printf("%.2f", cf_info->data_rate*8);
876 else
877 printf("n/a");
878 putquote();
879 }
880
881 if (cap_packet_size) {
882 putsep();
883 putquote();
884 printf("%.2f", cf_info->packet_size);
885 putquote();
886 }
887
888 if (cap_packet_rate) {
889 putsep();
890 putquote();
891 if (cf_info->times_known)
892 printf("%.2f", cf_info->packet_rate);
893 else
894 printf("n/a");
895 putquote();
896 }
897
898 if (cap_file_hashes) {
899 putsep();
900 putquote();
901 printf("%s", file_sha256);
902 putquote();
903
904 putsep();
905 putquote();
906 printf("%s", file_sha1);
907 putquote();
908 }
909
910 if (cap_order) {
911 putsep();
912 putquote();
913 printf("%s", order_string(cf_info->order));
914 putquote();
915 }
916
917 for (unsigned section_number = 0;
918 section_number < wtap_file_get_num_shbs(cf_info->wth);
919 section_number++) {
920 wtap_block_t shb;
921
922 shb = wtap_file_get_shb(cf_info->wth, section_number);
923 if (cap_file_more_info) {
924 char *str;
925
926 putsep();
927 putquote();
928 if (wtap_block_get_string_option_value(shb, OPT_SHB_HARDWARE2, &str) == WTAP_OPTTYPE_SUCCESS) {
929 printf("%s", str);
930 }
931 putquote();
932
933 putsep();
934 putquote();
935 if (wtap_block_get_string_option_value(shb, OPT_SHB_OS3, &str) == WTAP_OPTTYPE_SUCCESS) {
936 printf("%s", str);
937 }
938 putquote();
939
940 putsep();
941 putquote();
942 if (wtap_block_get_string_option_value(shb, OPT_SHB_USERAPPL4, &str) == WTAP_OPTTYPE_SUCCESS) {
943 printf("%s", str);
944 }
945 putquote();
946 }
947
948 /*
949 * One might argue that the following is silly to put into a table format,
950 * but oh well note that there may be *more than one* of each of these types
951 * of options. To mitigate some of the potential silliness the if(cap_comment)
952 * block is moved AFTER the if(cap_file_more_info) block. This will make any
953 * comments the last item(s) in each row. We now have a new -K option to
954 * disable cap_comment to more easily manage the potential silliness.
955 * Potential silliness includes multiple comments (therefore resulting in
956 * more than one additional column and/or comments with embedded newlines
957 * and/or possible delimiters).
958 *
959 * To mitigate embedded newlines and other special characters, use -M
960 */
961 if (cap_comment) {
962 unsigned int i;
963 char *opt_comment;
964 bool_Bool have_cap = false0;
965
966 for (i = 0; wtap_block_get_nth_string_option_value(shb, OPT_COMMENT1, i, &opt_comment) == WTAP_OPTTYPE_SUCCESS; i++) {
967 have_cap = true1;
968 putsep();
969 putquote();
970 if (machine_readable){
971 printf("%s", g_strescape(opt_comment, NULL((void*)0)));
972 } else {
973 printf("%s", opt_comment);
974 }
975 putquote();
976 }
977 if(!have_cap) {
978 /* Maintain column alignment when we have no OPT_COMMENT */
979 putsep();
980 putquote();
981 putquote();
982 }
983 }
984
985 }
986
987 if (pkt_comments && cf_info->pkt_cmts != NULL((void*)0)) {
988 for(p = cf_info->pkt_cmts; p != NULL((void*)0); prev = p, p = p->next, g_free(prev)) {
989 putsep();
990 putquote();
991 if (machine_readable) {
992 printf("%s", g_strescape(p->cmt, NULL((void*)0)));
993 } else {
994 printf("%s", p->cmt);
995 }
996 g_free(p->cmt);
997 putquote();
998 }
999 }
1000
1001 printf("\n");
1002}
1003
1004static void
1005cleanup_capture_info(capture_info *cf_info)
1006{
1007 unsigned int i;
1008 ws_assert(cf_info != NULL)do { if ((1) && !(cf_info != ((void*)0))) ws_log_fatal_full
("Main", LOG_LEVEL_ERROR, "capinfos.c", 1008, __func__, "assertion failed: %s"
, "cf_info != ((void*)0)"); } while (0)
;
1009
1010 g_free(cf_info->encap_counts);
1011 cf_info->encap_counts = NULL((void*)0);
1012
1013 g_array_free(cf_info->interface_packet_counts, true1);
1014 cf_info->interface_packet_counts = NULL((void*)0);
1015
1016 if (cf_info->idb_info_strings) {
1017 for (i = 0; i < cf_info->idb_info_strings->len; i++) {
1018 char *s = g_array_index(cf_info->idb_info_strings, char*, i)(((char**) (void *) (cf_info->idb_info_strings)->data) [
(i)])
;
1019 g_free(s);
1020 }
1021 g_array_free(cf_info->idb_info_strings, true1);
1022 }
1023 cf_info->idb_info_strings = NULL((void*)0);
1024}
1025
1026static void
1027count_ipv4_address(const unsigned int addr _U___attribute__((unused)), const char *name _U___attribute__((unused)), const bool_Bool static_entry _U___attribute__((unused)))
1028{
1029 num_ipv4_addresses++;
1030}
1031
1032static void
1033count_ipv6_address(const ws_in6_addr *addrp _U___attribute__((unused)), const char *name _U___attribute__((unused)), const bool_Bool static_entry _U___attribute__((unused)))
1034{
1035 num_ipv6_addresses++;
1036}
1037
1038static void
1039count_decryption_secret(uint32_t secrets_type _U___attribute__((unused)), const void *secrets _U___attribute__((unused)), unsigned int size _U___attribute__((unused)))
1040{
1041 /* XXX - count them based on the secrets type (which is an opaque code,
1042 not a small integer)? */
1043 num_decryption_secrets++;
1044}
1045
1046static void
1047hash_to_str(const unsigned char *hash, size_t length, char *str)
1048{
1049 int i;
1050
1051 for (i = 0; i < (int) length; i++) {
1052 snprintf(str+(i*2), 3, "%02x", hash[i]);
1053 }
1054}
1055
1056static void
1057calculate_hashes(const char *filename)
1058{
1059 FILE *fh;
1060 size_t hash_bytes;
1061
1062 (void) g_strlcpy(file_sha256, "<unknown>", HASH_STR_SIZE(65));
1063 (void) g_strlcpy(file_sha1, "<unknown>", HASH_STR_SIZE(65));
1064
1065 if (cap_file_hashes) {
18
Assuming 'cap_file_hashes' is true
19
Taking true branch
1066 fh = ws_fopenfopen(filename, "rb");
1067 if (fh
19.1
'fh' is non-null
&& hd) {
20
Assuming 'hd' is non-null
21
Taking true branch
1068 while((hash_bytes = fread(hash_buf, 1, HASH_BUF_SIZE(1024 * 1024), fh)) > 0) {
22
Assuming stream reaches end-of-file here
23
Assuming the condition is true
24
Loop condition is true. Entering loop body
25
Read function called when stream is in EOF state. Function has no effect
1069 gcry_md_write(hd, hash_buf, hash_bytes);
1070 }
1071 gcry_md_final(hd)gcry_md_ctl ((hd), GCRYCTL_FINALIZE, ((void*)0), 0);
1072 hash_to_str(gcry_md_read(hd, GCRY_MD_SHA256), HASH_SIZE_SHA25632, file_sha256);
1073 hash_to_str(gcry_md_read(hd, GCRY_MD_SHA1), HASH_SIZE_SHA120, file_sha1);
1074 }
1075 if (fh) fclose(fh);
1076 if (hd) gcry_md_reset(hd);
1077 }
1078}
1079
1080static int
1081process_cap_file(const char *filename, bool_Bool need_separator)
1082{
1083 int status = 0;
1084 int err;
1085 char *err_info;
1086 int64_t size;
1087 int64_t data_offset;
1088
1089 uint32_t packet = 0;
1090 int64_t bytes = 0;
1091 uint32_t snaplen_min_inferred = 0xffffffff;
1092 uint32_t snaplen_max_inferred = 0;
1093 wtap_rec rec;
1094 capture_info cf_info;
1095 bool_Bool have_times = true1;
1096 nstime_t earliest_packet_time;
1097 int earliest_packet_time_tsprec;
1098 nstime_t latest_packet_time;
1099 int latest_packet_time_tsprec;
1100 nstime_t cur_time;
1101 nstime_t prev_time;
1102 bool_Bool know_order = false0;
1103 order_t order = IN_ORDER;
1104 unsigned int i;
1105 wtapng_iface_descriptions_t *idb_info;
1106
1107 pkt_cmt *pc = NULL((void*)0), *prev = NULL((void*)0);
1108
1109 cf_info.wth = wtap_open_offline(filename, WTAP_TYPE_AUTO0, &err, &err_info, false0, application_configuration_environment_prefix());
1110 if (!cf_info.wth) {
15
Assuming field 'wth' is non-null
16
Taking false branch
1111 report_cfile_open_failure(filename, err, err_info);
1112 return 2;
1113 }
1114
1115 /*
1116 * Calculate the checksums. Do this after wtap_open_offline, so we don't
1117 * bother calculating them for files that are not known capture types
1118 * where we wouldn't print them anyway.
1119 */
1120 calculate_hashes(filename);
17
Calling 'calculate_hashes'
1121
1122 if (need_separator && long_report) {
1123 printf("\n");
1124 }
1125
1126 nstime_set_zero(&earliest_packet_time);
1127 earliest_packet_time_tsprec = WTAP_TSPREC_UNKNOWN-2;
1128 nstime_set_zero(&latest_packet_time);
1129 latest_packet_time_tsprec = WTAP_TSPREC_UNKNOWN-2;
1130 nstime_set_zero(&cur_time);
1131 nstime_set_zero(&prev_time);
1132
1133 cf_info.encap_counts = g_new0(int,WTAP_NUM_ENCAP_TYPES)((int *) g_malloc0_n ((wtap_get_num_encap_types()), sizeof (int
)))
;
1134
1135 idb_info = wtap_file_get_idb_info(cf_info.wth);
1136
1137 ws_assert(idb_info->interface_data != NULL)do { if ((1) && !(idb_info->interface_data != ((void
*)0))) ws_log_fatal_full("Main", LOG_LEVEL_ERROR, "capinfos.c"
, 1137, __func__, "assertion failed: %s", "idb_info->interface_data != ((void*)0)"
); } while (0)
;
1138
1139 cf_info.pkt_cmts = NULL((void*)0);
1140 cf_info.num_interfaces = idb_info->interface_data->len;
1141 cf_info.interface_packet_counts = g_array_sized_new(false0, true1, sizeof(uint32_t), cf_info.num_interfaces);
1142 g_array_set_size(cf_info.interface_packet_counts, cf_info.num_interfaces);
1143 cf_info.pkt_interface_id_unknown = 0;
1144
1145 g_free(idb_info);
1146 idb_info = NULL((void*)0);
1147
1148 /* Zero out the counters for the callbacks. */
1149 num_ipv4_addresses = 0;
1150 num_ipv6_addresses = 0;
1151 num_decryption_secrets = 0;
1152
1153 /* Register callbacks for new name<->address maps from the file and
1154 decryption secrets from the file. */
1155 wtap_set_cb_new_ipv4(cf_info.wth, count_ipv4_address);
1156 wtap_set_cb_new_ipv6(cf_info.wth, count_ipv6_address);
1157 wtap_set_cb_new_secrets(cf_info.wth, count_decryption_secret);
1158
1159 /* Tally up data that we need to parse through the file to find */
1160 wtap_rec_init(&rec, DEFAULT_INIT_BUFFER_SIZE_2048(2 * 1024));
1161 while (wtap_read(cf_info.wth, &rec, &err, &err_info, &data_offset)) {
1162 if (rec.presence_flags & WTAP_HAS_TS0x00000001) {
1163 prev_time = cur_time;
1164 cur_time = rec.ts;
1165 if (packet == 0) {
1166 earliest_packet_time = rec.ts;
1167 earliest_packet_time_tsprec = rec.tsprec;
1168 latest_packet_time = rec.ts;
1169 latest_packet_time_tsprec = rec.tsprec;
1170 prev_time = rec.ts;
1171 }
1172 if (nstime_cmp(&cur_time, &prev_time) < 0) {
1173 order = NOT_IN_ORDER;
1174 }
1175 if (nstime_cmp(&cur_time, &earliest_packet_time) < 0) {
1176 earliest_packet_time = cur_time;
1177 earliest_packet_time_tsprec = rec.tsprec;
1178 }
1179 if (nstime_cmp(&cur_time, &latest_packet_time) > 0) {
1180 latest_packet_time = cur_time;
1181 latest_packet_time_tsprec = rec.tsprec;
1182 }
1183 } else {
1184 have_times = false0; /* at least one packet has no time stamp */
1185 if (order != NOT_IN_ORDER)
1186 order = ORDER_UNKNOWN;
1187 }
1188
1189 if (rec.rec_type == REC_TYPE_PACKET0) {
1190 bytes += rec.rec_header.packet_header.len;
1191 packet++;
1192 /* packet comments */
1193 if (pkt_comments && wtap_block_count_option(rec.block, OPT_COMMENT1) > 0) {
1194 char *cmt_buff;
1195 for (i = 0; wtap_block_get_nth_string_option_value(rec.block, OPT_COMMENT1, i, &cmt_buff) == WTAP_OPTTYPE_SUCCESS; i++) {
1196 pc = g_new0(pkt_cmt, 1)((pkt_cmt *) g_malloc0_n ((1), sizeof (pkt_cmt)));
1197
1198 pc->recno = packet;
1199 pc->cmt = g_strdup(cmt_buff)g_strdup_inline (cmt_buff);
1200 pc->next = NULL((void*)0);
1201
1202 if (prev == NULL((void*)0))
1203 cf_info.pkt_cmts = pc;
1204 else
1205 prev->next = pc;
1206
1207 prev = pc;
1208 }
1209 }
1210
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;
1220 }
1221
1222 if ((rec.rec_header.packet_header.pkt_encap > 0) &&
1223 (rec.rec_header.packet_header.pkt_encap < WTAP_NUM_ENCAP_TYPESwtap_get_num_encap_types())) {
1224 cf_info.encap_counts[rec.rec_header.packet_header.pkt_encap] += 1;
1225 } else {
1226 fprintf(stderrstderr, "capinfos: Unknown packet encapsulation %d in frame %u of file \"%s\"\n",
1227 rec.rec_header.packet_header.pkt_encap, packet, filename);
1228 }
1229
1230 /* Packet interface_id info */
1231 if (rec.presence_flags & WTAP_HAS_INTERFACE_ID0x00000004) {
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) {
1234 /*
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
1238 * interfaces.
1239 */
1240 idb_info = wtap_file_get_idb_info(cf_info.wth);
1241
1242 cf_info.num_interfaces = idb_info->interface_data->len;
1243 g_array_set_size(cf_info.interface_packet_counts, cf_info.num_interfaces);
1244
1245 g_free(idb_info);
1246 idb_info = NULL((void*)0);
1247 }
1248 if (rec.rec_header.packet_header.interface_id < cf_info.num_interfaces) {
1249 g_array_index(cf_info.interface_packet_counts, uint32_t,(((uint32_t*) (void *) (cf_info.interface_packet_counts)->
data) [(rec.rec_header.packet_header.interface_id)])
1250 rec.rec_header.packet_header.interface_id)(((uint32_t*) (void *) (cf_info.interface_packet_counts)->
data) [(rec.rec_header.packet_header.interface_id)])
+= 1;
1251 }
1252 else {
1253 cf_info.pkt_interface_id_unknown += 1;
1254 }
1255 }
1256 else {
1257 /* it's for interface_id 0 */
1258 if (cf_info.num_interfaces != 0) {
1259 g_array_index(cf_info.interface_packet_counts, uint32_t, 0)(((uint32_t*) (void *) (cf_info.interface_packet_counts)->
data) [(0)])
+= 1;
1260 }
1261 else {
1262 cf_info.pkt_interface_id_unknown += 1;
1263 }
1264 }
1265 }
1266
1267 wtap_rec_reset(&rec);
1268 } /* while */
1269 wtap_rec_cleanup(&rec);
1270
1271 /*
1272 * Get IDB info strings.
1273 * We do this at the end, so we can get information for all IDBs in
1274 * the file, even those that come after packet records, and so that
1275 * we get, for example, a count of the number of statistics entries
1276 * for each interface as of the *end* of the file.
1277 */
1278 idb_info = wtap_file_get_idb_info(cf_info.wth);
1279
1280 cf_info.idb_info_strings = g_array_sized_new(false0, false0, sizeof(char*), cf_info.num_interfaces);
1281 cf_info.num_interfaces = idb_info->interface_data->len;
1282 for (i = 0; i < cf_info.num_interfaces; i++) {
1283 const wtap_block_t if_descr = g_array_index(idb_info->interface_data, wtap_block_t, i)(((wtap_block_t*) (void *) (idb_info->interface_data)->
data) [(i)])
;
1284 char *s = wtap_get_debug_if_descr(if_descr, 21, "\n");
1285 g_array_append_val(cf_info.idb_info_strings, s)g_array_append_vals (cf_info.idb_info_strings, &(s), 1);
1286 }
1287
1288 g_free(idb_info);
1289 idb_info = NULL((void*)0);
1290
1291 if (err != 0) {
1292 fprintf(stderrstderr,
1293 "capinfos: An error occurred after reading %u packets from \"%s\".\n",
1294 packet, filename);
1295 report_cfile_read_failure(filename, err, err_info);
1296 if (err == WTAP_ERR_SHORT_READ-12) {
1297 /* Don't give up completely with this one. */
1298 status = 1;
1299 fprintf(stderrstderr,
1300 " (will continue anyway, checksums might be incorrect)\n");
1301 } else {
1302 cleanup_capture_info(&cf_info);
1303 wtap_close(cf_info.wth);
1304 return 2;
1305 }
1306 }
1307
1308 /* File size */
1309 size = wtap_file_size(cf_info.wth, &err);
1310 if (size == -1) {
1311 fprintf(stderrstderr,
1312 "capinfos: Can't get size of \"%s\": %s.\n",
1313 filename, g_strerror(err));
1314 cleanup_capture_info(&cf_info);
1315 wtap_close(cf_info.wth);
1316 return 2;
1317 }
1318
1319 cf_info.filesize = size;
1320
1321 /* File Type */
1322 cf_info.file_type = wtap_file_type_subtype(cf_info.wth);
1323 cf_info.compression_type = wtap_get_compression_type(cf_info.wth);
1324
1325 /* File Encapsulation */
1326 cf_info.file_encap = wtap_file_encap(cf_info.wth);
1327
1328 cf_info.file_tsprec = wtap_file_tsprec(cf_info.wth);
1329
1330 /* Packet size limit (snaplen) */
1331 cf_info.snaplen = wtap_snapshot_length(cf_info.wth);
1332 if (cf_info.snaplen > 0)
1333 cf_info.snap_set = true1;
1334 else
1335 cf_info.snap_set = false0;
1336
1337 cf_info.snaplen_min_inferred = snaplen_min_inferred;
1338 cf_info.snaplen_max_inferred = snaplen_max_inferred;
1339
1340 /* # of packets */
1341 cf_info.packet_count = packet;
1342
1343 /* File Times */
1344 cf_info.times_known = have_times;
1345 cf_info.earliest_packet_time = earliest_packet_time;
1346 cf_info.earliest_packet_time_tsprec = earliest_packet_time_tsprec;
1347 cf_info.latest_packet_time = latest_packet_time;
1348 cf_info.latest_packet_time_tsprec = latest_packet_time_tsprec;
1349 nstime_delta(&cf_info.duration, &latest_packet_time, &earliest_packet_time);
1350 /* Duration precision is the higher of the earliest and latest packet timestamp precisions. */
1351 if (cf_info.latest_packet_time_tsprec > cf_info.earliest_packet_time_tsprec)
1352 cf_info.duration_tsprec = cf_info.latest_packet_time_tsprec;
1353 else
1354 cf_info.duration_tsprec = cf_info.earliest_packet_time_tsprec;
1355 cf_info.know_order = know_order;
1356 cf_info.order = order;
1357
1358 /* Number of packet bytes */
1359 cf_info.packet_bytes = bytes;
1360
1361 cf_info.data_rate = 0.0;
1362 cf_info.packet_rate = 0.0;
1363 cf_info.packet_size = 0.0;
1364
1365 if (packet > 0) {
1366 double delta_time = nstime_to_sec(&latest_packet_time) - nstime_to_sec(&earliest_packet_time);
1367 if (delta_time > 0.0) {
1368 cf_info.data_rate = (double)bytes / delta_time; /* Data rate per second */
1369 cf_info.packet_rate = (double)packet / delta_time; /* packet rate per second */
1370 }
1371 cf_info.packet_size = (double)bytes / packet; /* Avg packet size */
1372 }
1373
1374 if (!long_report && table_report_header) {
1375 print_stats_table_header(&cf_info);
1376 }
1377
1378 if (long_report) {
1379 print_stats(filename, &cf_info);
1380 } else {
1381 print_stats_table(filename, &cf_info);
1382 }
1383
1384 cleanup_capture_info(&cf_info);
1385 wtap_close(cf_info.wth);
1386
1387 return status;
1388}
1389
1390static void
1391print_usage(FILE *output)
1392{
1393 fprintf(output, "\n");
1394 fprintf(output, "Usage: capinfos [options] <infile> ...\n");
1395 fprintf(output, "\n");
1396 fprintf(output, "General infos:\n");
1397 fprintf(output, " -t display the capture file type\n");
1398 fprintf(output, " -E display the capture file encapsulation\n");
1399 fprintf(output, " -I display the capture file interface information\n");
1400 fprintf(output, " -F display additional capture file information\n");
1401 fprintf(output, " -H display the SHA256 and SHA1 hashes of the file\n");
1402 fprintf(output, " -k display the capture comment\n");
1403 fprintf(output, " -p display individual packet comments\n");
1404 fprintf(output, "\n");
1405 fprintf(output, "Size infos:\n");
1406 fprintf(output, " -c display the number of packets\n");
1407 fprintf(output, " -s display the size of the file (in bytes)\n");
1408 fprintf(output, " -d display the total length of all packets (in bytes)\n");
1409 fprintf(output, " -l display the packet size limit (snapshot length)\n");
1410 fprintf(output, "\n");
1411 fprintf(output, "Time infos:\n");
1412 fprintf(output, " -u display the capture duration (in seconds)\n");
1413 fprintf(output, " -a display the timestamp of the earliest packet\n");
1414 fprintf(output, " -e display the timestamp of the latest packet\n");
1415 fprintf(output, " -o display the capture file chronological status (True/False)\n");
1416 fprintf(output, " -S display earliest and latest packet timestamps as seconds\n");
1417 fprintf(output, "\n");
1418 fprintf(output, "Statistic infos:\n");
1419 fprintf(output, " -y display average data rate (in bytes/sec)\n");
1420 fprintf(output, " -i display average data rate (in bits/sec)\n");
1421 fprintf(output, " -z display average packet size (in bytes)\n");
1422 fprintf(output, " -x display average packet rate (in packets/sec)\n");
1423 fprintf(output, "\n");
1424 fprintf(output, "Metadata infos:\n");
1425 fprintf(output, " -n display number of resolved IPv4 and IPv6 addresses\n");
1426 fprintf(output, " -D display number of decryption secrets\n");
1427 fprintf(output, "\n");
1428 fprintf(output, "Output format:\n");
1429 fprintf(output, " -L generate long report (default)\n");
1430 fprintf(output, " -T generate table report\n");
1431 fprintf(output, " -M display machine-readable values in long reports\n");
1432 fprintf(output, "\n");
1433 fprintf(output, "Table report options:\n");
1434 fprintf(output, " -R generate header record (default)\n");
1435 fprintf(output, " -r do not generate header record\n");
1436 fprintf(output, "\n");
1437 fprintf(output, " -B separate infos with TAB character (default)\n");
1438 fprintf(output, " -m separate infos with comma (,) character\n");
1439 fprintf(output, " -b separate infos with SPACE character\n");
1440 fprintf(output, "\n");
1441 fprintf(output, " -N do not quote infos (default)\n");
1442 fprintf(output, " -q quote infos with single quotes (')\n");
1443 fprintf(output, " -Q quote infos with double quotes (\")\n");
1444 fprintf(output, "\n");
1445 fprintf(output, "Miscellaneous:\n");
1446 fprintf(output, " -h, --help display this help and exit\n");
1447 fprintf(output, " -v, --version display version info and exit\n");
1448 fprintf(output, " -C cancel processing if file open fails (default is to continue)\n");
1449 fprintf(output, " -A generate all infos (default)\n");
1450 fprintf(output, " -K disable displaying the capture comment\n");
1451 fprintf(output, " -P disable displaying individual packet comments\n");
1452 fprintf(output, "\n");
1453 fprintf(output, "Options are processed from left to right order with later options superseding\n");
1454 fprintf(output, "or adding to earlier options.\n");
1455 fprintf(output, "\n");
1456 fprintf(output, "If no options are given the default is to display all infos in long report\n");
1457 fprintf(output, "output format.\n");
1458}
1459
1460int
1461main(int argc, char *argv[])
1462{
1463 char *configuration_init_error;
1464 bool_Bool need_separator = false0;
1465 int opt;
1466 int overall_error_status = EXIT_SUCCESS0;
1467 static const struct ws_option long_options[] = {
1468 {"help", ws_no_argument0, NULL((void*)0), 'h'},
1469 {"version", ws_no_argument0, NULL((void*)0), 'v'},
1470 LONGOPT_WSLOG{"log-level", 1, ((void*)0), 5000 +1}, {"log-domain", 1, ((void
*)0), 5000 +2}, {"log-domains", 1, ((void*)0), 5000 +2}, {"log-file"
, 1, ((void*)0), 5000 +3}, {"log-fatal", 1, ((void*)0), 5000 +
4}, {"log-fatal-domain", 1, ((void*)0), 5000 +5}, {"log-fatal-domains"
, 1, ((void*)0), 5000 +5}, {"log-debug", 1, ((void*)0), 5000 +
6}, {"log-noisy", 1, ((void*)0), 5000 +7},
1471 {0, 0, 0, 0 }
1472 };
1473 const struct file_extension_info* file_extensions;
1474 unsigned num_extensions;
1475
1476#define OPTSTRING"abcdehiklmnopqrstuvxyzABCDEFHIKLMNPQRST" "abcdehiklmnopqrstuvxyzABCDEFHIKLMNPQRST"
1477 static const char optstring[] = OPTSTRING"abcdehiklmnopqrstuvxyzABCDEFHIKLMNPQRST";
1478
1479 int status = 0;
1480
1481 /* Set the program name. */
1482 g_set_prgname("capinfos");
1483
1484 /*
1485 * Set the C-language locale to the native environment and set the
1486 * code page to UTF-8 on Windows.
1487 */
1488#ifdef _WIN32
1489 setlocale(LC_ALL6, ".UTF-8");
1490#else
1491 setlocale(LC_ALL6, "");
1492#endif
1493
1494 cmdarg_err_init(stderr_cmdarg_err, stderr_cmdarg_err_cont);
1495
1496 /* Initialize log handler early so we can have proper logging during startup. */
1497 ws_log_init(vcmdarg_err, "Capinfos Debug Console");
1498
1499 /* Early logging command-line initialization. */
1500 ws_log_parse_args(&argc, argv, optstring, long_options, vcmdarg_err, WS_EXIT_INVALID_OPTION1);
1501
1502 ws_noisy("Finished log init and parsing command line log arguments")do { if (1) { ws_log_full("Main", LOG_LEVEL_NOISY, "capinfos.c"
, 1502, __func__, "Finished log init and parsing command line log arguments"
); } } while (0)
;
1
Taking true branch
2
Loop condition is false. Exiting loop
1503
1504 /* Get the decimal point. */
1505 decimal_point = g_strdup(localeconv()->decimal_point)g_strdup_inline (localeconv()->decimal_point);
1506
1507#ifdef _WIN32
1508 create_app_running_mutex();
1509#endif /* _WIN32 */
1510
1511 /*
1512 * Get credential information for later use.
1513 */
1514 init_process_policies();
1515
1516 /*
1517 * Attempt to get the pathname of the directory containing the
1518 * executable file.
1519 */
1520 configuration_init_error = configuration_init(argv[0], "wireshark");
1521 if (configuration_init_error != NULL((void*)0)) {
3
Assuming 'configuration_init_error' is equal to NULL
4
Taking false branch
1522 fprintf(stderrstderr,
1523 "capinfos: Can't get pathname of directory containing the capinfos program: %s.\n",
1524 configuration_init_error);
1525 g_free(configuration_init_error);
1526 }
1527
1528 /* Initialize the version information. */
1529 ws_init_version_info("Capinfos", NULL((void*)0), get_ws_vcs_version_info, NULL((void*)0), NULL((void*)0));
1530
1531 init_report_failure_message("capinfos");
1532
1533 application_file_extensions(&file_extensions, &num_extensions);
1534 wtap_init(true1, application_configuration_environment_prefix(), file_extensions, num_extensions);
1535
1536 /* Process the options */
1537 while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL((void*)0))) !=-1) {
5
Assuming the condition is false
6
Loop condition is false. Execution continues on line 1729
1538
1539 switch (opt) {
1540
1541 case 't':
1542 if (report_all_infos) disable_all_infos();
1543 cap_file_type = true1;
1544 break;
1545
1546 case 'E':
1547 if (report_all_infos) disable_all_infos();
1548 cap_file_encap = true1;
1549 break;
1550
1551 case 'l':
1552 if (report_all_infos) disable_all_infos();
1553 cap_snaplen = true1;
1554 break;
1555
1556 case 'c':
1557 if (report_all_infos) disable_all_infos();
1558 cap_packet_count = true1;
1559 break;
1560
1561 case 's':
1562 if (report_all_infos) disable_all_infos();
1563 cap_file_size = true1;
1564 break;
1565
1566 case 'd':
1567 if (report_all_infos) disable_all_infos();
1568 cap_data_size = true1;
1569 break;
1570
1571 case 'u':
1572 if (report_all_infos) disable_all_infos();
1573 cap_duration = true1;
1574 break;
1575
1576 case 'a':
1577 if (report_all_infos) disable_all_infos();
1578 cap_earliest_packet_time = true1;
1579 break;
1580
1581 case 'e':
1582 if (report_all_infos) disable_all_infos();
1583 cap_latest_packet_time = true1;
1584 break;
1585
1586 case 'S':
1587 time_as_secs = true1;
1588 break;
1589
1590 case 'y':
1591 if (report_all_infos) disable_all_infos();
1592 cap_data_rate_byte = true1;
1593 break;
1594
1595 case 'i':
1596 if (report_all_infos) disable_all_infos();
1597 cap_data_rate_bit = true1;
1598 break;
1599
1600 case 'z':
1601 if (report_all_infos) disable_all_infos();
1602 cap_packet_size = true1;
1603 break;
1604
1605 case 'x':
1606 if (report_all_infos) disable_all_infos();
1607 cap_packet_rate = true1;
1608 break;
1609
1610 case 'H':
1611 if (report_all_infos) disable_all_infos();
1612 cap_file_hashes = true1;
1613 break;
1614
1615 case 'o':
1616 if (report_all_infos) disable_all_infos();
1617 cap_order = true1;
1618 break;
1619
1620 case 'k':
1621 if (report_all_infos) disable_all_infos();
1622 cap_comment = true1;
1623 break;
1624
1625 case 'p':
1626 if (report_all_infos) disable_all_infos();
1627 pkt_comments = true1;
1628 break;
1629
1630 case 'K':
1631 cap_comment = false0;
1632 break;
1633
1634 case 'P':
1635 pkt_comments = false0;
1636 break;
1637
1638 case 'F':
1639 if (report_all_infos) disable_all_infos();
1640 cap_file_more_info = true1;
1641 break;
1642
1643 case 'I':
1644 if (report_all_infos) disable_all_infos();
1645 cap_file_idb = true1;
1646 break;
1647
1648 case 'n':
1649 if (report_all_infos) disable_all_infos();
1650 cap_file_nrb = true1;
1651 break;
1652
1653 case 'D':
1654 if (report_all_infos) disable_all_infos();
1655 cap_file_dsb = true1;
1656 break;
1657
1658 case 'C':
1659 stop_after_failure = true1;
1660 break;
1661
1662 case 'A':
1663 enable_all_infos();
1664 break;
1665
1666 case 'L':
1667 long_report = true1;
1668 break;
1669
1670 case 'T':
1671 long_report = false0;
1672 break;
1673
1674 case 'M':
1675 machine_readable = true1;
1676 break;
1677
1678 case 'R':
1679 table_report_header = true1;
1680 break;
1681
1682 case 'r':
1683 table_report_header = false0;
1684 break;
1685
1686 case 'N':
1687 quote_char = '\0';
1688 break;
1689
1690 case 'q':
1691 quote_char = '\'';
1692 break;
1693
1694 case 'Q':
1695 quote_char = '"';
1696 break;
1697
1698 case 'B':
1699 field_separator = '\t';
1700 break;
1701
1702 case 'm':
1703 field_separator = ',';
1704 break;
1705
1706 case 'b':
1707 field_separator = ' ';
1708 break;
1709
1710 case 'h':
1711 show_help_header("Print various information (infos) about capture files.");
1712 print_usage(stdoutstdout);
1713 goto exit;
1714 break;
1715
1716 case 'v':
1717 show_version();
1718 goto exit;
1719 break;
1720
1721 case '?': /* Bad flag - print usage message */
1722 print_usage(stderrstderr);
1723 overall_error_status = WS_EXIT_INVALID_OPTION1;
1724 goto exit;
1725 break;
1726 }
1727 }
1728
1729 if ((argc - ws_optind) < 1) {
7
Assuming the condition is false
8
Taking false branch
1730 print_usage(stderrstderr);
1731 overall_error_status = WS_EXIT_INVALID_OPTION1;
1732 goto exit;
1733 }
1734
1735 if (cap_file_hashes
8.1
'cap_file_hashes' is true
) {
9
Taking true branch
1736 gcry_check_version(NULL((void*)0));
1737 gcry_md_open(&hd, GCRY_MD_SHA256, 0);
1738 if (hd)
10
Assuming 'hd' is null
11
Taking false branch
1739 gcry_md_enable(hd, GCRY_MD_SHA1);
1740
1741 hash_buf = (char *)g_malloc(HASH_BUF_SIZE(1024 * 1024));
1742 }
1743
1744 overall_error_status = 0;
1745
1746 for (opt = ws_optind; opt < argc; opt++) {
12
Assuming 'opt' is < 'argc'
13
Loop condition is true. Entering loop body
1747
1748 status = process_cap_file(argv[opt], need_separator);
14
Calling 'process_cap_file'
1749 if (status) {
1750 /* Something failed. It's been reported; remember that processing
1751 one file failed and, if -C was specified, stop. */
1752 overall_error_status = status;
1753 if (stop_after_failure)
1754 goto exit;
1755 }
1756 if (status != 2) {
1757 /* Either it succeeded or it got a "short read" but printed
1758 information anyway. Note that we need a blank line before
1759 the next file's information, to separate it from the
1760 previous file. */
1761 need_separator = true1;
1762 }
1763 }
1764
1765exit:
1766 g_free(hash_buf);
1767 gcry_md_close(hd);
1768 wtap_cleanup();
1769 free_progdirs();
1770 return overall_error_status;
1771}