Bug Summary

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