nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 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 | * This program is free software; you can redistribute it and/or |
||
11 | * modify it under the terms of the GNU General Public License |
||
12 | * as published by the Free Software Foundation; either version 2 |
||
13 | * of the License, or (at your option) any later version. |
||
14 | * |
||
15 | * This program is distributed in the hope that it will be useful, |
||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
18 | * GNU General Public License for more details. |
||
19 | * |
||
20 | * You should have received a copy of the GNU General Public License |
||
21 | * along with this program; if not, write to the Free Software |
||
22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
||
23 | */ |
||
24 | |||
25 | /* |
||
26 | * 2009-09-19: jyoung |
||
27 | * |
||
28 | * New capinfos features |
||
29 | * |
||
30 | * Continue processing additional files after |
||
31 | * a wiretap open failure. The new -C option |
||
32 | * reverts to capinfos' original behavior which |
||
33 | * is to cancel any further file processing at |
||
34 | * first file open failure. |
||
35 | * |
||
36 | * Change the behavior of how the default display |
||
37 | * of all infos is initiated. This gets rid of a |
||
38 | * special post getopt() argument count test. |
||
39 | * |
||
40 | * Add new table output format (with related options) |
||
41 | * This feature allows outputting the various infos |
||
42 | * into a tab delimited text file, or to a comma |
||
43 | * separated variables file (*.csv) instead of the |
||
44 | * original "long" format. |
||
45 | * |
||
46 | * 2011-04-05: wmeier |
||
47 | * behaviour changed: Upon exit capinfos will return |
||
48 | * an error status if an error occurred at any |
||
49 | * point during "continuous" file processing. |
||
50 | * (Previously a success status was always |
||
51 | * returned if the -C option was not used). |
||
52 | * |
||
53 | |||
54 | */ |
||
55 | |||
56 | |||
57 | #include <config.h> |
||
58 | |||
59 | #include <stdio.h> |
||
60 | #include <stdlib.h> |
||
61 | #include <string.h> |
||
62 | #include <stdarg.h> |
||
63 | #include <locale.h> |
||
64 | #include <errno.h> |
||
65 | |||
66 | #ifdef HAVE_GETOPT_H |
||
67 | #include <getopt.h> |
||
68 | #endif |
||
69 | |||
70 | #include <glib.h> |
||
71 | |||
72 | #include <wiretap/wtap.h> |
||
73 | |||
74 | #include <wsutil/crash_info.h> |
||
75 | #include <wsutil/filesystem.h> |
||
76 | #include <wsutil/privileges.h> |
||
77 | #include <ws_version_info.h> |
||
78 | #include <wiretap/wtap_opttypes.h> |
||
79 | |||
80 | #ifdef HAVE_PLUGINS |
||
81 | #include <wsutil/plugins.h> |
||
82 | #endif |
||
83 | |||
84 | #include <wsutil/report_err.h> |
||
85 | #include <wsutil/str_util.h> |
||
86 | #include <wsutil/file_util.h> |
||
87 | |||
88 | #include <wsutil/wsgcrypt.h> |
||
89 | |||
90 | #ifndef HAVE_GETOPT_LONG |
||
91 | #include "wsutil/wsgetopt.h" |
||
92 | #endif |
||
93 | |||
94 | #ifdef _WIN32 |
||
95 | #include <wsutil/unicode-utils.h> |
||
96 | #endif /* _WIN32 */ |
||
97 | |||
98 | /* |
||
99 | * By default capinfos now continues processing |
||
100 | * the next filename if and when wiretap detects |
||
101 | * a problem opening a file. |
||
102 | * Use the '-C' option to revert back to original |
||
103 | * capinfos behavior which is to abort any |
||
104 | * additional file processing at first open file |
||
105 | * failure. |
||
106 | */ |
||
107 | |||
108 | static gboolean continue_after_wtap_open_offline_failure = TRUE; |
||
109 | |||
110 | /* |
||
111 | * table report variables |
||
112 | */ |
||
113 | |||
114 | static gboolean long_report = TRUE; /* By default generate long report */ |
||
115 | static gchar table_report_header = TRUE; /* Generate column header by default */ |
||
116 | static gchar field_separator = '\t'; /* Use TAB as field separator by default */ |
||
117 | static gchar quote_char = '\0'; /* Do NOT quote fields by default */ |
||
118 | static gboolean machine_readable = FALSE; /* Display machine-readable numbers */ |
||
119 | |||
120 | /* |
||
121 | * capinfos has the ability to report on a number of |
||
122 | * various characteristics ("infos") for each input file. |
||
123 | * |
||
124 | * By default reporting of all info fields is enabled. |
||
125 | * |
||
126 | * Optionally the reporting of any specific info field |
||
127 | * or combination of info fields can be enabled with |
||
128 | * individual options. |
||
129 | */ |
||
130 | |||
131 | static gboolean report_all_infos = TRUE; /* Report all infos */ |
||
132 | |||
133 | static gboolean cap_file_type = TRUE; /* Report capture type */ |
||
134 | static gboolean cap_file_encap = TRUE; /* Report encapsulation */ |
||
135 | static gboolean cap_snaplen = TRUE; /* Packet size limit (snaplen)*/ |
||
136 | static gboolean cap_packet_count = TRUE; /* Report packet count */ |
||
137 | static gboolean cap_file_size = TRUE; /* Report file size */ |
||
138 | static gboolean cap_comment = TRUE; /* Display the capture comment */ |
||
139 | static gboolean cap_file_more_info = TRUE; /* Report more file info */ |
||
140 | static gboolean cap_file_idb = TRUE; /* Report Interface info */ |
||
141 | |||
142 | static gboolean cap_data_size = TRUE; /* Report packet byte size */ |
||
143 | static gboolean cap_duration = TRUE; /* Report capture duration */ |
||
144 | static gboolean cap_start_time = TRUE; /* Report capture start time */ |
||
145 | static gboolean cap_end_time = TRUE; /* Report capture end time */ |
||
146 | static gboolean time_as_secs = FALSE; /* Report time values as raw seconds */ |
||
147 | |||
148 | static gboolean cap_data_rate_byte = TRUE; /* Report data rate bytes/sec */ |
||
149 | static gboolean cap_data_rate_bit = TRUE; /* Report data rate bites/sec */ |
||
150 | static gboolean cap_packet_size = TRUE; /* Report average packet size */ |
||
151 | static gboolean cap_packet_rate = TRUE; /* Report average packet rate */ |
||
152 | static gboolean cap_order = TRUE; /* Report if packets are in chronological order (True/False) */ |
||
153 | |||
154 | #ifdef HAVE_LIBGCRYPT |
||
155 | static gboolean cap_file_hashes = TRUE; /* Calculate file hashes */ |
||
156 | |||
157 | #define HASH_SIZE_SHA1 20 |
||
158 | #define HASH_SIZE_RMD160 20 |
||
159 | #define HASH_SIZE_MD5 16 |
||
160 | |||
161 | #define HASH_STR_SIZE (41) /* Max hash size * 2 + '\0' */ |
||
162 | #define HASH_BUF_SIZE (1024 * 1024) |
||
163 | |||
164 | |||
165 | static gchar file_sha1[HASH_STR_SIZE]; |
||
166 | static gchar file_rmd160[HASH_STR_SIZE]; |
||
167 | static gchar file_md5[HASH_STR_SIZE]; |
||
168 | |||
169 | #define FILE_HASH_OPT "H" |
||
170 | #else |
||
171 | #define FILE_HASH_OPT "" |
||
172 | #endif /* HAVE_LIBGCRYPT */ |
||
173 | |||
174 | /* |
||
175 | * If we have at least two packets with time stamps, and they're not in |
||
176 | * order - i.e., the later packet has a time stamp older than the earlier |
||
177 | * packet - the time stamps are known not to be in order. |
||
178 | * |
||
179 | * If every packet has a time stamp, and they're all in order, the time |
||
180 | * stamp is known to be in order. |
||
181 | * |
||
182 | * Otherwise, we have no idea. |
||
183 | */ |
||
184 | typedef enum { |
||
185 | IN_ORDER, |
||
186 | NOT_IN_ORDER, |
||
187 | ORDER_UNKNOWN |
||
188 | } order_t; |
||
189 | |||
190 | typedef struct _capture_info { |
||
191 | const char *filename; |
||
192 | guint16 file_type; |
||
193 | gboolean iscompressed; |
||
194 | int file_encap; |
||
195 | int file_tsprec; |
||
196 | gint64 filesize; |
||
197 | wtap_block_t shb; |
||
198 | guint64 packet_bytes; |
||
199 | gboolean times_known; |
||
200 | nstime_t start_time; |
||
201 | int start_time_tsprec; |
||
202 | nstime_t stop_time; |
||
203 | int stop_time_tsprec; |
||
204 | guint32 packet_count; |
||
205 | gboolean snap_set; /* If set in capture file header */ |
||
206 | guint32 snaplen; /* value from the capture file header */ |
||
207 | guint32 snaplen_min_inferred; /* If caplen < len for 1 or more rcds */ |
||
208 | guint32 snaplen_max_inferred; /* ... */ |
||
209 | gboolean drops_known; |
||
210 | guint32 drop_count; |
||
211 | |||
212 | nstime_t duration; |
||
213 | int duration_tsprec; |
||
214 | double packet_rate; |
||
215 | double packet_size; |
||
216 | double data_rate; /* in bytes */ |
||
217 | gboolean know_order; |
||
218 | order_t order; |
||
219 | |||
220 | int *encap_counts; /* array of per_packet encap counts; array has one entry per wtap_encap type */ |
||
221 | |||
222 | guint num_interfaces; /* number of IDBs, and thus size of interface_packet_counts array */ |
||
223 | GArray *interface_packet_counts; /* array of per_packet interface_id counts; one entry per file IDB */ |
||
224 | guint32 pkt_interface_id_unknown; /* counts if packet interface_id didn't match a known one */ |
||
225 | GArray *idb_info_strings; /* array of IDB info strings */ |
||
226 | } capture_info; |
||
227 | |||
228 | static char *decimal_point; |
||
229 | |||
230 | static void |
||
231 | enable_all_infos(void) |
||
232 | { |
||
233 | report_all_infos = TRUE; |
||
234 | |||
235 | cap_file_type = TRUE; |
||
236 | cap_file_encap = TRUE; |
||
237 | cap_snaplen = TRUE; |
||
238 | cap_packet_count = TRUE; |
||
239 | cap_file_size = TRUE; |
||
240 | cap_comment = TRUE; |
||
241 | cap_file_more_info = TRUE; |
||
242 | cap_file_idb = TRUE; |
||
243 | |||
244 | cap_data_size = TRUE; |
||
245 | cap_duration = TRUE; |
||
246 | cap_start_time = TRUE; |
||
247 | cap_end_time = TRUE; |
||
248 | cap_order = TRUE; |
||
249 | |||
250 | cap_data_rate_byte = TRUE; |
||
251 | cap_data_rate_bit = TRUE; |
||
252 | cap_packet_size = TRUE; |
||
253 | cap_packet_rate = TRUE; |
||
254 | |||
255 | #ifdef HAVE_LIBGCRYPT |
||
256 | cap_file_hashes = TRUE; |
||
257 | #endif /* HAVE_LIBGCRYPT */ |
||
258 | } |
||
259 | |||
260 | static void |
||
261 | disable_all_infos(void) |
||
262 | { |
||
263 | report_all_infos = FALSE; |
||
264 | |||
265 | cap_file_type = FALSE; |
||
266 | cap_file_encap = FALSE; |
||
267 | cap_snaplen = FALSE; |
||
268 | cap_packet_count = FALSE; |
||
269 | cap_file_size = FALSE; |
||
270 | cap_comment = FALSE; |
||
271 | cap_file_more_info = FALSE; |
||
272 | cap_file_idb = FALSE; |
||
273 | |||
274 | cap_data_size = FALSE; |
||
275 | cap_duration = FALSE; |
||
276 | cap_start_time = FALSE; |
||
277 | cap_end_time = FALSE; |
||
278 | cap_order = FALSE; |
||
279 | |||
280 | cap_data_rate_byte = FALSE; |
||
281 | cap_data_rate_bit = FALSE; |
||
282 | cap_packet_size = FALSE; |
||
283 | cap_packet_rate = FALSE; |
||
284 | |||
285 | #ifdef HAVE_LIBGCRYPT |
||
286 | cap_file_hashes = FALSE; |
||
287 | #endif /* HAVE_LIBGCRYPT */ |
||
288 | } |
||
289 | |||
290 | static const gchar * |
||
291 | order_string(order_t order) |
||
292 | { |
||
293 | switch (order) { |
||
294 | |||
295 | case IN_ORDER: |
||
296 | return "True"; |
||
297 | |||
298 | case NOT_IN_ORDER: |
||
299 | return "False"; |
||
300 | |||
301 | case ORDER_UNKNOWN: |
||
302 | return "Unknown"; |
||
303 | |||
304 | default: |
||
305 | return "???"; /* "cannot happen" (the next step is "Profit!") */ |
||
306 | } |
||
307 | } |
||
308 | |||
309 | static gchar * |
||
310 | absolute_time_string(nstime_t *timer, int tsprecision, capture_info *cf_info) |
||
311 | { |
||
312 | static gchar time_string_buf[4+1+2+1+2+1+2+1+2+1+2+1+9+1+1]; |
||
313 | struct tm *ti_tm; |
||
314 | |||
315 | if (cf_info->times_known && cf_info->packet_count > 0) { |
||
316 | if (time_as_secs) { |
||
317 | switch (tsprecision) { |
||
318 | |||
319 | case WTAP_TSPREC_SEC: |
||
320 | g_snprintf(time_string_buf, sizeof time_string_buf, |
||
321 | "%lu", |
||
322 | (unsigned long)timer->secs); |
||
323 | break; |
||
324 | |||
325 | case WTAP_TSPREC_DSEC: |
||
326 | g_snprintf(time_string_buf, sizeof time_string_buf, |
||
327 | "%lu%s%01d", |
||
328 | (unsigned long)timer->secs, |
||
329 | decimal_point, |
||
330 | timer->nsecs / 100000000); |
||
331 | break; |
||
332 | |||
333 | case WTAP_TSPREC_CSEC: |
||
334 | g_snprintf(time_string_buf, sizeof time_string_buf, |
||
335 | "%lu%s%02d", |
||
336 | (unsigned long)timer->secs, |
||
337 | decimal_point, |
||
338 | timer->nsecs / 10000000); |
||
339 | break; |
||
340 | |||
341 | case WTAP_TSPREC_MSEC: |
||
342 | g_snprintf(time_string_buf, sizeof time_string_buf, |
||
343 | "%lu%s%03d", |
||
344 | (unsigned long)timer->secs, |
||
345 | decimal_point, |
||
346 | timer->nsecs / 1000000); |
||
347 | break; |
||
348 | |||
349 | case WTAP_TSPREC_USEC: |
||
350 | g_snprintf(time_string_buf, sizeof time_string_buf, |
||
351 | "%lu%s%06d", |
||
352 | (unsigned long)timer->secs, |
||
353 | decimal_point, |
||
354 | timer->nsecs / 1000); |
||
355 | break; |
||
356 | |||
357 | case WTAP_TSPREC_NSEC: |
||
358 | g_snprintf(time_string_buf, sizeof time_string_buf, |
||
359 | "%lu%s%09d", |
||
360 | (unsigned long)timer->secs, |
||
361 | decimal_point, |
||
362 | timer->nsecs); |
||
363 | break; |
||
364 | |||
365 | default: |
||
366 | g_snprintf(time_string_buf, sizeof time_string_buf, |
||
367 | "Unknown precision %d", |
||
368 | tsprecision); |
||
369 | break; |
||
370 | } |
||
371 | return time_string_buf; |
||
372 | } else { |
||
373 | ti_tm = localtime(&timer->secs); |
||
374 | if (ti_tm == NULL) { |
||
375 | g_snprintf(time_string_buf, sizeof time_string_buf, "Not representable"); |
||
376 | return time_string_buf; |
||
377 | } |
||
378 | switch (tsprecision) { |
||
379 | |||
380 | case WTAP_TSPREC_SEC: |
||
381 | g_snprintf(time_string_buf, sizeof time_string_buf, |
||
382 | "%04d-%02d-%02d %02d:%02d:%02d", |
||
383 | ti_tm->tm_year + 1900, |
||
384 | ti_tm->tm_mon + 1, |
||
385 | ti_tm->tm_mday, |
||
386 | ti_tm->tm_hour, |
||
387 | ti_tm->tm_min, |
||
388 | ti_tm->tm_sec); |
||
389 | break; |
||
390 | |||
391 | case WTAP_TSPREC_DSEC: |
||
392 | g_snprintf(time_string_buf, sizeof time_string_buf, |
||
393 | "%04d-%02d-%02d %02d:%02d:%02d%s%01d", |
||
394 | ti_tm->tm_year + 1900, |
||
395 | ti_tm->tm_mon + 1, |
||
396 | ti_tm->tm_mday, |
||
397 | ti_tm->tm_hour, |
||
398 | ti_tm->tm_min, |
||
399 | ti_tm->tm_sec, |
||
400 | decimal_point, |
||
401 | timer->nsecs / 100000000); |
||
402 | break; |
||
403 | |||
404 | case WTAP_TSPREC_CSEC: |
||
405 | g_snprintf(time_string_buf, sizeof time_string_buf, |
||
406 | "%04d-%02d-%02d %02d:%02d:%02d%s%02d", |
||
407 | ti_tm->tm_year + 1900, |
||
408 | ti_tm->tm_mon + 1, |
||
409 | ti_tm->tm_mday, |
||
410 | ti_tm->tm_hour, |
||
411 | ti_tm->tm_min, |
||
412 | ti_tm->tm_sec, |
||
413 | decimal_point, |
||
414 | timer->nsecs / 10000000); |
||
415 | break; |
||
416 | |||
417 | case WTAP_TSPREC_MSEC: |
||
418 | g_snprintf(time_string_buf, sizeof time_string_buf, |
||
419 | "%04d-%02d-%02d %02d:%02d:%02d%s%03d", |
||
420 | ti_tm->tm_year + 1900, |
||
421 | ti_tm->tm_mon + 1, |
||
422 | ti_tm->tm_mday, |
||
423 | ti_tm->tm_hour, |
||
424 | ti_tm->tm_min, |
||
425 | ti_tm->tm_sec, |
||
426 | decimal_point, |
||
427 | timer->nsecs / 1000000); |
||
428 | break; |
||
429 | |||
430 | case WTAP_TSPREC_USEC: |
||
431 | g_snprintf(time_string_buf, sizeof time_string_buf, |
||
432 | "%04d-%02d-%02d %02d:%02d:%02d%s%06d", |
||
433 | ti_tm->tm_year + 1900, |
||
434 | ti_tm->tm_mon + 1, |
||
435 | ti_tm->tm_mday, |
||
436 | ti_tm->tm_hour, |
||
437 | ti_tm->tm_min, |
||
438 | ti_tm->tm_sec, |
||
439 | decimal_point, |
||
440 | timer->nsecs / 1000); |
||
441 | break; |
||
442 | |||
443 | case WTAP_TSPREC_NSEC: |
||
444 | g_snprintf(time_string_buf, sizeof time_string_buf, |
||
445 | "%04d-%02d-%02d %02d:%02d:%02d%s%09d", |
||
446 | ti_tm->tm_year + 1900, |
||
447 | ti_tm->tm_mon + 1, |
||
448 | ti_tm->tm_mday, |
||
449 | ti_tm->tm_hour, |
||
450 | ti_tm->tm_min, |
||
451 | ti_tm->tm_sec, |
||
452 | decimal_point, |
||
453 | timer->nsecs); |
||
454 | break; |
||
455 | |||
456 | default: |
||
457 | g_snprintf(time_string_buf, sizeof time_string_buf, |
||
458 | "Unknown precision %d", |
||
459 | tsprecision); |
||
460 | break; |
||
461 | } |
||
462 | return time_string_buf; |
||
463 | } |
||
464 | } |
||
465 | |||
466 | g_snprintf(time_string_buf, sizeof time_string_buf, "n/a"); |
||
467 | return time_string_buf; |
||
468 | } |
||
469 | |||
470 | static gchar * |
||
471 | relative_time_string(nstime_t *timer, int tsprecision, capture_info *cf_info, gboolean want_seconds) |
||
472 | { |
||
473 | const gchar *second = want_seconds ? " second" : ""; |
||
474 | const gchar *plural = want_seconds ? "s" : ""; |
||
475 | static gchar time_string_buf[4+1+2+1+2+1+2+1+2+1+2+1+1]; |
||
476 | |||
477 | if (cf_info->times_known && cf_info->packet_count > 0) { |
||
478 | switch (tsprecision) { |
||
479 | |||
480 | case WTAP_TSPREC_SEC: |
||
481 | g_snprintf(time_string_buf, sizeof time_string_buf, |
||
482 | "%lu%s%s", |
||
483 | (unsigned long)timer->secs, |
||
484 | second, |
||
485 | timer->secs == 1 ? "" : plural); |
||
486 | break; |
||
487 | |||
488 | case WTAP_TSPREC_DSEC: |
||
489 | g_snprintf(time_string_buf, sizeof time_string_buf, |
||
490 | "%lu%s%01d%s%s", |
||
491 | (unsigned long)timer->secs, |
||
492 | decimal_point, |
||
493 | timer->nsecs / 100000000, |
||
494 | second, |
||
495 | (timer->secs == 1 && timer->nsecs == 0) ? "" : plural); |
||
496 | break; |
||
497 | |||
498 | case WTAP_TSPREC_CSEC: |
||
499 | g_snprintf(time_string_buf, sizeof time_string_buf, |
||
500 | "%lu%s%02d%s%s", |
||
501 | (unsigned long)timer->secs, |
||
502 | decimal_point, |
||
503 | timer->nsecs / 10000000, |
||
504 | second, |
||
505 | (timer->secs == 1 && timer->nsecs == 0) ? "" : plural); |
||
506 | break; |
||
507 | |||
508 | case WTAP_TSPREC_MSEC: |
||
509 | g_snprintf(time_string_buf, sizeof time_string_buf, |
||
510 | "%lu%s%03d%s%s", |
||
511 | (unsigned long)timer->secs, |
||
512 | decimal_point, |
||
513 | timer->nsecs / 1000000, |
||
514 | second, |
||
515 | (timer->secs == 1 && timer->nsecs == 0) ? "" : plural); |
||
516 | break; |
||
517 | |||
518 | case WTAP_TSPREC_USEC: |
||
519 | g_snprintf(time_string_buf, sizeof time_string_buf, |
||
520 | "%lu%s%06d%s%s", |
||
521 | (unsigned long)timer->secs, |
||
522 | decimal_point, |
||
523 | timer->nsecs / 1000, |
||
524 | second, |
||
525 | (timer->secs == 1 && timer->nsecs == 0) ? "" : plural); |
||
526 | break; |
||
527 | |||
528 | case WTAP_TSPREC_NSEC: |
||
529 | g_snprintf(time_string_buf, sizeof time_string_buf, |
||
530 | "%lu%s%09d%s%s", |
||
531 | (unsigned long)timer->secs, |
||
532 | decimal_point, |
||
533 | timer->nsecs, |
||
534 | second, |
||
535 | (timer->secs == 1 && timer->nsecs == 0) ? "" : plural); |
||
536 | break; |
||
537 | |||
538 | default: |
||
539 | g_snprintf(time_string_buf, sizeof time_string_buf, |
||
540 | "Unknown precision %d", |
||
541 | tsprecision); |
||
542 | break; |
||
543 | } |
||
544 | return time_string_buf; |
||
545 | } |
||
546 | |||
547 | g_snprintf(time_string_buf, sizeof time_string_buf, "n/a"); |
||
548 | return time_string_buf; |
||
549 | } |
||
550 | |||
551 | static void print_value(const gchar *text_p1, gint width, const gchar *text_p2, double value) { |
||
552 | if (value > 0.0) |
||
553 | printf("%s%.*f%s\n", text_p1, width, value, text_p2); |
||
554 | else |
||
555 | printf("%sn/a\n", text_p1); |
||
556 | } |
||
557 | |||
558 | /* multi-line comments would conflict with the formatting that capinfos uses |
||
559 | we replace linefeeds with spaces */ |
||
560 | static void |
||
561 | string_replace_newlines(gchar *str) |
||
562 | { |
||
563 | gchar *p; |
||
564 | |||
565 | if (str) { |
||
566 | p = str; |
||
567 | while (*p != '\0') { |
||
568 | if (*p == '\n') |
||
569 | *p = ' '; |
||
570 | if (*p == '\r') |
||
571 | *p = ' '; |
||
572 | p++; |
||
573 | } |
||
574 | } |
||
575 | } |
||
576 | |||
577 | static void |
||
578 | show_option_string(const char *prefix, const char *option_str) |
||
579 | { |
||
580 | char *str; |
||
581 | |||
582 | if (option_str != NULL && option_str[0] != '\0') { |
||
583 | str = g_strdup(option_str); |
||
584 | string_replace_newlines(str); |
||
585 | printf("%s%s\n", prefix, str); |
||
586 | g_free(str); |
||
587 | } |
||
588 | } |
||
589 | |||
590 | static void |
||
591 | print_stats(const gchar *filename, capture_info *cf_info) |
||
592 | { |
||
593 | const gchar *file_type_string, *file_encap_string; |
||
594 | gchar *size_string; |
||
595 | |||
596 | /* Build printable strings for various stats */ |
||
597 | file_type_string = wtap_file_type_subtype_string(cf_info->file_type); |
||
598 | file_encap_string = wtap_encap_string(cf_info->file_encap); |
||
599 | |||
600 | if (filename) printf ("File name: %s\n", filename); |
||
601 | if (cap_file_type) printf ("File type: %s%s\n", |
||
602 | file_type_string, |
||
603 | cf_info->iscompressed ? " (gzip compressed)" : ""); |
||
604 | |||
605 | if (cap_file_encap) { |
||
606 | printf ("File encapsulation: %s\n", file_encap_string); |
||
607 | if (cf_info->file_encap == WTAP_ENCAP_PER_PACKET) { |
||
608 | int i; |
||
609 | printf ("Encapsulation in use by packets (# of pkts):\n"); |
||
610 | for (i=0; i<WTAP_NUM_ENCAP_TYPES; i++) { |
||
611 | if (cf_info->encap_counts[i] > 0) |
||
612 | printf(" %s (%d)\n", |
||
613 | wtap_encap_string(i), cf_info->encap_counts[i]); |
||
614 | } |
||
615 | } |
||
616 | } |
||
617 | if (cap_file_more_info) { |
||
618 | printf ("File timestamp precision: %s (%d)\n", |
||
619 | wtap_tsprec_string(cf_info->file_tsprec), cf_info->file_tsprec); |
||
620 | } |
||
621 | |||
622 | if (cap_snaplen && cf_info->snap_set) |
||
623 | printf ("Packet size limit: file hdr: %u bytes\n", cf_info->snaplen); |
||
624 | else if (cap_snaplen && !cf_info->snap_set) |
||
625 | printf ("Packet size limit: file hdr: (not set)\n"); |
||
626 | if (cf_info->snaplen_max_inferred > 0) { |
||
627 | if (cf_info->snaplen_min_inferred == cf_info->snaplen_max_inferred) |
||
628 | printf ("Packet size limit: inferred: %u bytes\n", cf_info->snaplen_min_inferred); |
||
629 | else |
||
630 | printf ("Packet size limit: inferred: %u bytes - %u bytes (range)\n", |
||
631 | cf_info->snaplen_min_inferred, cf_info->snaplen_max_inferred); |
||
632 | } |
||
633 | if (cap_packet_count) { |
||
634 | printf ("Number of packets: "); |
||
635 | if (machine_readable) { |
||
636 | printf ("%u\n", cf_info->packet_count); |
||
637 | } else { |
||
638 | size_string = format_size(cf_info->packet_count, format_size_unit_none); |
||
639 | printf ("%s\n", size_string); |
||
640 | g_free(size_string); |
||
641 | } |
||
642 | } |
||
643 | if (cap_file_size) { |
||
644 | printf ("File size: "); |
||
645 | if (machine_readable) { |
||
646 | printf ("%" G_GINT64_MODIFIER "d bytes\n", cf_info->filesize); |
||
647 | } else { |
||
648 | size_string = format_size(cf_info->filesize, format_size_unit_bytes); |
||
649 | printf ("%s\n", size_string); |
||
650 | g_free(size_string); |
||
651 | } |
||
652 | } |
||
653 | if (cap_data_size) { |
||
654 | printf ("Data size: "); |
||
655 | if (machine_readable) { |
||
656 | printf ("%" G_GINT64_MODIFIER "u bytes\n", cf_info->packet_bytes); |
||
657 | } else { |
||
658 | size_string = format_size(cf_info->packet_bytes, format_size_unit_bytes); |
||
659 | printf ("%s\n", size_string); |
||
660 | g_free(size_string); |
||
661 | } |
||
662 | } |
||
663 | if (cf_info->times_known) { |
||
664 | if (cap_duration) /* XXX - shorten to hh:mm:ss */ |
||
665 | printf("Capture duration: %s\n", relative_time_string(&cf_info->duration, cf_info->duration_tsprec, cf_info, TRUE)); |
||
666 | if (cap_start_time) |
||
667 | printf("First packet time: %s\n", absolute_time_string(&cf_info->start_time, cf_info->start_time_tsprec, cf_info)); |
||
668 | if (cap_end_time) |
||
669 | printf("Last packet time: %s\n", absolute_time_string(&cf_info->stop_time, cf_info->stop_time_tsprec, cf_info)); |
||
670 | if (cap_data_rate_byte) { |
||
671 | printf("Data byte rate: "); |
||
672 | if (machine_readable) { |
||
673 | print_value("", 2, " bytes/sec", cf_info->data_rate); |
||
674 | } else { |
||
675 | size_string = format_size((gint64)cf_info->data_rate, format_size_unit_bytes_s); |
||
676 | printf ("%s\n", size_string); |
||
677 | g_free(size_string); |
||
678 | } |
||
679 | } |
||
680 | if (cap_data_rate_bit) { |
||
681 | printf("Data bit rate: "); |
||
682 | if (machine_readable) { |
||
683 | print_value("", 2, " bits/sec", cf_info->data_rate*8); |
||
684 | } else { |
||
685 | size_string = format_size((gint64)(cf_info->data_rate*8), format_size_unit_bits_s); |
||
686 | printf ("%s\n", size_string); |
||
687 | g_free(size_string); |
||
688 | } |
||
689 | } |
||
690 | } |
||
691 | if (cap_packet_size) printf("Average packet size: %.2f bytes\n", cf_info->packet_size); |
||
692 | if (cf_info->times_known) { |
||
693 | if (cap_packet_rate) { |
||
694 | printf("Average packet rate: "); |
||
695 | if (machine_readable) { |
||
696 | print_value("", 2, " packets/sec", cf_info->packet_rate); |
||
697 | } else { |
||
698 | size_string = format_size((gint64)cf_info->packet_rate, format_size_unit_packets_s); |
||
699 | printf ("%s\n", size_string); |
||
700 | g_free(size_string); |
||
701 | } |
||
702 | } |
||
703 | } |
||
704 | #ifdef HAVE_LIBGCRYPT |
||
705 | if (cap_file_hashes) { |
||
706 | printf ("SHA1: %s\n", file_sha1); |
||
707 | printf ("RIPEMD160: %s\n", file_rmd160); |
||
708 | printf ("MD5: %s\n", file_md5); |
||
709 | } |
||
710 | #endif /* HAVE_LIBGCRYPT */ |
||
711 | if (cap_order) printf ("Strict time order: %s\n", order_string(cf_info->order)); |
||
712 | |||
713 | if (cf_info->shb != NULL) { |
||
714 | if (cap_comment) { |
||
715 | unsigned int i; |
||
716 | char *str; |
||
717 | |||
718 | for (i = 0; wtap_block_get_nth_string_option_value(cf_info->shb, OPT_COMMENT, i, &str) == WTAP_OPTTYPE_SUCCESS; i++) { |
||
719 | show_option_string("Capture comment: ", str); |
||
720 | } |
||
721 | } |
||
722 | if (cap_file_more_info) { |
||
723 | char *str; |
||
724 | |||
725 | if (wtap_block_get_string_option_value(cf_info->shb, OPT_SHB_HARDWARE, &str) == WTAP_OPTTYPE_SUCCESS) |
||
726 | show_option_string("Capture hardware: ", str); |
||
727 | if (wtap_block_get_string_option_value(cf_info->shb, OPT_SHB_OS, &str) == WTAP_OPTTYPE_SUCCESS) |
||
728 | show_option_string("Capture oper-sys: ", str); |
||
729 | if (wtap_block_get_string_option_value(cf_info->shb, OPT_SHB_USERAPPL, &str) == WTAP_OPTTYPE_SUCCESS) |
||
730 | show_option_string("Capture application: ", str); |
||
731 | } |
||
732 | |||
733 | if (cap_file_idb && cf_info->num_interfaces != 0) { |
||
734 | guint i; |
||
735 | g_assert(cf_info->num_interfaces == cf_info->idb_info_strings->len); |
||
736 | printf ("Number of interfaces in file: %u\n", cf_info->num_interfaces); |
||
737 | for (i = 0; i < cf_info->idb_info_strings->len; i++) { |
||
738 | gchar *s = g_array_index(cf_info->idb_info_strings, gchar*, i); |
||
739 | guint32 packet_count = 0; |
||
740 | if (i < cf_info->interface_packet_counts->len) |
||
741 | packet_count = g_array_index(cf_info->interface_packet_counts, guint32, i); |
||
742 | printf ("Interface #%u info:\n", i); |
||
743 | printf ("%s", s); |
||
744 | printf (" Number of packets = %u\n", packet_count); |
||
745 | } |
||
746 | } |
||
747 | } |
||
748 | } |
||
749 | |||
750 | static void |
||
751 | putsep(void) |
||
752 | { |
||
753 | if (field_separator) putchar(field_separator); |
||
754 | } |
||
755 | |||
756 | static void |
||
757 | putquote(void) |
||
758 | { |
||
759 | if (quote_char) putchar(quote_char); |
||
760 | } |
||
761 | |||
762 | static void |
||
763 | print_stats_table_header_label(const gchar *label) |
||
764 | { |
||
765 | putsep(); |
||
766 | putquote(); |
||
767 | printf("%s", label); |
||
768 | putquote(); |
||
769 | } |
||
770 | |||
771 | static void |
||
772 | print_stats_table_header(void) |
||
773 | { |
||
774 | putquote(); |
||
775 | printf("File name"); |
||
776 | putquote(); |
||
777 | |||
778 | if (cap_file_type) print_stats_table_header_label("File type"); |
||
779 | if (cap_file_encap) print_stats_table_header_label("File encapsulation"); |
||
780 | if (cap_file_more_info) print_stats_table_header_label("File time precision"); |
||
781 | if (cap_snaplen) print_stats_table_header_label("Packet size limit"); |
||
782 | if (cap_snaplen) print_stats_table_header_label("Packet size limit min (inferred)"); |
||
783 | if (cap_snaplen) print_stats_table_header_label("Packet size limit max (inferred)"); |
||
784 | if (cap_packet_count) print_stats_table_header_label("Number of packets"); |
||
785 | if (cap_file_size) print_stats_table_header_label("File size (bytes)"); |
||
786 | if (cap_data_size) print_stats_table_header_label("Data size (bytes)"); |
||
787 | if (cap_duration) print_stats_table_header_label("Capture duration (seconds)"); |
||
788 | if (cap_start_time) print_stats_table_header_label("Start time"); |
||
789 | if (cap_end_time) print_stats_table_header_label("End time"); |
||
790 | if (cap_data_rate_byte) print_stats_table_header_label("Data byte rate (bytes/sec)"); |
||
791 | if (cap_data_rate_bit) print_stats_table_header_label("Data bit rate (bits/sec)"); |
||
792 | if (cap_packet_size) print_stats_table_header_label("Average packet size (bytes)"); |
||
793 | if (cap_packet_rate) print_stats_table_header_label("Average packet rate (packets/sec)"); |
||
794 | #ifdef HAVE_LIBGCRYPT |
||
795 | if (cap_file_hashes) { |
||
796 | print_stats_table_header_label("SHA1"); |
||
797 | print_stats_table_header_label("RIPEMD160"); |
||
798 | print_stats_table_header_label("MD5"); |
||
799 | } |
||
800 | #endif /* HAVE_LIBGCRYPT */ |
||
801 | if (cap_order) print_stats_table_header_label("Strict time order"); |
||
802 | if (cap_comment) print_stats_table_header_label("Capture comment"); |
||
803 | if (cap_file_more_info) { |
||
804 | print_stats_table_header_label("Capture hardware"); |
||
805 | print_stats_table_header_label("Capture oper-sys"); |
||
806 | print_stats_table_header_label("Capture application"); |
||
807 | } |
||
808 | |||
809 | printf("\n"); |
||
810 | } |
||
811 | |||
812 | static void |
||
813 | print_stats_table(const gchar *filename, capture_info *cf_info) |
||
814 | { |
||
815 | const gchar *file_type_string, *file_encap_string; |
||
816 | |||
817 | /* Build printable strings for various stats */ |
||
818 | file_type_string = wtap_file_type_subtype_string(cf_info->file_type); |
||
819 | file_encap_string = wtap_encap_string(cf_info->file_encap); |
||
820 | |||
821 | if (filename) { |
||
822 | putquote(); |
||
823 | printf("%s", filename); |
||
824 | putquote(); |
||
825 | } |
||
826 | |||
827 | if (cap_file_type) { |
||
828 | putsep(); |
||
829 | putquote(); |
||
830 | printf("%s", file_type_string); |
||
831 | putquote(); |
||
832 | } |
||
833 | |||
834 | /* ToDo: If WTAP_ENCAP_PER_PACKET, show the list of encapsulations encountered; |
||
835 | * Output a line for each different encap with all fields repeated except |
||
836 | * the encapsulation field which has "Per Packet: ..." for each |
||
837 | * encapsulation type seen ? |
||
838 | */ |
||
839 | if (cap_file_encap) { |
||
840 | putsep(); |
||
841 | putquote(); |
||
842 | printf("%s", file_encap_string); |
||
843 | putquote(); |
||
844 | } |
||
845 | |||
846 | if (cap_file_more_info) { |
||
847 | putsep(); |
||
848 | putquote(); |
||
849 | printf("%s", wtap_tsprec_string(cf_info->file_tsprec)); |
||
850 | putquote(); |
||
851 | } |
||
852 | |||
853 | if (cap_snaplen) { |
||
854 | putsep(); |
||
855 | putquote(); |
||
856 | if (cf_info->snap_set) |
||
857 | printf("%u", cf_info->snaplen); |
||
858 | else |
||
859 | printf("(not set)"); |
||
860 | putquote(); |
||
861 | if (cf_info->snaplen_max_inferred > 0) { |
||
862 | putsep(); |
||
863 | putquote(); |
||
864 | printf("%u", cf_info->snaplen_min_inferred); |
||
865 | putquote(); |
||
866 | putsep(); |
||
867 | putquote(); |
||
868 | printf("%u", cf_info->snaplen_max_inferred); |
||
869 | putquote(); |
||
870 | } |
||
871 | else { |
||
872 | putsep(); |
||
873 | putquote(); |
||
874 | printf("n/a"); |
||
875 | putquote(); |
||
876 | putsep(); |
||
877 | putquote(); |
||
878 | printf("n/a"); |
||
879 | putquote(); |
||
880 | } |
||
881 | } |
||
882 | |||
883 | if (cap_packet_count) { |
||
884 | putsep(); |
||
885 | putquote(); |
||
886 | printf("%u", cf_info->packet_count); |
||
887 | putquote(); |
||
888 | } |
||
889 | |||
890 | if (cap_file_size) { |
||
891 | putsep(); |
||
892 | putquote(); |
||
893 | printf("%" G_GINT64_MODIFIER "d", cf_info->filesize); |
||
894 | putquote(); |
||
895 | } |
||
896 | |||
897 | if (cap_data_size) { |
||
898 | putsep(); |
||
899 | putquote(); |
||
900 | printf("%" G_GINT64_MODIFIER "u", cf_info->packet_bytes); |
||
901 | putquote(); |
||
902 | } |
||
903 | |||
904 | if (cap_duration) { |
||
905 | putsep(); |
||
906 | putquote(); |
||
907 | printf("%s", relative_time_string(&cf_info->duration, cf_info->duration_tsprec, cf_info, FALSE)); |
||
908 | putquote(); |
||
909 | } |
||
910 | |||
911 | if (cap_start_time) { |
||
912 | putsep(); |
||
913 | putquote(); |
||
914 | printf("%s", absolute_time_string(&cf_info->start_time, cf_info->start_time_tsprec, cf_info)); |
||
915 | putquote(); |
||
916 | } |
||
917 | |||
918 | if (cap_end_time) { |
||
919 | putsep(); |
||
920 | putquote(); |
||
921 | printf("%s", absolute_time_string(&cf_info->stop_time, cf_info->stop_time_tsprec, cf_info)); |
||
922 | putquote(); |
||
923 | } |
||
924 | |||
925 | if (cap_data_rate_byte) { |
||
926 | putsep(); |
||
927 | putquote(); |
||
928 | if (cf_info->times_known) |
||
929 | printf("%.2f", cf_info->data_rate); |
||
930 | else |
||
931 | printf("n/a"); |
||
932 | putquote(); |
||
933 | } |
||
934 | |||
935 | if (cap_data_rate_bit) { |
||
936 | putsep(); |
||
937 | putquote(); |
||
938 | if (cf_info->times_known) |
||
939 | printf("%.2f", cf_info->data_rate*8); |
||
940 | else |
||
941 | printf("n/a"); |
||
942 | putquote(); |
||
943 | } |
||
944 | |||
945 | if (cap_packet_size) { |
||
946 | putsep(); |
||
947 | putquote(); |
||
948 | printf("%.2f", cf_info->packet_size); |
||
949 | putquote(); |
||
950 | } |
||
951 | |||
952 | if (cap_packet_rate) { |
||
953 | putsep(); |
||
954 | putquote(); |
||
955 | if (cf_info->times_known) |
||
956 | printf("%.2f", cf_info->packet_rate); |
||
957 | else |
||
958 | printf("n/a"); |
||
959 | putquote(); |
||
960 | } |
||
961 | |||
962 | #ifdef HAVE_LIBGCRYPT |
||
963 | if (cap_file_hashes) { |
||
964 | putsep(); |
||
965 | putquote(); |
||
966 | printf("%s", file_sha1); |
||
967 | putquote(); |
||
968 | |||
969 | putsep(); |
||
970 | putquote(); |
||
971 | printf("%s", file_rmd160); |
||
972 | putquote(); |
||
973 | |||
974 | putsep(); |
||
975 | putquote(); |
||
976 | printf("%s", file_md5); |
||
977 | putquote(); |
||
978 | } |
||
979 | #endif /* HAVE_LIBGCRYPT */ |
||
980 | |||
981 | if (cap_order) { |
||
982 | putsep(); |
||
983 | putquote(); |
||
984 | printf("%s", order_string(cf_info->order)); |
||
985 | putquote(); |
||
986 | } |
||
987 | |||
988 | if (cf_info->shb != NULL) { |
||
989 | /* |
||
990 | * this is silly to put into a table format, but oh well |
||
991 | * note that there may be *more than one* of each of these types |
||
992 | * of options |
||
993 | */ |
||
994 | if (cap_comment) { |
||
995 | unsigned int i; |
||
996 | char *opt_comment; |
||
997 | |||
998 | for (i = 0; wtap_block_get_nth_string_option_value(cf_info->shb, OPT_COMMENT, i, &opt_comment) == WTAP_OPTTYPE_SUCCESS; i++) { |
||
999 | putsep(); |
||
1000 | putquote(); |
||
1001 | printf("%s", opt_comment); |
||
1002 | putquote(); |
||
1003 | } |
||
1004 | } |
||
1005 | |||
1006 | if (cap_file_more_info) { |
||
1007 | char *str; |
||
1008 | |||
1009 | if (wtap_block_get_string_option_value(cf_info->shb, OPT_SHB_HARDWARE, &str) == WTAP_OPTTYPE_SUCCESS) { |
||
1010 | putsep(); |
||
1011 | putquote(); |
||
1012 | printf("%s", str); |
||
1013 | putquote(); |
||
1014 | } |
||
1015 | if (wtap_block_get_string_option_value(cf_info->shb, OPT_SHB_OS, &str) == WTAP_OPTTYPE_SUCCESS) { |
||
1016 | putsep(); |
||
1017 | putquote(); |
||
1018 | printf("%s", str); |
||
1019 | putquote(); |
||
1020 | } |
||
1021 | if (wtap_block_get_string_option_value(cf_info->shb, OPT_SHB_USERAPPL, &str) == WTAP_OPTTYPE_SUCCESS) { |
||
1022 | putsep(); |
||
1023 | putquote(); |
||
1024 | printf("%s", str); |
||
1025 | putquote(); |
||
1026 | } |
||
1027 | } |
||
1028 | } |
||
1029 | |||
1030 | printf("\n"); |
||
1031 | } |
||
1032 | |||
1033 | static void |
||
1034 | cleanup_capture_info(capture_info *cf_info) |
||
1035 | { |
||
1036 | guint i; |
||
1037 | g_assert(cf_info != NULL); |
||
1038 | |||
1039 | g_free(cf_info->encap_counts); |
||
1040 | cf_info->encap_counts = NULL; |
||
1041 | |||
1042 | g_array_free(cf_info->interface_packet_counts, TRUE); |
||
1043 | cf_info->interface_packet_counts = NULL; |
||
1044 | |||
1045 | if (cf_info->idb_info_strings) { |
||
1046 | for (i = 0; i < cf_info->idb_info_strings->len; i++) { |
||
1047 | gchar *s = g_array_index(cf_info->idb_info_strings, gchar*, i); |
||
1048 | g_free(s); |
||
1049 | } |
||
1050 | g_array_free(cf_info->idb_info_strings, TRUE); |
||
1051 | } |
||
1052 | cf_info->idb_info_strings = NULL; |
||
1053 | } |
||
1054 | |||
1055 | static int |
||
1056 | process_cap_file(wtap *wth, const char *filename) |
||
1057 | { |
||
1058 | int status = 0; |
||
1059 | int err; |
||
1060 | gchar *err_info; |
||
1061 | gint64 size; |
||
1062 | gint64 data_offset; |
||
1063 | |||
1064 | guint32 packet = 0; |
||
1065 | gint64 bytes = 0; |
||
1066 | guint32 snaplen_min_inferred = 0xffffffff; |
||
1067 | guint32 snaplen_max_inferred = 0; |
||
1068 | const struct wtap_pkthdr *phdr; |
||
1069 | capture_info cf_info; |
||
1070 | gboolean have_times = TRUE; |
||
1071 | nstime_t start_time; |
||
1072 | int start_time_tsprec; |
||
1073 | nstime_t stop_time; |
||
1074 | int stop_time_tsprec; |
||
1075 | nstime_t cur_time; |
||
1076 | nstime_t prev_time; |
||
1077 | gboolean know_order = FALSE; |
||
1078 | order_t order = IN_ORDER; |
||
1079 | guint i; |
||
1080 | wtapng_iface_descriptions_t *idb_info; |
||
1081 | |||
1082 | g_assert(wth != NULL); |
||
1083 | g_assert(filename != NULL); |
||
1084 | |||
1085 | nstime_set_zero(&start_time); |
||
1086 | start_time_tsprec = WTAP_TSPREC_UNKNOWN; |
||
1087 | nstime_set_zero(&stop_time); |
||
1088 | stop_time_tsprec = WTAP_TSPREC_UNKNOWN; |
||
1089 | nstime_set_zero(&cur_time); |
||
1090 | nstime_set_zero(&prev_time); |
||
1091 | |||
1092 | cf_info.shb = wtap_file_get_shb(wth); |
||
1093 | |||
1094 | cf_info.encap_counts = g_new0(int,WTAP_NUM_ENCAP_TYPES); |
||
1095 | |||
1096 | idb_info = wtap_file_get_idb_info(wth); |
||
1097 | |||
1098 | g_assert(idb_info->interface_data != NULL); |
||
1099 | |||
1100 | cf_info.num_interfaces = idb_info->interface_data->len; |
||
1101 | cf_info.interface_packet_counts = g_array_sized_new(FALSE, TRUE, sizeof(guint32), cf_info.num_interfaces); |
||
1102 | g_array_set_size(cf_info.interface_packet_counts, cf_info.num_interfaces); |
||
1103 | cf_info.pkt_interface_id_unknown = 0; |
||
1104 | |||
1105 | g_free(idb_info); |
||
1106 | idb_info = NULL; |
||
1107 | |||
1108 | /* Tally up data that we need to parse through the file to find */ |
||
1109 | while (wtap_read(wth, &err, &err_info, &data_offset)) { |
||
1110 | phdr = wtap_phdr(wth); |
||
1111 | if (phdr->presence_flags & WTAP_HAS_TS) { |
||
1112 | prev_time = cur_time; |
||
1113 | cur_time = phdr->ts; |
||
1114 | if (packet == 0) { |
||
1115 | start_time = phdr->ts; |
||
1116 | start_time_tsprec = phdr->pkt_tsprec; |
||
1117 | stop_time = phdr->ts; |
||
1118 | stop_time_tsprec = phdr->pkt_tsprec; |
||
1119 | prev_time = phdr->ts; |
||
1120 | } |
||
1121 | if (nstime_cmp(&cur_time, &prev_time) < 0) { |
||
1122 | order = NOT_IN_ORDER; |
||
1123 | } |
||
1124 | if (nstime_cmp(&cur_time, &start_time) < 0) { |
||
1125 | start_time = cur_time; |
||
1126 | start_time_tsprec = phdr->pkt_tsprec; |
||
1127 | } |
||
1128 | if (nstime_cmp(&cur_time, &stop_time) > 0) { |
||
1129 | stop_time = cur_time; |
||
1130 | stop_time_tsprec = phdr->pkt_tsprec; |
||
1131 | } |
||
1132 | } else { |
||
1133 | have_times = FALSE; /* at least one packet has no time stamp */ |
||
1134 | if (order != NOT_IN_ORDER) |
||
1135 | order = ORDER_UNKNOWN; |
||
1136 | } |
||
1137 | |||
1138 | if (phdr->rec_type == REC_TYPE_PACKET) { |
||
1139 | bytes+=phdr->len; |
||
1140 | packet++; |
||
1141 | |||
1142 | /* If caplen < len for a rcd, then presumably */ |
||
1143 | /* 'Limit packet capture length' was done for this rcd. */ |
||
1144 | /* Keep track as to the min/max actual snapshot lengths */ |
||
1145 | /* seen for this file. */ |
||
1146 | if (phdr->caplen < phdr->len) { |
||
1147 | if (phdr->caplen < snaplen_min_inferred) |
||
1148 | snaplen_min_inferred = phdr->caplen; |
||
1149 | if (phdr->caplen > snaplen_max_inferred) |
||
1150 | snaplen_max_inferred = phdr->caplen; |
||
1151 | } |
||
1152 | |||
1153 | if ((phdr->pkt_encap > 0) && (phdr->pkt_encap < WTAP_NUM_ENCAP_TYPES)) { |
||
1154 | cf_info.encap_counts[phdr->pkt_encap] += 1; |
||
1155 | } else { |
||
1156 | fprintf(stderr, "capinfos: Unknown packet encapsulation %d in frame %u of file \"%s\"\n", |
||
1157 | phdr->pkt_encap, packet, filename); |
||
1158 | } |
||
1159 | |||
1160 | /* Packet interface_id info */ |
||
1161 | if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID) { |
||
1162 | /* cf_info.num_interfaces is size, not index, so it's one more than max index */ |
||
1163 | if (phdr->interface_id >= cf_info.num_interfaces) { |
||
1164 | /* |
||
1165 | * OK, re-fetch the number of interfaces, as there might have |
||
1166 | * been an interface that was in the middle of packets, and |
||
1167 | * grow the array to be big enough for the new number of |
||
1168 | * interfaces. |
||
1169 | */ |
||
1170 | idb_info = wtap_file_get_idb_info(wth); |
||
1171 | |||
1172 | cf_info.num_interfaces = idb_info->interface_data->len; |
||
1173 | g_array_set_size(cf_info.interface_packet_counts, cf_info.num_interfaces); |
||
1174 | |||
1175 | g_free(idb_info); |
||
1176 | idb_info = NULL; |
||
1177 | } |
||
1178 | if (phdr->interface_id < cf_info.num_interfaces) { |
||
1179 | g_array_index(cf_info.interface_packet_counts, guint32, phdr->interface_id) += 1; |
||
1180 | } |
||
1181 | else { |
||
1182 | cf_info.pkt_interface_id_unknown += 1; |
||
1183 | } |
||
1184 | } |
||
1185 | else { |
||
1186 | /* it's for interface_id 0 */ |
||
1187 | if (cf_info.num_interfaces != 0) { |
||
1188 | g_array_index(cf_info.interface_packet_counts, guint32, 0) += 1; |
||
1189 | } |
||
1190 | else { |
||
1191 | cf_info.pkt_interface_id_unknown += 1; |
||
1192 | } |
||
1193 | } |
||
1194 | } |
||
1195 | |||
1196 | } /* while */ |
||
1197 | |||
1198 | /* |
||
1199 | * Get IDB info strings. |
||
1200 | * We do this at the end, so we can get information for all IDBs in |
||
1201 | * the file, even those that come after packet records. |
||
1202 | */ |
||
1203 | idb_info = wtap_file_get_idb_info(wth); |
||
1204 | |||
1205 | cf_info.idb_info_strings = g_array_sized_new(FALSE, FALSE, sizeof(gchar*), cf_info.num_interfaces); |
||
1206 | cf_info.num_interfaces = idb_info->interface_data->len; |
||
1207 | for (i = 0; i < cf_info.num_interfaces; i++) { |
||
1208 | const wtap_block_t if_descr = g_array_index(idb_info->interface_data, wtap_block_t, i); |
||
1209 | gchar *s = wtap_get_debug_if_descr(if_descr, 21, "\n"); |
||
1210 | g_array_append_val(cf_info.idb_info_strings, s); |
||
1211 | } |
||
1212 | |||
1213 | g_free(idb_info); |
||
1214 | idb_info = NULL; |
||
1215 | |||
1216 | if (err != 0) { |
||
1217 | fprintf(stderr, |
||
1218 | "capinfos: An error occurred after reading %u packets from \"%s\": %s.\n", |
||
1219 | packet, filename, wtap_strerror(err)); |
||
1220 | if (err == WTAP_ERR_SHORT_READ) { |
||
1221 | /* Don't give up completely with this one. */ |
||
1222 | status = 1; |
||
1223 | fprintf(stderr, |
||
1224 | " (will continue anyway, checksums might be incorrect)\n"); |
||
1225 | } else { |
||
1226 | if (err_info != NULL) { |
||
1227 | fprintf(stderr, "(%s)\n", err_info); |
||
1228 | g_free(err_info); |
||
1229 | } |
||
1230 | |||
1231 | cleanup_capture_info(&cf_info); |
||
1232 | return 1; |
||
1233 | } |
||
1234 | } |
||
1235 | |||
1236 | /* File size */ |
||
1237 | size = wtap_file_size(wth, &err); |
||
1238 | if (size == -1) { |
||
1239 | fprintf(stderr, |
||
1240 | "capinfos: Can't get size of \"%s\": %s.\n", |
||
1241 | filename, g_strerror(err)); |
||
1242 | cleanup_capture_info(&cf_info); |
||
1243 | return 1; |
||
1244 | } |
||
1245 | |||
1246 | cf_info.filesize = size; |
||
1247 | |||
1248 | /* File Type */ |
||
1249 | cf_info.file_type = wtap_file_type_subtype(wth); |
||
1250 | cf_info.iscompressed = wtap_iscompressed(wth); |
||
1251 | |||
1252 | /* File Encapsulation */ |
||
1253 | cf_info.file_encap = wtap_file_encap(wth); |
||
1254 | |||
1255 | cf_info.file_tsprec = wtap_file_tsprec(wth); |
||
1256 | |||
1257 | /* Packet size limit (snaplen) */ |
||
1258 | cf_info.snaplen = wtap_snapshot_length(wth); |
||
1259 | if (cf_info.snaplen > 0) |
||
1260 | cf_info.snap_set = TRUE; |
||
1261 | else |
||
1262 | cf_info.snap_set = FALSE; |
||
1263 | |||
1264 | cf_info.snaplen_min_inferred = snaplen_min_inferred; |
||
1265 | cf_info.snaplen_max_inferred = snaplen_max_inferred; |
||
1266 | |||
1267 | /* # of packets */ |
||
1268 | cf_info.packet_count = packet; |
||
1269 | |||
1270 | /* File Times */ |
||
1271 | cf_info.times_known = have_times; |
||
1272 | cf_info.start_time = start_time; |
||
1273 | cf_info.start_time_tsprec = start_time_tsprec; |
||
1274 | cf_info.stop_time = stop_time; |
||
1275 | cf_info.stop_time_tsprec = stop_time_tsprec; |
||
1276 | nstime_delta(&cf_info.duration, &stop_time, &start_time); |
||
1277 | /* Duration precision is the higher of the start and stop time precisions. */ |
||
1278 | if (cf_info.stop_time_tsprec > cf_info.start_time_tsprec) |
||
1279 | cf_info.duration_tsprec = cf_info.stop_time_tsprec; |
||
1280 | else |
||
1281 | cf_info.duration_tsprec = cf_info.start_time_tsprec; |
||
1282 | cf_info.know_order = know_order; |
||
1283 | cf_info.order = order; |
||
1284 | |||
1285 | /* Number of packet bytes */ |
||
1286 | cf_info.packet_bytes = bytes; |
||
1287 | |||
1288 | cf_info.data_rate = 0.0; |
||
1289 | cf_info.packet_rate = 0.0; |
||
1290 | cf_info.packet_size = 0.0; |
||
1291 | |||
1292 | if (packet > 0) { |
||
1293 | double delta_time = nstime_to_sec(&stop_time) - nstime_to_sec(&start_time); |
||
1294 | if (delta_time > 0.0) { |
||
1295 | cf_info.data_rate = (double)bytes / delta_time; /* Data rate per second */ |
||
1296 | cf_info.packet_rate = (double)packet / delta_time; /* packet rate per second */ |
||
1297 | } |
||
1298 | cf_info.packet_size = (double)bytes / packet; /* Avg packet size */ |
||
1299 | } |
||
1300 | |||
1301 | if (long_report) { |
||
1302 | print_stats(filename, &cf_info); |
||
1303 | } else { |
||
1304 | print_stats_table(filename, &cf_info); |
||
1305 | } |
||
1306 | |||
1307 | cleanup_capture_info(&cf_info); |
||
1308 | |||
1309 | return status; |
||
1310 | } |
||
1311 | |||
1312 | static void |
||
1313 | print_usage(FILE *output) |
||
1314 | { |
||
1315 | fprintf(output, "\n"); |
||
1316 | fprintf(output, "Usage: capinfos [options] <infile> ...\n"); |
||
1317 | fprintf(output, "\n"); |
||
1318 | fprintf(output, "General infos:\n"); |
||
1319 | fprintf(output, " -t display the capture file type\n"); |
||
1320 | fprintf(output, " -E display the capture file encapsulation\n"); |
||
1321 | fprintf(output, " -I display the capture file interface information\n"); |
||
1322 | fprintf(output, " -F display additional capture file information\n"); |
||
1323 | #ifdef HAVE_LIBGCRYPT |
||
1324 | fprintf(output, " -H display the SHA1, RMD160, and MD5 hashes of the file\n"); |
||
1325 | #endif |
||
1326 | fprintf(output, " -k display the capture comment\n"); |
||
1327 | fprintf(output, "\n"); |
||
1328 | fprintf(output, "Size infos:\n"); |
||
1329 | fprintf(output, " -c display the number of packets\n"); |
||
1330 | fprintf(output, " -s display the size of the file (in bytes)\n"); |
||
1331 | fprintf(output, " -d display the total length of all packets (in bytes)\n"); |
||
1332 | fprintf(output, " -l display the packet size limit (snapshot length)\n"); |
||
1333 | fprintf(output, "\n"); |
||
1334 | fprintf(output, "Time infos:\n"); |
||
1335 | fprintf(output, " -u display the capture duration (in seconds)\n"); |
||
1336 | fprintf(output, " -a display the capture start time\n"); |
||
1337 | fprintf(output, " -e display the capture end time\n"); |
||
1338 | fprintf(output, " -o display the capture file chronological status (True/False)\n"); |
||
1339 | fprintf(output, " -S display start and end times as seconds\n"); |
||
1340 | fprintf(output, "\n"); |
||
1341 | fprintf(output, "Statistic infos:\n"); |
||
1342 | fprintf(output, " -y display average data rate (in bytes/sec)\n"); |
||
1343 | fprintf(output, " -i display average data rate (in bits/sec)\n"); |
||
1344 | fprintf(output, " -z display average packet size (in bytes)\n"); |
||
1345 | fprintf(output, " -x display average packet rate (in packets/sec)\n"); |
||
1346 | fprintf(output, "\n"); |
||
1347 | fprintf(output, "Output format:\n"); |
||
1348 | fprintf(output, " -L generate long report (default)\n"); |
||
1349 | fprintf(output, " -T generate table report\n"); |
||
1350 | fprintf(output, " -M display machine-readable values in long reports\n"); |
||
1351 | fprintf(output, "\n"); |
||
1352 | fprintf(output, "Table report options:\n"); |
||
1353 | fprintf(output, " -R generate header record (default)\n"); |
||
1354 | fprintf(output, " -r do not generate header record\n"); |
||
1355 | fprintf(output, "\n"); |
||
1356 | fprintf(output, " -B separate infos with TAB character (default)\n"); |
||
1357 | fprintf(output, " -m separate infos with comma (,) character\n"); |
||
1358 | fprintf(output, " -b separate infos with SPACE character\n"); |
||
1359 | fprintf(output, "\n"); |
||
1360 | fprintf(output, " -N do not quote infos (default)\n"); |
||
1361 | fprintf(output, " -q quote infos with single quotes (')\n"); |
||
1362 | fprintf(output, " -Q quote infos with double quotes (\")\n"); |
||
1363 | fprintf(output, "\n"); |
||
1364 | fprintf(output, "Miscellaneous:\n"); |
||
1365 | fprintf(output, " -h display this help and exit\n"); |
||
1366 | fprintf(output, " -C cancel processing if file open fails (default is to continue)\n"); |
||
1367 | fprintf(output, " -A generate all infos (default)\n"); |
||
1368 | fprintf(output, "\n"); |
||
1369 | fprintf(output, "Options are processed from left to right order with later options superceding\n"); |
||
1370 | fprintf(output, "or adding to earlier options.\n"); |
||
1371 | fprintf(output, "\n"); |
||
1372 | fprintf(output, "If no options are given the default is to display all infos in long report\n"); |
||
1373 | fprintf(output, "output format.\n"); |
||
1374 | #ifndef HAVE_LIBGCRYPT |
||
1375 | fprintf(output, "\nFile hashing support (-H) is not present.\n"); |
||
1376 | #endif |
||
1377 | } |
||
1378 | |||
1379 | #ifdef HAVE_PLUGINS |
||
1380 | /* |
||
1381 | * Don't report failures to load plugins because most (non-wiretap) plugins |
||
1382 | * *should* fail to load (because we're not linked against libwireshark and |
||
1383 | * dissector plugins need libwireshark). |
||
1384 | */ |
||
1385 | static void |
||
1386 | failure_message(const char *msg_format _U_, va_list ap _U_) |
||
1387 | { |
||
1388 | return; |
||
1389 | } |
||
1390 | #endif |
||
1391 | |||
1392 | #ifdef HAVE_LIBGCRYPT |
||
1393 | static void |
||
1394 | hash_to_str(const unsigned char *hash, size_t length, char *str) { |
||
1395 | int i; |
||
1396 | |||
1397 | for (i = 0; i < (int) length; i++) { |
||
1398 | g_snprintf(str+(i*2), 3, "%02x", hash[i]); |
||
1399 | } |
||
1400 | } |
||
1401 | #endif /* HAVE_LIBGCRYPT */ |
||
1402 | |||
1403 | int |
||
1404 | main(int argc, char *argv[]) |
||
1405 | { |
||
1406 | GString *comp_info_str; |
||
1407 | GString *runtime_info_str; |
||
1408 | wtap *wth; |
||
1409 | int err; |
||
1410 | gchar *err_info; |
||
1411 | int opt; |
||
1412 | int overall_error_status; |
||
1413 | static const struct option long_options[] = { |
||
1414 | {"help", no_argument, NULL, 'h'}, |
||
1415 | {"version", no_argument, NULL, 'v'}, |
||
1416 | {0, 0, 0, 0 } |
||
1417 | }; |
||
1418 | |||
1419 | int status = 0; |
||
1420 | #ifdef HAVE_PLUGINS |
||
1421 | char *init_progfile_dir_error; |
||
1422 | #endif |
||
1423 | #ifdef HAVE_LIBGCRYPT |
||
1424 | FILE *fh; |
||
1425 | char *hash_buf = NULL; |
||
1426 | gcry_md_hd_t hd = NULL; |
||
1427 | size_t hash_bytes; |
||
1428 | #endif |
||
1429 | |||
1430 | /* Set the C-language locale to the native environment. */ |
||
1431 | setlocale(LC_ALL, ""); |
||
1432 | |||
1433 | /* Get the decimal point. */ |
||
1434 | decimal_point = g_strdup(localeconv()->decimal_point); |
||
1435 | |||
1436 | /* Get the compile-time version information string */ |
||
1437 | comp_info_str = get_compiled_version_info(NULL, NULL); |
||
1438 | |||
1439 | /* Get the run-time version information string */ |
||
1440 | runtime_info_str = get_runtime_version_info(NULL); |
||
1441 | |||
1442 | /* Add it to the information to be reported on a crash. */ |
||
1443 | ws_add_crash_info("Capinfos (Wireshark) %s\n" |
||
1444 | "\n" |
||
1445 | "%s" |
||
1446 | "\n" |
||
1447 | "%s", |
||
1448 | get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str); |
||
1449 | |||
1450 | #ifdef _WIN32 |
||
1451 | arg_list_utf_16to8(argc, argv); |
||
1452 | create_app_running_mutex(); |
||
1453 | #endif /* _WIN32 */ |
||
1454 | |||
1455 | /* |
||
1456 | * Get credential information for later use. |
||
1457 | */ |
||
1458 | init_process_policies(); |
||
1459 | init_open_routines(); |
||
1460 | |||
1461 | #ifdef HAVE_PLUGINS |
||
1462 | if ((init_progfile_dir_error = init_progfile_dir(argv[0], main))) { |
||
1463 | g_warning("capinfos: init_progfile_dir(): %s", init_progfile_dir_error); |
||
1464 | g_free(init_progfile_dir_error); |
||
1465 | } else { |
||
1466 | /* Register all the plugin types we have. */ |
||
1467 | wtap_register_plugin_types(); /* Types known to libwiretap */ |
||
1468 | |||
1469 | init_report_err(failure_message, NULL, NULL, NULL); |
||
1470 | |||
1471 | /* Scan for plugins. This does *not* call their registration routines; |
||
1472 | that's done later. */ |
||
1473 | scan_plugins(); |
||
1474 | |||
1475 | /* Register all libwiretap plugin modules. */ |
||
1476 | register_all_wiretap_modules(); |
||
1477 | } |
||
1478 | #endif |
||
1479 | |||
1480 | /* Process the options */ |
||
1481 | /* FILE_HASH_OPT will be "H" if libgcrypt is compiled in, so don't use "H" */ |
||
1482 | while ((opt = getopt_long(argc, argv, "abcdehiklmoqrstuvxyzABCEF" FILE_HASH_OPT "ILMNQRST", long_options, NULL)) !=-1) { |
||
1483 | |||
1484 | switch (opt) { |
||
1485 | |||
1486 | case 't': |
||
1487 | if (report_all_infos) disable_all_infos(); |
||
1488 | cap_file_type = TRUE; |
||
1489 | break; |
||
1490 | |||
1491 | case 'E': |
||
1492 | if (report_all_infos) disable_all_infos(); |
||
1493 | cap_file_encap = TRUE; |
||
1494 | break; |
||
1495 | |||
1496 | case 'l': |
||
1497 | if (report_all_infos) disable_all_infos(); |
||
1498 | cap_snaplen = TRUE; |
||
1499 | break; |
||
1500 | |||
1501 | case 'c': |
||
1502 | if (report_all_infos) disable_all_infos(); |
||
1503 | cap_packet_count = TRUE; |
||
1504 | break; |
||
1505 | |||
1506 | case 's': |
||
1507 | if (report_all_infos) disable_all_infos(); |
||
1508 | cap_file_size = TRUE; |
||
1509 | break; |
||
1510 | |||
1511 | case 'd': |
||
1512 | if (report_all_infos) disable_all_infos(); |
||
1513 | cap_data_size = TRUE; |
||
1514 | break; |
||
1515 | |||
1516 | case 'u': |
||
1517 | if (report_all_infos) disable_all_infos(); |
||
1518 | cap_duration = TRUE; |
||
1519 | break; |
||
1520 | |||
1521 | case 'a': |
||
1522 | if (report_all_infos) disable_all_infos(); |
||
1523 | cap_start_time = TRUE; |
||
1524 | break; |
||
1525 | |||
1526 | case 'e': |
||
1527 | if (report_all_infos) disable_all_infos(); |
||
1528 | cap_end_time = TRUE; |
||
1529 | break; |
||
1530 | |||
1531 | case 'S': |
||
1532 | time_as_secs = TRUE; |
||
1533 | break; |
||
1534 | |||
1535 | case 'y': |
||
1536 | if (report_all_infos) disable_all_infos(); |
||
1537 | cap_data_rate_byte = TRUE; |
||
1538 | break; |
||
1539 | |||
1540 | case 'i': |
||
1541 | if (report_all_infos) disable_all_infos(); |
||
1542 | cap_data_rate_bit = TRUE; |
||
1543 | break; |
||
1544 | |||
1545 | case 'z': |
||
1546 | if (report_all_infos) disable_all_infos(); |
||
1547 | cap_packet_size = TRUE; |
||
1548 | break; |
||
1549 | |||
1550 | case 'x': |
||
1551 | if (report_all_infos) disable_all_infos(); |
||
1552 | cap_packet_rate = TRUE; |
||
1553 | break; |
||
1554 | |||
1555 | #ifdef HAVE_LIBGCRYPT |
||
1556 | case 'H': |
||
1557 | if (report_all_infos) disable_all_infos(); |
||
1558 | cap_file_hashes = TRUE; |
||
1559 | break; |
||
1560 | #endif |
||
1561 | |||
1562 | case 'o': |
||
1563 | if (report_all_infos) disable_all_infos(); |
||
1564 | cap_order = TRUE; |
||
1565 | break; |
||
1566 | |||
1567 | case 'k': |
||
1568 | if (report_all_infos) disable_all_infos(); |
||
1569 | cap_comment = TRUE; |
||
1570 | break; |
||
1571 | |||
1572 | case 'F': |
||
1573 | if (report_all_infos) disable_all_infos(); |
||
1574 | cap_file_more_info = TRUE; |
||
1575 | break; |
||
1576 | |||
1577 | case 'I': |
||
1578 | if (report_all_infos) disable_all_infos(); |
||
1579 | cap_file_idb = TRUE; |
||
1580 | break; |
||
1581 | |||
1582 | case 'C': |
||
1583 | continue_after_wtap_open_offline_failure = FALSE; |
||
1584 | break; |
||
1585 | |||
1586 | case 'A': |
||
1587 | enable_all_infos(); |
||
1588 | break; |
||
1589 | |||
1590 | case 'L': |
||
1591 | long_report = TRUE; |
||
1592 | break; |
||
1593 | |||
1594 | case 'T': |
||
1595 | long_report = FALSE; |
||
1596 | break; |
||
1597 | |||
1598 | case 'M': |
||
1599 | machine_readable = TRUE; |
||
1600 | break; |
||
1601 | |||
1602 | case 'R': |
||
1603 | table_report_header = TRUE; |
||
1604 | break; |
||
1605 | |||
1606 | case 'r': |
||
1607 | table_report_header = FALSE; |
||
1608 | break; |
||
1609 | |||
1610 | case 'N': |
||
1611 | quote_char = '\0'; |
||
1612 | break; |
||
1613 | |||
1614 | case 'q': |
||
1615 | quote_char = '\''; |
||
1616 | break; |
||
1617 | |||
1618 | case 'Q': |
||
1619 | quote_char = '"'; |
||
1620 | break; |
||
1621 | |||
1622 | case 'B': |
||
1623 | field_separator = '\t'; |
||
1624 | break; |
||
1625 | |||
1626 | case 'm': |
||
1627 | field_separator = ','; |
||
1628 | break; |
||
1629 | |||
1630 | case 'b': |
||
1631 | field_separator = ' '; |
||
1632 | break; |
||
1633 | |||
1634 | case 'h': |
||
1635 | printf("Capinfos (Wireshark) %s\n" |
||
1636 | "Print various information (infos) about capture files.\n" |
||
1637 | "See https://www.wireshark.org for more information.\n", |
||
1638 | get_ws_vcs_version_info()); |
||
1639 | print_usage(stdout); |
||
1640 | exit(0); |
||
1641 | break; |
||
1642 | |||
1643 | case 'v': |
||
1644 | show_version("Capinfos (Wireshark)", comp_info_str, runtime_info_str); |
||
1645 | g_string_free(comp_info_str, TRUE); |
||
1646 | g_string_free(runtime_info_str, TRUE); |
||
1647 | exit(0); |
||
1648 | break; |
||
1649 | |||
1650 | case '?': /* Bad flag - print usage message */ |
||
1651 | print_usage(stderr); |
||
1652 | exit(1); |
||
1653 | break; |
||
1654 | } |
||
1655 | } |
||
1656 | |||
1657 | if ((argc - optind) < 1) { |
||
1658 | print_usage(stderr); |
||
1659 | exit(1); |
||
1660 | } |
||
1661 | |||
1662 | if (!long_report && table_report_header) { |
||
1663 | print_stats_table_header(); |
||
1664 | } |
||
1665 | |||
1666 | #ifdef HAVE_LIBGCRYPT |
||
1667 | if (cap_file_hashes) { |
||
1668 | gcry_check_version(NULL); |
||
1669 | gcry_md_open(&hd, GCRY_MD_SHA1, 0); |
||
1670 | if (hd) { |
||
1671 | gcry_md_enable(hd, GCRY_MD_RMD160); |
||
1672 | gcry_md_enable(hd, GCRY_MD_MD5); |
||
1673 | } |
||
1674 | hash_buf = (char *)g_malloc(HASH_BUF_SIZE); |
||
1675 | } |
||
1676 | #endif |
||
1677 | |||
1678 | overall_error_status = 0; |
||
1679 | |||
1680 | for (opt = optind; opt < argc; opt++) { |
||
1681 | |||
1682 | #ifdef HAVE_LIBGCRYPT |
||
1683 | g_strlcpy(file_sha1, "<unknown>", HASH_STR_SIZE); |
||
1684 | g_strlcpy(file_rmd160, "<unknown>", HASH_STR_SIZE); |
||
1685 | g_strlcpy(file_md5, "<unknown>", HASH_STR_SIZE); |
||
1686 | |||
1687 | if (cap_file_hashes) { |
||
1688 | fh = ws_fopen(argv[opt], "rb"); |
||
1689 | if (fh && hd) { |
||
1690 | while((hash_bytes = fread(hash_buf, 1, HASH_BUF_SIZE, fh)) > 0) { |
||
1691 | gcry_md_write(hd, hash_buf, hash_bytes); |
||
1692 | } |
||
1693 | gcry_md_final(hd); |
||
1694 | hash_to_str(gcry_md_read(hd, GCRY_MD_SHA1), HASH_SIZE_SHA1, file_sha1); |
||
1695 | hash_to_str(gcry_md_read(hd, GCRY_MD_RMD160), HASH_SIZE_RMD160, file_rmd160); |
||
1696 | hash_to_str(gcry_md_read(hd, GCRY_MD_MD5), HASH_SIZE_MD5, file_md5); |
||
1697 | } |
||
1698 | if (fh) fclose(fh); |
||
1699 | if (hd) gcry_md_reset(hd); |
||
1700 | } |
||
1701 | #endif /* HAVE_LIBGCRYPT */ |
||
1702 | |||
1703 | wth = wtap_open_offline(argv[opt], WTAP_TYPE_AUTO, &err, &err_info, FALSE); |
||
1704 | |||
1705 | if (!wth) { |
||
1706 | fprintf(stderr, "capinfos: Can't open %s: %s\n", argv[opt], |
||
1707 | wtap_strerror(err)); |
||
1708 | if (err_info != NULL) { |
||
1709 | fprintf(stderr, "(%s)\n", err_info); |
||
1710 | g_free(err_info); |
||
1711 | } |
||
1712 | overall_error_status = 1; /* remember that an error has occurred */ |
||
1713 | if (!continue_after_wtap_open_offline_failure) |
||
1714 | exit(1); /* error status */ |
||
1715 | } |
||
1716 | |||
1717 | if (wth) { |
||
1718 | if ((opt > optind) && (long_report)) |
||
1719 | printf("\n"); |
||
1720 | status = process_cap_file(wth, argv[opt]); |
||
1721 | |||
1722 | wtap_close(wth); |
||
1723 | if (status) |
||
1724 | exit(status); |
||
1725 | } |
||
1726 | } |
||
1727 | |||
1728 | return overall_error_status; |
||
1729 | } |
||
1730 | |||
1731 | /* |
||
1732 | * Editor modelines - http://www.wireshark.org/tools/modelines.html |
||
1733 | * |
||
1734 | * Local variables: |
||
1735 | * c-basic-offset: 2 |
||
1736 | * tab-width: 8 |
||
1737 | * indent-tabs-mode: nil |
||
1738 | * End: |
||
1739 | * |
||
1740 | * vi: set shiftwidth=2 tabstop=8 expandtab: |
||
1741 | * :indentSize=2:tabSize=8:noTabs=true: |
||
1742 | */ |