Revert "TODO: smb2: simplify preauth_hash calculation..."
[wireshark-sm.git] / tfshark.c
blob7311b4391d1aef71bf6f5ddd31d887e9fd5660d7
1 /* tfshark.c
3 * Text-mode variant of Fileshark, based off of TShark,
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include <config.h>
14 #define WS_LOG_DOMAIN LOG_DOMAIN_MAIN
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <locale.h>
20 #include <limits.h>
22 #include <ws_exit_codes.h>
23 #include <wsutil/ws_getopt.h>
25 #include <errno.h>
27 #include <glib.h>
29 #include <epan/exceptions.h>
30 #include <epan/epan.h>
32 #include <wsutil/clopts_common.h>
33 #include <wsutil/cmdarg_err.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 <wsutil/version_info.h>
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>
66 #include <wiretap/wtap-int.h>
67 #include <wiretap/file_wrappers.h>
69 #include <epan/funnel.h>
71 #ifdef HAVE_PLUGINS
72 #include <wsutil/plugins.h>
73 #endif
75 /* Additional exit codes */
76 #define NO_FILE_SPECIFIED 1
78 capture_file cfile;
80 static guint32 cum_bytes;
81 static frame_data ref_frame;
82 static frame_data prev_dis_frame;
83 static frame_data prev_cap_frame;
85 static gboolean prefs_loaded;
87 static gboolean perform_two_pass_analysis;
90 * The way the packet decode is to be written.
92 typedef enum {
93 WRITE_TEXT, /* summary or detail text */
94 WRITE_XML, /* PDML or PSML */
95 WRITE_FIELDS /* User defined list of fields */
96 /* Add CSV and the like here */
97 } output_action_e;
99 static output_action_e output_action;
100 static gboolean do_dissection; /* TRUE if we have to dissect each packet */
101 static gboolean print_packet_info; /* TRUE if we're to print packet information */
102 static gint print_summary = -1; /* TRUE if we're to print packet summary information */
103 static gboolean print_details; /* TRUE if we're to print packet details information */
104 static gboolean print_hex; /* TRUE if we're to print hex/ascci information */
105 static gboolean line_buffered;
106 static gboolean really_quiet;
108 static print_format_e print_format = PR_FMT_TEXT;
109 static print_stream_t *print_stream;
111 static output_fields_t* output_fields;
113 /* The line separator used between packets, changeable via the -S option */
114 static const char *separator = "";
116 static gboolean process_file(capture_file *, int, gint64);
117 static gboolean process_packet_single_pass(capture_file *cf,
118 epan_dissect_t *edt, gint64 offset, wtap_rec *rec,
119 const guchar *pd);
120 static void show_print_file_io_error(int err);
121 static gboolean write_preamble(capture_file *cf);
122 static gboolean print_packet(capture_file *cf, epan_dissect_t *edt);
123 static gboolean write_finale(void);
125 static void tfshark_cmdarg_err(const char *msg_format, va_list ap);
126 static void tfshark_cmdarg_err_cont(const char *msg_format, va_list ap);
128 static GHashTable *output_only_tables;
130 #if 0
131 struct string_elem {
132 const char *sstr; /* The short string */
133 const char *lstr; /* The long string */
136 static gint
137 string_compare(gconstpointer a, gconstpointer b)
139 return strcmp(((const struct string_elem *)a)->sstr,
140 ((const struct string_elem *)b)->sstr);
143 static void
144 string_elem_print(gpointer data, gpointer not_used _U_)
146 fprintf(stderr, " %s - %s\n",
147 ((struct string_elem *)data)->sstr,
148 ((struct string_elem *)data)->lstr);
150 #endif
152 static void
153 print_usage(FILE *output)
155 fprintf(output, "\n");
156 fprintf(output, "Usage: tfshark [options] ...\n");
157 fprintf(output, "\n");
159 /*fprintf(output, "\n");*/
160 fprintf(output, "Input file:\n");
161 fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin)\n");
163 fprintf(output, "\n");
164 fprintf(output, "Processing:\n");
165 fprintf(output, " -2 perform a two-pass analysis\n");
166 fprintf(output, " -R <read filter> packet Read filter in Wireshark display filter syntax\n");
167 fprintf(output, " (requires -2)\n");
168 fprintf(output, " -Y <display filter> packet displaY filter in Wireshark display filter\n");
169 fprintf(output, " syntax\n");
170 fprintf(output, " -d %s ...\n", DECODE_AS_ARG_TEMPLATE);
171 fprintf(output, " \"Decode As\", see the man page for details\n");
172 fprintf(output, " Example: tcp.port==8888,http\n");
174 /*fprintf(output, "\n");*/
175 fprintf(output, "Output:\n");
176 fprintf(output, " -C <config profile> start with specified configuration profile\n");
177 fprintf(output, " -V add output of packet tree (Packet Details)\n");
178 fprintf(output, " -O <protocols> Only show packet details of these protocols, comma\n");
179 fprintf(output, " separated\n");
180 fprintf(output, " -S <separator> the line separator to print between packets\n");
181 fprintf(output, " -x add output of hex and ASCII dump (Packet Bytes)\n");
182 fprintf(output, " -T pdml|ps|psml|text|fields\n");
183 fprintf(output, " format of text output (def: text)\n");
184 fprintf(output, " -e <field> field to print if -Tfields selected (e.g. tcp.port,\n");
185 fprintf(output, " _ws.col.info)\n");
186 fprintf(output, " this option can be repeated to print multiple fields\n");
187 fprintf(output, " -E<fieldsoption>=<value> set options for output when -Tfields selected:\n");
188 fprintf(output, " header=y|n switch headers on and off\n");
189 fprintf(output, " separator=/t|/s|<char> select tab, space, printable character as separator\n");
190 fprintf(output, " occurrence=f|l|a print first, last or all occurrences of each field\n");
191 fprintf(output, " aggregator=,|/s|<char> select comma, space, printable character as\n");
192 fprintf(output, " aggregator\n");
193 fprintf(output, " quote=d|s|n select double, single, no quotes for values\n");
194 fprintf(output, " -t a|ad|d|dd|e|r|u|ud output format of time stamps (def: r: rel. to first)\n");
195 fprintf(output, " -u s|hms output format of seconds (def: s: seconds)\n");
196 fprintf(output, " -l flush standard output after each packet\n");
197 fprintf(output, " -q be more quiet on stdout (e.g. when using statistics)\n");
198 fprintf(output, " -Q only log true errors to stderr (quieter than -q)\n");
199 fprintf(output, " -X <key>:<value> eXtension options, see the man page for details\n");
200 fprintf(output, " -z <statistics> various statistics, see the man page for details\n");
201 fprintf(output, "\n");
203 ws_log_print_usage(output);
204 fprintf(output, "\n");
206 fprintf(output, "Miscellaneous:\n");
207 fprintf(output, " -h display this help and exit\n");
208 fprintf(output, " -v display version info and exit\n");
209 fprintf(output, " -o <name>:<value> ... override preference setting\n");
210 fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
211 fprintf(output, " -G [report] dump one of several available reports and exit\n");
212 fprintf(output, " default report=\"fields\"\n");
213 fprintf(output, " use \"-G ?\" for more help\n");
216 static void
217 glossary_option_help(void)
219 FILE *output;
221 output = stdout;
223 fprintf(output, "%s\n", get_appname_and_version());
225 fprintf(output, "\n");
226 fprintf(output, "Usage: tfshark -G [report]\n");
227 fprintf(output, "\n");
228 fprintf(output, "Glossary table reports:\n");
229 fprintf(output, " -G column-formats dump column format codes and exit\n");
230 fprintf(output, " -G decodes dump \"layer type\"/\"decode as\" associations and exit\n");
231 fprintf(output, " -G dissector-tables dump dissector table names, types, and properties\n");
232 fprintf(output, " -G fields dump fields glossary and exit\n");
233 fprintf(output, " -G ftypes dump field type basic and descriptive names\n");
234 fprintf(output, " -G heuristic-decodes dump heuristic dissector tables\n");
235 fprintf(output, " -G plugins dump installed plugins and exit\n");
236 fprintf(output, " -G protocols dump protocols in registration database and exit\n");
237 fprintf(output, " -G values dump value, range, true/false strings and exit\n");
238 fprintf(output, "\n");
239 fprintf(output, "Preference reports:\n");
240 fprintf(output, " -G currentprefs dump current preferences and exit\n");
241 fprintf(output, " -G defaultprefs dump default preferences and exit\n");
242 fprintf(output, "\n");
245 static void
246 print_current_user(void)
248 gchar *cur_user, *cur_group;
250 if (started_with_special_privs()) {
251 cur_user = get_cur_username();
252 cur_group = get_cur_groupname();
253 fprintf(stderr, "Running as user \"%s\" and group \"%s\".",
254 cur_user, cur_group);
255 g_free(cur_user);
256 g_free(cur_group);
257 if (running_with_special_privs()) {
258 fprintf(stderr, " This could be dangerous.");
260 fprintf(stderr, "\n");
265 main(int argc, char *argv[])
267 char *configuration_init_error;
268 int opt;
269 static const struct ws_option long_options[] = {
270 {"help", ws_no_argument, NULL, 'h'},
271 {"version", ws_no_argument, NULL, 'v'},
272 {0, 0, 0, 0 }
274 gboolean arg_error = FALSE;
276 int err;
277 volatile gboolean success;
278 volatile int exit_status = 0;
279 gboolean quiet = FALSE;
280 gchar *volatile cf_name = NULL;
281 gchar *rfilter = NULL;
282 gchar *dfilter = NULL;
283 dfilter_t *rfcode = NULL;
284 dfilter_t *dfcode = NULL;
285 df_error_t *df_err;
286 e_prefs *prefs_p;
287 gchar *output_only = NULL;
290 * The leading + ensures that getopt_long() does not permute the argv[]
291 * entries.
293 * We have to make sure that the first getopt_long() preserves the content
294 * of argv[] for the subsequent getopt_long() call.
296 * We use getopt_long() in both cases to ensure that we're using a routine
297 * whose permutation behavior we can control in the same fashion on all
298 * platforms, and so that, if we ever need to process a long argument before
299 * doing further initialization, we can do so.
301 * Glibc and Solaris libc document that a leading + disables permutation
302 * of options, regardless of whether POSIXLY_CORRECT is set or not; *BSD
303 * and macOS don't document it, but do so anyway.
305 * We do *not* use a leading - because the behavior of a leading - is
306 * platform-dependent.
308 #define OPTSTRING "+2C:d:e:E:hK:lo:O:qQr:R:S:t:T:u:vVxX:Y:z:"
310 static const char optstring[] = OPTSTRING;
311 static const struct report_message_routines tfshark_report_routines = {
312 failure_message,
313 failure_message,
314 open_failure_message,
315 read_failure_message,
316 write_failure_message,
317 cfile_open_failure_message,
318 cfile_dump_open_failure_message,
319 cfile_read_failure_message,
320 cfile_write_failure_message,
321 cfile_close_failure_message
325 * Set the C-language locale to the native environment and set the
326 * code page to UTF-8 on Windows.
328 #ifdef _WIN32
329 setlocale(LC_ALL, ".UTF-8");
330 #else
331 setlocale(LC_ALL, "");
332 #endif
334 cmdarg_err_init(tfshark_cmdarg_err, tfshark_cmdarg_err_cont);
336 /* Initialize log handler early so we can have proper logging during startup. */
337 ws_log_init("tfshark", vcmdarg_err);
339 /* Early logging command-line initialization. */
340 ws_log_parse_args(&argc, argv, vcmdarg_err, WS_EXIT_INVALID_OPTION);
342 ws_noisy("Finished log init and parsing command line log arguments");
344 #ifdef _WIN32
345 create_app_running_mutex();
346 #endif /* _WIN32 */
349 * Get credential information for later use, and drop privileges
350 * before doing anything else.
351 * Let the user know if anything happened.
353 init_process_policies();
354 relinquish_special_privs_perm();
355 print_current_user();
358 * Attempt to get the pathname of the directory containing the
359 * executable file.
361 configuration_init_error = configuration_init(argv[0], NULL);
362 if (configuration_init_error != NULL) {
363 fprintf(stderr,
364 "tfshark: Can't get pathname of directory containing the tfshark program: %s.\n",
365 configuration_init_error);
366 g_free(configuration_init_error);
369 initialize_funnel_ops();
371 /* Initialize the version information. */
372 ws_init_version_info("TFShark",
373 epan_gather_compile_info,
374 epan_gather_runtime_info);
376 * In order to have the -X opts assigned before the wslua machine starts
377 * we need to call getopts before epan_init() gets called.
379 * In order to handle, for example, -o options, we also need to call it
380 * *after* epan_init() gets called, so that the dissectors have had a
381 * chance to register their preferences.
383 * XXX - can we do this all with one getopt_long() call, saving the
384 * arguments we can't handle until after initializing libwireshark,
385 * and then process them after initializing libwireshark?
387 ws_opterr = 0;
389 while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
390 switch (opt) {
391 case 'C': /* Configuration Profile */
392 if (profile_exists (ws_optarg, FALSE)) {
393 set_profile_name (ws_optarg);
394 } else if (profile_exists (ws_optarg, TRUE)) {
395 char *pf_dir_path, *pf_dir_path2, *pf_filename;
396 /* Copy from global profile */
397 if (create_persconffile_profile(ws_optarg, &pf_dir_path) == -1) {
398 cmdarg_err("Can't create directory\n\"%s\":\n%s.",
399 pf_dir_path, g_strerror(errno));
401 g_free(pf_dir_path);
402 exit_status = WS_EXIT_INVALID_FILE;
403 goto clean_exit;
405 if (copy_persconffile_profile(ws_optarg, ws_optarg, TRUE, &pf_filename,
406 &pf_dir_path, &pf_dir_path2) == -1) {
407 cmdarg_err("Can't copy file \"%s\" in directory\n\"%s\" to\n\"%s\":\n%s.",
408 pf_filename, pf_dir_path2, pf_dir_path, g_strerror(errno));
410 g_free(pf_filename);
411 g_free(pf_dir_path);
412 g_free(pf_dir_path2);
413 exit_status = WS_EXIT_INVALID_FILE;
414 goto clean_exit;
416 set_profile_name (ws_optarg);
417 } else {
418 cmdarg_err("Configuration Profile \"%s\" does not exist", ws_optarg);
419 return 1;
421 break;
422 case 'O': /* Only output these protocols */
423 output_only = g_strdup(ws_optarg);
424 /* FALLTHROUGH */
425 case 'V': /* Verbose */
426 print_details = TRUE;
427 print_packet_info = TRUE;
428 break;
429 case 'x': /* Print packet data in hex (and ASCII) */
430 print_hex = TRUE;
431 /* The user asked for hex output, so let's ensure they get it,
432 * even if they're writing to a file.
434 print_packet_info = TRUE;
435 break;
436 case 'X':
437 ex_opt_add(ws_optarg);
438 break;
439 default:
440 break;
445 * Print packet summary information is the default, unless either -V or -x
446 * were specified. Note that this is new behavior, which
447 * allows for the possibility of printing only hex/ascii output without
448 * necessarily requiring that either the summary or details be printed too.
450 if (print_summary == -1)
451 print_summary = (print_details || print_hex) ? FALSE : TRUE;
453 init_report_message("tfshark", &tfshark_report_routines);
455 timestamp_set_type(TS_RELATIVE);
456 timestamp_set_precision(TS_PREC_AUTO);
457 timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
460 * Libwiretap must be initialized before libwireshark is, so that
461 * dissection-time handlers for file-type-dependent blocks can
462 * register using the file type/subtype value for the file type.
464 * XXX - TFShark shouldn't use libwiretap, as it's a file dissector
465 * and should read all files as raw bytes and then try to dissect them.
466 * It needs to handle file types its own way, because we would want
467 * to support dissecting file-type-specific blocks when dissecting
468 * capture files, but that mechanism should support plugins for
469 * other files, too, if *their* formats are extensible.
471 wtap_init(TRUE);
473 /* Register all dissectors; we must do this before checking for the
474 "-G" flag, as the "-G" flag dumps information registered by the
475 dissectors, and we must do it before we read the preferences, in
476 case any dissectors register preferences. */
477 if (!epan_init(NULL, NULL, TRUE)) {
478 exit_status = WS_EXIT_INIT_FAILED;
479 goto clean_exit;
482 /* Register all tap listeners; we do this before we parse the arguments,
483 as the "-z" argument can specify a registered tap. */
485 /* we register the plugin taps before the other taps because
486 stats_tree taps plugins will be registered as tap listeners
487 by stats_tree_stat.c and need to registered before that */
489 /* XXX Disable tap registration for now until we can get tfshark set up with
490 * its own set of taps and the necessary registration function etc.
491 register_all_tap_listeners();
494 /* If invoked with the "-G" flag, we dump out information based on
495 the argument to the "-G" flag; if no argument is specified,
496 for backwards compatibility we dump out a glossary of display
497 filter symbols.
499 XXX - we do this here, for now, to support "-G" with no arguments.
500 If none of our build or other processes uses "-G" with no arguments,
501 we can just process it with the other arguments. */
502 if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
503 proto_initialize_all_prefixes();
505 if (argc == 2)
506 proto_registrar_dump_fields();
507 else {
508 if (strcmp(argv[2], "column-formats") == 0)
509 column_dump_column_formats();
510 else if (strcmp(argv[2], "currentprefs") == 0) {
511 epan_load_settings();
512 write_prefs(NULL);
514 else if (strcmp(argv[2], "decodes") == 0)
515 dissector_dump_decodes();
516 else if (strcmp(argv[2], "defaultprefs") == 0)
517 write_prefs(NULL);
518 else if (strcmp(argv[2], "dissector-tables") == 0)
519 dissector_dump_dissector_tables();
520 else if (strcmp(argv[2], "fields") == 0)
521 proto_registrar_dump_fields();
522 else if (strcmp(argv[2], "ftypes") == 0)
523 proto_registrar_dump_ftypes();
524 else if (strcmp(argv[2], "heuristic-decodes") == 0)
525 dissector_dump_heur_decodes();
526 else if (strcmp(argv[2], "plugins") == 0) {
527 #ifdef HAVE_PLUGINS
528 plugins_dump_all();
529 #endif
530 #ifdef HAVE_LUA
531 wslua_plugins_dump_all();
532 #endif
534 else if (strcmp(argv[2], "protocols") == 0)
535 proto_registrar_dump_protocols();
536 else if (strcmp(argv[2], "values") == 0)
537 proto_registrar_dump_values();
538 else if (strcmp(argv[2], "?") == 0)
539 glossary_option_help();
540 else if (strcmp(argv[2], "-?") == 0)
541 glossary_option_help();
542 else {
543 cmdarg_err("Invalid \"%s\" option for -G flag, enter -G ? for more help.", argv[2]);
544 exit_status = WS_EXIT_INVALID_OPTION;
545 goto clean_exit;
548 goto clean_exit;
551 /* Load libwireshark settings from the current profile. */
552 prefs_p = epan_load_settings();
553 prefs_loaded = TRUE;
555 cap_file_init(&cfile);
557 /* Print format defaults to this. */
558 print_format = PR_FMT_TEXT;
560 output_fields = output_fields_new();
563 * To reset the options parser, set ws_optreset to 1 and set ws_optind to 1.
565 * Also reset ws_opterr to 1, so that error messages are printed by
566 * getopt_long().
568 ws_optreset = 1;
569 ws_optind = 1;
570 ws_opterr = 1;
572 /* Now get our args */
573 while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
574 switch (opt) {
575 case '2': /* Perform two-pass analysis */
576 perform_two_pass_analysis = TRUE;
577 break;
578 case 'C':
579 /* already processed; just ignore it now */
580 break;
581 case 'e':
582 /* Field entry */
583 output_fields_add(output_fields, ws_optarg);
584 break;
585 case 'E':
586 /* Field option */
587 if (!output_fields_set_option(output_fields, ws_optarg)) {
588 cmdarg_err("\"%s\" is not a valid field output option=value pair.", ws_optarg);
589 output_fields_list_options(stderr);
590 exit_status = WS_EXIT_INVALID_OPTION;
591 goto clean_exit;
593 break;
595 case 'h': /* Print help and exit */
596 show_help_header("Analyze file structure.");
597 print_usage(stdout);
598 goto clean_exit;
599 break;
600 case 'l': /* "Line-buffer" standard output */
601 /* The ANSI C standard does not appear to *require* that a
602 line-buffered stream be flushed to the host environment
603 whenever a newline is written, it just says that, on such a
604 stream, characters "are intended to be transmitted to or
605 from the host environment as a block when a new-line
606 character is encountered".
608 The Visual C++ 6.0 C implementation doesn't do what is
609 intended; even if you set a stream to be line-buffered, it
610 still doesn't flush the buffer at the end of every line.
612 The whole reason for the "-l" flag in either tcpdump or
613 TShark is to allow the output of a live capture to be piped
614 to a program or script and to have that script see the
615 information for the packet as soon as it's printed, rather
616 than having to wait until a standard I/O buffer fills up.
618 So, if the "-l" flag is specified, we flush the standard
619 output at the end of a packet. This will do the right thing
620 if we're printing packet summary lines, and, as we print the
621 entire protocol tree for a single packet without waiting for
622 anything to happen, it should be as good as line-buffered
623 mode if we're printing protocol trees - arguably even
624 better, as it may do fewer writes. */
625 line_buffered = TRUE;
626 break;
627 case 'o': /* Override preference from command line */
629 char *errmsg = NULL;
631 switch (prefs_set_pref(ws_optarg, &errmsg)) {
633 case PREFS_SET_OK:
634 break;
636 case PREFS_SET_SYNTAX_ERR:
637 cmdarg_err("Invalid -o flag \"%s\"%s%s", ws_optarg,
638 errmsg ? ": " : "", errmsg ? errmsg : "");
639 g_free(errmsg);
640 exit_status = WS_EXIT_INVALID_OPTION;
641 goto clean_exit;
642 break;
644 case PREFS_SET_NO_SUCH_PREF:
645 cmdarg_err("-o flag \"%s\" specifies unknown preference", ws_optarg);
646 exit_status = WS_EXIT_INVALID_OPTION;
647 goto clean_exit;
648 break;
650 case PREFS_SET_OBSOLETE:
651 cmdarg_err("-o flag \"%s\" specifies obsolete preference", ws_optarg);
652 exit_status = WS_EXIT_INVALID_OPTION;
653 goto clean_exit;
654 break;
656 break;
658 case 'q': /* Quiet */
659 quiet = TRUE;
660 break;
661 case 'Q': /* Really quiet */
662 quiet = TRUE;
663 really_quiet = TRUE;
664 break;
665 case 'r': /* Read capture file x */
666 cf_name = g_strdup(ws_optarg);
667 break;
668 case 'R': /* Read file filter */
669 rfilter = ws_optarg;
670 break;
671 case 'S': /* Set the line Separator to be printed between packets */
672 separator = g_strdup(ws_optarg);
673 break;
674 case 'T': /* printing Type */
675 if (strcmp(ws_optarg, "text") == 0) {
676 output_action = WRITE_TEXT;
677 print_format = PR_FMT_TEXT;
678 } else if (strcmp(ws_optarg, "ps") == 0) {
679 output_action = WRITE_TEXT;
680 print_format = PR_FMT_PS;
681 } else if (strcmp(ws_optarg, "pdml") == 0) {
682 output_action = WRITE_XML;
683 print_details = TRUE; /* Need details */
684 print_summary = FALSE; /* Don't allow summary */
685 } else if (strcmp(ws_optarg, "psml") == 0) {
686 output_action = WRITE_XML;
687 print_details = FALSE; /* Don't allow details */
688 print_summary = TRUE; /* Need summary */
689 } else if (strcmp(ws_optarg, "fields") == 0) {
690 output_action = WRITE_FIELDS;
691 print_details = TRUE; /* Need full tree info */
692 print_summary = FALSE; /* Don't allow summary */
693 } else {
694 cmdarg_err("Invalid -T parameter \"%s\"; it must be one of:", ws_optarg); /* x */
695 cmdarg_err_cont("\t\"fields\" The values of fields specified with the -e option, in a form\n"
696 "\t specified by the -E option.\n"
697 "\t\"pdml\" Packet Details Markup Language, an XML-based format for the\n"
698 "\t details of a decoded packet. This information is equivalent to\n"
699 "\t the packet details printed with the -V flag.\n"
700 "\t\"ps\" PostScript for a human-readable one-line summary of each of\n"
701 "\t the packets, or a multi-line view of the details of each of\n"
702 "\t the packets, depending on whether the -V flag was specified.\n"
703 "\t\"psml\" Packet Summary Markup Language, an XML-based format for the\n"
704 "\t summary information of a decoded packet. This information is\n"
705 "\t equivalent to the information shown in the one-line summary\n"
706 "\t printed by default.\n"
707 "\t\"text\" Text of a human-readable one-line summary of each of the\n"
708 "\t packets, or a multi-line view of the details of each of the\n"
709 "\t packets, depending on whether the -V flag was specified.\n"
710 "\t This is the default.");
711 exit_status = WS_EXIT_INVALID_OPTION;
712 goto clean_exit;
714 break;
715 case 'v': /* Show version and exit */
716 show_version();
717 goto clean_exit;
718 case 'O': /* Only output these protocols */
719 /* already processed; just ignore it now */
720 break;
721 case 'V': /* Verbose */
722 /* already processed; just ignore it now */
723 break;
724 case 'x': /* Print packet data in hex (and ASCII) */
725 /* already processed; just ignore it now */
726 break;
727 case 'X':
728 /* already processed; just ignore it now */
729 break;
730 case 'Y':
731 dfilter = ws_optarg;
732 break;
733 case 'z':
734 /* We won't call the init function for the stat this soon
735 as it would disallow MATE's fields (which are registered
736 by the preferences set callback) from being used as
737 part of a tap filter. Instead, we just add the argument
738 to a list of stat arguments. */
739 if (strcmp("help", ws_optarg) == 0) {
740 fprintf(stderr, "tfshark: The available statistics for the \"-z\" option are:\n");
741 list_stat_cmd_args();
742 goto clean_exit;
744 if (!process_stat_cmd_arg(ws_optarg)) {
745 cmdarg_err("Invalid -z argument \"%s\"; it must be one of:", ws_optarg);
746 list_stat_cmd_args();
747 exit_status = WS_EXIT_INVALID_OPTION;
748 goto clean_exit;
750 break;
751 case 'd': /* Decode as rule */
752 case 'K': /* Kerberos keytab file */
753 case 't': /* Time stamp type */
754 case 'u': /* Seconds type */
755 case LONGOPT_DISABLE_PROTOCOL: /* disable dissection of protocol */
756 case LONGOPT_ENABLE_HEURISTIC: /* enable heuristic dissection of protocol */
757 case LONGOPT_DISABLE_HEURISTIC: /* disable heuristic dissection of protocol */
758 case LONGOPT_ENABLE_PROTOCOL: /* enable dissection of protocol (that is disabled by default) */
759 if (!dissect_opts_handle_opt(opt, ws_optarg)) {
760 exit_status = WS_EXIT_INVALID_OPTION;
761 goto clean_exit;
763 break;
764 default:
765 case '?': /* Bad flag - print usage message */
766 print_usage(stderr);
767 exit_status = WS_EXIT_INVALID_OPTION;
768 goto clean_exit;
769 break;
773 /* If we specified output fields, but not the output field type... */
774 if (WRITE_FIELDS != output_action && 0 != output_fields_num_fields(output_fields)) {
775 cmdarg_err("Output fields were specified with \"-e\", "
776 "but \"-Tfields\" was not specified.");
777 return 1;
778 } else if (WRITE_FIELDS == output_action && 0 == output_fields_num_fields(output_fields)) {
779 cmdarg_err("\"-Tfields\" was specified, but no fields were "
780 "specified with \"-e\".");
782 exit_status = WS_EXIT_INVALID_OPTION;
783 goto clean_exit;
786 /* We require a -r flag specifying a file to read. */
787 if (cf_name == NULL) {
788 cmdarg_err("A file to read must be specified with \"-r\".");
789 exit_status = NO_FILE_SPECIFIED;
790 goto clean_exit;
793 /* If no display filter has been specified, and there are still command-
794 line arguments, treat them as the tokens of a display filter. */
795 if (ws_optind < argc) {
796 if (dfilter != NULL) {
797 cmdarg_err("Display filters were specified both with \"-Y\" "
798 "and with additional command-line arguments.");
799 exit_status = WS_EXIT_INVALID_OPTION;
800 goto clean_exit;
802 dfilter = get_args_as_string(argc, argv, ws_optind);
805 /* if "-q" wasn't specified, we should print packet information */
806 if (!quiet)
807 print_packet_info = TRUE;
809 if (arg_error) {
810 print_usage(stderr);
811 exit_status = WS_EXIT_INVALID_OPTION;
812 goto clean_exit;
815 if (print_hex) {
816 if (output_action != WRITE_TEXT) {
817 cmdarg_err("Raw packet hex data can only be printed as text or PostScript");
818 exit_status = WS_EXIT_INVALID_OPTION;
819 goto clean_exit;
823 if (output_only != NULL) {
824 char *ps;
826 if (!print_details) {
827 cmdarg_err("-O requires -V");
828 exit_status = WS_EXIT_INVALID_OPTION;
829 goto clean_exit;
832 output_only_tables = g_hash_table_new (g_str_hash, g_str_equal);
833 for (ps = strtok (output_only, ","); ps; ps = strtok (NULL, ",")) {
834 g_hash_table_insert(output_only_tables, (gpointer)ps, (gpointer)ps);
838 if (rfilter != NULL && !perform_two_pass_analysis) {
839 cmdarg_err("-R without -2 is deprecated. For single-pass filtering use -Y.");
840 exit_status = WS_EXIT_INVALID_OPTION;
841 goto clean_exit;
844 /* Notify all registered modules that have had any of their preferences
845 changed either from one of the preferences file or from the command
846 line that their preferences have changed. */
847 prefs_apply_all();
850 * Enabled and disabled protocols and heuristic dissectors as per
851 * command-line options.
853 if (!setup_enabled_and_disabled_protocols()) {
854 exit_status = WS_EXIT_INVALID_OPTION;
855 goto clean_exit;
858 /* Build the column format array */
859 build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
861 if (rfilter != NULL) {
862 if (!dfilter_compile(rfilter, &rfcode, &df_err)) {
863 cmdarg_err("%s", df_err->msg);
864 df_error_free(&df_err);
865 exit_status = WS_EXIT_INVALID_FILTER;
866 goto clean_exit;
869 cfile.rfcode = rfcode;
871 if (dfilter != NULL) {
872 if (!dfilter_compile(dfilter, &dfcode, &df_err)) {
873 cmdarg_err("%s", df_err->msg);
874 df_error_free(&df_err);
875 exit_status = WS_EXIT_INVALID_FILTER;
876 goto clean_exit;
879 cfile.dfcode = dfcode;
881 if (print_packet_info) {
882 /* If we're printing as text or PostScript, we have
883 to create a print stream. */
884 if (output_action == WRITE_TEXT) {
885 switch (print_format) {
887 case PR_FMT_TEXT:
888 print_stream = print_stream_text_stdio_new(stdout);
889 break;
891 case PR_FMT_PS:
892 print_stream = print_stream_ps_stdio_new(stdout);
893 break;
895 default:
896 ws_assert_not_reached();
901 /* We have to dissect each packet if:
903 we're printing information about each packet;
905 we're using a read filter on the packets;
907 we're using a display filter on the packets;
909 we're using any taps that need dissection. */
910 do_dissection = print_packet_info || rfcode || dfcode || tap_listeners_require_dissection();
913 * Read the file.
916 /* TODO: if tfshark is ever changed to give the user a choice of which
917 open_routine reader to use, then the following needs to change. */
918 if (cf_open(&cfile, cf_name, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK) {
919 exit_status = WS_EXIT_OPEN_ERROR;
920 goto clean_exit;
923 /* Start statistics taps; we do so after successfully opening the
924 capture file, so we know we have something to compute stats
925 on, and after registering all dissectors, so that MATE will
926 have registered its field array so we can have a tap filter
927 with one of MATE's late-registered fields as part of the
928 filter. */
929 start_requested_stats();
931 /* Process the packets in the file */
932 TRY {
933 /* XXX - for now there is only 1 packet */
934 success = process_file(&cfile, 1, 0);
936 CATCH(OutOfMemoryError) {
937 fprintf(stderr,
938 "Out Of Memory.\n"
939 "\n"
940 "Sorry, but TFShark has to terminate now.\n"
941 "\n"
942 "Some infos / workarounds can be found at:\n"
943 WS_WIKI_URL("KnownBugs/OutOfMemory") "\n");
944 success = FALSE;
946 ENDTRY;
948 if (!success) {
949 /* We still dump out the results of taps, etc., as we might have
950 read some packets; however, we exit with an error status. */
951 exit_status = 2;
954 g_free(cf_name);
956 if (cfile.provider.frames != NULL) {
957 free_frame_data_sequence(cfile.provider.frames);
958 cfile.provider.frames = NULL;
961 draw_tap_listeners(TRUE);
962 funnel_dump_all_text_windows();
964 clean_exit:
965 destroy_print_stream(print_stream);
966 epan_free(cfile.epan);
967 epan_cleanup();
969 output_fields_free(output_fields);
970 output_fields = NULL;
972 col_cleanup(&cfile.cinfo);
973 wtap_cleanup();
974 return exit_status;
977 static const char *
978 no_interface_name(struct packet_provider_data *prov _U_, guint32 interface_id _U_, unsigned section_number _U_)
980 return "";
983 static epan_t *
984 tfshark_epan_new(capture_file *cf)
986 static const struct packet_provider_funcs funcs = {
987 /* XXX - there should be no need for time stamps */
988 cap_file_provider_get_frame_ts,
989 no_interface_name,
990 NULL,
991 NULL,
994 return epan_new(&cf->provider, &funcs);
997 static gboolean
998 process_packet_first_pass(capture_file *cf, epan_dissect_t *edt,
999 gint64 offset, wtap_rec *rec,
1000 const guchar *pd)
1002 frame_data fdlocal;
1003 guint32 framenum;
1004 gboolean passed;
1006 /* The frame number of this packet is one more than the count of
1007 frames in this packet. */
1008 framenum = cf->count + 1;
1010 /* If we're not running a display filter and we're not printing any
1011 packet information, we don't need to do a dissection. This means
1012 that all packets can be marked as 'passed'. */
1013 passed = TRUE;
1015 frame_data_init(&fdlocal, framenum, rec, offset, cum_bytes);
1017 /* If we're going to print packet information, or we're going to
1018 run a read filter, or display filter, or we're going to process taps, set up to
1019 do a dissection and do so. */
1020 if (edt) {
1021 /* If we're running a read filter, prime the epan_dissect_t with that
1022 filter. */
1023 if (cf->rfcode)
1024 epan_dissect_prime_with_dfilter(edt, cf->rfcode);
1026 /* This is the first pass, so prime the epan_dissect_t with the
1027 hfids postdissectors want on the first pass. */
1028 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1030 frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time,
1031 &cf->provider.ref, cf->provider.prev_dis);
1032 if (cf->provider.ref == &fdlocal) {
1033 ref_frame = fdlocal;
1034 cf->provider.ref = &ref_frame;
1037 epan_dissect_file_run(edt, rec,
1038 file_tvbuff_new(&cf->provider, &fdlocal, pd),
1039 &fdlocal, NULL);
1041 /* Run the read filter if we have one. */
1042 if (cf->rfcode)
1043 passed = dfilter_apply_edt(cf->rfcode, edt);
1046 if (passed) {
1047 frame_data_set_after_dissect(&fdlocal, &cum_bytes);
1048 cf->provider.prev_cap = cf->provider.prev_dis = frame_data_sequence_add(cf->provider.frames, &fdlocal);
1050 /* If we're not doing dissection then there won't be any dependent frames.
1051 * More importantly, edt.pi.fd.dependent_frames won't be initialized because
1052 * epan hasn't been initialized.
1054 if (edt && edt->pi.fd->dependent_frames) {
1055 g_hash_table_foreach(edt->pi.fd->dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
1058 cf->count++;
1059 } else {
1060 /* if we don't add it to the frame_data_sequence, clean it up right now
1061 * to avoid leaks */
1062 frame_data_destroy(&fdlocal);
1065 if (edt)
1066 epan_dissect_reset(edt);
1068 return passed;
1071 static gboolean
1072 process_packet_second_pass(capture_file *cf, epan_dissect_t *edt,
1073 frame_data *fdata, wtap_rec *rec,
1074 Buffer *buf)
1076 column_info *cinfo;
1077 gboolean passed;
1079 /* If we're not running a display filter and we're not printing any
1080 packet information, we don't need to do a dissection. This means
1081 that all packets can be marked as 'passed'. */
1082 passed = TRUE;
1084 /* If we're going to print packet information, or we're going to
1085 run a read filter, or we're going to process taps, set up to
1086 do a dissection and do so. */
1087 if (edt) {
1089 /* If we're running a display filter, prime the epan_dissect_t with that
1090 filter. */
1091 if (cf->dfcode)
1092 epan_dissect_prime_with_dfilter(edt, cf->dfcode);
1094 /* This is the first and only pass, so prime the epan_dissect_t
1095 with the hfids postdissectors want on the first pass. */
1096 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1098 col_custom_prime_edt(edt, &cf->cinfo);
1100 /* We only need the columns if either
1101 1) some tap needs the columns
1103 2) we're printing packet info but we're *not* verbose; in verbose
1104 mode, we print the protocol tree, not the protocol summary.
1106 if ((tap_listeners_require_columns()) || (print_packet_info && print_summary))
1107 cinfo = &cf->cinfo;
1108 else
1109 cinfo = NULL;
1111 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1112 &cf->provider.ref, cf->provider.prev_dis);
1113 if (cf->provider.ref == fdata) {
1114 ref_frame = *fdata;
1115 cf->provider.ref = &ref_frame;
1118 epan_dissect_file_run_with_taps(edt, rec,
1119 file_tvbuff_new_buffer(&cf->provider, fdata, buf), fdata, cinfo);
1121 /* Run the read/display filter if we have one. */
1122 if (cf->dfcode)
1123 passed = dfilter_apply_edt(cf->dfcode, edt);
1126 if (passed) {
1127 frame_data_set_after_dissect(fdata, &cum_bytes);
1128 /* Process this packet. */
1129 if (print_packet_info) {
1130 /* We're printing packet information; print the information for
1131 this packet. */
1132 print_packet(cf, edt);
1134 /* If we're doing "line-buffering", flush the standard output
1135 after every packet. See the comment above, for the "-l"
1136 option, for an explanation of why we do that. */
1137 if (line_buffered)
1138 fflush(stdout);
1140 if (ferror(stdout)) {
1141 show_print_file_io_error(errno);
1142 return FALSE;
1145 cf->provider.prev_dis = fdata;
1147 cf->provider.prev_cap = fdata;
1149 if (edt) {
1150 epan_dissect_reset(edt);
1152 return passed || fdata->dependent_of_displayed;
1155 static gboolean
1156 local_wtap_read(capture_file *cf, wtap_rec *file_rec _U_, int *err, gchar **err_info _U_, gint64 *data_offset _U_, guint8** data_buffer)
1158 /* int bytes_read; */
1159 gint64 packet_size = wtap_file_size(cf->provider.wth, err);
1161 *data_buffer = (guint8*)g_malloc((gsize)packet_size);
1162 /* bytes_read =*/ file_read(*data_buffer, (unsigned int)packet_size, cf->provider.wth->fh);
1164 #if 0 /* no more filetap */
1165 if (bytes_read < 0) {
1166 *err = file_error(cf->provider.wth->fh, err_info);
1167 if (*err == 0)
1168 *err = FTAP_ERR_SHORT_READ;
1169 return FALSE;
1170 } else if (bytes_read == 0) {
1171 /* Done with file, no error */
1172 return FALSE;
1176 /* XXX - SET FRAME SIZE EQUAL TO TOTAL FILE SIZE */
1177 file_rec->rec_header.packet_header.caplen = (guint32)packet_size;
1178 file_rec->rec_header.packet_header.len = (guint32)packet_size;
1181 * Set the packet encapsulation to the file's encapsulation
1182 * value; if that's not WTAP_ENCAP_PER_PACKET, it's the
1183 * right answer (and means that the read routine for this
1184 * capture file type doesn't have to set it), and if it
1185 * *is* WTAP_ENCAP_PER_PACKET, the caller needs to set it
1186 * anyway.
1188 wth->rec.rec_header.packet_header.pkt_encap = wth->file_encap;
1190 if (!wth->subtype_read(wth, err, err_info, data_offset)) {
1192 * If we didn't get an error indication, we read
1193 * the last packet. See if there's any deferred
1194 * error, as might, for example, occur if we're
1195 * reading a compressed file, and we got an error
1196 * reading compressed data from the file, but
1197 * got enough compressed data to decompress the
1198 * last packet of the file.
1200 if (*err == 0)
1201 *err = file_error(wth->fh, err_info);
1202 return FALSE; /* failure */
1206 * It makes no sense for the captured data length to be bigger
1207 * than the actual data length.
1209 if (wth->rec.rec_header.packet_header.caplen > wth->rec.rec_header.packet_header.len)
1210 wth->rec.rec_header.packet_header.caplen = wth->rec.rec_header.packet_header.len;
1213 * Make sure that it's not WTAP_ENCAP_PER_PACKET, as that
1214 * probably means the file has that encapsulation type
1215 * but the read routine didn't set this packet's
1216 * encapsulation type.
1218 ws_assert(wth->rec.rec_header.packet_header.pkt_encap != WTAP_ENCAP_PER_PACKET);
1219 #endif
1221 return TRUE; /* success */
1224 static gboolean
1225 process_file(capture_file *cf, int max_packet_count, gint64 max_byte_count)
1227 guint32 framenum;
1228 int err;
1229 gchar *err_info = NULL;
1230 gint64 data_offset = 0;
1231 gboolean filtering_tap_listeners;
1232 guint tap_flags;
1233 Buffer buf;
1234 epan_dissect_t *edt = NULL;
1235 wtap_rec file_rec;
1236 guint8* raw_data;
1238 if (print_packet_info) {
1239 if (!write_preamble(cf)) {
1240 err = errno;
1241 show_print_file_io_error(err);
1242 goto out;
1246 /* Do we have any tap listeners with filters? */
1247 filtering_tap_listeners = have_filtering_tap_listeners();
1249 /* Get the union of the flags for all tap listeners. */
1250 tap_flags = union_of_tap_listener_flags();
1252 wtap_rec_init(&file_rec);
1254 /* XXX - TEMPORARY HACK TO ELF DISSECTOR */
1255 file_rec.rec_header.packet_header.pkt_encap = 1234;
1257 if (perform_two_pass_analysis) {
1258 frame_data *fdata;
1260 /* Allocate a frame_data_sequence for all the frames. */
1261 cf->provider.frames = new_frame_data_sequence();
1263 if (do_dissection) {
1264 gboolean create_proto_tree;
1267 * Determine whether we need to create a protocol tree.
1268 * We do if:
1270 * we're going to apply a read filter;
1272 * a postdissector wants field values or protocols
1273 * on the first pass.
1275 create_proto_tree =
1276 (cf->rfcode != NULL || postdissectors_want_hfids());
1278 /* We're not going to display the protocol tree on this pass,
1279 so it's not going to be "visible". */
1280 edt = epan_dissect_new(cf->epan, create_proto_tree, FALSE);
1282 while (local_wtap_read(cf, &file_rec, &err, &err_info, &data_offset, &raw_data)) {
1283 if (process_packet_first_pass(cf, edt, data_offset, &file_rec, raw_data)) {
1285 /* Stop reading if we have the maximum number of packets;
1286 * When the -c option has not been used, max_packet_count
1287 * starts at 0, which practically means, never stop reading.
1288 * (unless we roll over max_packet_count ?)
1290 if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
1291 err = 0; /* This is not an error */
1292 break;
1297 if (edt) {
1298 epan_dissect_free(edt);
1299 edt = NULL;
1302 #if 0
1303 /* Close the sequential I/O side, to free up memory it requires. */
1304 wtap_sequential_close(cf->provider.wth);
1305 #endif
1307 /* Allow the protocol dissectors to free up memory that they
1308 * don't need after the sequential run-through of the packets. */
1309 postseq_cleanup_all_protocols();
1311 cf->provider.prev_dis = NULL;
1312 cf->provider.prev_cap = NULL;
1313 ws_buffer_init(&buf, 1514);
1315 if (do_dissection) {
1316 gboolean create_proto_tree;
1319 * Determine whether we need to create a protocol tree.
1320 * We do if:
1322 * we're going to apply a display filter;
1324 * we're going to print the protocol tree;
1326 * one of the tap listeners requires a protocol tree;
1328 * we have custom columns (which require field values, which
1329 * currently requires that we build a protocol tree).
1331 create_proto_tree =
1332 (cf->dfcode || print_details || filtering_tap_listeners ||
1333 (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo));
1335 /* The protocol tree will be "visible", i.e., printed, only if we're
1336 printing packet details, which is true if we're printing stuff
1337 ("print_packet_info" is true) and we're in verbose mode
1338 ("packet_details" is true). */
1339 edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details);
1342 for (framenum = 1; err == 0 && framenum <= cf->count; framenum++) {
1343 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1344 #if 0
1345 if (wtap_seek_read(cf->provider.wth, fdata->file_off,
1346 &buf, fdata->cap_len, &err, &err_info)) {
1347 process_packet_second_pass(cf, edt, fdata, &cf->rec, &buf, tap_flags);
1349 #else
1350 if (!process_packet_second_pass(cf, edt, fdata, &cf->rec, &buf))
1351 return FALSE;
1352 #endif
1355 if (edt) {
1356 epan_dissect_free(edt);
1357 edt = NULL;
1360 ws_buffer_free(&buf);
1362 else {
1363 framenum = 0;
1365 if (do_dissection) {
1366 gboolean create_proto_tree;
1369 * Determine whether we need to create a protocol tree.
1370 * We do if:
1372 * we're going to apply a read filter;
1374 * we're going to apply a display filter;
1376 * we're going to print the protocol tree;
1378 * one of the tap listeners is going to apply a filter;
1380 * one of the tap listeners requires a protocol tree;
1382 * a postdissector wants field values or protocols
1383 * on the first pass;
1385 * we have custom columns (which require field values, which
1386 * currently requires that we build a protocol tree).
1388 create_proto_tree =
1389 (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners ||
1390 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids() ||
1391 have_custom_cols(&cf->cinfo));
1393 /* The protocol tree will be "visible", i.e., printed, only if we're
1394 printing packet details, which is true if we're printing stuff
1395 ("print_packet_info" is true) and we're in verbose mode
1396 ("packet_details" is true). */
1397 edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details);
1400 while (local_wtap_read(cf, &file_rec, &err, &err_info, &data_offset, &raw_data)) {
1402 framenum++;
1404 if (!process_packet_single_pass(cf, edt, data_offset,
1405 &file_rec/*wtap_get_rec(cf->provider.wth)*/,
1406 raw_data))
1407 return FALSE;
1409 /* Stop reading if we have the maximum number of packets;
1410 * When the -c option has not been used, max_packet_count
1411 * starts at 0, which practically means, never stop reading.
1412 * (unless we roll over max_packet_count ?)
1414 if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
1415 err = 0; /* This is not an error */
1416 break;
1420 if (edt) {
1421 epan_dissect_free(edt);
1422 edt = NULL;
1426 wtap_rec_cleanup(&file_rec);
1428 if (err != 0) {
1430 * Print a message noting that the read failed somewhere along the line.
1432 * If we're printing packet data, and the standard output and error are
1433 * going to the same place, flush the standard output, so everything
1434 * buffered up is written, and then print a newline to the standard error
1435 * before printing the error message, to separate it from the packet
1436 * data. (Alas, that only works on UN*X; st_dev is meaningless, and
1437 * the _fstat() documentation at Microsoft doesn't indicate whether
1438 * st_ino is even supported.)
1440 #ifndef _WIN32
1441 if (print_packet_info) {
1442 ws_statb64 stat_stdout, stat_stderr;
1444 if (ws_fstat64(1, &stat_stdout) == 0 && ws_fstat64(2, &stat_stderr) == 0) {
1445 if (stat_stdout.st_dev == stat_stderr.st_dev &&
1446 stat_stdout.st_ino == stat_stderr.st_ino) {
1447 fflush(stdout);
1448 fprintf(stderr, "\n");
1452 #endif
1453 #if 0
1454 switch (err) {
1456 case FTAP_ERR_UNSUPPORTED:
1457 cmdarg_err("The file \"%s\" contains record data that TFShark doesn't support.\n(%s)",
1458 cf->filename, err_info);
1459 g_free(err_info);
1460 break;
1462 case FTAP_ERR_UNSUPPORTED_ENCAP:
1463 cmdarg_err("The file \"%s\" has a packet with a network type that TFShark doesn't support.\n(%s)",
1464 cf->filename, err_info);
1465 g_free(err_info);
1466 break;
1468 case FTAP_ERR_CANT_READ:
1469 cmdarg_err("An attempt to read from the file \"%s\" failed for some unknown reason.",
1470 cf->filename);
1471 break;
1473 case FTAP_ERR_SHORT_READ:
1474 cmdarg_err("The file \"%s\" appears to have been cut short in the middle of a packet.",
1475 cf->filename);
1476 break;
1478 case FTAP_ERR_BAD_FILE:
1479 cmdarg_err("The file \"%s\" appears to be damaged or corrupt.\n(%s)",
1480 cf->filename, err_info);
1481 g_free(err_info);
1482 break;
1484 case FTAP_ERR_DECOMPRESS:
1485 cmdarg_err("The compressed file \"%s\" appears to be damaged or corrupt.\n"
1486 "(%s)", cf->filename, err_info);
1487 break;
1489 default:
1490 cmdarg_err("An error occurred while reading the file \"%s\": %s.",
1491 cf->filename, ftap_strerror(err));
1492 break;
1494 #endif
1495 } else {
1496 if (print_packet_info) {
1497 if (!write_finale()) {
1498 err = errno;
1499 show_print_file_io_error(err);
1504 out:
1505 wtap_close(cf->provider.wth);
1506 cf->provider.wth = NULL;
1508 return (err != 0);
1511 static gboolean
1512 process_packet_single_pass(capture_file *cf, epan_dissect_t *edt, gint64 offset,
1513 wtap_rec *rec, const guchar *pd)
1515 frame_data fdata;
1516 column_info *cinfo;
1517 gboolean passed;
1519 /* Count this packet. */
1520 cf->count++;
1522 /* If we're not running a display filter and we're not printing any
1523 packet information, we don't need to do a dissection. This means
1524 that all packets can be marked as 'passed'. */
1525 passed = TRUE;
1527 frame_data_init(&fdata, cf->count, rec, offset, cum_bytes);
1529 /* If we're going to print packet information, or we're going to
1530 run a read filter, or we're going to process taps, set up to
1531 do a dissection and do so. */
1532 if (edt) {
1533 /* If we're running a filter, prime the epan_dissect_t with that
1534 filter. */
1535 if (cf->dfcode)
1536 epan_dissect_prime_with_dfilter(edt, cf->dfcode);
1538 col_custom_prime_edt(edt, &cf->cinfo);
1540 /* We only need the columns if either
1541 1) some tap needs the columns
1543 2) we're printing packet info but we're *not* verbose; in verbose
1544 mode, we print the protocol tree, not the protocol summary.
1546 3) there is a column mapped as an individual field */
1547 if ((tap_listeners_require_columns()) || (print_packet_info && print_summary) || output_fields_has_cols(output_fields))
1548 cinfo = &cf->cinfo;
1549 else
1550 cinfo = NULL;
1552 frame_data_set_before_dissect(&fdata, &cf->elapsed_time,
1553 &cf->provider.ref, cf->provider.prev_dis);
1554 if (cf->provider.ref == &fdata) {
1555 ref_frame = fdata;
1556 cf->provider.ref = &ref_frame;
1559 epan_dissect_file_run_with_taps(edt, rec,
1560 frame_tvbuff_new(&cf->provider, &fdata, pd),
1561 &fdata, cinfo);
1563 /* Run the filter if we have it. */
1564 if (cf->dfcode)
1565 passed = dfilter_apply_edt(cf->dfcode, edt);
1568 if (passed) {
1569 frame_data_set_after_dissect(&fdata, &cum_bytes);
1571 /* Process this packet. */
1572 if (print_packet_info) {
1573 /* We're printing packet information; print the information for
1574 this packet. */
1575 print_packet(cf, edt);
1577 /* If we're doing "line-buffering", flush the standard output
1578 after every packet. See the comment above, for the "-l"
1579 option, for an explanation of why we do that. */
1580 if (line_buffered)
1581 fflush(stdout);
1583 if (ferror(stdout)) {
1584 show_print_file_io_error(errno);
1585 return FALSE;
1589 /* this must be set after print_packet() [bug #8160] */
1590 prev_dis_frame = fdata;
1591 cf->provider.prev_dis = &prev_dis_frame;
1594 prev_cap_frame = fdata;
1595 cf->provider.prev_cap = &prev_cap_frame;
1597 if (edt) {
1598 epan_dissect_reset(edt);
1599 frame_data_destroy(&fdata);
1601 return passed;
1604 static gboolean
1605 write_preamble(capture_file *cf)
1607 switch (output_action) {
1609 case WRITE_TEXT:
1610 return print_preamble(print_stream, cf->filename, get_ws_vcs_version_info());
1612 case WRITE_XML:
1613 if (print_details)
1614 write_pdml_preamble(stdout, cf->filename);
1615 else
1616 write_psml_preamble(&cf->cinfo, stdout);
1617 return !ferror(stdout);
1619 case WRITE_FIELDS:
1620 write_fields_preamble(output_fields, stdout);
1621 return !ferror(stdout);
1623 default:
1624 ws_assert_not_reached();
1625 return FALSE;
1629 static char *
1630 get_line_buf(size_t len)
1632 static char *line_bufp = NULL;
1633 static size_t line_buf_len = 256;
1634 size_t new_line_buf_len;
1636 for (new_line_buf_len = line_buf_len; len > new_line_buf_len;
1637 new_line_buf_len *= 2)
1639 if (line_bufp == NULL) {
1640 line_buf_len = new_line_buf_len;
1641 line_bufp = (char *)g_malloc(line_buf_len + 1);
1642 } else {
1643 if (new_line_buf_len > line_buf_len) {
1644 line_buf_len = new_line_buf_len;
1645 line_bufp = (char *)g_realloc(line_bufp, line_buf_len + 1);
1648 return line_bufp;
1651 static inline void
1652 put_string(char *dest, const char *str, size_t str_len)
1654 memcpy(dest, str, str_len);
1655 dest[str_len] = '\0';
1658 static inline void
1659 put_spaces_string(char *dest, const char *str, size_t str_len, size_t str_with_spaces)
1661 size_t i;
1663 for (i = str_len; i < str_with_spaces; i++)
1664 *dest++ = ' ';
1666 put_string(dest, str, str_len);
1669 static inline void
1670 put_string_spaces(char *dest, const char *str, size_t str_len, size_t str_with_spaces)
1672 size_t i;
1674 memcpy(dest, str, str_len);
1675 for (i = str_len; i < str_with_spaces; i++)
1676 dest[i] = ' ';
1678 dest[str_with_spaces] = '\0';
1681 static gboolean
1682 print_columns(capture_file *cf)
1684 char *line_bufp;
1685 int i;
1686 size_t buf_offset;
1687 size_t column_len;
1688 size_t col_len;
1689 col_item_t* col_item;
1691 line_bufp = get_line_buf(256);
1692 buf_offset = 0;
1693 *line_bufp = '\0';
1694 for (i = 0; i < cf->cinfo.num_cols; i++) {
1695 col_item = &cf->cinfo.columns[i];
1696 /* Skip columns not marked as visible. */
1697 if (!get_column_visible(i))
1698 continue;
1699 const gchar* col_text = get_column_text(&cf->cinfo, i);
1700 switch (col_item->col_fmt) {
1701 case COL_NUMBER:
1702 column_len = col_len = strlen(col_text);
1703 if (column_len < 3)
1704 column_len = 3;
1705 line_bufp = get_line_buf(buf_offset + column_len);
1706 put_spaces_string(line_bufp + buf_offset, col_text, col_len, column_len);
1707 break;
1709 case COL_CLS_TIME:
1710 case COL_REL_TIME:
1711 case COL_ABS_TIME:
1712 case COL_ABS_YMD_TIME: /* XXX - wider */
1713 case COL_ABS_YDOY_TIME: /* XXX - wider */
1714 case COL_UTC_TIME:
1715 case COL_UTC_YMD_TIME: /* XXX - wider */
1716 case COL_UTC_YDOY_TIME: /* XXX - wider */
1717 column_len = col_len = strlen(col_text);
1718 if (column_len < 10)
1719 column_len = 10;
1720 line_bufp = get_line_buf(buf_offset + column_len);
1721 put_spaces_string(line_bufp + buf_offset, col_text, col_len, column_len);
1722 break;
1724 case COL_DEF_SRC:
1725 case COL_RES_SRC:
1726 case COL_UNRES_SRC:
1727 case COL_DEF_DL_SRC:
1728 case COL_RES_DL_SRC:
1729 case COL_UNRES_DL_SRC:
1730 case COL_DEF_NET_SRC:
1731 case COL_RES_NET_SRC:
1732 case COL_UNRES_NET_SRC:
1733 column_len = col_len = strlen(col_text);
1734 if (column_len < 12)
1735 column_len = 12;
1736 line_bufp = get_line_buf(buf_offset + column_len);
1737 put_spaces_string(line_bufp + buf_offset, col_text, col_len, column_len);
1738 break;
1740 case COL_DEF_DST:
1741 case COL_RES_DST:
1742 case COL_UNRES_DST:
1743 case COL_DEF_DL_DST:
1744 case COL_RES_DL_DST:
1745 case COL_UNRES_DL_DST:
1746 case COL_DEF_NET_DST:
1747 case COL_RES_NET_DST:
1748 case COL_UNRES_NET_DST:
1749 column_len = col_len = strlen(col_text);
1750 if (column_len < 12)
1751 column_len = 12;
1752 line_bufp = get_line_buf(buf_offset + column_len);
1753 put_string_spaces(line_bufp + buf_offset, col_text, col_len, column_len);
1754 break;
1756 default:
1757 column_len = strlen(col_text);
1758 line_bufp = get_line_buf(buf_offset + column_len);
1759 put_string(line_bufp + buf_offset, col_text, column_len);
1760 break;
1762 buf_offset += column_len;
1763 if (i != cf->cinfo.num_cols - 1) {
1765 * This isn't the last column, so we need to print a
1766 * separator between this column and the next.
1768 * If we printed a network source and are printing a
1769 * network destination of the same type next, separate
1770 * them with " -> "; if we printed a network destination
1771 * and are printing a network source of the same type
1772 * next, separate them with " <- "; otherwise separate them
1773 * with a space.
1775 * We add enough space to the buffer for " <- " or " -> ",
1776 * even if we're only adding " ".
1778 line_bufp = get_line_buf(buf_offset + 4);
1779 switch (col_item->col_fmt) {
1781 case COL_DEF_SRC:
1782 case COL_RES_SRC:
1783 case COL_UNRES_SRC:
1784 switch (cf->cinfo.columns[i+1].col_fmt) {
1786 case COL_DEF_DST:
1787 case COL_RES_DST:
1788 case COL_UNRES_DST:
1789 put_string(line_bufp + buf_offset, " -> ", 4);
1790 buf_offset += 4;
1791 break;
1793 default:
1794 put_string(line_bufp + buf_offset, " ", 1);
1795 buf_offset += 1;
1796 break;
1798 break;
1800 case COL_DEF_DL_SRC:
1801 case COL_RES_DL_SRC:
1802 case COL_UNRES_DL_SRC:
1803 switch (cf->cinfo.columns[i+1].col_fmt) {
1805 case COL_DEF_DL_DST:
1806 case COL_RES_DL_DST:
1807 case COL_UNRES_DL_DST:
1808 put_string(line_bufp + buf_offset, " -> ", 4);
1809 buf_offset += 4;
1810 break;
1812 default:
1813 put_string(line_bufp + buf_offset, " ", 1);
1814 buf_offset += 1;
1815 break;
1817 break;
1819 case COL_DEF_NET_SRC:
1820 case COL_RES_NET_SRC:
1821 case COL_UNRES_NET_SRC:
1822 switch (cf->cinfo.columns[i+1].col_fmt) {
1824 case COL_DEF_NET_DST:
1825 case COL_RES_NET_DST:
1826 case COL_UNRES_NET_DST:
1827 put_string(line_bufp + buf_offset, " -> ", 4);
1828 buf_offset += 4;
1829 break;
1831 default:
1832 put_string(line_bufp + buf_offset, " ", 1);
1833 buf_offset += 1;
1834 break;
1836 break;
1838 case COL_DEF_DST:
1839 case COL_RES_DST:
1840 case COL_UNRES_DST:
1841 switch (cf->cinfo.columns[i+1].col_fmt) {
1843 case COL_DEF_SRC:
1844 case COL_RES_SRC:
1845 case COL_UNRES_SRC:
1846 put_string(line_bufp + buf_offset, " <- ", 4);
1847 buf_offset += 4;
1848 break;
1850 default:
1851 put_string(line_bufp + buf_offset, " ", 1);
1852 buf_offset += 1;
1853 break;
1855 break;
1857 case COL_DEF_DL_DST:
1858 case COL_RES_DL_DST:
1859 case COL_UNRES_DL_DST:
1860 switch (cf->cinfo.columns[i+1].col_fmt) {
1862 case COL_DEF_DL_SRC:
1863 case COL_RES_DL_SRC:
1864 case COL_UNRES_DL_SRC:
1865 put_string(line_bufp + buf_offset, " <- ", 4);
1866 buf_offset += 4;
1867 break;
1869 default:
1870 put_string(line_bufp + buf_offset, " ", 1);
1871 buf_offset += 1;
1872 break;
1874 break;
1876 case COL_DEF_NET_DST:
1877 case COL_RES_NET_DST:
1878 case COL_UNRES_NET_DST:
1879 switch (cf->cinfo.columns[i+1].col_fmt) {
1881 case COL_DEF_NET_SRC:
1882 case COL_RES_NET_SRC:
1883 case COL_UNRES_NET_SRC:
1884 put_string(line_bufp + buf_offset, " <- ", 4);
1885 buf_offset += 4;
1886 break;
1888 default:
1889 put_string(line_bufp + buf_offset, " ", 1);
1890 buf_offset += 1;
1891 break;
1893 break;
1895 default:
1896 put_string(line_bufp + buf_offset, " ", 1);
1897 buf_offset += 1;
1898 break;
1902 return print_line(print_stream, 0, line_bufp);
1905 static gboolean
1906 print_packet(capture_file *cf, epan_dissect_t *edt)
1908 if (print_summary || output_fields_has_cols(output_fields)) {
1909 /* Just fill in the columns. */
1910 epan_dissect_fill_in_columns(edt, FALSE, TRUE);
1912 if (print_summary) {
1913 /* Now print them. */
1914 switch (output_action) {
1916 case WRITE_TEXT:
1917 if (!print_columns(cf))
1918 return FALSE;
1919 break;
1921 case WRITE_XML:
1922 write_psml_columns(edt, stdout, FALSE);
1923 return !ferror(stdout);
1924 case WRITE_FIELDS: /*No non-verbose "fields" format */
1925 ws_assert_not_reached();
1926 break;
1930 if (print_details) {
1931 /* Print the information in the protocol tree. */
1932 switch (output_action) {
1934 case WRITE_TEXT:
1935 if (!proto_tree_print(print_details ? print_dissections_expanded : print_dissections_none,
1936 print_hex, edt, output_only_tables, print_stream))
1937 return FALSE;
1938 if (!print_hex) {
1939 if (!print_line(print_stream, 0, separator))
1940 return FALSE;
1942 break;
1944 case WRITE_XML:
1945 write_pdml_proto_tree(NULL, edt, &cf->cinfo, stdout, FALSE);
1946 printf("\n");
1947 return !ferror(stdout);
1948 case WRITE_FIELDS:
1949 write_fields_proto_tree(output_fields, edt, &cf->cinfo, stdout);
1950 printf("\n");
1951 return !ferror(stdout);
1954 if (print_hex) {
1955 if (print_summary || print_details) {
1956 if (!print_line(print_stream, 0, ""))
1957 return FALSE;
1959 if (!print_hex_data(print_stream, edt, HEXDUMP_SOURCE_MULTI | HEXDUMP_ASCII_INCLUDE))
1960 return FALSE;
1961 if (!print_line(print_stream, 0, separator))
1962 return FALSE;
1964 return TRUE;
1967 static gboolean
1968 write_finale(void)
1970 switch (output_action) {
1972 case WRITE_TEXT:
1973 return print_finale(print_stream);
1975 case WRITE_XML:
1976 if (print_details)
1977 write_pdml_finale(stdout);
1978 else
1979 write_psml_finale(stdout);
1980 return !ferror(stdout);
1982 case WRITE_FIELDS:
1983 write_fields_finale(output_fields, stdout);
1984 return !ferror(stdout);
1986 default:
1987 ws_assert_not_reached();
1988 return FALSE;
1992 cf_status_t
1993 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err _U_)
1995 /* The open isn't implemented yet. Fill in the information for this file. */
1997 /* Create new epan session for dissection. */
1998 epan_free(cf->epan);
1999 cf->epan = tfshark_epan_new(cf);
2001 cf->provider.wth = NULL; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2002 cf->f_datalen = 0; /* not used, but set it anyway */
2004 /* Set the file name because we need it to set the follow stream filter.
2005 XXX - is that still true? We need it for other reasons, though,
2006 in any case. */
2007 cf->filename = g_strdup(fname);
2009 /* Indicate whether it's a permanent or temporary file. */
2010 cf->is_tempfile = is_tempfile;
2012 /* No user changes yet. */
2013 cf->unsaved_changes = FALSE;
2015 cf->cd_t = 0; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2016 cf->open_type = type;
2017 cf->count = 0;
2018 cf->drops_known = FALSE;
2019 cf->drops = 0;
2020 cf->snap = 0; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2021 nstime_set_zero(&cf->elapsed_time);
2022 cf->provider.ref = NULL;
2023 cf->provider.prev_dis = NULL;
2024 cf->provider.prev_cap = NULL;
2026 cf->state = FILE_READ_IN_PROGRESS;
2028 return CF_OK;
2030 /* fail: */
2032 gchar *err_info;
2033 char err_msg[2048+1];
2034 snprintf(err_msg, sizeof err_msg,
2035 cf_open_error_message(*err, err_info, FALSE, cf->cd_t), fname);
2036 cmdarg_err("%s", err_msg);
2037 return CF_ERROR;
2041 static void
2042 show_print_file_io_error(int err)
2044 switch (err) {
2046 case ENOSPC:
2047 cmdarg_err("Not all the packets could be printed because there is "
2048 "no space left on the file system.");
2049 break;
2051 #ifdef EDQUOT
2052 case EDQUOT:
2053 cmdarg_err("Not all the packets could be printed because you are "
2054 "too close to, or over your disk quota.");
2055 break;
2056 #endif
2058 default:
2059 cmdarg_err("An error occurred while printing packets: %s.",
2060 g_strerror(err));
2061 break;
2066 * Report an error in command-line arguments.
2068 static void
2069 tfshark_cmdarg_err(const char *msg_format, va_list ap)
2071 fprintf(stderr, "tfshark: ");
2072 vfprintf(stderr, msg_format, ap);
2073 fprintf(stderr, "\n");
2077 * Report additional information for an error in command-line arguments.
2079 static void
2080 tfshark_cmdarg_err_cont(const char *msg_format, va_list ap)
2082 vfprintf(stderr, msg_format, ap);
2083 fprintf(stderr, "\n");