File: | builds/wireshark/wireshark/capinfos.c |
Warning: | line 744, column 5 Potential leak of memory pointed to by 'buf' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
92 | static bool_Bool stop_after_failure; | |||
93 | ||||
94 | /* | |||
95 | * table report variables | |||
96 | */ | |||
97 | ||||
98 | static bool_Bool long_report = true1; /* By default generate long report */ | |||
99 | static bool_Bool table_report_header = true1; /* Generate column header by default */ | |||
100 | static char field_separator = '\t'; /* Use TAB as field separator by default */ | |||
101 | static char quote_char = '\0'; /* Do NOT quote fields by default */ | |||
102 | static 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 | ||||
115 | static bool_Bool report_all_infos = true1; /* Report all infos */ | |||
116 | ||||
117 | static bool_Bool cap_file_type = true1; /* Report capture type */ | |||
118 | static bool_Bool cap_file_encap = true1; /* Report encapsulation */ | |||
119 | static bool_Bool cap_snaplen = true1; /* Packet size limit (snaplen)*/ | |||
120 | static bool_Bool cap_packet_count = true1; /* Report packet count */ | |||
121 | static bool_Bool cap_file_size = true1; /* Report file size */ | |||
122 | static bool_Bool cap_comment = true1; /* Display the capture comment */ | |||
123 | static bool_Bool cap_file_more_info = true1; /* Report more file info */ | |||
124 | static bool_Bool cap_file_idb = true1; /* Report Interface info */ | |||
125 | static bool_Bool cap_file_nrb = true1; /* Report Name Resolution Block info */ | |||
126 | static bool_Bool cap_file_dsb = true1; /* Report Decryption Secrets Block info */ | |||
127 | ||||
128 | static bool_Bool cap_data_size = true1; /* Report packet byte size */ | |||
129 | static bool_Bool cap_duration = true1; /* Report capture duration */ | |||
130 | static bool_Bool cap_earliest_packet_time = true1; /* Report timestamp of earliest packet */ | |||
131 | static bool_Bool cap_latest_packet_time = true1; /* Report timestamp of latest packet */ | |||
132 | static bool_Bool time_as_secs; /* Report time values as raw seconds */ | |||
133 | ||||
134 | static bool_Bool cap_data_rate_byte = true1; /* Report data rate bytes/sec */ | |||
135 | static bool_Bool cap_data_rate_bit = true1; /* Report data rate bites/sec */ | |||
136 | static bool_Bool cap_packet_size = true1; /* Report average packet size */ | |||
137 | static bool_Bool cap_packet_rate = true1; /* Report average packet rate */ | |||
138 | static bool_Bool cap_order = true1; /* Report if packets are in chronological order (True/False) */ | |||
139 | static bool_Bool pkt_comments = true1; /* Report individual packet comments */ | |||
140 | ||||
141 | static 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 | ||||
151 | static char file_sha256[HASH_STR_SIZE(65)]; | |||
152 | static char file_sha1[HASH_STR_SIZE(65)]; | |||
153 | ||||
154 | static char *hash_buf; | |||
155 | static gcry_md_hd_t hd; | |||
156 | ||||
157 | static unsigned int num_ipv4_addresses; | |||
158 | static unsigned int num_ipv6_addresses; | |||
159 | static 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 | */ | |||
171 | typedef enum { | |||
172 | IN_ORDER, | |||
173 | NOT_IN_ORDER, | |||
174 | ORDER_UNKNOWN | |||
175 | } order_t; | |||
176 | ||||
177 | typedef struct _pkt_cmt { | |||
178 | int recno; | |||
179 | char *cmt; | |||
180 | struct _pkt_cmt *next; | |||
181 | } pkt_cmt; | |||
182 | ||||
183 | typedef 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 | ||||
222 | static char *decimal_point; | |||
223 | ||||
224 | static void | |||
225 | enable_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 | ||||
255 | static void | |||
256 | disable_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 | ||||
286 | static const char * | |||
287 | order_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 | ||||
305 | static char * | |||
306 | absolute_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 | ||||
352 | static char * | |||
353 | relative_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 | ||||
426 | static 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 */ | |||
436 | static void | |||
437 | string_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 | ||||
453 | static void | |||
454 | show_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 | ||||
466 | static void | |||
467 | print_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 | ||||
671 | static void | |||
672 | putsep(void) | |||
673 | { | |||
674 | if (field_separator) putchar(field_separator); | |||
675 | } | |||
676 | ||||
677 | static void | |||
678 | putquote(void) | |||
679 | { | |||
680 | if (quote_char) putchar(quote_char); | |||
681 | } | |||
682 | ||||
683 | static void | |||
684 | print_stats_table_header_label(const char *label) | |||
685 | { | |||
686 | putsep(); | |||
687 | putquote(); | |||
688 | printf("%s", label); | |||
689 | putquote(); | |||
690 | } | |||
691 | ||||
692 | static void | |||
693 | print_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"); | |||
704 | if (cap_file_encap) print_stats_table_header_label("File encapsulation"); | |||
705 | if (cap_file_more_info) print_stats_table_header_label("File time precision"); | |||
706 | if (cap_snaplen) { | |||
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"); | |||
712 | if (cap_file_size) print_stats_table_header_label("File size (bytes)"); | |||
713 | if (cap_data_size) print_stats_table_header_label("Data size (bytes)"); | |||
714 | if (cap_duration) print_stats_table_header_label("Capture duration (seconds)"); | |||
715 | if (cap_earliest_packet_time) print_stats_table_header_label("Start time"); | |||
716 | if (cap_latest_packet_time) print_stats_table_header_label("End time"); | |||
717 | if (cap_data_rate_byte) print_stats_table_header_label("Data byte rate (bytes/sec)"); | |||
718 | if (cap_data_rate_bit) print_stats_table_header_label("Data bit rate (bits/sec)"); | |||
719 | if (cap_packet_size) print_stats_table_header_label("Average packet size (bytes)"); | |||
720 | if (cap_packet_rate) print_stats_table_header_label("Average packet rate (packets/sec)"); | |||
721 | if (cap_file_hashes) { | |||
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"); | |||
726 | if (cap_file_more_info
| |||
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"); | |||
732 | ||||
733 | if (pkt_comments && cf_info->pkt_cmts != NULL((void*)0)) { | |||
734 | /* Packet 2^64 Comment" + NULL */ | |||
735 | buf_len = strlen("Packet 18446744073709551616 Comment") + 1; | |||
736 | buf = (char *)g_malloc0(buf_len); | |||
737 | ||||
738 | for (p = cf_info->pkt_cmts; p
| |||
739 | snprintf(buf, buf_len, "Packet %d Comment", p->recno); | |||
740 | print_stats_table_header_label(buf); | |||
741 | } | |||
742 | } | |||
743 | ||||
744 | printf("\n"); | |||
| ||||
745 | } | |||
746 | ||||
747 | static void | |||
748 | print_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 | ||||
1004 | static void | |||
1005 | cleanup_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 | ||||
1026 | static void | |||
1027 | count_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 | ||||
1032 | static void | |||
1033 | count_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 | ||||
1038 | static void | |||
1039 | count_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 | ||||
1046 | static void | |||
1047 | hash_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 | ||||
1056 | static void | |||
1057 | calculate_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 | ||||
1080 | static int | |||
1081 | process_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) { | |||
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
| |||
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); | |||
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)) { | |||
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++) { | |||
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) { | |||
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) { | |||
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) | |||
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) | |||
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
| |||
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) { | |||
1375 | print_stats_table_header(&cf_info); | |||
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 | ||||
1390 | static void | |||
1391 | print_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 | ||||
1460 | int | |||
1461 | main(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); | |||
| ||||
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)) { | |||
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) { | |||
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) { | |||
1727 | print_usage(stderrstderr); | |||
1728 | overall_error_status = WS_EXIT_INVALID_OPTION1; | |||
1729 | goto exit; | |||
1730 | } | |||
1731 | ||||
1732 | if (cap_file_hashes
| |||
1733 | gcry_check_version(NULL((void*)0)); | |||
1734 | gcry_md_open(&hd, GCRY_MD_SHA256, 0); | |||
1735 | if (hd) | |||
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++) { | |||
1744 | ||||
1745 | status = process_cap_file(argv[opt], need_separator); | |||
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 | ||||
1762 | exit: | |||
1763 | g_free(hash_buf); | |||
1764 | gcry_md_close(hd); | |||
1765 | wtap_cleanup(); | |||
1766 | free_progdirs(); | |||
1767 | return overall_error_status; | |||
1768 | } |