Bug Summary

File:capinfos.c
Warning:line 1066, column 33
File position of the stream might be 'indeterminate' after a failed operation. Can cause undefined behavior

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