Bug Summary

File:builds/wireshark/wireshark/capinfos.c
Warning:line 744, column 5
Potential leak of memory pointed to by 'buf'

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-18/lib/clang/18 -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-18/lib/clang/18/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 -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 -dwarf-debug-flags /usr/lib/llvm-18/bin/clang -### --analyze -x c -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 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -fvisibility=hidden -fexcess-precision=fast -fstrict-flex-arrays=3 -fstack-clash-protection -fcf-protection=full -D _GLIBCXX_ASSERTIONS -fstack-protector-strong -fno-delete-null-pointer-checks -fno-strict-overflow -fno-strict-aliasing -fexceptions -Wno-format-truncation -Wno-format-nonliteral -fdiagnostics-color=always -Wno-pointer-sign -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -std=gnu11 -fPIE /builds/wireshark/wireshark/capinfos.c -o /builds/wireshark/wireshark/sbout/2025-05-08-100309-3825-1 -Xclang -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2025-05-08-100309-3825-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 <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 int 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 %d Comment: %s\n", p->recno, g_strescape(p->cmt, NULL((void*)0)));
637 } else {
638 printf("Packet %d 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
684print_stats_table_header_label(const char *label)
685{
686 putsep();
687 putquote();
688 printf("%s", label);
689 putquote();
690}
691
692static void
693print_stats_table_header(capture_info *cf_info)
694{
695 pkt_cmt *p;
696 char *buf;
697 size_t buf_len;
698
699 putquote();
700 printf("File name");
701 putquote();
702
703 if (cap_file_type) print_stats_table_header_label("File type");
35
Assuming 'cap_file_type' is false
36
Taking false branch
704 if (cap_file_encap) print_stats_table_header_label("File encapsulation");
37
Assuming 'cap_file_encap' is false
38
Taking false branch
705 if (cap_file_more_info) print_stats_table_header_label("File time precision");
39
Assuming 'cap_file_more_info' is false
40
Taking false branch
706 if (cap_snaplen) {
41
Assuming 'cap_snaplen' is false
42
Taking false branch
707 print_stats_table_header_label("Packet size limit");
708 print_stats_table_header_label("Packet size limit min (inferred)");
709 print_stats_table_header_label("Packet size limit max (inferred)");
710 }
711 if (cap_packet_count) print_stats_table_header_label("Number of packets");
43
Assuming 'cap_packet_count' is false
44
Taking false branch
712 if (cap_file_size) print_stats_table_header_label("File size (bytes)");
45
Assuming 'cap_file_size' is false
46
Taking false branch
713 if (cap_data_size) print_stats_table_header_label("Data size (bytes)");
47
Assuming 'cap_data_size' is false
48
Taking false branch
714 if (cap_duration) print_stats_table_header_label("Capture duration (seconds)");
49
Assuming 'cap_duration' is false
50
Taking false branch
715 if (cap_earliest_packet_time) print_stats_table_header_label("Start time");
51
Assuming 'cap_earliest_packet_time' is false
52
Taking false branch
716 if (cap_latest_packet_time) print_stats_table_header_label("End time");
53
Assuming 'cap_latest_packet_time' is false
54
Taking false branch
717 if (cap_data_rate_byte) print_stats_table_header_label("Data byte rate (bytes/sec)");
55
Assuming 'cap_data_rate_byte' is false
56
Taking false branch
718 if (cap_data_rate_bit) print_stats_table_header_label("Data bit rate (bits/sec)");
57
Assuming 'cap_data_rate_bit' is false
58
Taking false branch
719 if (cap_packet_size) print_stats_table_header_label("Average packet size (bytes)");
59
Assuming 'cap_packet_size' is false
60
Taking false branch
720 if (cap_packet_rate) print_stats_table_header_label("Average packet rate (packets/sec)");
61
Assuming 'cap_packet_rate' is false
62
Taking false branch
721 if (cap_file_hashes) {
63
Assuming 'cap_file_hashes' is false
64
Taking false branch
722 print_stats_table_header_label("SHA256");
723 print_stats_table_header_label("SHA1");
724 }
725 if (cap_order) print_stats_table_header_label("Strict time order");
65
Assuming 'cap_order' is false
66
Taking false branch
726 if (cap_file_more_info
66.1
'cap_file_more_info' is false
) {
67
Taking false branch
727 print_stats_table_header_label("Capture hardware");
728 print_stats_table_header_label("Capture oper-sys");
729 print_stats_table_header_label("Capture application");
730 }
731 if (cap_comment) print_stats_table_header_label("Capture comment");
68
Assuming 'cap_comment' is false
732
733 if (pkt_comments && cf_info->pkt_cmts != NULL((void*)0)) {
69
Assuming 'pkt_comments' is true
70
Assuming field 'pkt_cmts' is not equal to NULL
71
Taking true branch
734 /* Packet 2^64 Comment" + NULL */
735 buf_len = strlen("Packet 18446744073709551616 Comment") + 1;
736 buf = (char *)g_malloc0(buf_len);
72
Memory is allocated
737
738 for (p = cf_info->pkt_cmts; p
72.1
'p' is not equal to NULL
!= NULL((void*)0)
; p = p->next) {
73
Loop condition is true. Entering loop body
74
Assuming 'p' is equal to NULL
75
Loop condition is false. Execution continues on line 744
739 snprintf(buf, buf_len, "Packet %d Comment", p->recno);
740 print_stats_table_header_label(buf);
741 }
742 }
743
744 printf("\n");
76
Potential leak of memory pointed to by 'buf'
745}
746
747static void
748print_stats_table(const char *filename, capture_info *cf_info)
749{
750 const char *file_type_string, *file_encap_string;
751 pkt_cmt *p, *prev;
752
753 /* Build printable strings for various stats */
754 file_type_string = wtap_file_type_subtype_name(cf_info->file_type);
755 file_encap_string = wtap_encap_name(cf_info->file_encap);
756
757 if (filename) {
758 putquote();
759 printf("%s", filename);
760 putquote();
761 }
762
763 if (cap_file_type) {
764 putsep();
765 putquote();
766 printf("%s", file_type_string);
767 putquote();
768 }
769
770 /* ToDo: If WTAP_ENCAP_PER_PACKET, show the list of encapsulations encountered;
771 * Output a line for each different encap with all fields repeated except
772 * the encapsulation field which has "Per Packet: ..." for each
773 * encapsulation type seen ?
774 */
775 if (cap_file_encap) {
776 putsep();
777 putquote();
778 printf("%s", file_encap_string);
779 putquote();
780 }
781
782 if (cap_file_more_info) {
783 putsep();
784 putquote();
785 printf("%s", wtap_tsprec_string(cf_info->file_tsprec));
786 putquote();
787 }
788
789 if (cap_snaplen) {
790 putsep();
791 putquote();
792 if (cf_info->snap_set)
793 printf("%u", cf_info->snaplen);
794 else
795 printf("(not set)");
796 putquote();
797 if (cf_info->snaplen_max_inferred > 0) {
798 putsep();
799 putquote();
800 printf("%u", cf_info->snaplen_min_inferred);
801 putquote();
802 putsep();
803 putquote();
804 printf("%u", cf_info->snaplen_max_inferred);
805 putquote();
806 }
807 else {
808 putsep();
809 putquote();
810 printf("n/a");
811 putquote();
812 putsep();
813 putquote();
814 printf("n/a");
815 putquote();
816 }
817 }
818
819 if (cap_packet_count) {
820 putsep();
821 putquote();
822 printf("%u", cf_info->packet_count);
823 putquote();
824 }
825
826 if (cap_file_size) {
827 putsep();
828 putquote();
829 printf("%" PRId64"l" "d", cf_info->filesize);
830 putquote();
831 }
832
833 if (cap_data_size) {
834 putsep();
835 putquote();
836 printf("%" PRIu64"l" "u", cf_info->packet_bytes);
837 putquote();
838 }
839
840 if (cap_duration) {
841 putsep();
842 putquote();
843 printf("%s", relative_time_string(&cf_info->duration, cf_info->duration_tsprec, cf_info, false0));
844 putquote();
845 }
846
847 if (cap_earliest_packet_time) {
848 putsep();
849 putquote();
850 printf("%s", absolute_time_string(&cf_info->earliest_packet_time, cf_info->earliest_packet_time_tsprec, cf_info));
851 putquote();
852 }
853
854 if (cap_latest_packet_time) {
855 putsep();
856 putquote();
857 printf("%s", absolute_time_string(&cf_info->latest_packet_time, cf_info->latest_packet_time_tsprec, cf_info));
858 putquote();
859 }
860
861 if (cap_data_rate_byte) {
862 putsep();
863 putquote();
864 if (cf_info->times_known)
865 printf("%.2f", cf_info->data_rate);
866 else
867 printf("n/a");
868 putquote();
869 }
870
871 if (cap_data_rate_bit) {
872 putsep();
873 putquote();
874 if (cf_info->times_known)
875 printf("%.2f", cf_info->data_rate*8);
876 else
877 printf("n/a");
878 putquote();
879 }
880
881 if (cap_packet_size) {
882 putsep();
883 putquote();
884 printf("%.2f", cf_info->packet_size);
885 putquote();
886 }
887
888 if (cap_packet_rate) {
889 putsep();
890 putquote();
891 if (cf_info->times_known)
892 printf("%.2f", cf_info->packet_rate);
893 else
894 printf("n/a");
895 putquote();
896 }
897
898 if (cap_file_hashes) {
899 putsep();
900 putquote();
901 printf("%s", file_sha256);
902 putquote();
903
904 putsep();
905 putquote();
906 printf("%s", file_sha1);
907 putquote();
908 }
909
910 if (cap_order) {
911 putsep();
912 putquote();
913 printf("%s", order_string(cf_info->order));
914 putquote();
915 }
916
917 for (unsigned section_number = 0;
918 section_number < wtap_file_get_num_shbs(cf_info->wth);
919 section_number++) {
920 wtap_block_t shb;
921
922 shb = wtap_file_get_shb(cf_info->wth, section_number);
923 if (cap_file_more_info) {
924 char *str;
925
926 putsep();
927 putquote();
928 if (wtap_block_get_string_option_value(shb, OPT_SHB_HARDWARE2, &str) == WTAP_OPTTYPE_SUCCESS) {
929 printf("%s", str);
930 }
931 putquote();
932
933 putsep();
934 putquote();
935 if (wtap_block_get_string_option_value(shb, OPT_SHB_OS3, &str) == WTAP_OPTTYPE_SUCCESS) {
936 printf("%s", str);
937 }
938 putquote();
939
940 putsep();
941 putquote();
942 if (wtap_block_get_string_option_value(shb, OPT_SHB_USERAPPL4, &str) == WTAP_OPTTYPE_SUCCESS) {
943 printf("%s", str);
944 }
945 putquote();
946 }
947
948 /*
949 * One might argue that the following is silly to put into a table format,
950 * but oh well note that there may be *more than one* of each of these types
951 * of options. To mitigate some of the potential silliness the if(cap_comment)
952 * block is moved AFTER the if(cap_file_more_info) block. This will make any
953 * comments the last item(s) in each row. We now have a new -K option to
954 * disable cap_comment to more easily manage the potential silliness.
955 * Potential silliness includes multiple comments (therefore resulting in
956 * more than one additional column and/or comments with embedded newlines
957 * and/or possible delimiters).
958 *
959 * To mitigate embedded newlines and other special characters, use -M
960 */
961 if (cap_comment) {
962 unsigned int i;
963 char *opt_comment;
964 bool_Bool have_cap = false0;
965
966 for (i = 0; wtap_block_get_nth_string_option_value(shb, OPT_COMMENT1, i, &opt_comment) == WTAP_OPTTYPE_SUCCESS; i++) {
967 have_cap = true1;
968 putsep();
969 putquote();
970 if (machine_readable){
971 printf("%s", g_strescape(opt_comment, NULL((void*)0)));
972 } else {
973 printf("%s", opt_comment);
974 }
975 putquote();
976 }
977 if(!have_cap) {
978 /* Maintain column alignment when we have no OPT_COMMENT */
979 putsep();
980 putquote();
981 putquote();
982 }
983 }
984
985 }
986
987 if (pkt_comments && cf_info->pkt_cmts != NULL((void*)0)) {
988 for(p = cf_info->pkt_cmts; p != NULL((void*)0); prev = p, p = p->next, g_free(prev)) {
989 putsep();
990 putquote();
991 if (machine_readable) {
992 printf("%s", g_strescape(p->cmt, NULL((void*)0)));
993 } else {
994 printf("%s", p->cmt);
995 }
996 g_free(p->cmt);
997 putquote();
998 }
999 }
1000
1001 printf("\n");
1002}
1003
1004static void
1005cleanup_capture_info(capture_info *cf_info)
1006{
1007 unsigned int i;
1008 ws_assert(cf_info != NULL)do { if ((1) && !(cf_info != ((void*)0))) ws_log_fatal_full
("Main", LOG_LEVEL_ERROR, "capinfos.c", 1008, __func__, "assertion failed: %s"
, "cf_info != ((void*)0)"); } while (0)
;
1009
1010 g_free(cf_info->encap_counts);
1011 cf_info->encap_counts = NULL((void*)0);
1012
1013 g_array_free(cf_info->interface_packet_counts, true1);
1014 cf_info->interface_packet_counts = NULL((void*)0);
1015
1016 if (cf_info->idb_info_strings) {
1017 for (i = 0; i < cf_info->idb_info_strings->len; i++) {
1018 char *s = g_array_index(cf_info->idb_info_strings, char*, i)(((char**) (void *) (cf_info->idb_info_strings)->data) [
(i)])
;
1019 g_free(s);
1020 }
1021 g_array_free(cf_info->idb_info_strings, true1);
1022 }
1023 cf_info->idb_info_strings = NULL((void*)0);
1024}
1025
1026static void
1027count_ipv4_address(const unsigned int addr _U___attribute__((unused)), const char *name _U___attribute__((unused)), const bool_Bool static_entry _U___attribute__((unused)))
1028{
1029 num_ipv4_addresses++;
1030}
1031
1032static void
1033count_ipv6_address(const ws_in6_addr *addrp _U___attribute__((unused)), const char *name _U___attribute__((unused)), const bool_Bool static_entry _U___attribute__((unused)))
1034{
1035 num_ipv6_addresses++;
1036}
1037
1038static void
1039count_decryption_secret(uint32_t secrets_type _U___attribute__((unused)), const void *secrets _U___attribute__((unused)), unsigned int size _U___attribute__((unused)))
1040{
1041 /* XXX - count them based on the secrets type (which is an opaque code,
1042 not a small integer)? */
1043 num_decryption_secrets++;
1044}
1045
1046static void
1047hash_to_str(const unsigned char *hash, size_t length, char *str)
1048{
1049 int i;
1050
1051 for (i = 0; i < (int) length; i++) {
1052 snprintf(str+(i*2), 3, "%02x", hash[i]);
1053 }
1054}
1055
1056static void
1057calculate_hashes(const char *filename)
1058{
1059 FILE *fh;
1060 size_t hash_bytes;
1061
1062 (void) g_strlcpy(file_sha256, "<unknown>", HASH_STR_SIZE(65));
1063 (void) g_strlcpy(file_sha1, "<unknown>", HASH_STR_SIZE(65));
1064
1065 if (cap_file_hashes) {
1066 fh = ws_fopenfopen(filename, "rb");
1067 if (fh && hd) {
1068 while((hash_bytes = fread(hash_buf, 1, HASH_BUF_SIZE(1024 * 1024), fh)) > 0) {
1069 gcry_md_write(hd, hash_buf, hash_bytes);
1070 }
1071 gcry_md_final(hd)gcry_md_ctl ((hd), GCRYCTL_FINALIZE, ((void*)0), 0);
1072 hash_to_str(gcry_md_read(hd, GCRY_MD_SHA256), HASH_SIZE_SHA25632, file_sha256);
1073 hash_to_str(gcry_md_read(hd, GCRY_MD_SHA1), HASH_SIZE_SHA120, file_sha1);
1074 }
1075 if (fh) fclose(fh);
1076 if (hd) gcry_md_reset(hd);
1077 }
1078}
1079
1080static int
1081process_cap_file(const char *filename, bool_Bool need_separator)
1082{
1083 int status = 0;
1084 int err;
1085 char *err_info;
1086 int64_t size;
1087 int64_t data_offset;
1088
1089 uint32_t packet = 0;
1090 int64_t bytes = 0;
1091 uint32_t snaplen_min_inferred = 0xffffffff;
1092 uint32_t snaplen_max_inferred = 0;
1093 wtap_rec rec;
1094 capture_info cf_info;
1095 bool_Bool have_times = true1;
1096 nstime_t earliest_packet_time;
1097 int earliest_packet_time_tsprec;
1098 nstime_t latest_packet_time;
1099 int latest_packet_time_tsprec;
1100 nstime_t cur_time;
1101 nstime_t prev_time;
1102 bool_Bool know_order = false0;
1103 order_t order = IN_ORDER;
1104 unsigned int i;
1105 wtapng_iface_descriptions_t *idb_info;
1106
1107 pkt_cmt *pc = NULL((void*)0), *prev = NULL((void*)0);
1108
1109 cf_info.wth = wtap_open_offline(filename, WTAP_TYPE_AUTO0, &err, &err_info, false0);
1110 if (!cf_info.wth) {
15
Assuming field 'wth' is non-null
16
Taking false branch
1111 cfile_open_failure_message(filename, err, err_info);
1112 return 2;
1113 }
1114
1115 /*
1116 * Calculate the checksums. Do this after wtap_open_offline, so we don't
1117 * bother calculating them for files that are not known capture types
1118 * where we wouldn't print them anyway.
1119 */
1120 calculate_hashes(filename);
1121
1122 if (need_separator
16.1
'need_separator' is false
&& long_report) {
1123 printf("\n");
1124 }
1125
1126 nstime_set_zero(&earliest_packet_time);
1127 earliest_packet_time_tsprec = WTAP_TSPREC_UNKNOWN-2;
1128 nstime_set_zero(&latest_packet_time);
1129 latest_packet_time_tsprec = WTAP_TSPREC_UNKNOWN-2;
1130 nstime_set_zero(&cur_time);
1131 nstime_set_zero(&prev_time);
1132
1133 cf_info.encap_counts = g_new0(int,WTAP_NUM_ENCAP_TYPES)((int *) g_malloc0_n ((wtap_get_num_encap_types()), sizeof (int
)))
;
1134
1135 idb_info = wtap_file_get_idb_info(cf_info.wth);
1136
1137 ws_assert(idb_info->interface_data != NULL)do { if ((1) && !(idb_info->interface_data != ((void
*)0))) ws_log_fatal_full("Main", LOG_LEVEL_ERROR, "capinfos.c"
, 1137, __func__, "assertion failed: %s", "idb_info->interface_data != ((void*)0)"
); } while (0)
;
17
Assuming field 'interface_data' is not equal to null
18
Taking false branch
19
Loop condition is false. Exiting loop
1138
1139 cf_info.pkt_cmts = NULL((void*)0);
1140 cf_info.num_interfaces = idb_info->interface_data->len;
1141 cf_info.interface_packet_counts = g_array_sized_new(false0, true1, sizeof(uint32_t), cf_info.num_interfaces);
1142 g_array_set_size(cf_info.interface_packet_counts, cf_info.num_interfaces);
1143 cf_info.pkt_interface_id_unknown = 0;
1144
1145 g_free(idb_info);
1146 idb_info = NULL((void*)0);
1147
1148 /* Zero out the counters for the callbacks. */
1149 num_ipv4_addresses = 0;
1150 num_ipv6_addresses = 0;
1151 num_decryption_secrets = 0;
1152
1153 /* Register callbacks for new name<->address maps from the file and
1154 decryption secrets from the file. */
1155 wtap_set_cb_new_ipv4(cf_info.wth, count_ipv4_address);
1156 wtap_set_cb_new_ipv6(cf_info.wth, count_ipv6_address);
1157 wtap_set_cb_new_secrets(cf_info.wth, count_decryption_secret);
1158
1159 /* Tally up data that we need to parse through the file to find */
1160 wtap_rec_init(&rec, 1514);
1161 while (wtap_read(cf_info.wth, &rec, &err, &err_info, &data_offset)) {
20
Loop condition is false. Execution continues on line 1269
1162 if (rec.presence_flags & WTAP_HAS_TS0x00000001) {
1163 prev_time = cur_time;
1164 cur_time = rec.ts;
1165 if (packet == 0) {
1166 earliest_packet_time = rec.ts;
1167 earliest_packet_time_tsprec = rec.tsprec;
1168 latest_packet_time = rec.ts;
1169 latest_packet_time_tsprec = rec.tsprec;
1170 prev_time = rec.ts;
1171 }
1172 if (nstime_cmp(&cur_time, &prev_time) < 0) {
1173 order = NOT_IN_ORDER;
1174 }
1175 if (nstime_cmp(&cur_time, &earliest_packet_time) < 0) {
1176 earliest_packet_time = cur_time;
1177 earliest_packet_time_tsprec = rec.tsprec;
1178 }
1179 if (nstime_cmp(&cur_time, &latest_packet_time) > 0) {
1180 latest_packet_time = cur_time;
1181 latest_packet_time_tsprec = rec.tsprec;
1182 }
1183 } else {
1184 have_times = false0; /* at least one packet has no time stamp */
1185 if (order != NOT_IN_ORDER)
1186 order = ORDER_UNKNOWN;
1187 }
1188
1189 if (rec.rec_type == REC_TYPE_PACKET0) {
1190 bytes += rec.rec_header.packet_header.len;
1191 packet++;
1192 /* packet comments */
1193 if (pkt_comments && wtap_block_count_option(rec.block, OPT_COMMENT1) > 0) {
1194 char *cmt_buff;
1195 for (i = 0; wtap_block_get_nth_string_option_value(rec.block, OPT_COMMENT1, i, &cmt_buff) == WTAP_OPTTYPE_SUCCESS; i++) {
1196 pc = g_new0(pkt_cmt, 1)((pkt_cmt *) g_malloc0_n ((1), sizeof (pkt_cmt)));
1197
1198 pc->recno = packet;
1199 pc->cmt = g_strdup(cmt_buff)g_strdup_inline (cmt_buff);
1200 pc->next = NULL((void*)0);
1201
1202 if (prev == NULL((void*)0))
1203 cf_info.pkt_cmts = pc;
1204 else
1205 prev->next = pc;
1206
1207 prev = pc;
1208 }
1209 }
1210
1211 /* If caplen < len for a rcd, then presumably */
1212 /* 'Limit packet capture length' was done for this rcd. */
1213 /* Keep track as to the min/max actual snapshot lengths */
1214 /* seen for this file. */
1215 if (rec.rec_header.packet_header.caplen < rec.rec_header.packet_header.len) {
1216 if (rec.rec_header.packet_header.caplen < snaplen_min_inferred)
1217 snaplen_min_inferred = rec.rec_header.packet_header.caplen;
1218 if (rec.rec_header.packet_header.caplen > snaplen_max_inferred)
1219 snaplen_max_inferred = rec.rec_header.packet_header.caplen;
1220 }
1221
1222 if ((rec.rec_header.packet_header.pkt_encap > 0) &&
1223 (rec.rec_header.packet_header.pkt_encap < WTAP_NUM_ENCAP_TYPESwtap_get_num_encap_types())) {
1224 cf_info.encap_counts[rec.rec_header.packet_header.pkt_encap] += 1;
1225 } else {
1226 fprintf(stderrstderr, "capinfos: Unknown packet encapsulation %d in frame %u of file \"%s\"\n",
1227 rec.rec_header.packet_header.pkt_encap, packet, filename);
1228 }
1229
1230 /* Packet interface_id info */
1231 if (rec.presence_flags & WTAP_HAS_INTERFACE_ID0x00000004) {
1232 /* cf_info.num_interfaces is size, not index, so it's one more than max index */
1233 if (rec.rec_header.packet_header.interface_id >= cf_info.num_interfaces) {
1234 /*
1235 * OK, re-fetch the number of interfaces, as there might have
1236 * been an interface that was in the middle of packets, and
1237 * grow the array to be big enough for the new number of
1238 * interfaces.
1239 */
1240 idb_info = wtap_file_get_idb_info(cf_info.wth);
1241
1242 cf_info.num_interfaces = idb_info->interface_data->len;
1243 g_array_set_size(cf_info.interface_packet_counts, cf_info.num_interfaces);
1244
1245 g_free(idb_info);
1246 idb_info = NULL((void*)0);
1247 }
1248 if (rec.rec_header.packet_header.interface_id < cf_info.num_interfaces) {
1249 g_array_index(cf_info.interface_packet_counts, uint32_t,(((uint32_t*) (void *) (cf_info.interface_packet_counts)->
data) [(rec.rec_header.packet_header.interface_id)])
1250 rec.rec_header.packet_header.interface_id)(((uint32_t*) (void *) (cf_info.interface_packet_counts)->
data) [(rec.rec_header.packet_header.interface_id)])
+= 1;
1251 }
1252 else {
1253 cf_info.pkt_interface_id_unknown += 1;
1254 }
1255 }
1256 else {
1257 /* it's for interface_id 0 */
1258 if (cf_info.num_interfaces != 0) {
1259 g_array_index(cf_info.interface_packet_counts, uint32_t, 0)(((uint32_t*) (void *) (cf_info.interface_packet_counts)->
data) [(0)])
+= 1;
1260 }
1261 else {
1262 cf_info.pkt_interface_id_unknown += 1;
1263 }
1264 }
1265 }
1266
1267 wtap_rec_reset(&rec);
1268 } /* while */
1269 wtap_rec_cleanup(&rec);
1270
1271 /*
1272 * Get IDB info strings.
1273 * We do this at the end, so we can get information for all IDBs in
1274 * the file, even those that come after packet records, and so that
1275 * we get, for example, a count of the number of statistics entries
1276 * for each interface as of the *end* of the file.
1277 */
1278 idb_info = wtap_file_get_idb_info(cf_info.wth);
1279
1280 cf_info.idb_info_strings = g_array_sized_new(false0, false0, sizeof(char*), cf_info.num_interfaces);
1281 cf_info.num_interfaces = idb_info->interface_data->len;
1282 for (i = 0; i < cf_info.num_interfaces; i++) {
21
Assuming 'i' is >= field 'num_interfaces'
22
Loop condition is false. Execution continues on line 1288
1283 const wtap_block_t if_descr = g_array_index(idb_info->interface_data, wtap_block_t, i)(((wtap_block_t*) (void *) (idb_info->interface_data)->
data) [(i)])
;
1284 char *s = wtap_get_debug_if_descr(if_descr, 21, "\n");
1285 g_array_append_val(cf_info.idb_info_strings, s)g_array_append_vals (cf_info.idb_info_strings, &(s), 1);
1286 }
1287
1288 g_free(idb_info);
1289 idb_info = NULL((void*)0);
1290
1291 if (err != 0) {
23
Assuming 'err' is equal to 0
24
Taking false branch
1292 fprintf(stderrstderr,
1293 "capinfos: An error occurred after reading %u packets from \"%s\".\n",
1294 packet, filename);
1295 cfile_read_failure_message(filename, err, err_info);
1296 if (err == WTAP_ERR_SHORT_READ-12) {
1297 /* Don't give up completely with this one. */
1298 status = 1;
1299 fprintf(stderrstderr,
1300 " (will continue anyway, checksums might be incorrect)\n");
1301 } else {
1302 cleanup_capture_info(&cf_info);
1303 wtap_close(cf_info.wth);
1304 return 2;
1305 }
1306 }
1307
1308 /* File size */
1309 size = wtap_file_size(cf_info.wth, &err);
1310 if (size == -1) {
25
Assuming the condition is false
26
Taking false branch
1311 fprintf(stderrstderr,
1312 "capinfos: Can't get size of \"%s\": %s.\n",
1313 filename, g_strerror(err));
1314 cleanup_capture_info(&cf_info);
1315 wtap_close(cf_info.wth);
1316 return 2;
1317 }
1318
1319 cf_info.filesize = size;
1320
1321 /* File Type */
1322 cf_info.file_type = wtap_file_type_subtype(cf_info.wth);
1323 cf_info.compression_type = wtap_get_compression_type(cf_info.wth);
1324
1325 /* File Encapsulation */
1326 cf_info.file_encap = wtap_file_encap(cf_info.wth);
1327
1328 cf_info.file_tsprec = wtap_file_tsprec(cf_info.wth);
1329
1330 /* Packet size limit (snaplen) */
1331 cf_info.snaplen = wtap_snapshot_length(cf_info.wth);
1332 if (cf_info.snaplen > 0)
27
Assuming field 'snaplen' is <= 0
28
Taking false branch
1333 cf_info.snap_set = true1;
1334 else
1335 cf_info.snap_set = false0;
1336
1337 cf_info.snaplen_min_inferred = snaplen_min_inferred;
1338 cf_info.snaplen_max_inferred = snaplen_max_inferred;
1339
1340 /* # of packets */
1341 cf_info.packet_count = packet;
1342
1343 /* File Times */
1344 cf_info.times_known = have_times;
1345 cf_info.earliest_packet_time = earliest_packet_time;
1346 cf_info.earliest_packet_time_tsprec = earliest_packet_time_tsprec;
1347 cf_info.latest_packet_time = latest_packet_time;
1348 cf_info.latest_packet_time_tsprec = latest_packet_time_tsprec;
1349 nstime_delta(&cf_info.duration, &latest_packet_time, &earliest_packet_time);
1350 /* Duration precision is the higher of the earliest and latest packet timestamp precisions. */
1351 if (cf_info.latest_packet_time_tsprec > cf_info.earliest_packet_time_tsprec)
29
Assuming field 'latest_packet_time_tsprec' is <= field 'earliest_packet_time_tsprec'
30
Taking false branch
1352 cf_info.duration_tsprec = cf_info.latest_packet_time_tsprec;
1353 else
1354 cf_info.duration_tsprec = cf_info.earliest_packet_time_tsprec;
1355 cf_info.know_order = know_order;
1356 cf_info.order = order;
1357
1358 /* Number of packet bytes */
1359 cf_info.packet_bytes = bytes;
1360
1361 cf_info.data_rate = 0.0;
1362 cf_info.packet_rate = 0.0;
1363 cf_info.packet_size = 0.0;
1364
1365 if (packet
30.1
'packet' is <= 0
> 0) {
1366 double delta_time = nstime_to_sec(&latest_packet_time) - nstime_to_sec(&earliest_packet_time);
1367 if (delta_time > 0.0) {
1368 cf_info.data_rate = (double)bytes / delta_time; /* Data rate per second */
1369 cf_info.packet_rate = (double)packet / delta_time; /* packet rate per second */
1370 }
1371 cf_info.packet_size = (double)bytes / packet; /* Avg packet size */
1372 }
1373
1374 if (!long_report && table_report_header) {
31
Assuming 'long_report' is false
32
Assuming 'table_report_header' is true
33
Taking true branch
1375 print_stats_table_header(&cf_info);
34
Calling 'print_stats_table_header'
1376 }
1377
1378 if (long_report) {
1379 print_stats(filename, &cf_info);
1380 } else {
1381 print_stats_table(filename, &cf_info);
1382 }
1383
1384 cleanup_capture_info(&cf_info);
1385 wtap_close(cf_info.wth);
1386
1387 return status;
1388}
1389
1390static void
1391print_usage(FILE *output)
1392{
1393 fprintf(output, "\n");
1394 fprintf(output, "Usage: capinfos [options] <infile> ...\n");
1395 fprintf(output, "\n");
1396 fprintf(output, "General infos:\n");
1397 fprintf(output, " -t display the capture file type\n");
1398 fprintf(output, " -E display the capture file encapsulation\n");
1399 fprintf(output, " -I display the capture file interface information\n");
1400 fprintf(output, " -F display additional capture file information\n");
1401 fprintf(output, " -H display the SHA256 and SHA1 hashes of the file\n");
1402 fprintf(output, " -k display the capture comment\n");
1403 fprintf(output, " -p display individual packet comments\n");
1404 fprintf(output, "\n");
1405 fprintf(output, "Size infos:\n");
1406 fprintf(output, " -c display the number of packets\n");
1407 fprintf(output, " -s display the size of the file (in bytes)\n");
1408 fprintf(output, " -d display the total length of all packets (in bytes)\n");
1409 fprintf(output, " -l display the packet size limit (snapshot length)\n");
1410 fprintf(output, "\n");
1411 fprintf(output, "Time infos:\n");
1412 fprintf(output, " -u display the capture duration (in seconds)\n");
1413 fprintf(output, " -a display the timestamp of the earliest packet\n");
1414 fprintf(output, " -e display the timestamp of the latest packet\n");
1415 fprintf(output, " -o display the capture file chronological status (True/False)\n");
1416 fprintf(output, " -S display earliest and latest packet timestamps as seconds\n");
1417 fprintf(output, "\n");
1418 fprintf(output, "Statistic infos:\n");
1419 fprintf(output, " -y display average data rate (in bytes/sec)\n");
1420 fprintf(output, " -i display average data rate (in bits/sec)\n");
1421 fprintf(output, " -z display average packet size (in bytes)\n");
1422 fprintf(output, " -x display average packet rate (in packets/sec)\n");
1423 fprintf(output, "\n");
1424 fprintf(output, "Metadata infos:\n");
1425 fprintf(output, " -n display number of resolved IPv4 and IPv6 addresses\n");
1426 fprintf(output, " -D display number of decryption secrets\n");
1427 fprintf(output, "\n");
1428 fprintf(output, "Output format:\n");
1429 fprintf(output, " -L generate long report (default)\n");
1430 fprintf(output, " -T generate table report\n");
1431 fprintf(output, " -M display machine-readable values in long reports\n");
1432 fprintf(output, "\n");
1433 fprintf(output, "Table report options:\n");
1434 fprintf(output, " -R generate header record (default)\n");
1435 fprintf(output, " -r do not generate header record\n");
1436 fprintf(output, "\n");
1437 fprintf(output, " -B separate infos with TAB character (default)\n");
1438 fprintf(output, " -m separate infos with comma (,) character\n");
1439 fprintf(output, " -b separate infos with SPACE character\n");
1440 fprintf(output, "\n");
1441 fprintf(output, " -N do not quote infos (default)\n");
1442 fprintf(output, " -q quote infos with single quotes (')\n");
1443 fprintf(output, " -Q quote infos with double quotes (\")\n");
1444 fprintf(output, "\n");
1445 fprintf(output, "Miscellaneous:\n");
1446 fprintf(output, " -h, --help display this help and exit\n");
1447 fprintf(output, " -v, --version display version info and exit\n");
1448 fprintf(output, " -C cancel processing if file open fails (default is to continue)\n");
1449 fprintf(output, " -A generate all infos (default)\n");
1450 fprintf(output, " -K disable displaying the capture comment\n");
1451 fprintf(output, " -P disable displaying individual packet comments\n");
1452 fprintf(output, "\n");
1453 fprintf(output, "Options are processed from left to right order with later options superseding\n");
1454 fprintf(output, "or adding to earlier options.\n");
1455 fprintf(output, "\n");
1456 fprintf(output, "If no options are given the default is to display all infos in long report\n");
1457 fprintf(output, "output format.\n");
1458}
1459
1460int
1461main(int argc, char *argv[])
1462{
1463 char *configuration_init_error;
1464 bool_Bool need_separator = false0;
1465 int opt;
1466 int overall_error_status = EXIT_SUCCESS0;
1467 static const struct ws_option long_options[] = {
1468 {"help", ws_no_argument0, NULL((void*)0), 'h'},
1469 {"version", ws_no_argument0, NULL((void*)0), 'v'},
1470 LONGOPT_WSLOG{"log-level", 1, ((void*)0), 3000 +1000 +1}, {"log-domain", 1
, ((void*)0), 3000 +1000 +2}, {"log-domains", 1, ((void*)0), 3000
+1000 +2}, {"log-file", 1, ((void*)0), 3000 +1000 +3}, {"log-fatal"
, 1, ((void*)0), 3000 +1000 +4}, {"log-fatal-domain", 1, ((void
*)0), 3000 +1000 +5}, {"log-fatal-domains", 1, ((void*)0), 3000
+1000 +5}, {"log-debug", 1, ((void*)0), 3000 +1000 +6}, {"log-noisy"
, 1, ((void*)0), 3000 +1000 +7},
1471 {0, 0, 0, 0 }
1472 };
1473
1474#define OPTSTRING"abcdehiklmnopqrstuvxyzABCDEFHIKLMNPQRST" "abcdehiklmnopqrstuvxyzABCDEFHIKLMNPQRST"
1475 static const char optstring[] = OPTSTRING"abcdehiklmnopqrstuvxyzABCDEFHIKLMNPQRST";
1476
1477 int status = 0;
1478
1479 /* Set the program name. */
1480 g_set_prgname("capinfos");
1481
1482 /*
1483 * Set the C-language locale to the native environment and set the
1484 * code page to UTF-8 on Windows.
1485 */
1486#ifdef _WIN32
1487 setlocale(LC_ALL6, ".UTF-8");
1488#else
1489 setlocale(LC_ALL6, "");
1490#endif
1491
1492 cmdarg_err_init(stderr_cmdarg_err, stderr_cmdarg_err_cont);
1493
1494 /* Initialize log handler early so we can have proper logging during startup. */
1495 ws_log_init(vcmdarg_err);
1496
1497 /* Early logging command-line initialization. */
1498 ws_log_parse_args(&argc, argv, optstring, long_options, vcmdarg_err, WS_EXIT_INVALID_OPTION1);
1499
1500 ws_noisy("Finished log init and parsing command line log arguments")do { if (1) { ws_log_full("Main", LOG_LEVEL_NOISY, "capinfos.c"
, 1500, __func__, "Finished log init and parsing command line log arguments"
); } } while (0)
;
1
Taking true branch
2
Loop condition is false. Exiting loop
1501
1502 /* Get the decimal point. */
1503 decimal_point = g_strdup(localeconv()->decimal_point)g_strdup_inline (localeconv()->decimal_point);
1504
1505#ifdef _WIN32
1506 create_app_running_mutex();
1507#endif /* _WIN32 */
1508
1509 /*
1510 * Get credential information for later use.
1511 */
1512 init_process_policies();
1513
1514 /*
1515 * Attempt to get the pathname of the directory containing the
1516 * executable file.
1517 */
1518 configuration_init_error = configuration_init(argv[0]);
1519 if (configuration_init_error != NULL((void*)0)) {
3
Assuming 'configuration_init_error' is equal to NULL
4
Taking false branch
1520 fprintf(stderrstderr,
1521 "capinfos: Can't get pathname of directory containing the capinfos program: %s.\n",
1522 configuration_init_error);
1523 g_free(configuration_init_error);
1524 }
1525
1526 /* Initialize the version information. */
1527 ws_init_version_info("Capinfos", NULL((void*)0), NULL((void*)0));
1528
1529 init_report_failure_message("capinfos");
1530
1531 wtap_init(true1);
1532
1533 /* Process the options */
1534 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 1726
1535
1536 switch (opt) {
1537
1538 case 't':
1539 if (report_all_infos) disable_all_infos();
1540 cap_file_type = true1;
1541 break;
1542
1543 case 'E':
1544 if (report_all_infos) disable_all_infos();
1545 cap_file_encap = true1;
1546 break;
1547
1548 case 'l':
1549 if (report_all_infos) disable_all_infos();
1550 cap_snaplen = true1;
1551 break;
1552
1553 case 'c':
1554 if (report_all_infos) disable_all_infos();
1555 cap_packet_count = true1;
1556 break;
1557
1558 case 's':
1559 if (report_all_infos) disable_all_infos();
1560 cap_file_size = true1;
1561 break;
1562
1563 case 'd':
1564 if (report_all_infos) disable_all_infos();
1565 cap_data_size = true1;
1566 break;
1567
1568 case 'u':
1569 if (report_all_infos) disable_all_infos();
1570 cap_duration = true1;
1571 break;
1572
1573 case 'a':
1574 if (report_all_infos) disable_all_infos();
1575 cap_earliest_packet_time = true1;
1576 break;
1577
1578 case 'e':
1579 if (report_all_infos) disable_all_infos();
1580 cap_latest_packet_time = true1;
1581 break;
1582
1583 case 'S':
1584 time_as_secs = true1;
1585 break;
1586
1587 case 'y':
1588 if (report_all_infos) disable_all_infos();
1589 cap_data_rate_byte = true1;
1590 break;
1591
1592 case 'i':
1593 if (report_all_infos) disable_all_infos();
1594 cap_data_rate_bit = true1;
1595 break;
1596
1597 case 'z':
1598 if (report_all_infos) disable_all_infos();
1599 cap_packet_size = true1;
1600 break;
1601
1602 case 'x':
1603 if (report_all_infos) disable_all_infos();
1604 cap_packet_rate = true1;
1605 break;
1606
1607 case 'H':
1608 if (report_all_infos) disable_all_infos();
1609 cap_file_hashes = true1;
1610 break;
1611
1612 case 'o':
1613 if (report_all_infos) disable_all_infos();
1614 cap_order = true1;
1615 break;
1616
1617 case 'k':
1618 if (report_all_infos) disable_all_infos();
1619 cap_comment = true1;
1620 break;
1621
1622 case 'p':
1623 if (report_all_infos) disable_all_infos();
1624 pkt_comments = true1;
1625 break;
1626
1627 case 'K':
1628 cap_comment = false0;
1629 break;
1630
1631 case 'P':
1632 pkt_comments = false0;
1633 break;
1634
1635 case 'F':
1636 if (report_all_infos) disable_all_infos();
1637 cap_file_more_info = true1;
1638 break;
1639
1640 case 'I':
1641 if (report_all_infos) disable_all_infos();
1642 cap_file_idb = true1;
1643 break;
1644
1645 case 'n':
1646 if (report_all_infos) disable_all_infos();
1647 cap_file_nrb = true1;
1648 break;
1649
1650 case 'D':
1651 if (report_all_infos) disable_all_infos();
1652 cap_file_dsb = true1;
1653 break;
1654
1655 case 'C':
1656 stop_after_failure = true1;
1657 break;
1658
1659 case 'A':
1660 enable_all_infos();
1661 break;
1662
1663 case 'L':
1664 long_report = true1;
1665 break;
1666
1667 case 'T':
1668 long_report = false0;
1669 break;
1670
1671 case 'M':
1672 machine_readable = true1;
1673 break;
1674
1675 case 'R':
1676 table_report_header = true1;
1677 break;
1678
1679 case 'r':
1680 table_report_header = false0;
1681 break;
1682
1683 case 'N':
1684 quote_char = '\0';
1685 break;
1686
1687 case 'q':
1688 quote_char = '\'';
1689 break;
1690
1691 case 'Q':
1692 quote_char = '"';
1693 break;
1694
1695 case 'B':
1696 field_separator = '\t';
1697 break;
1698
1699 case 'm':
1700 field_separator = ',';
1701 break;
1702
1703 case 'b':
1704 field_separator = ' ';
1705 break;
1706
1707 case 'h':
1708 show_help_header("Print various information (infos) about capture files.");
1709 print_usage(stdoutstdout);
1710 goto exit;
1711 break;
1712
1713 case 'v':
1714 show_version();
1715 goto exit;
1716 break;
1717
1718 case '?': /* Bad flag - print usage message */
1719 print_usage(stderrstderr);
1720 overall_error_status = WS_EXIT_INVALID_OPTION1;
1721 goto exit;
1722 break;
1723 }
1724 }
1725
1726 if ((argc - ws_optind) < 1) {
7
Assuming the condition is false
8
Taking false branch
1727 print_usage(stderrstderr);
1728 overall_error_status = WS_EXIT_INVALID_OPTION1;
1729 goto exit;
1730 }
1731
1732 if (cap_file_hashes
8.1
'cap_file_hashes' is true
) {
9
Taking true branch
1733 gcry_check_version(NULL((void*)0));
1734 gcry_md_open(&hd, GCRY_MD_SHA256, 0);
1735 if (hd)
10
Assuming 'hd' is null
11
Taking false branch
1736 gcry_md_enable(hd, GCRY_MD_SHA1);
1737
1738 hash_buf = (char *)g_malloc(HASH_BUF_SIZE(1024 * 1024));
1739 }
1740
1741 overall_error_status = 0;
1742
1743 for (opt = ws_optind; opt < argc; opt++) {
12
Assuming 'opt' is < 'argc'
13
Loop condition is true. Entering loop body
1744
1745 status = process_cap_file(argv[opt], need_separator);
14
Calling 'process_cap_file'
1746 if (status) {
1747 /* Something failed. It's been reported; remember that processing
1748 one file failed and, if -C was specified, stop. */
1749 overall_error_status = status;
1750 if (stop_after_failure)
1751 goto exit;
1752 }
1753 if (status != 2) {
1754 /* Either it succeeded or it got a "short read" but printed
1755 information anyway. Note that we need a blank line before
1756 the next file's information, to separate it from the
1757 previous file. */
1758 need_separator = true1;
1759 }
1760 }
1761
1762exit:
1763 g_free(hash_buf);
1764 gcry_md_close(hd);
1765 wtap_cleanup();
1766 free_progdirs();
1767 return overall_error_status;
1768}