Bug Summary

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