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
26 #ifndef HAVE_GETOPT_LONG
27 #include "wsutil/wsgetopt.h"
32 #include <epan/exceptions.h>
33 #include <epan/epan.h>
35 #include <wsutil/clopts_common.h>
36 #include <wsutil/cmdarg_err.h>
37 #include <wsutil/crash_info.h>
38 #include <wsutil/filesystem.h>
39 #include <wsutil/file_util.h>
40 #include <wsutil/privileges.h>
41 #include <wsutil/report_message.h>
42 #include <version_info.h>
45 #include <epan/timestamp.h>
46 #include <epan/packet.h>
48 #include <epan/wslua/init_wslua.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>
58 #include "ui/decode_as_utils.h"
59 #include "ui/dissect_opts.h"
60 #include <epan/epan_dissect.h>
62 #include <epan/stat_tap_ui.h>
63 #include <epan/ex-opt.h>
66 #include <wiretap/wtap-int.h>
67 #include <wiretap/file_wrappers.h>
70 #include <wsutil/unicode-utils.h>
74 #include <epan/funnel.h>
77 #include <wsutil/plugins.h>
80 #define INVALID_OPTION 1
81 #define NO_FILE_SPECIFIED 1
83 #define INVALID_FILTER 2
88 static guint32 cum_bytes;
89 static frame_data ref_frame;
90 static frame_data prev_dis_frame;
91 static frame_data prev_cap_frame;
93 static gboolean prefs_loaded = FALSE;
95 static gboolean perform_two_pass_analysis;
98 * The way the packet decode is to be written.
101 WRITE_TEXT, /* summary or detail text */
102 WRITE_XML, /* PDML or PSML */
103 WRITE_FIELDS /* User defined list of fields */
104 /* Add CSV and the like here */
107 static output_action_e output_action;
108 static gboolean do_dissection; /* TRUE if we have to dissect each packet */
109 static gboolean print_packet_info; /* TRUE if we're to print packet information */
110 static gint print_summary = -1; /* TRUE if we're to print packet summary information */
111 static gboolean print_details; /* TRUE if we're to print packet details information */
112 static gboolean print_hex; /* TRUE if we're to print hex/ascci information */
113 static gboolean line_buffered;
114 static gboolean really_quiet = FALSE;
116 static print_format_e print_format = PR_FMT_TEXT;
117 static print_stream_t *print_stream;
119 static output_fields_t* output_fields = NULL;
121 /* The line separator used between packets, changeable via the -S option */
122 static const char *separator = "";
124 static gboolean process_file(capture_file *, int, gint64);
125 static gboolean process_packet_single_pass(capture_file *cf,
126 epan_dissect_t *edt, gint64 offset, wtap_rec *rec,
127 const guchar *pd, guint tap_flags);
128 static void show_print_file_io_error(int err);
129 static gboolean write_preamble(capture_file *cf);
130 static gboolean print_packet(capture_file *cf, epan_dissect_t *edt);
131 static gboolean write_finale(void);
132 static const char *cf_open_error_message(int err, gchar *err_info,
133 gboolean for_writing, int file_type);
135 static void failure_warning_message(const char *msg_format, va_list ap);
136 static void open_failure_message(const char *filename, int err,
137 gboolean for_writing);
138 static void read_failure_message(const char *filename, int err);
139 static void write_failure_message(const char *filename, int err);
140 static void failure_message_cont(const char *msg_format, va_list ap);
142 static GHashTable *output_only_tables = NULL;
146 const char *sstr; /* The short string */
147 const char *lstr; /* The long string */
151 string_compare(gconstpointer a, gconstpointer b)
153 return strcmp(((const struct string_elem *)a)->sstr,
154 ((const struct string_elem *)b)->sstr);
158 string_elem_print(gpointer data, gpointer not_used _U_)
160 fprintf(stderr, " %s - %s\n",
161 ((struct string_elem *)data)->sstr,
162 ((struct string_elem *)data)->lstr);
167 print_usage(FILE *output)
169 fprintf(output, "\n");
170 fprintf(output, "Usage: tfshark [options] ...\n");
171 fprintf(output, "\n");
173 /*fprintf(output, "\n");*/
174 fprintf(output, "Input file:\n");
175 fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin)\n");
177 fprintf(output, "\n");
178 fprintf(output, "Processing:\n");
179 fprintf(output, " -2 perform a two-pass analysis\n");
180 fprintf(output, " -R <read filter> packet Read filter in Wireshark display filter syntax\n");
181 fprintf(output, " (requires -2)\n");
182 fprintf(output, " -Y <display filter> packet displaY filter in Wireshark display filter\n");
183 fprintf(output, " syntax\n");
184 fprintf(output, " -d %s ...\n", DECODE_AS_ARG_TEMPLATE);
185 fprintf(output, " \"Decode As\", see the man page for details\n");
186 fprintf(output, " Example: tcp.port==8888,http\n");
188 /*fprintf(output, "\n");*/
189 fprintf(output, "Output:\n");
190 fprintf(output, " -C <config profile> start with specified configuration profile\n");
191 fprintf(output, " -V add output of packet tree (Packet Details)\n");
192 fprintf(output, " -O <protocols> Only show packet details of these protocols, comma\n");
193 fprintf(output, " separated\n");
194 fprintf(output, " -S <separator> the line separator to print between packets\n");
195 fprintf(output, " -x add output of hex and ASCII dump (Packet Bytes)\n");
196 fprintf(output, " -T pdml|ps|psml|text|fields\n");
197 fprintf(output, " format of text output (def: text)\n");
198 fprintf(output, " -e <field> field to print if -Tfields selected (e.g. tcp.port,\n");
199 fprintf(output, " _ws.col.Info)\n");
200 fprintf(output, " this option can be repeated to print multiple fields\n");
201 fprintf(output, " -E<fieldsoption>=<value> set options for output when -Tfields selected:\n");
202 fprintf(output, " header=y|n switch headers on and off\n");
203 fprintf(output, " separator=/t|/s|<char> select tab, space, printable character as separator\n");
204 fprintf(output, " occurrence=f|l|a print first, last or all occurrences of each field\n");
205 fprintf(output, " aggregator=,|/s|<char> select comma, space, printable character as\n");
206 fprintf(output, " aggregator\n");
207 fprintf(output, " quote=d|s|n select double, single, no quotes for values\n");
208 fprintf(output, " -t a|ad|d|dd|e|r|u|ud output format of time stamps (def: r: rel. to first)\n");
209 fprintf(output, " -u s|hms output format of seconds (def: s: seconds)\n");
210 fprintf(output, " -l flush standard output after each packet\n");
211 fprintf(output, " -q be more quiet on stdout (e.g. when using statistics)\n");
212 fprintf(output, " -Q only log true errors to stderr (quieter than -q)\n");
213 fprintf(output, " -X <key>:<value> eXtension options, see the man page for details\n");
214 fprintf(output, " -z <statistics> various statistics, see the man page for details\n");
216 fprintf(output, "\n");
217 fprintf(output, "Miscellaneous:\n");
218 fprintf(output, " -h display this help and exit\n");
219 fprintf(output, " -v display version info and exit\n");
220 fprintf(output, " -o <name>:<value> ... override preference setting\n");
221 fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
222 fprintf(output, " -G [report] dump one of several available reports and exit\n");
223 fprintf(output, " default report=\"fields\"\n");
224 fprintf(output, " use \"-G ?\" for more help\n");
228 glossary_option_help(void)
234 fprintf(output, "TFShark (Wireshark) %s\n", get_ws_vcs_version_info());
236 fprintf(output, "\n");
237 fprintf(output, "Usage: tfshark -G [report]\n");
238 fprintf(output, "\n");
239 fprintf(output, "Glossary table reports:\n");
240 fprintf(output, " -G column-formats dump column format codes and exit\n");
241 fprintf(output, " -G decodes dump \"layer type\"/\"decode as\" associations and exit\n");
242 fprintf(output, " -G dissector-tables dump dissector table names, types, and properties\n");
243 fprintf(output, " -G fields dump fields glossary and exit\n");
244 fprintf(output, " -G ftypes dump field type basic and descriptive names\n");
245 fprintf(output, " -G heuristic-decodes dump heuristic dissector tables\n");
246 fprintf(output, " -G plugins dump installed plugins and exit\n");
247 fprintf(output, " -G protocols dump protocols in registration database and exit\n");
248 fprintf(output, " -G values dump value, range, true/false strings and exit\n");
249 fprintf(output, "\n");
250 fprintf(output, "Preference reports:\n");
251 fprintf(output, " -G currentprefs dump current preferences and exit\n");
252 fprintf(output, " -G defaultprefs dump default preferences and exit\n");
253 fprintf(output, "\n");
257 tfshark_log_handler (const gchar *log_domain, GLogLevelFlags log_level,
258 const gchar *message, gpointer user_data)
260 /* ignore log message, if log_level isn't interesting based
261 upon the console log preferences.
262 If the preferences haven't been loaded yet, display the
265 The default console_log_level preference value is such that only
266 ERROR, CRITICAL and WARNING level messages are processed;
267 MESSAGE, INFO and DEBUG level messages are ignored.
269 XXX: Aug 07, 2009: Prior tshark g_log code was hardwired to process only
270 ERROR and CRITICAL level messages so the current code is a behavioral
271 change. The current behavior is the same as in Wireshark.
273 if (prefs_loaded && (log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0) {
277 g_log_default_handler(log_domain, log_level, message, user_data);
282 print_current_user(void) {
283 gchar *cur_user, *cur_group;
285 if (started_with_special_privs()) {
286 cur_user = get_cur_username();
287 cur_group = get_cur_groupname();
288 fprintf(stderr, "Running as user \"%s\" and group \"%s\".",
289 cur_user, cur_group);
292 if (running_with_special_privs()) {
293 fprintf(stderr, " This could be dangerous.");
295 fprintf(stderr, "\n");
300 get_tfshark_runtime_version_info(GString *str)
302 /* stuff used by libwireshark */
303 epan_get_runtime_version_info(str);
307 real_main(int argc, char *argv[])
309 GString *comp_info_str;
310 GString *runtime_info_str;
311 char *init_progfile_dir_error;
313 static const struct option long_options[] = {
314 {"help", no_argument, NULL, 'h'},
315 {"version", no_argument, NULL, 'v'},
318 gboolean arg_error = FALSE;
321 volatile gboolean success;
322 volatile int exit_status = 0;
323 gboolean quiet = FALSE;
324 gchar *volatile cf_name = NULL;
325 gchar *rfilter = NULL;
326 gchar *dfilter = NULL;
327 dfilter_t *rfcode = NULL;
328 dfilter_t *dfcode = NULL;
332 gchar *output_only = NULL;
335 * The leading + ensures that getopt_long() does not permute the argv[]
338 * We have to make sure that the first getopt_long() preserves the content
339 * of argv[] for the subsequent getopt_long() call.
341 * We use getopt_long() in both cases to ensure that we're using a routine
342 * whose permutation behavior we can control in the same fashion on all
343 * platforms, and so that, if we ever need to process a long argument before
344 * doing further initialization, we can do so.
346 * Glibc and Solaris libc document that a leading + disables permutation
347 * of options, regardless of whether POSIXLY_CORRECT is set or not; *BSD
348 * and macOS don't document it, but do so anyway.
350 * We do *not* use a leading - because the behavior of a leading - is
351 * platform-dependent.
353 #define OPTSTRING "+2C:d:e:E:hK:lo:O:qQr:R:S:t:T:u:vVxX:Y:z:"
355 static const char optstring[] = OPTSTRING;
357 /* Set the C-language locale to the native environment. */
358 setlocale(LC_ALL, "");
360 cmdarg_err_init(failure_warning_message, failure_message_cont);
363 create_app_running_mutex();
367 * Get credential information for later use, and drop privileges
368 * before doing anything else.
369 * Let the user know if anything happened.
371 init_process_policies();
372 relinquish_special_privs_perm();
373 print_current_user();
376 * Attempt to get the pathname of the directory containing the
379 init_progfile_dir_error = init_progfile_dir(argv[0]);
380 if (init_progfile_dir_error != NULL) {
382 "tfshark: Can't get pathname of directory containing the tfshark program: %s.\n",
383 init_progfile_dir_error);
384 g_free(init_progfile_dir_error);
387 initialize_funnel_ops();
389 /* Get the compile-time version information string */
390 comp_info_str = get_compiled_version_info(NULL, epan_get_compiled_version_info);
392 /* Get the run-time version information string */
393 runtime_info_str = get_runtime_version_info(get_tfshark_runtime_version_info);
395 /* Add it to the information to be reported on a crash. */
396 ws_add_crash_info("TFShark (Wireshark) %s\n"
401 get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
402 g_string_free(comp_info_str, TRUE);
403 g_string_free(runtime_info_str, TRUE);
406 * In order to have the -X opts assigned before the wslua machine starts
407 * we need to call getopts before epan_init() gets called.
409 * In order to handle, for example, -o options, we also need to call it
410 * *after* epan_init() gets called, so that the dissectors have had a
411 * chance to register their preferences.
413 * XXX - can we do this all with one getopt_long() call, saving the
414 * arguments we can't handle until after initializing libwireshark,
415 * and then process them after initializing libwireshark?
419 while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
421 case 'C': /* Configuration Profile */
422 if (profile_exists (optarg, FALSE)) {
423 set_profile_name (optarg);
425 cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
429 case 'O': /* Only output these protocols */
430 output_only = g_strdup(optarg);
432 case 'V': /* Verbose */
433 print_details = TRUE;
434 print_packet_info = TRUE;
436 case 'x': /* Print packet data in hex (and ASCII) */
438 /* The user asked for hex output, so let's ensure they get it,
439 * even if they're writing to a file.
441 print_packet_info = TRUE;
452 * Print packet summary information is the default, unless either -V or -x
453 * were specified. Note that this is new behavior, which
454 * allows for the possibility of printing only hex/ascii output without
455 * necessarily requiring that either the summary or details be printed too.
457 if (print_summary == -1)
458 print_summary = (print_details || print_hex) ? FALSE : TRUE;
460 /** Send All g_log messages to our own handler **/
464 G_LOG_LEVEL_CRITICAL|
469 G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
471 g_log_set_handler(NULL,
472 (GLogLevelFlags)log_flags,
473 tfshark_log_handler, NULL /* user_data */);
474 g_log_set_handler(LOG_DOMAIN_MAIN,
475 (GLogLevelFlags)log_flags,
476 tfshark_log_handler, NULL /* user_data */);
478 init_report_message(failure_warning_message, failure_warning_message,
479 open_failure_message, read_failure_message,
480 write_failure_message);
482 timestamp_set_type(TS_RELATIVE);
483 timestamp_set_precision(TS_PREC_AUTO);
484 timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
488 /* Register all dissectors; we must do this before checking for the
489 "-G" flag, as the "-G" flag dumps information registered by the
490 dissectors, and we must do it before we read the preferences, in
491 case any dissectors register preferences. */
492 if (!epan_init(NULL, NULL, TRUE)) {
493 exit_status = INIT_ERROR;
497 /* Register all tap listeners; we do this before we parse the arguments,
498 as the "-z" argument can specify a registered tap. */
500 /* we register the plugin taps before the other taps because
501 stats_tree taps plugins will be registered as tap listeners
502 by stats_tree_stat.c and need to registered before that */
504 /* XXX Disable tap registration for now until we can get tfshark set up with
505 * its own set of taps and the necessary registration function etc.
507 register_all_plugin_tap_listeners();
509 register_all_tap_listeners();
512 /* If invoked with the "-G" flag, we dump out information based on
513 the argument to the "-G" flag; if no argument is specified,
514 for backwards compatibility we dump out a glossary of display
517 XXX - we do this here, for now, to support "-G" with no arguments.
518 If none of our build or other processes uses "-G" with no arguments,
519 we can just process it with the other arguments. */
520 if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
521 proto_initialize_all_prefixes();
524 proto_registrar_dump_fields();
526 if (strcmp(argv[2], "column-formats") == 0)
527 column_dump_column_formats();
528 else if (strcmp(argv[2], "currentprefs") == 0) {
529 epan_load_settings();
532 else if (strcmp(argv[2], "decodes") == 0)
533 dissector_dump_decodes();
534 else if (strcmp(argv[2], "defaultprefs") == 0)
536 else if (strcmp(argv[2], "dissector-tables") == 0)
537 dissector_dump_dissector_tables();
538 else if (strcmp(argv[2], "fields") == 0)
539 proto_registrar_dump_fields();
540 else if (strcmp(argv[2], "ftypes") == 0)
541 proto_registrar_dump_ftypes();
542 else if (strcmp(argv[2], "heuristic-decodes") == 0)
543 dissector_dump_heur_decodes();
544 else if (strcmp(argv[2], "plugins") == 0) {
549 wslua_plugins_dump_all();
552 else if (strcmp(argv[2], "protocols") == 0)
553 proto_registrar_dump_protocols();
554 else if (strcmp(argv[2], "values") == 0)
555 proto_registrar_dump_values();
556 else if (strcmp(argv[2], "?") == 0)
557 glossary_option_help();
558 else if (strcmp(argv[2], "-?") == 0)
559 glossary_option_help();
561 cmdarg_err("Invalid \"%s\" option for -G flag, enter -G ? for more help.", argv[2]);
562 exit_status = INVALID_OPTION;
569 /* Load libwireshark settings from the current profile. */
570 prefs_p = epan_load_settings();
573 cap_file_init(&cfile);
575 /* Print format defaults to this. */
576 print_format = PR_FMT_TEXT;
578 output_fields = output_fields_new();
581 * To reset the options parser, set optreset to 1 on platforms that
582 * have optreset (documented in *BSD and macOS, apparently present but
583 * not documented in Solaris - the Illumos repository seems to
584 * suggest that the first Solaris getopt_long(), at least as of 2004,
585 * was based on the NetBSD one, it had optreset) and set optind to 1,
586 * and set optind to 0 otherwise (documented as working in the GNU
587 * getopt_long(). Setting optind to 0 didn't originally work in the
588 * NetBSD one, but that was added later - we don't want to depend on
589 * it if we have optreset).
591 * Also reset opterr to 1, so that error messages are printed by
602 /* Now get our args */
603 while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
605 case '2': /* Perform two pass analysis */
606 perform_two_pass_analysis = TRUE;
609 /* already processed; just ignore it now */
613 output_fields_add(output_fields, optarg);
617 if (!output_fields_set_option(output_fields, optarg)) {
618 cmdarg_err("\"%s\" is not a valid field output option=value pair.", optarg);
619 output_fields_list_options(stderr);
620 exit_status = INVALID_OPTION;
625 case 'h': /* Print help and exit */
626 printf("TFShark (Wireshark) %s\n"
627 "Dump and analyze network traffic.\n"
628 "See https://www.wireshark.org for more information.\n",
629 get_ws_vcs_version_info());
633 case 'l': /* "Line-buffer" standard output */
634 /* The ANSI C standard does not appear to *require* that a line-buffered
635 stream be flushed to the host environment whenever a newline is
636 written, it just says that, on such a stream, characters "are
637 intended to be transmitted to or from the host environment as a
638 block when a new-line character is encountered".
640 The Visual C++ 6.0 C implementation doesn't do what is intended;
641 even if you set a stream to be line-buffered, it still doesn't
642 flush the buffer at the end of every line.
644 The whole reason for the "-l" flag in either tcpdump or TShark
645 is to allow the output of a live capture to be piped to a program
646 or script and to have that script see the information for the
647 packet as soon as it's printed, rather than having to wait until
648 a standard I/O buffer fills up.
650 So, if the "-l" flag is specified, we flush the standard output
651 at the end of a packet. This will do the right thing if we're
652 printing packet summary lines, and, as we print the entire protocol
653 tree for a single packet without waiting for anything to happen,
654 it should be as good as line-buffered mode if we're printing
655 protocol trees - arguably even better, as it may do fewer
657 line_buffered = TRUE;
659 case 'o': /* Override preference from command line */
663 switch (prefs_set_pref(optarg, &errmsg)) {
668 case PREFS_SET_SYNTAX_ERR:
669 cmdarg_err("Invalid -o flag \"%s\"%s%s", optarg,
670 errmsg ? ": " : "", errmsg ? errmsg : "");
675 case PREFS_SET_NO_SUCH_PREF:
676 case PREFS_SET_OBSOLETE:
677 cmdarg_err("-o flag \"%s\" specifies unknown preference", optarg);
678 exit_status = INVALID_OPTION;
684 case 'q': /* Quiet */
687 case 'Q': /* Really quiet */
691 case 'r': /* Read capture file x */
692 cf_name = g_strdup(optarg);
694 case 'R': /* Read file filter */
697 case 'S': /* Set the line Separator to be printed between packets */
698 separator = g_strdup(optarg);
700 case 'T': /* printing Type */
701 if (strcmp(optarg, "text") == 0) {
702 output_action = WRITE_TEXT;
703 print_format = PR_FMT_TEXT;
704 } else if (strcmp(optarg, "ps") == 0) {
705 output_action = WRITE_TEXT;
706 print_format = PR_FMT_PS;
707 } else if (strcmp(optarg, "pdml") == 0) {
708 output_action = WRITE_XML;
709 print_details = TRUE; /* Need details */
710 print_summary = FALSE; /* Don't allow summary */
711 } else if (strcmp(optarg, "psml") == 0) {
712 output_action = WRITE_XML;
713 print_details = FALSE; /* Don't allow details */
714 print_summary = TRUE; /* Need summary */
715 } else if (strcmp(optarg, "fields") == 0) {
716 output_action = WRITE_FIELDS;
717 print_details = TRUE; /* Need full tree info */
718 print_summary = FALSE; /* Don't allow summary */
720 cmdarg_err("Invalid -T parameter \"%s\"; it must be one of:", optarg); /* x */
721 cmdarg_err_cont("\t\"fields\" The values of fields specified with the -e option, in a form\n"
722 "\t specified by the -E option.\n"
723 "\t\"pdml\" Packet Details Markup Language, an XML-based format for the\n"
724 "\t details of a decoded packet. This information is equivalent to\n"
725 "\t the packet details printed with the -V flag.\n"
726 "\t\"ps\" PostScript for a human-readable one-line summary of each of\n"
727 "\t the packets, or a multi-line view of the details of each of\n"
728 "\t the packets, depending on whether the -V flag was specified.\n"
729 "\t\"psml\" Packet Summary Markup Language, an XML-based format for the\n"
730 "\t summary information of a decoded packet. This information is\n"
731 "\t equivalent to the information shown in the one-line summary\n"
732 "\t printed by default.\n"
733 "\t\"text\" Text of a human-readable one-line summary of each of the\n"
734 "\t packets, or a multi-line view of the details of each of the\n"
735 "\t packets, depending on whether the -V flag was specified.\n"
736 "\t This is the default.");
737 exit_status = INVALID_OPTION;
741 case 'v': /* Show version and exit */
742 comp_info_str = get_compiled_version_info(NULL, epan_get_compiled_version_info);
743 runtime_info_str = get_runtime_version_info(get_tfshark_runtime_version_info);
744 show_version("TFShark (Wireshark)", comp_info_str, runtime_info_str);
745 g_string_free(comp_info_str, TRUE);
746 g_string_free(runtime_info_str, TRUE);
748 case 'O': /* Only output these protocols */
749 /* already processed; just ignore it now */
751 case 'V': /* Verbose */
752 /* already processed; just ignore it now */
754 case 'x': /* Print packet data in hex (and ASCII) */
755 /* already processed; just ignore it now */
758 /* already processed; just ignore it now */
764 /* We won't call the init function for the stat this soon
765 as it would disallow MATE's fields (which are registered
766 by the preferences set callback) from being used as
767 part of a tap filter. Instead, we just add the argument
768 to a list of stat arguments. */
769 if (strcmp("help", optarg) == 0) {
770 fprintf(stderr, "tfshark: The available statistics for the \"-z\" option are:\n");
771 list_stat_cmd_args();
774 if (!process_stat_cmd_arg(optarg)) {
775 cmdarg_err("Invalid -z argument \"%s\"; it must be one of:", optarg);
776 list_stat_cmd_args();
777 exit_status = INVALID_OPTION;
781 case 'd': /* Decode as rule */
782 case 'K': /* Kerberos keytab file */
783 case 't': /* Time stamp type */
784 case 'u': /* Seconds type */
785 case LONGOPT_DISABLE_PROTOCOL: /* disable dissection of protocol */
786 case LONGOPT_ENABLE_HEURISTIC: /* enable heuristic dissection of protocol */
787 case LONGOPT_DISABLE_HEURISTIC: /* disable heuristic dissection of protocol */
788 case LONGOPT_ENABLE_PROTOCOL: /* enable dissection of protocol (that is disabled by default) */
789 if (!dissect_opts_handle_opt(opt, optarg)) {
790 exit_status = INVALID_OPTION;
795 case '?': /* Bad flag - print usage message */
797 exit_status = INVALID_OPTION;
803 /* If we specified output fields, but not the output field type... */
804 if (WRITE_FIELDS != output_action && 0 != output_fields_num_fields(output_fields)) {
805 cmdarg_err("Output fields were specified with \"-e\", "
806 "but \"-Tfields\" was not specified.");
808 } else if (WRITE_FIELDS == output_action && 0 == output_fields_num_fields(output_fields)) {
809 cmdarg_err("\"-Tfields\" was specified, but no fields were "
810 "specified with \"-e\".");
812 exit_status = INVALID_OPTION;
816 /* We require a -r flag specifying a file to read. */
817 if (cf_name == NULL) {
818 cmdarg_err("A file to read must be specified with \"-r\".");
819 exit_status = NO_FILE_SPECIFIED;
823 /* If no display filter has been specified, and there are still command-
824 line arguments, treat them as the tokens of a display filter. */
826 if (dfilter != NULL) {
827 cmdarg_err("Display filters were specified both with \"-d\" "
828 "and with additional command-line arguments.");
829 exit_status = INVALID_OPTION;
832 dfilter = get_args_as_string(argc, argv, optind);
835 /* if "-q" wasn't specified, we should print packet information */
837 print_packet_info = TRUE;
841 exit_status = INVALID_OPTION;
846 if (output_action != WRITE_TEXT) {
847 cmdarg_err("Raw packet hex data can only be printed as text or PostScript");
848 exit_status = INVALID_OPTION;
853 if (output_only != NULL) {
856 if (!print_details) {
857 cmdarg_err("-O requires -V");
858 exit_status = INVALID_OPTION;
862 output_only_tables = g_hash_table_new (g_str_hash, g_str_equal);
863 for (ps = strtok (output_only, ","); ps; ps = strtok (NULL, ",")) {
864 g_hash_table_insert(output_only_tables, (gpointer)ps, (gpointer)ps);
868 if (rfilter != NULL && !perform_two_pass_analysis) {
869 cmdarg_err("-R without -2 is deprecated. For single-pass filtering use -Y.");
870 exit_status = INVALID_OPTION;
874 /* Notify all registered modules that have had any of their preferences
875 changed either from one of the preferences file or from the command
876 line that their preferences have changed. */
880 * Enabled and disabled protocols and heuristic dissectors as per
881 * command-line options.
883 if (!setup_enabled_and_disabled_protocols()) {
884 exit_status = INVALID_OPTION;
888 /* Build the column format array */
889 build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
891 if (rfilter != NULL) {
892 if (!dfilter_compile(rfilter, &rfcode, &err_msg)) {
893 cmdarg_err("%s", err_msg);
895 exit_status = INVALID_FILTER;
899 cfile.rfcode = rfcode;
901 if (dfilter != NULL) {
902 if (!dfilter_compile(dfilter, &dfcode, &err_msg)) {
903 cmdarg_err("%s", err_msg);
905 exit_status = INVALID_FILTER;
909 cfile.dfcode = dfcode;
911 if (print_packet_info) {
912 /* If we're printing as text or PostScript, we have
913 to create a print stream. */
914 if (output_action == WRITE_TEXT) {
915 switch (print_format) {
918 print_stream = print_stream_text_stdio_new(stdout);
922 print_stream = print_stream_ps_stdio_new(stdout);
926 g_assert_not_reached();
931 /* We have to dissect each packet if:
933 we're printing information about each packet;
935 we're using a read filter on the packets;
937 we're using a display filter on the packets;
939 we're using any taps that need dissection. */
940 do_dissection = print_packet_info || rfcode || dfcode || tap_listeners_require_dissection();
946 /* TODO: if tfshark is ever changed to give the user a choice of which
947 open_routine reader to use, then the following needs to change. */
948 if (cf_open(&cfile, cf_name, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK) {
949 exit_status = OPEN_ERROR;
953 /* Start statistics taps; we do so after successfully opening the
954 capture file, so we know we have something to compute stats
955 on, and after registering all dissectors, so that MATE will
956 have registered its field array so we can have a tap filter
957 with one of MATE's late-registered fields as part of the
959 start_requested_stats();
961 /* Process the packets in the file */
963 /* XXX - for now there is only 1 packet */
964 success = process_file(&cfile, 1, 0);
966 CATCH(OutOfMemoryError) {
970 "Sorry, but TFShark has to terminate now.\n"
972 "Some infos / workarounds can be found at:\n"
973 "https://wiki.wireshark.org/KnownBugs/OutOfMemory\n");
979 /* We still dump out the results of taps, etc., as we might have
980 read some packets; however, we exit with an error status. */
986 if (cfile.provider.frames != NULL) {
987 free_frame_data_sequence(cfile.provider.frames);
988 cfile.provider.frames = NULL;
991 draw_tap_listeners(TRUE);
992 funnel_dump_all_text_windows();
995 destroy_print_stream(print_stream);
996 epan_free(cfile.epan);
1000 output_fields_free(output_fields);
1001 output_fields = NULL;
1003 col_cleanup(&cfile.cinfo);
1010 wmain(int argc, wchar_t *wc_argv[])
1014 argv = arg_list_utf_16to8(argc, wc_argv);
1015 return real_main(argc, argv);
1019 main(int argc, char *argv[])
1021 return real_main(argc, argv);
1025 static const nstime_t *
1026 tfshark_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num)
1028 if (prov->ref && prov->ref->num == frame_num)
1029 return &prov->ref->abs_ts;
1031 if (prov->prev_dis && prov->prev_dis->num == frame_num)
1032 return &prov->prev_dis->abs_ts;
1034 if (prov->prev_cap && prov->prev_cap->num == frame_num)
1035 return &prov->prev_cap->abs_ts;
1038 frame_data *fd = frame_data_sequence_find(prov->frames, frame_num);
1040 return (fd) ? &fd->abs_ts : NULL;
1047 no_interface_name(struct packet_provider_data *prov _U_, guint32 interface_id _U_)
1053 tfshark_epan_new(capture_file *cf)
1055 static const struct packet_provider_funcs funcs = {
1056 tfshark_get_frame_ts,
1062 return epan_new(&cf->provider, &funcs);
1066 process_packet_first_pass(capture_file *cf, epan_dissect_t *edt,
1067 gint64 offset, wtap_rec *rec,
1074 /* The frame number of this packet is one more than the count of
1075 frames in this packet. */
1076 framenum = cf->count + 1;
1078 /* If we're not running a display filter and we're not printing any
1079 packet information, we don't need to do a dissection. This means
1080 that all packets can be marked as 'passed'. */
1083 frame_data_init(&fdlocal, framenum, rec, offset, cum_bytes);
1085 /* If we're going to print packet information, or we're going to
1086 run a read filter, or display filter, or we're going to process taps, set up to
1087 do a dissection and do so. */
1089 /* If we're running a read filter, prime the epan_dissect_t with that
1092 epan_dissect_prime_with_dfilter(edt, cf->rfcode);
1094 /* This is the first pass, so prime the epan_dissect_t with the
1095 hfids postdissectors want on the first pass. */
1096 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1098 frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time,
1099 &cf->provider.ref, cf->provider.prev_dis);
1100 if (cf->provider.ref == &fdlocal) {
1101 ref_frame = fdlocal;
1102 cf->provider.ref = &ref_frame;
1105 epan_dissect_file_run(edt, rec,
1106 file_tvbuff_new(&cf->provider, &fdlocal, pd),
1109 /* Run the read filter if we have one. */
1111 passed = dfilter_apply_edt(cf->rfcode, edt);
1115 frame_data_set_after_dissect(&fdlocal, &cum_bytes);
1116 cf->provider.prev_cap = cf->provider.prev_dis = frame_data_sequence_add(cf->provider.frames, &fdlocal);
1118 /* If we're not doing dissection then there won't be any dependent frames.
1119 * More importantly, edt.pi.dependent_frames won't be initialized because
1120 * epan hasn't been initialized.
1123 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
1128 /* if we don't add it to the frame_data_sequence, clean it up right now
1130 frame_data_destroy(&fdlocal);
1134 epan_dissect_reset(edt);
1140 process_packet_second_pass(capture_file *cf, epan_dissect_t *edt,
1141 frame_data *fdata, wtap_rec *rec,
1142 Buffer *buf, guint tap_flags)
1147 /* If we're not running a display filter and we're not printing any
1148 packet information, we don't need to do a dissection. This means
1149 that all packets can be marked as 'passed'. */
1152 /* If we're going to print packet information, or we're going to
1153 run a read filter, or we're going to process taps, set up to
1154 do a dissection and do so. */
1157 /* If we're running a display filter, prime the epan_dissect_t with that
1160 epan_dissect_prime_with_dfilter(edt, cf->dfcode);
1162 /* This is the first and only pass, so prime the epan_dissect_t
1163 with the hfids postdissectors want on the first pass. */
1164 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1166 col_custom_prime_edt(edt, &cf->cinfo);
1168 /* We only need the columns if either
1169 1) some tap needs the columns
1171 2) we're printing packet info but we're *not* verbose; in verbose
1172 mode, we print the protocol tree, not the protocol summary.
1174 if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary))
1179 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1180 &cf->provider.ref, cf->provider.prev_dis);
1181 if (cf->provider.ref == fdata) {
1183 cf->provider.ref = &ref_frame;
1186 epan_dissect_file_run_with_taps(edt, rec,
1187 file_tvbuff_new_buffer(&cf->provider, fdata, buf), fdata, cinfo);
1189 /* Run the read/display filter if we have one. */
1191 passed = dfilter_apply_edt(cf->dfcode, edt);
1195 frame_data_set_after_dissect(fdata, &cum_bytes);
1196 /* Process this packet. */
1197 if (print_packet_info) {
1198 /* We're printing packet information; print the information for
1200 print_packet(cf, edt);
1202 /* If we're doing "line-buffering", flush the standard output
1203 after every packet. See the comment above, for the "-l"
1204 option, for an explanation of why we do that. */
1208 if (ferror(stdout)) {
1209 show_print_file_io_error(errno);
1213 cf->provider.prev_dis = fdata;
1215 cf->provider.prev_cap = fdata;
1218 epan_dissect_reset(edt);
1220 return passed || fdata->flags.dependent_of_displayed;
1224 local_wtap_read(capture_file *cf, wtap_rec *file_rec _U_, int *err, gchar **err_info _U_, gint64 *data_offset _U_, guint8** data_buffer)
1226 /* int bytes_read; */
1227 gint64 packet_size = wtap_file_size(cf->provider.wth, err);
1229 *data_buffer = (guint8*)g_malloc((gsize)packet_size);
1230 /* bytes_read =*/ file_read(*data_buffer, (unsigned int)packet_size, cf->provider.wth->fh);
1232 #if 0 /* no more filetap */
1233 if (bytes_read < 0) {
1234 *err = file_error(cf->provider.wth->fh, err_info);
1236 *err = FTAP_ERR_SHORT_READ;
1238 } else if (bytes_read == 0) {
1239 /* Done with file, no error */
1244 /* XXX - SET FRAME SIZE EQUAL TO TOTAL FILE SIZE */
1245 file_rec->rec_header.packet_header.caplen = (guint32)packet_size;
1246 file_rec->rec_header.packet_header.len = (guint32)packet_size;
1249 * Set the packet encapsulation to the file's encapsulation
1250 * value; if that's not WTAP_ENCAP_PER_PACKET, it's the
1251 * right answer (and means that the read routine for this
1252 * capture file type doesn't have to set it), and if it
1253 * *is* WTAP_ENCAP_PER_PACKET, the caller needs to set it
1256 wth->rec.rec_header.packet_header.pkt_encap = wth->file_encap;
1258 if (!wth->subtype_read(wth, err, err_info, data_offset)) {
1260 * If we didn't get an error indication, we read
1261 * the last packet. See if there's any deferred
1262 * error, as might, for example, occur if we're
1263 * reading a compressed file, and we got an error
1264 * reading compressed data from the file, but
1265 * got enough compressed data to decompress the
1266 * last packet of the file.
1269 *err = file_error(wth->fh, err_info);
1270 return FALSE; /* failure */
1274 * It makes no sense for the captured data length to be bigger
1275 * than the actual data length.
1277 if (wth->rec.rec_header.packet_header.caplen > wth->rec.rec_header.packet_header.len)
1278 wth->rec.rec_header.packet_header.caplen = wth->rec.rec_header.packet_header.len;
1281 * Make sure that it's not WTAP_ENCAP_PER_PACKET, as that
1282 * probably means the file has that encapsulation type
1283 * but the read routine didn't set this packet's
1284 * encapsulation type.
1286 g_assert(wth->rec.rec_header.packet_header.pkt_encap != WTAP_ENCAP_PER_PACKET);
1289 return TRUE; /* success */
1293 process_file(capture_file *cf, int max_packet_count, gint64 max_byte_count)
1297 gchar *err_info = NULL;
1298 gint64 data_offset = 0;
1299 gboolean filtering_tap_listeners;
1302 epan_dissect_t *edt = NULL;
1306 if (print_packet_info) {
1307 if (!write_preamble(cf)) {
1309 show_print_file_io_error(err);
1314 /* Do we have any tap listeners with filters? */
1315 filtering_tap_listeners = have_filtering_tap_listeners();
1317 /* Get the union of the flags for all tap listeners. */
1318 tap_flags = union_of_tap_listener_flags();
1320 wtap_rec_init(&file_rec);
1322 /* XXX - TEMPORARY HACK TO ELF DISSECTOR */
1323 file_rec.rec_header.packet_header.pkt_encap = 1234;
1325 if (perform_two_pass_analysis) {
1328 /* Allocate a frame_data_sequence for all the frames. */
1329 cf->provider.frames = new_frame_data_sequence();
1331 if (do_dissection) {
1332 gboolean create_proto_tree;
1335 * Determine whether we need to create a protocol tree.
1338 * we're going to apply a read filter;
1340 * a postdissector wants field values or protocols
1341 * on the first pass.
1344 (cf->rfcode != NULL || postdissectors_want_hfids());
1346 /* We're not going to display the protocol tree on this pass,
1347 so it's not going to be "visible". */
1348 edt = epan_dissect_new(cf->epan, create_proto_tree, FALSE);
1350 while (local_wtap_read(cf, &file_rec, &err, &err_info, &data_offset, &raw_data)) {
1351 if (process_packet_first_pass(cf, edt, data_offset, &file_rec/*wtap_get_rec(cf->provider.wth)*/,
1352 wtap_get_buf_ptr(cf->provider.wth))) {
1354 /* Stop reading if we have the maximum number of packets;
1355 * When the -c option has not been used, max_packet_count
1356 * starts at 0, which practically means, never stop reading.
1357 * (unless we roll over max_packet_count ?)
1359 if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
1360 err = 0; /* This is not an error */
1367 epan_dissect_free(edt);
1372 /* Close the sequential I/O side, to free up memory it requires. */
1373 wtap_sequential_close(cf->provider.wth);
1376 /* Allow the protocol dissectors to free up memory that they
1377 * don't need after the sequential run-through of the packets. */
1378 postseq_cleanup_all_protocols();
1380 cf->provider.prev_dis = NULL;
1381 cf->provider.prev_cap = NULL;
1382 ws_buffer_init(&buf, 1500);
1384 if (do_dissection) {
1385 gboolean create_proto_tree;
1388 * Determine whether we need to create a protocol tree.
1391 * we're going to apply a display filter;
1393 * we're going to print the protocol tree;
1395 * one of the tap listeners requires a protocol tree;
1397 * we have custom columns (which require field values, which
1398 * currently requires that we build a protocol tree).
1401 (cf->dfcode || print_details || filtering_tap_listeners ||
1402 (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo));
1404 /* The protocol tree will be "visible", i.e., printed, only if we're
1405 printing packet details, which is true if we're printing stuff
1406 ("print_packet_info" is true) and we're in verbose mode
1407 ("packet_details" is true). */
1408 edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details);
1411 for (framenum = 1; err == 0 && framenum <= cf->count; framenum++) {
1412 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1414 if (wtap_seek_read(cf->provider.wth, fdata->file_off,
1415 &buf, fdata->cap_len, &err, &err_info)) {
1416 process_packet_second_pass(cf, edt, fdata, &cf->rec, &buf, tap_flags);
1419 if (!process_packet_second_pass(cf, edt, fdata, &cf->rec, &buf,
1426 epan_dissect_free(edt);
1430 ws_buffer_free(&buf);
1435 if (do_dissection) {
1436 gboolean create_proto_tree;
1439 * Determine whether we need to create a protocol tree.
1442 * we're going to apply a read filter;
1444 * we're going to apply a display filter;
1446 * we're going to print the protocol tree;
1448 * one of the tap listeners is going to apply a filter;
1450 * one of the tap listeners requires a protocol tree;
1452 * a postdissector wants field values or protocols
1453 * on the first pass;
1455 * we have custom columns (which require field values, which
1456 * currently requires that we build a protocol tree).
1459 (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners ||
1460 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids() ||
1461 have_custom_cols(&cf->cinfo));
1463 /* The protocol tree will be "visible", i.e., printed, only if we're
1464 printing packet details, which is true if we're printing stuff
1465 ("print_packet_info" is true) and we're in verbose mode
1466 ("packet_details" is true). */
1467 edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details);
1470 while (local_wtap_read(cf, &file_rec, &err, &err_info, &data_offset, &raw_data)) {
1474 if (!process_packet_single_pass(cf, edt, data_offset,
1475 &file_rec/*wtap_get_rec(cf->provider.wth)*/,
1476 raw_data, tap_flags))
1479 /* Stop reading if we have the maximum number of packets;
1480 * When the -c option has not been used, max_packet_count
1481 * starts at 0, which practically means, never stop reading.
1482 * (unless we roll over max_packet_count ?)
1484 if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
1485 err = 0; /* This is not an error */
1491 epan_dissect_free(edt);
1496 wtap_rec_cleanup(&file_rec);
1500 * Print a message noting that the read failed somewhere along the line.
1502 * If we're printing packet data, and the standard output and error are
1503 * going to the same place, flush the standard output, so everything
1504 * buffered up is written, and then print a newline to the standard error
1505 * before printing the error message, to separate it from the packet
1506 * data. (Alas, that only works on UN*X; st_dev is meaningless, and
1507 * the _fstat() documentation at Microsoft doesn't indicate whether
1508 * st_ino is even supported.)
1511 if (print_packet_info) {
1512 ws_statb64 stat_stdout, stat_stderr;
1514 if (ws_fstat64(1, &stat_stdout) == 0 && ws_fstat64(2, &stat_stderr) == 0) {
1515 if (stat_stdout.st_dev == stat_stderr.st_dev &&
1516 stat_stdout.st_ino == stat_stderr.st_ino) {
1518 fprintf(stderr, "\n");
1526 case FTAP_ERR_UNSUPPORTED:
1527 cmdarg_err("The file \"%s\" contains record data that TFShark doesn't support.\n(%s)",
1528 cf->filename, err_info);
1532 case FTAP_ERR_UNSUPPORTED_ENCAP:
1533 cmdarg_err("The file \"%s\" has a packet with a network type that TFShark doesn't support.\n(%s)",
1534 cf->filename, err_info);
1538 case FTAP_ERR_CANT_READ:
1539 cmdarg_err("An attempt to read from the file \"%s\" failed for some unknown reason.",
1543 case FTAP_ERR_SHORT_READ:
1544 cmdarg_err("The file \"%s\" appears to have been cut short in the middle of a packet.",
1548 case FTAP_ERR_BAD_FILE:
1549 cmdarg_err("The file \"%s\" appears to be damaged or corrupt.\n(%s)",
1550 cf->filename, err_info);
1554 case FTAP_ERR_DECOMPRESS:
1555 cmdarg_err("The compressed file \"%s\" appears to be damaged or corrupt.\n"
1556 "(%s)", cf->filename, err_info);
1560 cmdarg_err("An error occurred while reading the file \"%s\": %s.",
1561 cf->filename, ftap_strerror(err));
1566 if (print_packet_info) {
1567 if (!write_finale()) {
1569 show_print_file_io_error(err);
1575 wtap_close(cf->provider.wth);
1576 cf->provider.wth = NULL;
1582 process_packet_single_pass(capture_file *cf, epan_dissect_t *edt, gint64 offset,
1583 wtap_rec *rec, const guchar *pd,
1590 /* Count this packet. */
1593 /* If we're not running a display filter and we're not printing any
1594 packet information, we don't need to do a dissection. This means
1595 that all packets can be marked as 'passed'. */
1598 frame_data_init(&fdata, cf->count, rec, offset, cum_bytes);
1600 /* If we're going to print packet information, or we're going to
1601 run a read filter, or we're going to process taps, set up to
1602 do a dissection and do so. */
1604 /* If we're running a filter, prime the epan_dissect_t with that
1607 epan_dissect_prime_with_dfilter(edt, cf->dfcode);
1609 col_custom_prime_edt(edt, &cf->cinfo);
1611 /* We only need the columns if either
1612 1) some tap needs the columns
1614 2) we're printing packet info but we're *not* verbose; in verbose
1615 mode, we print the protocol tree, not the protocol summary.
1617 3) there is a column mapped as an individual field */
1618 if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary) || output_fields_has_cols(output_fields))
1623 frame_data_set_before_dissect(&fdata, &cf->elapsed_time,
1624 &cf->provider.ref, cf->provider.prev_dis);
1625 if (cf->provider.ref == &fdata) {
1627 cf->provider.ref = &ref_frame;
1630 epan_dissect_file_run_with_taps(edt, rec,
1631 frame_tvbuff_new(&cf->provider, &fdata, pd),
1634 /* Run the filter if we have it. */
1636 passed = dfilter_apply_edt(cf->dfcode, edt);
1640 frame_data_set_after_dissect(&fdata, &cum_bytes);
1642 /* Process this packet. */
1643 if (print_packet_info) {
1644 /* We're printing packet information; print the information for
1646 print_packet(cf, edt);
1648 /* If we're doing "line-buffering", flush the standard output
1649 after every packet. See the comment above, for the "-l"
1650 option, for an explanation of why we do that. */
1654 if (ferror(stdout)) {
1655 show_print_file_io_error(errno);
1660 /* this must be set after print_packet() [bug #8160] */
1661 prev_dis_frame = fdata;
1662 cf->provider.prev_dis = &prev_dis_frame;
1665 prev_cap_frame = fdata;
1666 cf->provider.prev_cap = &prev_cap_frame;
1669 epan_dissect_reset(edt);
1670 frame_data_destroy(&fdata);
1676 write_preamble(capture_file *cf)
1678 switch (output_action) {
1681 return print_preamble(print_stream, cf->filename, get_ws_vcs_version_info());
1685 write_pdml_preamble(stdout, cf->filename);
1687 write_psml_preamble(&cf->cinfo, stdout);
1688 return !ferror(stdout);
1691 write_fields_preamble(output_fields, stdout);
1692 return !ferror(stdout);
1695 g_assert_not_reached();
1701 get_line_buf(size_t len)
1703 static char *line_bufp = NULL;
1704 static size_t line_buf_len = 256;
1705 size_t new_line_buf_len;
1707 for (new_line_buf_len = line_buf_len; len > new_line_buf_len;
1708 new_line_buf_len *= 2)
1710 if (line_bufp == NULL) {
1711 line_buf_len = new_line_buf_len;
1712 line_bufp = (char *)g_malloc(line_buf_len + 1);
1714 if (new_line_buf_len > line_buf_len) {
1715 line_buf_len = new_line_buf_len;
1716 line_bufp = (char *)g_realloc(line_bufp, line_buf_len + 1);
1723 put_string(char *dest, const char *str, size_t str_len)
1725 memcpy(dest, str, str_len);
1726 dest[str_len] = '\0';
1730 put_spaces_string(char *dest, const char *str, size_t str_len, size_t str_with_spaces)
1734 for (i = str_len; i < str_with_spaces; i++)
1737 put_string(dest, str, str_len);
1741 put_string_spaces(char *dest, const char *str, size_t str_len, size_t str_with_spaces)
1745 memcpy(dest, str, str_len);
1746 for (i = str_len; i < str_with_spaces; i++)
1749 dest[str_with_spaces] = '\0';
1753 print_columns(capture_file *cf)
1760 col_item_t* col_item;
1762 line_bufp = get_line_buf(256);
1765 for (i = 0; i < cf->cinfo.num_cols; i++) {
1766 col_item = &cf->cinfo.columns[i];
1767 /* Skip columns not marked as visible. */
1768 if (!get_column_visible(i))
1770 switch (col_item->col_fmt) {
1772 column_len = col_len = strlen(col_item->col_data);
1775 line_bufp = get_line_buf(buf_offset + column_len);
1776 put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1782 case COL_ABS_YMD_TIME: /* XXX - wider */
1783 case COL_ABS_YDOY_TIME: /* XXX - wider */
1785 case COL_UTC_YMD_TIME: /* XXX - wider */
1786 case COL_UTC_YDOY_TIME: /* XXX - wider */
1787 column_len = col_len = strlen(col_item->col_data);
1788 if (column_len < 10)
1790 line_bufp = get_line_buf(buf_offset + column_len);
1791 put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1797 case COL_DEF_DL_SRC:
1798 case COL_RES_DL_SRC:
1799 case COL_UNRES_DL_SRC:
1800 case COL_DEF_NET_SRC:
1801 case COL_RES_NET_SRC:
1802 case COL_UNRES_NET_SRC:
1803 column_len = col_len = strlen(col_item->col_data);
1804 if (column_len < 12)
1806 line_bufp = get_line_buf(buf_offset + column_len);
1807 put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1813 case COL_DEF_DL_DST:
1814 case COL_RES_DL_DST:
1815 case COL_UNRES_DL_DST:
1816 case COL_DEF_NET_DST:
1817 case COL_RES_NET_DST:
1818 case COL_UNRES_NET_DST:
1819 column_len = col_len = strlen(col_item->col_data);
1820 if (column_len < 12)
1822 line_bufp = get_line_buf(buf_offset + column_len);
1823 put_string_spaces(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1827 column_len = strlen(col_item->col_data);
1828 line_bufp = get_line_buf(buf_offset + column_len);
1829 put_string(line_bufp + buf_offset, col_item->col_data, column_len);
1832 buf_offset += column_len;
1833 if (i != cf->cinfo.num_cols - 1) {
1835 * This isn't the last column, so we need to print a
1836 * separator between this column and the next.
1838 * If we printed a network source and are printing a
1839 * network destination of the same type next, separate
1840 * them with " -> "; if we printed a network destination
1841 * and are printing a network source of the same type
1842 * next, separate them with " <- "; otherwise separate them
1845 * We add enough space to the buffer for " <- " or " -> ",
1846 * even if we're only adding " ".
1848 line_bufp = get_line_buf(buf_offset + 4);
1849 switch (col_item->col_fmt) {
1854 switch (cf->cinfo.columns[i+1].col_fmt) {
1859 put_string(line_bufp + buf_offset, " -> ", 4);
1864 put_string(line_bufp + buf_offset, " ", 1);
1870 case COL_DEF_DL_SRC:
1871 case COL_RES_DL_SRC:
1872 case COL_UNRES_DL_SRC:
1873 switch (cf->cinfo.columns[i+1].col_fmt) {
1875 case COL_DEF_DL_DST:
1876 case COL_RES_DL_DST:
1877 case COL_UNRES_DL_DST:
1878 put_string(line_bufp + buf_offset, " -> ", 4);
1883 put_string(line_bufp + buf_offset, " ", 1);
1889 case COL_DEF_NET_SRC:
1890 case COL_RES_NET_SRC:
1891 case COL_UNRES_NET_SRC:
1892 switch (cf->cinfo.columns[i+1].col_fmt) {
1894 case COL_DEF_NET_DST:
1895 case COL_RES_NET_DST:
1896 case COL_UNRES_NET_DST:
1897 put_string(line_bufp + buf_offset, " -> ", 4);
1902 put_string(line_bufp + buf_offset, " ", 1);
1911 switch (cf->cinfo.columns[i+1].col_fmt) {
1916 put_string(line_bufp + buf_offset, " <- ", 4);
1921 put_string(line_bufp + buf_offset, " ", 1);
1927 case COL_DEF_DL_DST:
1928 case COL_RES_DL_DST:
1929 case COL_UNRES_DL_DST:
1930 switch (cf->cinfo.columns[i+1].col_fmt) {
1932 case COL_DEF_DL_SRC:
1933 case COL_RES_DL_SRC:
1934 case COL_UNRES_DL_SRC:
1935 put_string(line_bufp + buf_offset, " <- ", 4);
1940 put_string(line_bufp + buf_offset, " ", 1);
1946 case COL_DEF_NET_DST:
1947 case COL_RES_NET_DST:
1948 case COL_UNRES_NET_DST:
1949 switch (cf->cinfo.columns[i+1].col_fmt) {
1951 case COL_DEF_NET_SRC:
1952 case COL_RES_NET_SRC:
1953 case COL_UNRES_NET_SRC:
1954 put_string(line_bufp + buf_offset, " <- ", 4);
1959 put_string(line_bufp + buf_offset, " ", 1);
1966 put_string(line_bufp + buf_offset, " ", 1);
1972 return print_line(print_stream, 0, line_bufp);
1976 print_packet(capture_file *cf, epan_dissect_t *edt)
1978 if (print_summary || output_fields_has_cols(output_fields)) {
1979 /* Just fill in the columns. */
1980 epan_dissect_fill_in_columns(edt, FALSE, TRUE);
1982 if (print_summary) {
1983 /* Now print them. */
1984 switch (output_action) {
1987 if (!print_columns(cf))
1992 write_psml_columns(edt, stdout, FALSE);
1993 return !ferror(stdout);
1994 case WRITE_FIELDS: /*No non-verbose "fields" format */
1995 g_assert_not_reached();
2000 if (print_details) {
2001 /* Print the information in the protocol tree. */
2002 switch (output_action) {
2005 if (!proto_tree_print(print_details ? print_dissections_expanded : print_dissections_none,
2006 print_hex, edt, output_only_tables, print_stream))
2009 if (!print_line(print_stream, 0, separator))
2015 write_pdml_proto_tree(NULL, NULL, PF_NONE, edt, &cf->cinfo, stdout, FALSE);
2017 return !ferror(stdout);
2019 write_fields_proto_tree(output_fields, edt, &cf->cinfo, stdout);
2021 return !ferror(stdout);
2025 if (print_summary || print_details) {
2026 if (!print_line(print_stream, 0, ""))
2029 if (!print_hex_data(print_stream, edt))
2031 if (!print_line(print_stream, 0, separator))
2040 switch (output_action) {
2043 return print_finale(print_stream);
2047 write_pdml_finale(stdout);
2049 write_psml_finale(stdout);
2050 return !ferror(stdout);
2053 write_fields_finale(output_fields, stdout);
2054 return !ferror(stdout);
2057 g_assert_not_reached();
2063 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
2066 char err_msg[2048+1];
2068 /* The open isn't implemented yet. Fill in the information for this file. */
2070 /* Create new epan session for dissection. */
2071 epan_free(cf->epan);
2072 cf->epan = tfshark_epan_new(cf);
2074 cf->provider.wth = NULL; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2075 cf->f_datalen = 0; /* not used, but set it anyway */
2077 /* Set the file name because we need it to set the follow stream filter.
2078 XXX - is that still true? We need it for other reasons, though,
2080 cf->filename = g_strdup(fname);
2082 /* Indicate whether it's a permanent or temporary file. */
2083 cf->is_tempfile = is_tempfile;
2085 /* No user changes yet. */
2086 cf->unsaved_changes = FALSE;
2088 cf->cd_t = 0; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2089 cf->open_type = type;
2091 cf->drops_known = FALSE;
2093 cf->snap = 0; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2094 nstime_set_zero(&cf->elapsed_time);
2095 cf->provider.ref = NULL;
2096 cf->provider.prev_dis = NULL;
2097 cf->provider.prev_cap = NULL;
2099 cf->state = FILE_READ_IN_PROGRESS;
2104 g_snprintf(err_msg, sizeof err_msg,
2105 cf_open_error_message(*err, err_info, FALSE, cf->cd_t), fname);
2106 cmdarg_err("%s", err_msg);
2111 show_print_file_io_error(int err)
2116 cmdarg_err("Not all the packets could be printed because there is "
2117 "no space left on the file system.");
2122 cmdarg_err("Not all the packets could be printed because you are "
2123 "too close to, or over your disk quota.");
2128 cmdarg_err("An error occurred while printing packets: %s.",
2135 cf_open_error_message(int err, gchar *err_info _U_, gboolean for_writing,
2139 /* static char errmsg_errno[1024+1]; */
2143 /* Wiretap error. */
2146 case FTAP_ERR_NOT_REGULAR_FILE:
2147 errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
2150 case FTAP_ERR_RANDOM_OPEN_PIPE:
2151 /* Seen only when opening a capture file for reading. */
2152 errmsg = "The file \"%s\" is a pipe or FIFO; TFShark can't read pipe or FIFO files in two-pass mode.";
2155 case FTAP_ERR_FILE_UNKNOWN_FORMAT:
2156 /* Seen only when opening a capture file for reading. */
2157 errmsg = "The file \"%s\" isn't a capture file in a format TFShark understands.";
2160 case FTAP_ERR_UNSUPPORTED:
2161 /* Seen only when opening a capture file for reading. */
2162 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2163 "The file \"%%s\" isn't a capture file in a format TFShark understands.\n"
2166 errmsg = errmsg_errno;
2169 case FTAP_ERR_CANT_WRITE_TO_PIPE:
2170 /* Seen only when opening a capture file for writing. */
2171 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2172 "The file \"%%s\" is a pipe, and \"%s\" capture files can't be "
2173 "written to a pipe.", ftap_file_type_subtype_short_string(file_type));
2174 errmsg = errmsg_errno;
2177 case FTAP_ERR_UNSUPPORTED_FILE_TYPE:
2178 /* Seen only when opening a capture file for writing. */
2179 errmsg = "TFShark doesn't support writing capture files in that format.";
2182 case FTAP_ERR_UNSUPPORTED_ENCAP:
2184 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2185 "TFShark can't save this capture as a \"%s\" file.",
2186 ftap_file_type_subtype_short_string(file_type));
2188 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2189 "The file \"%%s\" is a capture for a network type that TFShark doesn't support.\n"
2193 errmsg = errmsg_errno;
2196 case FTAP_ERR_ENCAP_PER_RECORD_UNSUPPORTED:
2198 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2199 "TFShark can't save this capture as a \"%s\" file.",
2200 ftap_file_type_subtype_short_string(file_type));
2201 errmsg = errmsg_errno;
2203 errmsg = "The file \"%s\" is a capture for a network type that TFShark doesn't support.";
2206 case FTAP_ERR_BAD_FILE:
2207 /* Seen only when opening a capture file for reading. */
2208 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2209 "The file \"%%s\" appears to be damaged or corrupt.\n"
2212 errmsg = errmsg_errno;
2215 case FTAP_ERR_CANT_OPEN:
2217 errmsg = "The file \"%s\" could not be created for some unknown reason.";
2219 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
2222 case FTAP_ERR_SHORT_READ:
2223 errmsg = "The file \"%s\" appears to have been cut short"
2224 " in the middle of a packet or other data.";
2227 case FTAP_ERR_SHORT_WRITE:
2228 errmsg = "A full header couldn't be written to the file \"%s\".";
2231 case FTAP_ERR_COMPRESSION_NOT_SUPPORTED:
2232 errmsg = "This file type cannot be written as a compressed file.";
2235 case FTAP_ERR_DECOMPRESS:
2236 /* Seen only when opening a capture file for reading. */
2237 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2238 "The compressed file \"%%s\" appears to be damaged or corrupt.\n"
2241 errmsg = errmsg_errno;
2245 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2246 "The file \"%%s\" could not be %s: %s.",
2247 for_writing ? "created" : "opened",
2248 ftap_strerror(err));
2249 errmsg = errmsg_errno;
2254 errmsg = file_open_error_message(err, for_writing);
2259 * General errors and warnings are reported with an console message
2263 failure_warning_message(const char *msg_format, va_list ap)
2265 fprintf(stderr, "tfshark: ");
2266 vfprintf(stderr, msg_format, ap);
2267 fprintf(stderr, "\n");
2271 * Open/create errors are reported with an console message in TFShark.
2274 open_failure_message(const char *filename, int err, gboolean for_writing)
2276 fprintf(stderr, "tfshark: ");
2277 fprintf(stderr, file_open_error_message(err, for_writing), filename);
2278 fprintf(stderr, "\n");
2282 * Read errors are reported with an console message in TFShark.
2285 read_failure_message(const char *filename, int err)
2287 cmdarg_err("An error occurred while reading from the file \"%s\": %s.",
2288 filename, g_strerror(err));
2292 * Write errors are reported with an console message in TFShark.
2295 write_failure_message(const char *filename, int err)
2297 cmdarg_err("An error occurred while writing to the file \"%s\": %s.",
2298 filename, g_strerror(err));
2302 * Report additional information for an error in command-line arguments.
2305 failure_message_cont(const char *msg_format, va_list ap)
2307 vfprintf(stderr, msg_format, ap);
2308 fprintf(stderr, "\n");
2312 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2317 * indent-tabs-mode: nil
2320 * vi: set shiftwidth=2 tabstop=8 expandtab:
2321 * :indentSize=2:tabSize=8:noTabs=true: