Bug Summary

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