1 /* tfshark.c
2 *
3 * Text-mode variant of Fileshark, based off of TShark,
4 *
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12 #include <config.h>
13
14 #define WS_LOG_DOMAIN LOG_DOMAIN_MAIN
15
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <locale.h>
20 #include <limits.h>
21
22 #include <wsutil/ws_getopt.h>
23
24 #include <errno.h>
25
26 #include <glib.h>
27
28 #include <epan/exceptions.h>
29 #include <epan/epan.h>
30
31 #include <ui/clopts_common.h>
32 #include <ui/cmdarg_err.h>
33 #include <ui/exit_codes.h>
34 #include <ui/urls.h>
35 #include <wsutil/filesystem.h>
36 #include <wsutil/file_util.h>
37 #include <wsutil/privileges.h>
38 #include <wsutil/report_message.h>
39 #include <wsutil/wslog.h>
40 #include <wsutil/ws_assert.h>
41 #include <cli_main.h>
42 #include <ui/version_info.h>
43
44 #include "globals.h"
45 #include <epan/timestamp.h>
46 #include <epan/packet.h>
47 #ifdef HAVE_LUA
48 #include <epan/wslua/init_wslua.h>
49 #endif
50 #include "file.h"
51 #include "frame_tvbuff.h"
52 #include <epan/disabled_protos.h>
53 #include <epan/prefs.h>
54 #include <epan/column.h>
55 #include <epan/print.h>
56 #include <epan/addr_resolv.h>
57 #include "ui/util.h"
58 #include "ui/decode_as_utils.h"
59 #include "ui/dissect_opts.h"
60 #include "ui/failure_message.h"
61 #include <epan/epan_dissect.h>
62 #include <epan/tap.h>
63 #include <epan/stat_tap_ui.h>
64 #include <epan/ex-opt.h>
65 #include "extcap.h"
66
67 #include <wiretap/wtap-int.h>
68 #include <wiretap/file_wrappers.h>
69
70 #include <epan/funnel.h>
71
72 #ifdef HAVE_PLUGINS
73 #include <wsutil/plugins.h>
74 #endif
75
76 /* Additional exit codes */
77 #define NO_FILE_SPECIFIED 1
78
79 capture_file cfile;
80
81 static guint32 cum_bytes;
82 static frame_data ref_frame;
83 static frame_data prev_dis_frame;
84 static frame_data prev_cap_frame;
85
86 static gboolean prefs_loaded = FALSE;
87
88 static gboolean perform_two_pass_analysis;
89
90 /*
91 * The way the packet decode is to be written.
92 */
93 typedef enum {
94 WRITE_TEXT, /* summary or detail text */
95 WRITE_XML, /* PDML or PSML */
96 WRITE_FIELDS /* User defined list of fields */
97 /* Add CSV and the like here */
98 } output_action_e;
99
100 static output_action_e output_action;
101 static gboolean do_dissection; /* TRUE if we have to dissect each packet */
102 static gboolean print_packet_info; /* TRUE if we're to print packet information */
103 static gint print_summary = -1; /* TRUE if we're to print packet summary information */
104 static gboolean print_details; /* TRUE if we're to print packet details information */
105 static gboolean print_hex; /* TRUE if we're to print hex/ascci information */
106 static gboolean line_buffered;
107 static gboolean really_quiet = FALSE;
108
109 static print_format_e print_format = PR_FMT_TEXT;
110 static print_stream_t *print_stream;
111
112 static output_fields_t* output_fields = NULL;
113
114 /* The line separator used between packets, changeable via the -S option */
115 static const char *separator = "";
116
117 static gboolean process_file(capture_file *, int, gint64);
118 static gboolean process_packet_single_pass(capture_file *cf,
119 epan_dissect_t *edt, gint64 offset, wtap_rec *rec,
120 const guchar *pd, guint tap_flags);
121 static void show_print_file_io_error(int err);
122 static gboolean write_preamble(capture_file *cf);
123 static gboolean print_packet(capture_file *cf, epan_dissect_t *edt);
124 static gboolean write_finale(void);
125 static const char *cf_open_error_message(int err, gchar *err_info,
126 gboolean for_writing, int file_type);
127
128 static void tfshark_cmdarg_err(const char *msg_format, va_list ap);
129 static void tfshark_cmdarg_err_cont(const char *msg_format, va_list ap);
130
131 static GHashTable *output_only_tables = NULL;
132
133 #if 0
134 struct string_elem {
135 const char *sstr; /* The short string */
136 const char *lstr; /* The long string */
137 };
138
139 static gint
140 string_compare(gconstpointer a, gconstpointer b)
141 {
142 return strcmp(((const struct string_elem *)a)->sstr,
143 ((const struct string_elem *)b)->sstr);
144 }
145
146 static void
147 string_elem_print(gpointer data, gpointer not_used _U_)
148 {
149 fprintf(stderr, " %s - %s\n",
150 ((struct string_elem *)data)->sstr,
151 ((struct string_elem *)data)->lstr);
152 }
153 #endif
154
155 static void
print_usage(FILE * output)156 print_usage(FILE *output)
157 {
158 fprintf(output, "\n");
159 fprintf(output, "Usage: tfshark [options] ...\n");
160 fprintf(output, "\n");
161
162 /*fprintf(output, "\n");*/
163 fprintf(output, "Input file:\n");
164 fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin)\n");
165
166 fprintf(output, "\n");
167 fprintf(output, "Processing:\n");
168 fprintf(output, " -2 perform a two-pass analysis\n");
169 fprintf(output, " -R <read filter> packet Read filter in Wireshark display filter syntax\n");
170 fprintf(output, " (requires -2)\n");
171 fprintf(output, " -Y <display filter> packet displaY filter in Wireshark display filter\n");
172 fprintf(output, " syntax\n");
173 fprintf(output, " -d %s ...\n", DECODE_AS_ARG_TEMPLATE);
174 fprintf(output, " \"Decode As\", see the man page for details\n");
175 fprintf(output, " Example: tcp.port==8888,http\n");
176
177 /*fprintf(output, "\n");*/
178 fprintf(output, "Output:\n");
179 fprintf(output, " -C <config profile> start with specified configuration profile\n");
180 fprintf(output, " -V add output of packet tree (Packet Details)\n");
181 fprintf(output, " -O <protocols> Only show packet details of these protocols, comma\n");
182 fprintf(output, " separated\n");
183 fprintf(output, " -S <separator> the line separator to print between packets\n");
184 fprintf(output, " -x add output of hex and ASCII dump (Packet Bytes)\n");
185 fprintf(output, " -T pdml|ps|psml|text|fields\n");
186 fprintf(output, " format of text output (def: text)\n");
187 fprintf(output, " -e <field> field to print if -Tfields selected (e.g. tcp.port,\n");
188 fprintf(output, " _ws.col.Info)\n");
189 fprintf(output, " this option can be repeated to print multiple fields\n");
190 fprintf(output, " -E<fieldsoption>=<value> set options for output when -Tfields selected:\n");
191 fprintf(output, " header=y|n switch headers on and off\n");
192 fprintf(output, " separator=/t|/s|<char> select tab, space, printable character as separator\n");
193 fprintf(output, " occurrence=f|l|a print first, last or all occurrences of each field\n");
194 fprintf(output, " aggregator=,|/s|<char> select comma, space, printable character as\n");
195 fprintf(output, " aggregator\n");
196 fprintf(output, " quote=d|s|n select double, single, no quotes for values\n");
197 fprintf(output, " -t a|ad|d|dd|e|r|u|ud output format of time stamps (def: r: rel. to first)\n");
198 fprintf(output, " -u s|hms output format of seconds (def: s: seconds)\n");
199 fprintf(output, " -l flush standard output after each packet\n");
200 fprintf(output, " -q be more quiet on stdout (e.g. when using statistics)\n");
201 fprintf(output, " -Q only log true errors to stderr (quieter than -q)\n");
202 fprintf(output, " -X <key>:<value> eXtension options, see the man page for details\n");
203 fprintf(output, " -z <statistics> various statistics, see the man page for details\n");
204
205 ws_log_print_usage(output);
206
207 fprintf(output, "\n");
208 fprintf(output, "Miscellaneous:\n");
209 fprintf(output, " -h display this help and exit\n");
210 fprintf(output, " -v display version info and exit\n");
211 fprintf(output, " -o <name>:<value> ... override preference setting\n");
212 fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
213 fprintf(output, " -G [report] dump one of several available reports and exit\n");
214 fprintf(output, " default report=\"fields\"\n");
215 fprintf(output, " use \"-G ?\" for more help\n");
216 }
217
218 static void
glossary_option_help(void)219 glossary_option_help(void)
220 {
221 FILE *output;
222
223 output = stdout;
224
225 fprintf(output, "%s\n", get_appname_and_version());
226
227 fprintf(output, "\n");
228 fprintf(output, "Usage: tfshark -G [report]\n");
229 fprintf(output, "\n");
230 fprintf(output, "Glossary table reports:\n");
231 fprintf(output, " -G column-formats dump column format codes and exit\n");
232 fprintf(output, " -G decodes dump \"layer type\"/\"decode as\" associations and exit\n");
233 fprintf(output, " -G dissector-tables dump dissector table names, types, and properties\n");
234 fprintf(output, " -G fields dump fields glossary and exit\n");
235 fprintf(output, " -G ftypes dump field type basic and descriptive names\n");
236 fprintf(output, " -G heuristic-decodes dump heuristic dissector tables\n");
237 fprintf(output, " -G plugins dump installed plugins and exit\n");
238 fprintf(output, " -G protocols dump protocols in registration database and exit\n");
239 fprintf(output, " -G values dump value, range, true/false strings and exit\n");
240 fprintf(output, "\n");
241 fprintf(output, "Preference reports:\n");
242 fprintf(output, " -G currentprefs dump current preferences and exit\n");
243 fprintf(output, " -G defaultprefs dump default preferences and exit\n");
244 fprintf(output, "\n");
245 }
246
247 static void
print_current_user(void)248 print_current_user(void) {
249 gchar *cur_user, *cur_group;
250
251 if (started_with_special_privs()) {
252 cur_user = get_cur_username();
253 cur_group = get_cur_groupname();
254 fprintf(stderr, "Running as user \"%s\" and group \"%s\".",
255 cur_user, cur_group);
256 g_free(cur_user);
257 g_free(cur_group);
258 if (running_with_special_privs()) {
259 fprintf(stderr, " This could be dangerous.");
260 }
261 fprintf(stderr, "\n");
262 }
263 }
264
265 static void
get_tfshark_runtime_version_info(GString * str)266 get_tfshark_runtime_version_info(GString *str)
267 {
268 /* stuff used by libwireshark */
269 epan_get_runtime_version_info(str);
270 }
271
272 int
main(int argc,char * argv[])273 main(int argc, char *argv[])
274 {
275 char *init_progfile_dir_error;
276 int opt;
277 static const struct ws_option long_options[] = {
278 {"help", ws_no_argument, NULL, 'h'},
279 {"version", ws_no_argument, NULL, 'v'},
280 {0, 0, 0, 0 }
281 };
282 gboolean arg_error = FALSE;
283
284 int err;
285 volatile gboolean success;
286 volatile int exit_status = 0;
287 gboolean quiet = FALSE;
288 gchar *volatile cf_name = NULL;
289 gchar *rfilter = NULL;
290 gchar *dfilter = NULL;
291 dfilter_t *rfcode = NULL;
292 dfilter_t *dfcode = NULL;
293 gchar *err_msg;
294 e_prefs *prefs_p;
295 gchar *output_only = NULL;
296
297 /*
298 * The leading + ensures that getopt_long() does not permute the argv[]
299 * entries.
300 *
301 * We have to make sure that the first getopt_long() preserves the content
302 * of argv[] for the subsequent getopt_long() call.
303 *
304 * We use getopt_long() in both cases to ensure that we're using a routine
305 * whose permutation behavior we can control in the same fashion on all
306 * platforms, and so that, if we ever need to process a long argument before
307 * doing further initialization, we can do so.
308 *
309 * Glibc and Solaris libc document that a leading + disables permutation
310 * of options, regardless of whether POSIXLY_CORRECT is set or not; *BSD
311 * and macOS don't document it, but do so anyway.
312 *
313 * We do *not* use a leading - because the behavior of a leading - is
314 * platform-dependent.
315 */
316 #define OPTSTRING "+2C:d:e:E:hK:lo:O:qQr:R:S:t:T:u:vVxX:Y:z:"
317
318 static const char optstring[] = OPTSTRING;
319 static const struct report_message_routines tfshark_report_routines = {
320 failure_message,
321 failure_message,
322 open_failure_message,
323 read_failure_message,
324 write_failure_message,
325 cfile_open_failure_message,
326 cfile_dump_open_failure_message,
327 cfile_read_failure_message,
328 cfile_write_failure_message,
329 cfile_close_failure_message
330 };
331
332 /*
333 * Set the C-language locale to the native environment and set the
334 * code page to UTF-8 on Windows.
335 */
336 #ifdef _WIN32
337 setlocale(LC_ALL, ".UTF-8");
338 #else
339 setlocale(LC_ALL, "");
340 #endif
341
342 cmdarg_err_init(tfshark_cmdarg_err, tfshark_cmdarg_err_cont);
343
344 /* Initialize log handler early so we can have proper logging during startup. */
345 ws_log_init("tfshark", vcmdarg_err);
346
347 /* Early logging command-line initialization. */
348 ws_log_parse_args(&argc, argv, vcmdarg_err, INVALID_OPTION);
349
350 #ifdef _WIN32
351 create_app_running_mutex();
352 #endif /* _WIN32 */
353
354 /*
355 * Get credential information for later use, and drop privileges
356 * before doing anything else.
357 * Let the user know if anything happened.
358 */
359 init_process_policies();
360 relinquish_special_privs_perm();
361 print_current_user();
362
363 /*
364 * Attempt to get the pathname of the directory containing the
365 * executable file.
366 */
367 init_progfile_dir_error = init_progfile_dir(argv[0]);
368 if (init_progfile_dir_error != NULL) {
369 fprintf(stderr,
370 "tfshark: Can't get pathname of directory containing the tfshark program: %s.\n",
371 init_progfile_dir_error);
372 g_free(init_progfile_dir_error);
373 }
374
375 initialize_funnel_ops();
376
377 /* Initialize the version information. */
378 ws_init_version_info("TFShark (Wireshark)", NULL,
379 epan_get_compiled_version_info,
380 get_tfshark_runtime_version_info);
381
382 /*
383 * In order to have the -X opts assigned before the wslua machine starts
384 * we need to call getopts before epan_init() gets called.
385 *
386 * In order to handle, for example, -o options, we also need to call it
387 * *after* epan_init() gets called, so that the dissectors have had a
388 * chance to register their preferences.
389 *
390 * XXX - can we do this all with one getopt_long() call, saving the
391 * arguments we can't handle until after initializing libwireshark,
392 * and then process them after initializing libwireshark?
393 */
394 ws_opterr = 0;
395
396 while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
397 switch (opt) {
398 case 'C': /* Configuration Profile */
399 if (profile_exists (ws_optarg, FALSE)) {
400 set_profile_name (ws_optarg);
401 } else {
402 cmdarg_err("Configuration Profile \"%s\" does not exist", ws_optarg);
403 return 1;
404 }
405 break;
406 case 'O': /* Only output these protocols */
407 output_only = g_strdup(ws_optarg);
408 /* FALLTHROUGH */
409 case 'V': /* Verbose */
410 print_details = TRUE;
411 print_packet_info = TRUE;
412 break;
413 case 'x': /* Print packet data in hex (and ASCII) */
414 print_hex = TRUE;
415 /* The user asked for hex output, so let's ensure they get it,
416 * even if they're writing to a file.
417 */
418 print_packet_info = TRUE;
419 break;
420 case 'X':
421 ex_opt_add(ws_optarg);
422 break;
423 default:
424 break;
425 }
426 }
427
428 /*
429 * Print packet summary information is the default, unless either -V or -x
430 * were specified. Note that this is new behavior, which
431 * allows for the possibility of printing only hex/ascii output without
432 * necessarily requiring that either the summary or details be printed too.
433 */
434 if (print_summary == -1)
435 print_summary = (print_details || print_hex) ? FALSE : TRUE;
436
437 init_report_message("tfshark", &tfshark_report_routines);
438
439 timestamp_set_type(TS_RELATIVE);
440 timestamp_set_precision(TS_PREC_AUTO);
441 timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
442
443 /*
444 * Libwiretap must be initialized before libwireshark is, so that
445 * dissection-time handlers for file-type-dependent blocks can
446 * register using the file type/subtype value for the file type.
447 *
448 * XXX - TFShark shouldn't use libwiretap, as it's a file dissector
449 * and should read all files as raw bytes and then try to dissect them.
450 * It needs to handle file types its own way, because we would want
451 * to support dissecting file-type-specific blocks when dissecting
452 * capture files, but that mechanism should support plugins for
453 * other files, too, if *their* formats are extensible.
454 */
455 wtap_init(TRUE);
456
457 /* Register all dissectors; we must do this before checking for the
458 "-G" flag, as the "-G" flag dumps information registered by the
459 dissectors, and we must do it before we read the preferences, in
460 case any dissectors register preferences. */
461 if (!epan_init(NULL, NULL, TRUE)) {
462 exit_status = INIT_FAILED;
463 goto clean_exit;
464 }
465
466 /* Register all tap listeners; we do this before we parse the arguments,
467 as the "-z" argument can specify a registered tap. */
468
469 /* we register the plugin taps before the other taps because
470 stats_tree taps plugins will be registered as tap listeners
471 by stats_tree_stat.c and need to registered before that */
472
473 /* XXX Disable tap registration for now until we can get tfshark set up with
474 * its own set of taps and the necessary registration function etc.
475 register_all_tap_listeners();
476 */
477
478 /* If invoked with the "-G" flag, we dump out information based on
479 the argument to the "-G" flag; if no argument is specified,
480 for backwards compatibility we dump out a glossary of display
481 filter symbols.
482
483 XXX - we do this here, for now, to support "-G" with no arguments.
484 If none of our build or other processes uses "-G" with no arguments,
485 we can just process it with the other arguments. */
486 if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
487 proto_initialize_all_prefixes();
488
489 if (argc == 2)
490 proto_registrar_dump_fields();
491 else {
492 if (strcmp(argv[2], "column-formats") == 0)
493 column_dump_column_formats();
494 else if (strcmp(argv[2], "currentprefs") == 0) {
495 epan_load_settings();
496 write_prefs(NULL);
497 }
498 else if (strcmp(argv[2], "decodes") == 0)
499 dissector_dump_decodes();
500 else if (strcmp(argv[2], "defaultprefs") == 0)
501 write_prefs(NULL);
502 else if (strcmp(argv[2], "dissector-tables") == 0)
503 dissector_dump_dissector_tables();
504 else if (strcmp(argv[2], "fields") == 0)
505 proto_registrar_dump_fields();
506 else if (strcmp(argv[2], "ftypes") == 0)
507 proto_registrar_dump_ftypes();
508 else if (strcmp(argv[2], "heuristic-decodes") == 0)
509 dissector_dump_heur_decodes();
510 else if (strcmp(argv[2], "plugins") == 0) {
511 #ifdef HAVE_PLUGINS
512 plugins_dump_all();
513 #endif
514 #ifdef HAVE_LUA
515 wslua_plugins_dump_all();
516 #endif
517 }
518 else if (strcmp(argv[2], "protocols") == 0)
519 proto_registrar_dump_protocols();
520 else if (strcmp(argv[2], "values") == 0)
521 proto_registrar_dump_values();
522 else if (strcmp(argv[2], "?") == 0)
523 glossary_option_help();
524 else if (strcmp(argv[2], "-?") == 0)
525 glossary_option_help();
526 else {
527 cmdarg_err("Invalid \"%s\" option for -G flag, enter -G ? for more help.", argv[2]);
528 exit_status = INVALID_OPTION;
529 goto clean_exit;
530 }
531 }
532 goto clean_exit;
533 }
534
535 /* Load libwireshark settings from the current profile. */
536 prefs_p = epan_load_settings();
537 prefs_loaded = TRUE;
538
539 cap_file_init(&cfile);
540
541 /* Print format defaults to this. */
542 print_format = PR_FMT_TEXT;
543
544 output_fields = output_fields_new();
545
546 /*
547 * To reset the options parser, set ws_optreset to 1 and set ws_optind to 1.
548 *
549 * Also reset ws_opterr to 1, so that error messages are printed by
550 * getopt_long().
551 */
552 ws_optreset = 1;
553 ws_optind = 1;
554 ws_opterr = 1;
555
556 /* Now get our args */
557 while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
558 switch (opt) {
559 case '2': /* Perform two pass analysis */
560 perform_two_pass_analysis = TRUE;
561 break;
562 case 'C':
563 /* already processed; just ignore it now */
564 break;
565 case 'e':
566 /* Field entry */
567 output_fields_add(output_fields, ws_optarg);
568 break;
569 case 'E':
570 /* Field option */
571 if (!output_fields_set_option(output_fields, ws_optarg)) {
572 cmdarg_err("\"%s\" is not a valid field output option=value pair.", ws_optarg);
573 output_fields_list_options(stderr);
574 exit_status = INVALID_OPTION;
575 goto clean_exit;
576 }
577 break;
578
579 case 'h': /* Print help and exit */
580 show_help_header("Analyze file structure.");
581 print_usage(stdout);
582 goto clean_exit;
583 break;
584 case 'l': /* "Line-buffer" standard output */
585 /* The ANSI C standard does not appear to *require* that a line-buffered
586 stream be flushed to the host environment whenever a newline is
587 written, it just says that, on such a stream, characters "are
588 intended to be transmitted to or from the host environment as a
589 block when a new-line character is encountered".
590
591 The Visual C++ 6.0 C implementation doesn't do what is intended;
592 even if you set a stream to be line-buffered, it still doesn't
593 flush the buffer at the end of every line.
594
595 The whole reason for the "-l" flag in either tcpdump or TShark
596 is to allow the output of a live capture to be piped to a program
597 or script and to have that script see the information for the
598 packet as soon as it's printed, rather than having to wait until
599 a standard I/O buffer fills up.
600
601 So, if the "-l" flag is specified, we flush the standard output
602 at the end of a packet. This will do the right thing if we're
603 printing packet summary lines, and, as we print the entire protocol
604 tree for a single packet without waiting for anything to happen,
605 it should be as good as line-buffered mode if we're printing
606 protocol trees - arguably even better, as it may do fewer
607 writes. */
608 line_buffered = TRUE;
609 break;
610 case 'o': /* Override preference from command line */
611 {
612 char *errmsg = NULL;
613
614 switch (prefs_set_pref(ws_optarg, &errmsg)) {
615
616 case PREFS_SET_OK:
617 break;
618
619 case PREFS_SET_SYNTAX_ERR:
620 cmdarg_err("Invalid -o flag \"%s\"%s%s", ws_optarg,
621 errmsg ? ": " : "", errmsg ? errmsg : "");
622 g_free(errmsg);
623 exit_status = INVALID_OPTION;
624 goto clean_exit;
625 break;
626
627 case PREFS_SET_NO_SUCH_PREF:
628 cmdarg_err("-o flag \"%s\" specifies unknown preference", ws_optarg);
629 exit_status = INVALID_OPTION;
630 goto clean_exit;
631 break;
632
633 case PREFS_SET_OBSOLETE:
634 cmdarg_err("-o flag \"%s\" specifies obsolete preference", ws_optarg);
635 exit_status = INVALID_OPTION;
636 goto clean_exit;
637 break;
638 }
639 break;
640 }
641 case 'q': /* Quiet */
642 quiet = TRUE;
643 break;
644 case 'Q': /* Really quiet */
645 quiet = TRUE;
646 really_quiet = TRUE;
647 break;
648 case 'r': /* Read capture file x */
649 cf_name = g_strdup(ws_optarg);
650 break;
651 case 'R': /* Read file filter */
652 rfilter = ws_optarg;
653 break;
654 case 'S': /* Set the line Separator to be printed between packets */
655 separator = g_strdup(ws_optarg);
656 break;
657 case 'T': /* printing Type */
658 if (strcmp(ws_optarg, "text") == 0) {
659 output_action = WRITE_TEXT;
660 print_format = PR_FMT_TEXT;
661 } else if (strcmp(ws_optarg, "ps") == 0) {
662 output_action = WRITE_TEXT;
663 print_format = PR_FMT_PS;
664 } else if (strcmp(ws_optarg, "pdml") == 0) {
665 output_action = WRITE_XML;
666 print_details = TRUE; /* Need details */
667 print_summary = FALSE; /* Don't allow summary */
668 } else if (strcmp(ws_optarg, "psml") == 0) {
669 output_action = WRITE_XML;
670 print_details = FALSE; /* Don't allow details */
671 print_summary = TRUE; /* Need summary */
672 } else if (strcmp(ws_optarg, "fields") == 0) {
673 output_action = WRITE_FIELDS;
674 print_details = TRUE; /* Need full tree info */
675 print_summary = FALSE; /* Don't allow summary */
676 } else {
677 cmdarg_err("Invalid -T parameter \"%s\"; it must be one of:", ws_optarg); /* x */
678 cmdarg_err_cont("\t\"fields\" The values of fields specified with the -e option, in a form\n"
679 "\t specified by the -E option.\n"
680 "\t\"pdml\" Packet Details Markup Language, an XML-based format for the\n"
681 "\t details of a decoded packet. This information is equivalent to\n"
682 "\t the packet details printed with the -V flag.\n"
683 "\t\"ps\" PostScript for a human-readable one-line summary of each of\n"
684 "\t the packets, or a multi-line view of the details of each of\n"
685 "\t the packets, depending on whether the -V flag was specified.\n"
686 "\t\"psml\" Packet Summary Markup Language, an XML-based format for the\n"
687 "\t summary information of a decoded packet. This information is\n"
688 "\t equivalent to the information shown in the one-line summary\n"
689 "\t printed by default.\n"
690 "\t\"text\" Text of a human-readable one-line summary of each of the\n"
691 "\t packets, or a multi-line view of the details of each of the\n"
692 "\t packets, depending on whether the -V flag was specified.\n"
693 "\t This is the default.");
694 exit_status = INVALID_OPTION;
695 goto clean_exit;
696 }
697 break;
698 case 'v': /* Show version and exit */
699 show_version();
700 goto clean_exit;
701 case 'O': /* Only output these protocols */
702 /* already processed; just ignore it now */
703 break;
704 case 'V': /* Verbose */
705 /* already processed; just ignore it now */
706 break;
707 case 'x': /* Print packet data in hex (and ASCII) */
708 /* already processed; just ignore it now */
709 break;
710 case 'X':
711 /* already processed; just ignore it now */
712 break;
713 case 'Y':
714 dfilter = ws_optarg;
715 break;
716 case 'z':
717 /* We won't call the init function for the stat this soon
718 as it would disallow MATE's fields (which are registered
719 by the preferences set callback) from being used as
720 part of a tap filter. Instead, we just add the argument
721 to a list of stat arguments. */
722 if (strcmp("help", ws_optarg) == 0) {
723 fprintf(stderr, "tfshark: The available statistics for the \"-z\" option are:\n");
724 list_stat_cmd_args();
725 goto clean_exit;
726 }
727 if (!process_stat_cmd_arg(ws_optarg)) {
728 cmdarg_err("Invalid -z argument \"%s\"; it must be one of:", ws_optarg);
729 list_stat_cmd_args();
730 exit_status = INVALID_OPTION;
731 goto clean_exit;
732 }
733 break;
734 case 'd': /* Decode as rule */
735 case 'K': /* Kerberos keytab file */
736 case 't': /* Time stamp type */
737 case 'u': /* Seconds type */
738 case LONGOPT_DISABLE_PROTOCOL: /* disable dissection of protocol */
739 case LONGOPT_ENABLE_HEURISTIC: /* enable heuristic dissection of protocol */
740 case LONGOPT_DISABLE_HEURISTIC: /* disable heuristic dissection of protocol */
741 case LONGOPT_ENABLE_PROTOCOL: /* enable dissection of protocol (that is disabled by default) */
742 if (!dissect_opts_handle_opt(opt, ws_optarg)) {
743 exit_status = INVALID_OPTION;
744 goto clean_exit;
745 }
746 break;
747 default:
748 case '?': /* Bad flag - print usage message */
749 print_usage(stderr);
750 exit_status = INVALID_OPTION;
751 goto clean_exit;
752 break;
753 }
754 }
755
756 /* If we specified output fields, but not the output field type... */
757 if (WRITE_FIELDS != output_action && 0 != output_fields_num_fields(output_fields)) {
758 cmdarg_err("Output fields were specified with \"-e\", "
759 "but \"-Tfields\" was not specified.");
760 return 1;
761 } else if (WRITE_FIELDS == output_action && 0 == output_fields_num_fields(output_fields)) {
762 cmdarg_err("\"-Tfields\" was specified, but no fields were "
763 "specified with \"-e\".");
764
765 exit_status = INVALID_OPTION;
766 goto clean_exit;
767 }
768
769 /* We require a -r flag specifying a file to read. */
770 if (cf_name == NULL) {
771 cmdarg_err("A file to read must be specified with \"-r\".");
772 exit_status = NO_FILE_SPECIFIED;
773 goto clean_exit;
774 }
775
776 /* If no display filter has been specified, and there are still command-
777 line arguments, treat them as the tokens of a display filter. */
778 if (ws_optind < argc) {
779 if (dfilter != NULL) {
780 cmdarg_err("Display filters were specified both with \"-Y\" "
781 "and with additional command-line arguments.");
782 exit_status = INVALID_OPTION;
783 goto clean_exit;
784 }
785 dfilter = get_args_as_string(argc, argv, ws_optind);
786 }
787
788 /* if "-q" wasn't specified, we should print packet information */
789 if (!quiet)
790 print_packet_info = TRUE;
791
792 if (arg_error) {
793 print_usage(stderr);
794 exit_status = INVALID_OPTION;
795 goto clean_exit;
796 }
797
798 if (print_hex) {
799 if (output_action != WRITE_TEXT) {
800 cmdarg_err("Raw packet hex data can only be printed as text or PostScript");
801 exit_status = INVALID_OPTION;
802 goto clean_exit;
803 }
804 }
805
806 if (output_only != NULL) {
807 char *ps;
808
809 if (!print_details) {
810 cmdarg_err("-O requires -V");
811 exit_status = INVALID_OPTION;
812 goto clean_exit;
813 }
814
815 output_only_tables = g_hash_table_new (g_str_hash, g_str_equal);
816 for (ps = strtok (output_only, ","); ps; ps = strtok (NULL, ",")) {
817 g_hash_table_insert(output_only_tables, (gpointer)ps, (gpointer)ps);
818 }
819 }
820
821 if (rfilter != NULL && !perform_two_pass_analysis) {
822 cmdarg_err("-R without -2 is deprecated. For single-pass filtering use -Y.");
823 exit_status = INVALID_OPTION;
824 goto clean_exit;
825 }
826
827 /* Notify all registered modules that have had any of their preferences
828 changed either from one of the preferences file or from the command
829 line that their preferences have changed. */
830 prefs_apply_all();
831
832 /*
833 * Enabled and disabled protocols and heuristic dissectors as per
834 * command-line options.
835 */
836 if (!setup_enabled_and_disabled_protocols()) {
837 exit_status = INVALID_OPTION;
838 goto clean_exit;
839 }
840
841 /* Build the column format array */
842 build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
843
844 if (rfilter != NULL) {
845 if (!dfilter_compile(rfilter, &rfcode, &err_msg)) {
846 cmdarg_err("%s", err_msg);
847 g_free(err_msg);
848 exit_status = INVALID_FILTER;
849 goto clean_exit;
850 }
851 }
852 cfile.rfcode = rfcode;
853
854 if (dfilter != NULL) {
855 if (!dfilter_compile(dfilter, &dfcode, &err_msg)) {
856 cmdarg_err("%s", err_msg);
857 g_free(err_msg);
858 exit_status = INVALID_FILTER;
859 goto clean_exit;
860 }
861 }
862 cfile.dfcode = dfcode;
863
864 if (print_packet_info) {
865 /* If we're printing as text or PostScript, we have
866 to create a print stream. */
867 if (output_action == WRITE_TEXT) {
868 switch (print_format) {
869
870 case PR_FMT_TEXT:
871 print_stream = print_stream_text_stdio_new(stdout);
872 break;
873
874 case PR_FMT_PS:
875 print_stream = print_stream_ps_stdio_new(stdout);
876 break;
877
878 default:
879 ws_assert_not_reached();
880 }
881 }
882 }
883
884 /* We have to dissect each packet if:
885
886 we're printing information about each packet;
887
888 we're using a read filter on the packets;
889
890 we're using a display filter on the packets;
891
892 we're using any taps that need dissection. */
893 do_dissection = print_packet_info || rfcode || dfcode || tap_listeners_require_dissection();
894
895 /*
896 * Read the file.
897 */
898
899 /* TODO: if tfshark is ever changed to give the user a choice of which
900 open_routine reader to use, then the following needs to change. */
901 if (cf_open(&cfile, cf_name, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK) {
902 exit_status = OPEN_ERROR;
903 goto clean_exit;
904 }
905
906 /* Start statistics taps; we do so after successfully opening the
907 capture file, so we know we have something to compute stats
908 on, and after registering all dissectors, so that MATE will
909 have registered its field array so we can have a tap filter
910 with one of MATE's late-registered fields as part of the
911 filter. */
912 start_requested_stats();
913
914 /* Process the packets in the file */
915 TRY {
916 /* XXX - for now there is only 1 packet */
917 success = process_file(&cfile, 1, 0);
918 }
919 CATCH(OutOfMemoryError) {
920 fprintf(stderr,
921 "Out Of Memory.\n"
922 "\n"
923 "Sorry, but TFShark has to terminate now.\n"
924 "\n"
925 "Some infos / workarounds can be found at:\n"
926 WS_WIKI_URL("KnownBugs/OutOfMemory") "\n");
927 success = FALSE;
928 }
929 ENDTRY;
930
931 if (!success) {
932 /* We still dump out the results of taps, etc., as we might have
933 read some packets; however, we exit with an error status. */
934 exit_status = 2;
935 }
936
937 g_free(cf_name);
938
939 if (cfile.provider.frames != NULL) {
940 free_frame_data_sequence(cfile.provider.frames);
941 cfile.provider.frames = NULL;
942 }
943
944 draw_tap_listeners(TRUE);
945 funnel_dump_all_text_windows();
946
947 clean_exit:
948 destroy_print_stream(print_stream);
949 epan_free(cfile.epan);
950 epan_cleanup();
951 extcap_cleanup();
952
953 output_fields_free(output_fields);
954 output_fields = NULL;
955
956 col_cleanup(&cfile.cinfo);
957 wtap_cleanup();
958 return exit_status;
959 }
960
961 static const nstime_t *
tfshark_get_frame_ts(struct packet_provider_data * prov,guint32 frame_num)962 tfshark_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num)
963 {
964 if (prov->ref && prov->ref->num == frame_num)
965 return &prov->ref->abs_ts;
966
967 if (prov->prev_dis && prov->prev_dis->num == frame_num)
968 return &prov->prev_dis->abs_ts;
969
970 if (prov->prev_cap && prov->prev_cap->num == frame_num)
971 return &prov->prev_cap->abs_ts;
972
973 if (prov->frames) {
974 frame_data *fd = frame_data_sequence_find(prov->frames, frame_num);
975
976 return (fd) ? &fd->abs_ts : NULL;
977 }
978
979 return NULL;
980 }
981
982 static const char *
no_interface_name(struct packet_provider_data * prov _U_,guint32 interface_id _U_)983 no_interface_name(struct packet_provider_data *prov _U_, guint32 interface_id _U_)
984 {
985 return "";
986 }
987
988 static epan_t *
tfshark_epan_new(capture_file * cf)989 tfshark_epan_new(capture_file *cf)
990 {
991 static const struct packet_provider_funcs funcs = {
992 tfshark_get_frame_ts,
993 no_interface_name,
994 NULL,
995 NULL,
996 };
997
998 return epan_new(&cf->provider, &funcs);
999 }
1000
1001 static gboolean
process_packet_first_pass(capture_file * cf,epan_dissect_t * edt,gint64 offset,wtap_rec * rec,const guchar * pd)1002 process_packet_first_pass(capture_file *cf, epan_dissect_t *edt,
1003 gint64 offset, wtap_rec *rec,
1004 const guchar *pd)
1005 {
1006 frame_data fdlocal;
1007 guint32 framenum;
1008 gboolean passed;
1009
1010 /* The frame number of this packet is one more than the count of
1011 frames in this packet. */
1012 framenum = cf->count + 1;
1013
1014 /* If we're not running a display filter and we're not printing any
1015 packet information, we don't need to do a dissection. This means
1016 that all packets can be marked as 'passed'. */
1017 passed = TRUE;
1018
1019 frame_data_init(&fdlocal, framenum, rec, offset, cum_bytes);
1020
1021 /* If we're going to print packet information, or we're going to
1022 run a read filter, or display filter, or we're going to process taps, set up to
1023 do a dissection and do so. */
1024 if (edt) {
1025 /* If we're running a read filter, prime the epan_dissect_t with that
1026 filter. */
1027 if (cf->rfcode)
1028 epan_dissect_prime_with_dfilter(edt, cf->rfcode);
1029
1030 /* This is the first pass, so prime the epan_dissect_t with the
1031 hfids postdissectors want on the first pass. */
1032 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1033
1034 frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time,
1035 &cf->provider.ref, cf->provider.prev_dis);
1036 if (cf->provider.ref == &fdlocal) {
1037 ref_frame = fdlocal;
1038 cf->provider.ref = &ref_frame;
1039 }
1040
1041 epan_dissect_file_run(edt, rec,
1042 file_tvbuff_new(&cf->provider, &fdlocal, pd),
1043 &fdlocal, NULL);
1044
1045 /* Run the read filter if we have one. */
1046 if (cf->rfcode)
1047 passed = dfilter_apply_edt(cf->rfcode, edt);
1048 }
1049
1050 if (passed) {
1051 frame_data_set_after_dissect(&fdlocal, &cum_bytes);
1052 cf->provider.prev_cap = cf->provider.prev_dis = frame_data_sequence_add(cf->provider.frames, &fdlocal);
1053
1054 /* If we're not doing dissection then there won't be any dependent frames.
1055 * More importantly, edt.pi.dependent_frames won't be initialized because
1056 * epan hasn't been initialized.
1057 */
1058 if (edt) {
1059 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
1060 }
1061
1062 cf->count++;
1063 } else {
1064 /* if we don't add it to the frame_data_sequence, clean it up right now
1065 * to avoid leaks */
1066 frame_data_destroy(&fdlocal);
1067 }
1068
1069 if (edt)
1070 epan_dissect_reset(edt);
1071
1072 return passed;
1073 }
1074
1075 static gboolean
process_packet_second_pass(capture_file * cf,epan_dissect_t * edt,frame_data * fdata,wtap_rec * rec,Buffer * buf,guint tap_flags)1076 process_packet_second_pass(capture_file *cf, epan_dissect_t *edt,
1077 frame_data *fdata, wtap_rec *rec,
1078 Buffer *buf, guint tap_flags)
1079 {
1080 column_info *cinfo;
1081 gboolean passed;
1082
1083 /* If we're not running a display filter and we're not printing any
1084 packet information, we don't need to do a dissection. This means
1085 that all packets can be marked as 'passed'. */
1086 passed = TRUE;
1087
1088 /* If we're going to print packet information, or we're going to
1089 run a read filter, or we're going to process taps, set up to
1090 do a dissection and do so. */
1091 if (edt) {
1092
1093 /* If we're running a display filter, prime the epan_dissect_t with that
1094 filter. */
1095 if (cf->dfcode)
1096 epan_dissect_prime_with_dfilter(edt, cf->dfcode);
1097
1098 /* This is the first and only pass, so prime the epan_dissect_t
1099 with the hfids postdissectors want on the first pass. */
1100 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1101
1102 col_custom_prime_edt(edt, &cf->cinfo);
1103
1104 /* We only need the columns if either
1105 1) some tap needs the columns
1106 or
1107 2) we're printing packet info but we're *not* verbose; in verbose
1108 mode, we print the protocol tree, not the protocol summary.
1109 */
1110 if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary))
1111 cinfo = &cf->cinfo;
1112 else
1113 cinfo = NULL;
1114
1115 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1116 &cf->provider.ref, cf->provider.prev_dis);
1117 if (cf->provider.ref == fdata) {
1118 ref_frame = *fdata;
1119 cf->provider.ref = &ref_frame;
1120 }
1121
1122 epan_dissect_file_run_with_taps(edt, rec,
1123 file_tvbuff_new_buffer(&cf->provider, fdata, buf), fdata, cinfo);
1124
1125 /* Run the read/display filter if we have one. */
1126 if (cf->dfcode)
1127 passed = dfilter_apply_edt(cf->dfcode, edt);
1128 }
1129
1130 if (passed) {
1131 frame_data_set_after_dissect(fdata, &cum_bytes);
1132 /* Process this packet. */
1133 if (print_packet_info) {
1134 /* We're printing packet information; print the information for
1135 this packet. */
1136 print_packet(cf, edt);
1137
1138 /* If we're doing "line-buffering", flush the standard output
1139 after every packet. See the comment above, for the "-l"
1140 option, for an explanation of why we do that. */
1141 if (line_buffered)
1142 fflush(stdout);
1143
1144 if (ferror(stdout)) {
1145 show_print_file_io_error(errno);
1146 return FALSE;
1147 }
1148 }
1149 cf->provider.prev_dis = fdata;
1150 }
1151 cf->provider.prev_cap = fdata;
1152
1153 if (edt) {
1154 epan_dissect_reset(edt);
1155 }
1156 return passed || fdata->dependent_of_displayed;
1157 }
1158
1159 static gboolean
local_wtap_read(capture_file * cf,wtap_rec * file_rec _U_,int * err,gchar ** err_info _U_,gint64 * data_offset _U_,guint8 ** data_buffer)1160 local_wtap_read(capture_file *cf, wtap_rec *file_rec _U_, int *err, gchar **err_info _U_, gint64 *data_offset _U_, guint8** data_buffer)
1161 {
1162 /* int bytes_read; */
1163 gint64 packet_size = wtap_file_size(cf->provider.wth, err);
1164
1165 *data_buffer = (guint8*)g_malloc((gsize)packet_size);
1166 /* bytes_read =*/ file_read(*data_buffer, (unsigned int)packet_size, cf->provider.wth->fh);
1167
1168 #if 0 /* no more filetap */
1169 if (bytes_read < 0) {
1170 *err = file_error(cf->provider.wth->fh, err_info);
1171 if (*err == 0)
1172 *err = FTAP_ERR_SHORT_READ;
1173 return FALSE;
1174 } else if (bytes_read == 0) {
1175 /* Done with file, no error */
1176 return FALSE;
1177 }
1178
1179
1180 /* XXX - SET FRAME SIZE EQUAL TO TOTAL FILE SIZE */
1181 file_rec->rec_header.packet_header.caplen = (guint32)packet_size;
1182 file_rec->rec_header.packet_header.len = (guint32)packet_size;
1183
1184 /*
1185 * Set the packet encapsulation to the file's encapsulation
1186 * value; if that's not WTAP_ENCAP_PER_PACKET, it's the
1187 * right answer (and means that the read routine for this
1188 * capture file type doesn't have to set it), and if it
1189 * *is* WTAP_ENCAP_PER_PACKET, the caller needs to set it
1190 * anyway.
1191 */
1192 wth->rec.rec_header.packet_header.pkt_encap = wth->file_encap;
1193
1194 if (!wth->subtype_read(wth, err, err_info, data_offset)) {
1195 /*
1196 * If we didn't get an error indication, we read
1197 * the last packet. See if there's any deferred
1198 * error, as might, for example, occur if we're
1199 * reading a compressed file, and we got an error
1200 * reading compressed data from the file, but
1201 * got enough compressed data to decompress the
1202 * last packet of the file.
1203 */
1204 if (*err == 0)
1205 *err = file_error(wth->fh, err_info);
1206 return FALSE; /* failure */
1207 }
1208
1209 /*
1210 * It makes no sense for the captured data length to be bigger
1211 * than the actual data length.
1212 */
1213 if (wth->rec.rec_header.packet_header.caplen > wth->rec.rec_header.packet_header.len)
1214 wth->rec.rec_header.packet_header.caplen = wth->rec.rec_header.packet_header.len;
1215
1216 /*
1217 * Make sure that it's not WTAP_ENCAP_PER_PACKET, as that
1218 * probably means the file has that encapsulation type
1219 * but the read routine didn't set this packet's
1220 * encapsulation type.
1221 */
1222 ws_assert(wth->rec.rec_header.packet_header.pkt_encap != WTAP_ENCAP_PER_PACKET);
1223 #endif
1224
1225 return TRUE; /* success */
1226 }
1227
1228 static gboolean
process_file(capture_file * cf,int max_packet_count,gint64 max_byte_count)1229 process_file(capture_file *cf, int max_packet_count, gint64 max_byte_count)
1230 {
1231 guint32 framenum;
1232 int err;
1233 gchar *err_info = NULL;
1234 gint64 data_offset = 0;
1235 gboolean filtering_tap_listeners;
1236 guint tap_flags;
1237 Buffer buf;
1238 epan_dissect_t *edt = NULL;
1239 wtap_rec file_rec;
1240 guint8* raw_data;
1241
1242 if (print_packet_info) {
1243 if (!write_preamble(cf)) {
1244 err = errno;
1245 show_print_file_io_error(err);
1246 goto out;
1247 }
1248 }
1249
1250 /* Do we have any tap listeners with filters? */
1251 filtering_tap_listeners = have_filtering_tap_listeners();
1252
1253 /* Get the union of the flags for all tap listeners. */
1254 tap_flags = union_of_tap_listener_flags();
1255
1256 wtap_rec_init(&file_rec);
1257
1258 /* XXX - TEMPORARY HACK TO ELF DISSECTOR */
1259 file_rec.rec_header.packet_header.pkt_encap = 1234;
1260
1261 if (perform_two_pass_analysis) {
1262 frame_data *fdata;
1263
1264 /* Allocate a frame_data_sequence for all the frames. */
1265 cf->provider.frames = new_frame_data_sequence();
1266
1267 if (do_dissection) {
1268 gboolean create_proto_tree;
1269
1270 /*
1271 * Determine whether we need to create a protocol tree.
1272 * We do if:
1273 *
1274 * we're going to apply a read filter;
1275 *
1276 * a postdissector wants field values or protocols
1277 * on the first pass.
1278 */
1279 create_proto_tree =
1280 (cf->rfcode != NULL || postdissectors_want_hfids());
1281
1282 /* We're not going to display the protocol tree on this pass,
1283 so it's not going to be "visible". */
1284 edt = epan_dissect_new(cf->epan, create_proto_tree, FALSE);
1285 }
1286 while (local_wtap_read(cf, &file_rec, &err, &err_info, &data_offset, &raw_data)) {
1287 if (process_packet_first_pass(cf, edt, data_offset, &file_rec, raw_data)) {
1288
1289 /* Stop reading if we have the maximum number of packets;
1290 * When the -c option has not been used, max_packet_count
1291 * starts at 0, which practically means, never stop reading.
1292 * (unless we roll over max_packet_count ?)
1293 */
1294 if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
1295 err = 0; /* This is not an error */
1296 break;
1297 }
1298 }
1299 }
1300
1301 if (edt) {
1302 epan_dissect_free(edt);
1303 edt = NULL;
1304 }
1305
1306 #if 0
1307 /* Close the sequential I/O side, to free up memory it requires. */
1308 wtap_sequential_close(cf->provider.wth);
1309 #endif
1310
1311 /* Allow the protocol dissectors to free up memory that they
1312 * don't need after the sequential run-through of the packets. */
1313 postseq_cleanup_all_protocols();
1314
1315 cf->provider.prev_dis = NULL;
1316 cf->provider.prev_cap = NULL;
1317 ws_buffer_init(&buf, 1514);
1318
1319 if (do_dissection) {
1320 gboolean create_proto_tree;
1321
1322 /*
1323 * Determine whether we need to create a protocol tree.
1324 * We do if:
1325 *
1326 * we're going to apply a display filter;
1327 *
1328 * we're going to print the protocol tree;
1329 *
1330 * one of the tap listeners requires a protocol tree;
1331 *
1332 * we have custom columns (which require field values, which
1333 * currently requires that we build a protocol tree).
1334 */
1335 create_proto_tree =
1336 (cf->dfcode || print_details || filtering_tap_listeners ||
1337 (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo));
1338
1339 /* The protocol tree will be "visible", i.e., printed, only if we're
1340 printing packet details, which is true if we're printing stuff
1341 ("print_packet_info" is true) and we're in verbose mode
1342 ("packet_details" is true). */
1343 edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details);
1344 }
1345
1346 for (framenum = 1; err == 0 && framenum <= cf->count; framenum++) {
1347 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1348 #if 0
1349 if (wtap_seek_read(cf->provider.wth, fdata->file_off,
1350 &buf, fdata->cap_len, &err, &err_info)) {
1351 process_packet_second_pass(cf, edt, fdata, &cf->rec, &buf, tap_flags);
1352 }
1353 #else
1354 if (!process_packet_second_pass(cf, edt, fdata, &cf->rec, &buf,
1355 tap_flags))
1356 return FALSE;
1357 #endif
1358 }
1359
1360 if (edt) {
1361 epan_dissect_free(edt);
1362 edt = NULL;
1363 }
1364
1365 ws_buffer_free(&buf);
1366 }
1367 else {
1368 framenum = 0;
1369
1370 if (do_dissection) {
1371 gboolean create_proto_tree;
1372
1373 /*
1374 * Determine whether we need to create a protocol tree.
1375 * We do if:
1376 *
1377 * we're going to apply a read filter;
1378 *
1379 * we're going to apply a display filter;
1380 *
1381 * we're going to print the protocol tree;
1382 *
1383 * one of the tap listeners is going to apply a filter;
1384 *
1385 * one of the tap listeners requires a protocol tree;
1386 *
1387 * a postdissector wants field values or protocols
1388 * on the first pass;
1389 *
1390 * we have custom columns (which require field values, which
1391 * currently requires that we build a protocol tree).
1392 */
1393 create_proto_tree =
1394 (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners ||
1395 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids() ||
1396 have_custom_cols(&cf->cinfo));
1397
1398 /* The protocol tree will be "visible", i.e., printed, only if we're
1399 printing packet details, which is true if we're printing stuff
1400 ("print_packet_info" is true) and we're in verbose mode
1401 ("packet_details" is true). */
1402 edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details);
1403 }
1404
1405 while (local_wtap_read(cf, &file_rec, &err, &err_info, &data_offset, &raw_data)) {
1406
1407 framenum++;
1408
1409 if (!process_packet_single_pass(cf, edt, data_offset,
1410 &file_rec/*wtap_get_rec(cf->provider.wth)*/,
1411 raw_data, tap_flags))
1412 return FALSE;
1413
1414 /* Stop reading if we have the maximum number of packets;
1415 * When the -c option has not been used, max_packet_count
1416 * starts at 0, which practically means, never stop reading.
1417 * (unless we roll over max_packet_count ?)
1418 */
1419 if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
1420 err = 0; /* This is not an error */
1421 break;
1422 }
1423 }
1424
1425 if (edt) {
1426 epan_dissect_free(edt);
1427 edt = NULL;
1428 }
1429 }
1430
1431 wtap_rec_cleanup(&file_rec);
1432
1433 if (err != 0) {
1434 /*
1435 * Print a message noting that the read failed somewhere along the line.
1436 *
1437 * If we're printing packet data, and the standard output and error are
1438 * going to the same place, flush the standard output, so everything
1439 * buffered up is written, and then print a newline to the standard error
1440 * before printing the error message, to separate it from the packet
1441 * data. (Alas, that only works on UN*X; st_dev is meaningless, and
1442 * the _fstat() documentation at Microsoft doesn't indicate whether
1443 * st_ino is even supported.)
1444 */
1445 #ifndef _WIN32
1446 if (print_packet_info) {
1447 ws_statb64 stat_stdout, stat_stderr;
1448
1449 if (ws_fstat64(1, &stat_stdout) == 0 && ws_fstat64(2, &stat_stderr) == 0) {
1450 if (stat_stdout.st_dev == stat_stderr.st_dev &&
1451 stat_stdout.st_ino == stat_stderr.st_ino) {
1452 fflush(stdout);
1453 fprintf(stderr, "\n");
1454 }
1455 }
1456 }
1457 #endif
1458 #if 0
1459 switch (err) {
1460
1461 case FTAP_ERR_UNSUPPORTED:
1462 cmdarg_err("The file \"%s\" contains record data that TFShark doesn't support.\n(%s)",
1463 cf->filename, err_info);
1464 g_free(err_info);
1465 break;
1466
1467 case FTAP_ERR_UNSUPPORTED_ENCAP:
1468 cmdarg_err("The file \"%s\" has a packet with a network type that TFShark doesn't support.\n(%s)",
1469 cf->filename, err_info);
1470 g_free(err_info);
1471 break;
1472
1473 case FTAP_ERR_CANT_READ:
1474 cmdarg_err("An attempt to read from the file \"%s\" failed for some unknown reason.",
1475 cf->filename);
1476 break;
1477
1478 case FTAP_ERR_SHORT_READ:
1479 cmdarg_err("The file \"%s\" appears to have been cut short in the middle of a packet.",
1480 cf->filename);
1481 break;
1482
1483 case FTAP_ERR_BAD_FILE:
1484 cmdarg_err("The file \"%s\" appears to be damaged or corrupt.\n(%s)",
1485 cf->filename, err_info);
1486 g_free(err_info);
1487 break;
1488
1489 case FTAP_ERR_DECOMPRESS:
1490 cmdarg_err("The compressed file \"%s\" appears to be damaged or corrupt.\n"
1491 "(%s)", cf->filename, err_info);
1492 break;
1493
1494 default:
1495 cmdarg_err("An error occurred while reading the file \"%s\": %s.",
1496 cf->filename, ftap_strerror(err));
1497 break;
1498 }
1499 #endif
1500 } else {
1501 if (print_packet_info) {
1502 if (!write_finale()) {
1503 err = errno;
1504 show_print_file_io_error(err);
1505 }
1506 }
1507 }
1508
1509 out:
1510 wtap_close(cf->provider.wth);
1511 cf->provider.wth = NULL;
1512
1513 return (err != 0);
1514 }
1515
1516 static gboolean
process_packet_single_pass(capture_file * cf,epan_dissect_t * edt,gint64 offset,wtap_rec * rec,const guchar * pd,guint tap_flags)1517 process_packet_single_pass(capture_file *cf, epan_dissect_t *edt, gint64 offset,
1518 wtap_rec *rec, const guchar *pd,
1519 guint tap_flags)
1520 {
1521 frame_data fdata;
1522 column_info *cinfo;
1523 gboolean passed;
1524
1525 /* Count this packet. */
1526 cf->count++;
1527
1528 /* If we're not running a display filter and we're not printing any
1529 packet information, we don't need to do a dissection. This means
1530 that all packets can be marked as 'passed'. */
1531 passed = TRUE;
1532
1533 frame_data_init(&fdata, cf->count, rec, offset, cum_bytes);
1534
1535 /* If we're going to print packet information, or we're going to
1536 run a read filter, or we're going to process taps, set up to
1537 do a dissection and do so. */
1538 if (edt) {
1539 /* If we're running a filter, prime the epan_dissect_t with that
1540 filter. */
1541 if (cf->dfcode)
1542 epan_dissect_prime_with_dfilter(edt, cf->dfcode);
1543
1544 col_custom_prime_edt(edt, &cf->cinfo);
1545
1546 /* We only need the columns if either
1547 1) some tap needs the columns
1548 or
1549 2) we're printing packet info but we're *not* verbose; in verbose
1550 mode, we print the protocol tree, not the protocol summary.
1551 or
1552 3) there is a column mapped as an individual field */
1553 if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary) || output_fields_has_cols(output_fields))
1554 cinfo = &cf->cinfo;
1555 else
1556 cinfo = NULL;
1557
1558 frame_data_set_before_dissect(&fdata, &cf->elapsed_time,
1559 &cf->provider.ref, cf->provider.prev_dis);
1560 if (cf->provider.ref == &fdata) {
1561 ref_frame = fdata;
1562 cf->provider.ref = &ref_frame;
1563 }
1564
1565 epan_dissect_file_run_with_taps(edt, rec,
1566 frame_tvbuff_new(&cf->provider, &fdata, pd),
1567 &fdata, cinfo);
1568
1569 /* Run the filter if we have it. */
1570 if (cf->dfcode)
1571 passed = dfilter_apply_edt(cf->dfcode, edt);
1572 }
1573
1574 if (passed) {
1575 frame_data_set_after_dissect(&fdata, &cum_bytes);
1576
1577 /* Process this packet. */
1578 if (print_packet_info) {
1579 /* We're printing packet information; print the information for
1580 this packet. */
1581 print_packet(cf, edt);
1582
1583 /* If we're doing "line-buffering", flush the standard output
1584 after every packet. See the comment above, for the "-l"
1585 option, for an explanation of why we do that. */
1586 if (line_buffered)
1587 fflush(stdout);
1588
1589 if (ferror(stdout)) {
1590 show_print_file_io_error(errno);
1591 return FALSE;
1592 }
1593 }
1594
1595 /* this must be set after print_packet() [bug #8160] */
1596 prev_dis_frame = fdata;
1597 cf->provider.prev_dis = &prev_dis_frame;
1598 }
1599
1600 prev_cap_frame = fdata;
1601 cf->provider.prev_cap = &prev_cap_frame;
1602
1603 if (edt) {
1604 epan_dissect_reset(edt);
1605 frame_data_destroy(&fdata);
1606 }
1607 return passed;
1608 }
1609
1610 static gboolean
write_preamble(capture_file * cf)1611 write_preamble(capture_file *cf)
1612 {
1613 switch (output_action) {
1614
1615 case WRITE_TEXT:
1616 return print_preamble(print_stream, cf->filename, get_ws_vcs_version_info());
1617
1618 case WRITE_XML:
1619 if (print_details)
1620 write_pdml_preamble(stdout, cf->filename);
1621 else
1622 write_psml_preamble(&cf->cinfo, stdout);
1623 return !ferror(stdout);
1624
1625 case WRITE_FIELDS:
1626 write_fields_preamble(output_fields, stdout);
1627 return !ferror(stdout);
1628
1629 default:
1630 ws_assert_not_reached();
1631 return FALSE;
1632 }
1633 }
1634
1635 static char *
get_line_buf(size_t len)1636 get_line_buf(size_t len)
1637 {
1638 static char *line_bufp = NULL;
1639 static size_t line_buf_len = 256;
1640 size_t new_line_buf_len;
1641
1642 for (new_line_buf_len = line_buf_len; len > new_line_buf_len;
1643 new_line_buf_len *= 2)
1644 ;
1645 if (line_bufp == NULL) {
1646 line_buf_len = new_line_buf_len;
1647 line_bufp = (char *)g_malloc(line_buf_len + 1);
1648 } else {
1649 if (new_line_buf_len > line_buf_len) {
1650 line_buf_len = new_line_buf_len;
1651 line_bufp = (char *)g_realloc(line_bufp, line_buf_len + 1);
1652 }
1653 }
1654 return line_bufp;
1655 }
1656
1657 static inline void
put_string(char * dest,const char * str,size_t str_len)1658 put_string(char *dest, const char *str, size_t str_len)
1659 {
1660 memcpy(dest, str, str_len);
1661 dest[str_len] = '\0';
1662 }
1663
1664 static inline void
put_spaces_string(char * dest,const char * str,size_t str_len,size_t str_with_spaces)1665 put_spaces_string(char *dest, const char *str, size_t str_len, size_t str_with_spaces)
1666 {
1667 size_t i;
1668
1669 for (i = str_len; i < str_with_spaces; i++)
1670 *dest++ = ' ';
1671
1672 put_string(dest, str, str_len);
1673 }
1674
1675 static inline void
put_string_spaces(char * dest,const char * str,size_t str_len,size_t str_with_spaces)1676 put_string_spaces(char *dest, const char *str, size_t str_len, size_t str_with_spaces)
1677 {
1678 size_t i;
1679
1680 memcpy(dest, str, str_len);
1681 for (i = str_len; i < str_with_spaces; i++)
1682 dest[i] = ' ';
1683
1684 dest[str_with_spaces] = '\0';
1685 }
1686
1687 static gboolean
print_columns(capture_file * cf)1688 print_columns(capture_file *cf)
1689 {
1690 char *line_bufp;
1691 int i;
1692 size_t buf_offset;
1693 size_t column_len;
1694 size_t col_len;
1695 col_item_t* col_item;
1696
1697 line_bufp = get_line_buf(256);
1698 buf_offset = 0;
1699 *line_bufp = '\0';
1700 for (i = 0; i < cf->cinfo.num_cols; i++) {
1701 col_item = &cf->cinfo.columns[i];
1702 /* Skip columns not marked as visible. */
1703 if (!get_column_visible(i))
1704 continue;
1705 switch (col_item->col_fmt) {
1706 case COL_NUMBER:
1707 column_len = col_len = strlen(col_item->col_data);
1708 if (column_len < 3)
1709 column_len = 3;
1710 line_bufp = get_line_buf(buf_offset + column_len);
1711 put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1712 break;
1713
1714 case COL_CLS_TIME:
1715 case COL_REL_TIME:
1716 case COL_ABS_TIME:
1717 case COL_ABS_YMD_TIME: /* XXX - wider */
1718 case COL_ABS_YDOY_TIME: /* XXX - wider */
1719 case COL_UTC_TIME:
1720 case COL_UTC_YMD_TIME: /* XXX - wider */
1721 case COL_UTC_YDOY_TIME: /* XXX - wider */
1722 column_len = col_len = strlen(col_item->col_data);
1723 if (column_len < 10)
1724 column_len = 10;
1725 line_bufp = get_line_buf(buf_offset + column_len);
1726 put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1727 break;
1728
1729 case COL_DEF_SRC:
1730 case COL_RES_SRC:
1731 case COL_UNRES_SRC:
1732 case COL_DEF_DL_SRC:
1733 case COL_RES_DL_SRC:
1734 case COL_UNRES_DL_SRC:
1735 case COL_DEF_NET_SRC:
1736 case COL_RES_NET_SRC:
1737 case COL_UNRES_NET_SRC:
1738 column_len = col_len = strlen(col_item->col_data);
1739 if (column_len < 12)
1740 column_len = 12;
1741 line_bufp = get_line_buf(buf_offset + column_len);
1742 put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1743 break;
1744
1745 case COL_DEF_DST:
1746 case COL_RES_DST:
1747 case COL_UNRES_DST:
1748 case COL_DEF_DL_DST:
1749 case COL_RES_DL_DST:
1750 case COL_UNRES_DL_DST:
1751 case COL_DEF_NET_DST:
1752 case COL_RES_NET_DST:
1753 case COL_UNRES_NET_DST:
1754 column_len = col_len = strlen(col_item->col_data);
1755 if (column_len < 12)
1756 column_len = 12;
1757 line_bufp = get_line_buf(buf_offset + column_len);
1758 put_string_spaces(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1759 break;
1760
1761 default:
1762 column_len = strlen(col_item->col_data);
1763 line_bufp = get_line_buf(buf_offset + column_len);
1764 put_string(line_bufp + buf_offset, col_item->col_data, column_len);
1765 break;
1766 }
1767 buf_offset += column_len;
1768 if (i != cf->cinfo.num_cols - 1) {
1769 /*
1770 * This isn't the last column, so we need to print a
1771 * separator between this column and the next.
1772 *
1773 * If we printed a network source and are printing a
1774 * network destination of the same type next, separate
1775 * them with " -> "; if we printed a network destination
1776 * and are printing a network source of the same type
1777 * next, separate them with " <- "; otherwise separate them
1778 * with a space.
1779 *
1780 * We add enough space to the buffer for " <- " or " -> ",
1781 * even if we're only adding " ".
1782 */
1783 line_bufp = get_line_buf(buf_offset + 4);
1784 switch (col_item->col_fmt) {
1785
1786 case COL_DEF_SRC:
1787 case COL_RES_SRC:
1788 case COL_UNRES_SRC:
1789 switch (cf->cinfo.columns[i+1].col_fmt) {
1790
1791 case COL_DEF_DST:
1792 case COL_RES_DST:
1793 case COL_UNRES_DST:
1794 put_string(line_bufp + buf_offset, " -> ", 4);
1795 buf_offset += 4;
1796 break;
1797
1798 default:
1799 put_string(line_bufp + buf_offset, " ", 1);
1800 buf_offset += 1;
1801 break;
1802 }
1803 break;
1804
1805 case COL_DEF_DL_SRC:
1806 case COL_RES_DL_SRC:
1807 case COL_UNRES_DL_SRC:
1808 switch (cf->cinfo.columns[i+1].col_fmt) {
1809
1810 case COL_DEF_DL_DST:
1811 case COL_RES_DL_DST:
1812 case COL_UNRES_DL_DST:
1813 put_string(line_bufp + buf_offset, " -> ", 4);
1814 buf_offset += 4;
1815 break;
1816
1817 default:
1818 put_string(line_bufp + buf_offset, " ", 1);
1819 buf_offset += 1;
1820 break;
1821 }
1822 break;
1823
1824 case COL_DEF_NET_SRC:
1825 case COL_RES_NET_SRC:
1826 case COL_UNRES_NET_SRC:
1827 switch (cf->cinfo.columns[i+1].col_fmt) {
1828
1829 case COL_DEF_NET_DST:
1830 case COL_RES_NET_DST:
1831 case COL_UNRES_NET_DST:
1832 put_string(line_bufp + buf_offset, " -> ", 4);
1833 buf_offset += 4;
1834 break;
1835
1836 default:
1837 put_string(line_bufp + buf_offset, " ", 1);
1838 buf_offset += 1;
1839 break;
1840 }
1841 break;
1842
1843 case COL_DEF_DST:
1844 case COL_RES_DST:
1845 case COL_UNRES_DST:
1846 switch (cf->cinfo.columns[i+1].col_fmt) {
1847
1848 case COL_DEF_SRC:
1849 case COL_RES_SRC:
1850 case COL_UNRES_SRC:
1851 put_string(line_bufp + buf_offset, " <- ", 4);
1852 buf_offset += 4;
1853 break;
1854
1855 default:
1856 put_string(line_bufp + buf_offset, " ", 1);
1857 buf_offset += 1;
1858 break;
1859 }
1860 break;
1861
1862 case COL_DEF_DL_DST:
1863 case COL_RES_DL_DST:
1864 case COL_UNRES_DL_DST:
1865 switch (cf->cinfo.columns[i+1].col_fmt) {
1866
1867 case COL_DEF_DL_SRC:
1868 case COL_RES_DL_SRC:
1869 case COL_UNRES_DL_SRC:
1870 put_string(line_bufp + buf_offset, " <- ", 4);
1871 buf_offset += 4;
1872 break;
1873
1874 default:
1875 put_string(line_bufp + buf_offset, " ", 1);
1876 buf_offset += 1;
1877 break;
1878 }
1879 break;
1880
1881 case COL_DEF_NET_DST:
1882 case COL_RES_NET_DST:
1883 case COL_UNRES_NET_DST:
1884 switch (cf->cinfo.columns[i+1].col_fmt) {
1885
1886 case COL_DEF_NET_SRC:
1887 case COL_RES_NET_SRC:
1888 case COL_UNRES_NET_SRC:
1889 put_string(line_bufp + buf_offset, " <- ", 4);
1890 buf_offset += 4;
1891 break;
1892
1893 default:
1894 put_string(line_bufp + buf_offset, " ", 1);
1895 buf_offset += 1;
1896 break;
1897 }
1898 break;
1899
1900 default:
1901 put_string(line_bufp + buf_offset, " ", 1);
1902 buf_offset += 1;
1903 break;
1904 }
1905 }
1906 }
1907 return print_line(print_stream, 0, line_bufp);
1908 }
1909
1910 static gboolean
print_packet(capture_file * cf,epan_dissect_t * edt)1911 print_packet(capture_file *cf, epan_dissect_t *edt)
1912 {
1913 if (print_summary || output_fields_has_cols(output_fields)) {
1914 /* Just fill in the columns. */
1915 epan_dissect_fill_in_columns(edt, FALSE, TRUE);
1916
1917 if (print_summary) {
1918 /* Now print them. */
1919 switch (output_action) {
1920
1921 case WRITE_TEXT:
1922 if (!print_columns(cf))
1923 return FALSE;
1924 break;
1925
1926 case WRITE_XML:
1927 write_psml_columns(edt, stdout, FALSE);
1928 return !ferror(stdout);
1929 case WRITE_FIELDS: /*No non-verbose "fields" format */
1930 ws_assert_not_reached();
1931 break;
1932 }
1933 }
1934 }
1935 if (print_details) {
1936 /* Print the information in the protocol tree. */
1937 switch (output_action) {
1938
1939 case WRITE_TEXT:
1940 if (!proto_tree_print(print_details ? print_dissections_expanded : print_dissections_none,
1941 print_hex, edt, output_only_tables, print_stream))
1942 return FALSE;
1943 if (!print_hex) {
1944 if (!print_line(print_stream, 0, separator))
1945 return FALSE;
1946 }
1947 break;
1948
1949 case WRITE_XML:
1950 write_pdml_proto_tree(NULL, NULL, PF_NONE, edt, &cf->cinfo, stdout, FALSE);
1951 printf("\n");
1952 return !ferror(stdout);
1953 case WRITE_FIELDS:
1954 write_fields_proto_tree(output_fields, edt, &cf->cinfo, stdout);
1955 printf("\n");
1956 return !ferror(stdout);
1957 }
1958 }
1959 if (print_hex) {
1960 if (print_summary || print_details) {
1961 if (!print_line(print_stream, 0, ""))
1962 return FALSE;
1963 }
1964 if (!print_hex_data(print_stream, edt))
1965 return FALSE;
1966 if (!print_line(print_stream, 0, separator))
1967 return FALSE;
1968 }
1969 return TRUE;
1970 }
1971
1972 static gboolean
write_finale(void)1973 write_finale(void)
1974 {
1975 switch (output_action) {
1976
1977 case WRITE_TEXT:
1978 return print_finale(print_stream);
1979
1980 case WRITE_XML:
1981 if (print_details)
1982 write_pdml_finale(stdout);
1983 else
1984 write_psml_finale(stdout);
1985 return !ferror(stdout);
1986
1987 case WRITE_FIELDS:
1988 write_fields_finale(output_fields, stdout);
1989 return !ferror(stdout);
1990
1991 default:
1992 ws_assert_not_reached();
1993 return FALSE;
1994 }
1995 }
1996
1997 cf_status_t
cf_open(capture_file * cf,const char * fname,unsigned int type,gboolean is_tempfile,int * err)1998 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
1999 {
2000 gchar *err_info;
2001 char err_msg[2048+1];
2002
2003 /* The open isn't implemented yet. Fill in the information for this file. */
2004
2005 /* Create new epan session for dissection. */
2006 epan_free(cf->epan);
2007 cf->epan = tfshark_epan_new(cf);
2008
2009 cf->provider.wth = NULL; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2010 cf->f_datalen = 0; /* not used, but set it anyway */
2011
2012 /* Set the file name because we need it to set the follow stream filter.
2013 XXX - is that still true? We need it for other reasons, though,
2014 in any case. */
2015 cf->filename = g_strdup(fname);
2016
2017 /* Indicate whether it's a permanent or temporary file. */
2018 cf->is_tempfile = is_tempfile;
2019
2020 /* No user changes yet. */
2021 cf->unsaved_changes = FALSE;
2022
2023 cf->cd_t = 0; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2024 cf->open_type = type;
2025 cf->count = 0;
2026 cf->drops_known = FALSE;
2027 cf->drops = 0;
2028 cf->snap = 0; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2029 nstime_set_zero(&cf->elapsed_time);
2030 cf->provider.ref = NULL;
2031 cf->provider.prev_dis = NULL;
2032 cf->provider.prev_cap = NULL;
2033
2034 cf->state = FILE_READ_IN_PROGRESS;
2035
2036 return CF_OK;
2037
2038 /* fail: */
2039 g_snprintf(err_msg, sizeof err_msg,
2040 cf_open_error_message(*err, err_info, FALSE, cf->cd_t), fname);
2041 cmdarg_err("%s", err_msg);
2042 return CF_ERROR;
2043 }
2044
2045 static void
show_print_file_io_error(int err)2046 show_print_file_io_error(int err)
2047 {
2048 switch (err) {
2049
2050 case ENOSPC:
2051 cmdarg_err("Not all the packets could be printed because there is "
2052 "no space left on the file system.");
2053 break;
2054
2055 #ifdef EDQUOT
2056 case EDQUOT:
2057 cmdarg_err("Not all the packets could be printed because you are "
2058 "too close to, or over your disk quota.");
2059 break;
2060 #endif
2061
2062 default:
2063 cmdarg_err("An error occurred while printing packets: %s.",
2064 g_strerror(err));
2065 break;
2066 }
2067 }
2068
2069 static const char *
cf_open_error_message(int err,gchar * err_info _U_,gboolean for_writing,int file_type _U_)2070 cf_open_error_message(int err, gchar *err_info _U_, gboolean for_writing,
2071 int file_type _U_)
2072 {
2073 const char *errmsg;
2074 /* static char errmsg_errno[1024+1]; */
2075
2076 #if 0
2077 if (err < 0) {
2078 /* Wiretap error. */
2079 switch (err) {
2080
2081 case FTAP_ERR_NOT_REGULAR_FILE:
2082 errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
2083 break;
2084
2085 case FTAP_ERR_RANDOM_OPEN_PIPE:
2086 /* Seen only when opening a capture file for reading. */
2087 errmsg = "The file \"%s\" is a pipe or FIFO; TFShark can't read pipe or FIFO files in two-pass mode.";
2088 break;
2089
2090 case FTAP_ERR_FILE_UNKNOWN_FORMAT:
2091 /* Seen only when opening a capture file for reading. */
2092 errmsg = "The file \"%s\" isn't a capture file in a format TFShark understands.";
2093 break;
2094
2095 case FTAP_ERR_UNSUPPORTED:
2096 /* Seen only when opening a capture file for reading. */
2097 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2098 "The file \"%%s\" isn't a capture file in a format TFShark understands.\n"
2099 "(%s)", err_info);
2100 g_free(err_info);
2101 errmsg = errmsg_errno;
2102 break;
2103
2104 case FTAP_ERR_CANT_WRITE_TO_PIPE:
2105 /* Seen only when opening a capture file for writing. */
2106 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2107 "The file \"%%s\" is a pipe, and \"%s\" capture files can't be "
2108 "written to a pipe.", ftap_file_type_subtype_short_string(file_type));
2109 errmsg = errmsg_errno;
2110 break;
2111
2112 case FTAP_ERR_UNSUPPORTED_FILE_TYPE:
2113 /* Seen only when opening a capture file for writing. */
2114 errmsg = "TFShark doesn't support writing capture files in that format.";
2115 break;
2116
2117 case FTAP_ERR_UNSUPPORTED_ENCAP:
2118 if (for_writing) {
2119 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2120 "TFShark can't save this capture as a \"%s\" file.",
2121 ftap_file_type_subtype_short_string(file_type));
2122 } else {
2123 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2124 "The file \"%%s\" is a capture for a network type that TFShark doesn't support.\n"
2125 "(%s)", err_info);
2126 g_free(err_info);
2127 }
2128 errmsg = errmsg_errno;
2129 break;
2130
2131 case FTAP_ERR_ENCAP_PER_RECORD_UNSUPPORTED:
2132 if (for_writing) {
2133 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2134 "TFShark can't save this capture as a \"%s\" file.",
2135 ftap_file_type_subtype_short_string(file_type));
2136 errmsg = errmsg_errno;
2137 } else
2138 errmsg = "The file \"%s\" is a capture for a network type that TFShark doesn't support.";
2139 break;
2140
2141 case FTAP_ERR_BAD_FILE:
2142 /* Seen only when opening a capture file for reading. */
2143 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2144 "The file \"%%s\" appears to be damaged or corrupt.\n"
2145 "(%s)", err_info);
2146 g_free(err_info);
2147 errmsg = errmsg_errno;
2148 break;
2149
2150 case FTAP_ERR_CANT_OPEN:
2151 if (for_writing)
2152 errmsg = "The file \"%s\" could not be created for some unknown reason.";
2153 else
2154 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
2155 break;
2156
2157 case FTAP_ERR_SHORT_READ:
2158 errmsg = "The file \"%s\" appears to have been cut short"
2159 " in the middle of a packet or other data.";
2160 break;
2161
2162 case FTAP_ERR_SHORT_WRITE:
2163 errmsg = "A full header couldn't be written to the file \"%s\".";
2164 break;
2165
2166 case FTAP_ERR_COMPRESSION_NOT_SUPPORTED:
2167 errmsg = "This file type cannot be written as a compressed file.";
2168 break;
2169
2170 case FTAP_ERR_DECOMPRESS:
2171 /* Seen only when opening a capture file for reading. */
2172 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2173 "The compressed file \"%%s\" appears to be damaged or corrupt.\n"
2174 "(%s)", err_info);
2175 g_free(err_info);
2176 errmsg = errmsg_errno;
2177 break;
2178
2179 default:
2180 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2181 "The file \"%%s\" could not be %s: %s.",
2182 for_writing ? "created" : "opened",
2183 ftap_strerror(err));
2184 errmsg = errmsg_errno;
2185 break;
2186 }
2187 } else
2188 #endif
2189 errmsg = file_open_error_message(err, for_writing);
2190 return errmsg;
2191 }
2192
2193 /*
2194 * Report an error in command-line arguments.
2195 */
2196 static void
tfshark_cmdarg_err(const char * msg_format,va_list ap)2197 tfshark_cmdarg_err(const char *msg_format, va_list ap)
2198 {
2199 fprintf(stderr, "tfshark: ");
2200 vfprintf(stderr, msg_format, ap);
2201 fprintf(stderr, "\n");
2202 }
2203
2204 /*
2205 * Report additional information for an error in command-line arguments.
2206 */
2207 static void
tfshark_cmdarg_err_cont(const char * msg_format,va_list ap)2208 tfshark_cmdarg_err_cont(const char *msg_format, va_list ap)
2209 {
2210 vfprintf(stderr, msg_format, ap);
2211 fprintf(stderr, "\n");
2212 }
2213
2214 /*
2215 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2216 *
2217 * Local variables:
2218 * c-basic-offset: 2
2219 * tab-width: 8
2220 * indent-tabs-mode: nil
2221 * End:
2222 *
2223 * vi: set shiftwidth=2 tabstop=8 expandtab:
2224 * :indentSize=2:tabSize=8:noTabs=true:
2225 */
2226