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 <ui/clopts_common.h>
36 #include <ui/cmdarg_err.h>
37 #include <wsutil/filesystem.h>
38 #include <wsutil/file_util.h>
39 #include <wsutil/privileges.h>
40 #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 <epan/funnel.h>
73 #include <wsutil/plugins.h>
76 #define INVALID_OPTION 1
77 #define NO_FILE_SPECIFIED 1
79 #define INVALID_FILTER 2
84 static guint32 cum_bytes;
85 static frame_data ref_frame;
86 static frame_data prev_dis_frame;
87 static frame_data prev_cap_frame;
89 static gboolean prefs_loaded = FALSE;
91 static gboolean perform_two_pass_analysis;
94 * The way the packet decode is to be written.
97 WRITE_TEXT, /* summary or detail text */
98 WRITE_XML, /* PDML or PSML */
99 WRITE_FIELDS /* User defined list of fields */
100 /* Add CSV and the like here */
103 static output_action_e output_action;
104 static gboolean do_dissection; /* TRUE if we have to dissect each packet */
105 static gboolean print_packet_info; /* TRUE if we're to print packet information */
106 static gint print_summary = -1; /* TRUE if we're to print packet summary information */
107 static gboolean print_details; /* TRUE if we're to print packet details information */
108 static gboolean print_hex; /* TRUE if we're to print hex/ascci information */
109 static gboolean line_buffered;
110 static gboolean really_quiet = FALSE;
112 static print_format_e print_format = PR_FMT_TEXT;
113 static print_stream_t *print_stream;
115 static output_fields_t* output_fields = NULL;
117 /* The line separator used between packets, changeable via the -S option */
118 static const char *separator = "";
120 static gboolean process_file(capture_file *, int, gint64);
121 static gboolean process_packet_single_pass(capture_file *cf,
122 epan_dissect_t *edt, gint64 offset, wtap_rec *rec,
123 const guchar *pd, guint tap_flags);
124 static void show_print_file_io_error(int err);
125 static gboolean write_preamble(capture_file *cf);
126 static gboolean print_packet(capture_file *cf, epan_dissect_t *edt);
127 static gboolean write_finale(void);
128 static const char *cf_open_error_message(int err, gchar *err_info,
129 gboolean for_writing, int file_type);
131 static void failure_warning_message(const char *msg_format, va_list ap);
132 static void open_failure_message(const char *filename, int err,
133 gboolean for_writing);
134 static void read_failure_message(const char *filename, int err);
135 static void write_failure_message(const char *filename, int err);
136 static void failure_message_cont(const char *msg_format, va_list ap);
138 static GHashTable *output_only_tables = NULL;
142 const char *sstr; /* The short string */
143 const char *lstr; /* The long string */
147 string_compare(gconstpointer a, gconstpointer b)
149 return strcmp(((const struct string_elem *)a)->sstr,
150 ((const struct string_elem *)b)->sstr);
154 string_elem_print(gpointer data, gpointer not_used _U_)
156 fprintf(stderr, " %s - %s\n",
157 ((struct string_elem *)data)->sstr,
158 ((struct string_elem *)data)->lstr);
163 print_usage(FILE *output)
165 fprintf(output, "\n");
166 fprintf(output, "Usage: tfshark [options] ...\n");
167 fprintf(output, "\n");
169 /*fprintf(output, "\n");*/
170 fprintf(output, "Input file:\n");
171 fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin)\n");
173 fprintf(output, "\n");
174 fprintf(output, "Processing:\n");
175 fprintf(output, " -2 perform a two-pass analysis\n");
176 fprintf(output, " -R <read filter> packet Read filter in Wireshark display filter syntax\n");
177 fprintf(output, " (requires -2)\n");
178 fprintf(output, " -Y <display filter> packet displaY filter in Wireshark display filter\n");
179 fprintf(output, " syntax\n");
180 fprintf(output, " -d %s ...\n", DECODE_AS_ARG_TEMPLATE);
181 fprintf(output, " \"Decode As\", see the man page for details\n");
182 fprintf(output, " Example: tcp.port==8888,http\n");
184 /*fprintf(output, "\n");*/
185 fprintf(output, "Output:\n");
186 fprintf(output, " -C <config profile> start with specified configuration profile\n");
187 fprintf(output, " -V add output of packet tree (Packet Details)\n");
188 fprintf(output, " -O <protocols> Only show packet details of these protocols, comma\n");
189 fprintf(output, " separated\n");
190 fprintf(output, " -S <separator> the line separator to print between packets\n");
191 fprintf(output, " -x add output of hex and ASCII dump (Packet Bytes)\n");
192 fprintf(output, " -T pdml|ps|psml|text|fields\n");
193 fprintf(output, " format of text output (def: text)\n");
194 fprintf(output, " -e <field> field to print if -Tfields selected (e.g. tcp.port,\n");
195 fprintf(output, " _ws.col.Info)\n");
196 fprintf(output, " this option can be repeated to print multiple fields\n");
197 fprintf(output, " -E<fieldsoption>=<value> set options for output when -Tfields selected:\n");
198 fprintf(output, " header=y|n switch headers on and off\n");
199 fprintf(output, " separator=/t|/s|<char> select tab, space, printable character as separator\n");
200 fprintf(output, " occurrence=f|l|a print first, last or all occurrences of each field\n");
201 fprintf(output, " aggregator=,|/s|<char> select comma, space, printable character as\n");
202 fprintf(output, " aggregator\n");
203 fprintf(output, " quote=d|s|n select double, single, no quotes for values\n");
204 fprintf(output, " -t a|ad|d|dd|e|r|u|ud output format of time stamps (def: r: rel. to first)\n");
205 fprintf(output, " -u s|hms output format of seconds (def: s: seconds)\n");
206 fprintf(output, " -l flush standard output after each packet\n");
207 fprintf(output, " -q be more quiet on stdout (e.g. when using statistics)\n");
208 fprintf(output, " -Q only log true errors to stderr (quieter than -q)\n");
209 fprintf(output, " -X <key>:<value> eXtension options, see the man page for details\n");
210 fprintf(output, " -z <statistics> various statistics, see the man page for details\n");
212 fprintf(output, "\n");
213 fprintf(output, "Miscellaneous:\n");
214 fprintf(output, " -h display this help and exit\n");
215 fprintf(output, " -v display version info and exit\n");
216 fprintf(output, " -o <name>:<value> ... override preference setting\n");
217 fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
218 fprintf(output, " -G [report] dump one of several available reports and exit\n");
219 fprintf(output, " default report=\"fields\"\n");
220 fprintf(output, " use \"-G ?\" for more help\n");
224 glossary_option_help(void)
230 fprintf(output, "%s\n", get_appname_and_version());
232 fprintf(output, "\n");
233 fprintf(output, "Usage: tfshark -G [report]\n");
234 fprintf(output, "\n");
235 fprintf(output, "Glossary table reports:\n");
236 fprintf(output, " -G column-formats dump column format codes and exit\n");
237 fprintf(output, " -G decodes dump \"layer type\"/\"decode as\" associations and exit\n");
238 fprintf(output, " -G dissector-tables dump dissector table names, types, and properties\n");
239 fprintf(output, " -G fields dump fields glossary and exit\n");
240 fprintf(output, " -G ftypes dump field type basic and descriptive names\n");
241 fprintf(output, " -G heuristic-decodes dump heuristic dissector tables\n");
242 fprintf(output, " -G plugins dump installed plugins and exit\n");
243 fprintf(output, " -G protocols dump protocols in registration database and exit\n");
244 fprintf(output, " -G values dump value, range, true/false strings and exit\n");
245 fprintf(output, "\n");
246 fprintf(output, "Preference reports:\n");
247 fprintf(output, " -G currentprefs dump current preferences and exit\n");
248 fprintf(output, " -G defaultprefs dump default preferences and exit\n");
249 fprintf(output, "\n");
253 tfshark_log_handler (const gchar *log_domain, GLogLevelFlags log_level,
254 const gchar *message, gpointer user_data)
256 /* ignore log message, if log_level isn't interesting based
257 upon the console log preferences.
258 If the preferences haven't been loaded yet, display the
261 The default console_log_level preference value is such that only
262 ERROR, CRITICAL and WARNING level messages are processed;
263 MESSAGE, INFO and DEBUG level messages are ignored.
265 XXX: Aug 07, 2009: Prior tshark g_log code was hardwired to process only
266 ERROR and CRITICAL level messages so the current code is a behavioral
267 change. The current behavior is the same as in Wireshark.
269 if (prefs_loaded && (log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0) {
273 g_log_default_handler(log_domain, log_level, message, user_data);
278 print_current_user(void) {
279 gchar *cur_user, *cur_group;
281 if (started_with_special_privs()) {
282 cur_user = get_cur_username();
283 cur_group = get_cur_groupname();
284 fprintf(stderr, "Running as user \"%s\" and group \"%s\".",
285 cur_user, cur_group);
288 if (running_with_special_privs()) {
289 fprintf(stderr, " This could be dangerous.");
291 fprintf(stderr, "\n");
296 get_tfshark_runtime_version_info(GString *str)
298 /* stuff used by libwireshark */
299 epan_get_runtime_version_info(str);
303 main(int argc, char *argv[])
305 char *init_progfile_dir_error;
307 static const struct option long_options[] = {
308 {"help", no_argument, NULL, 'h'},
309 {"version", no_argument, NULL, 'v'},
312 gboolean arg_error = FALSE;
315 volatile gboolean success;
316 volatile int exit_status = 0;
317 gboolean quiet = FALSE;
318 gchar *volatile cf_name = NULL;
319 gchar *rfilter = NULL;
320 gchar *dfilter = NULL;
321 dfilter_t *rfcode = NULL;
322 dfilter_t *dfcode = NULL;
326 gchar *output_only = NULL;
329 * The leading + ensures that getopt_long() does not permute the argv[]
332 * We have to make sure that the first getopt_long() preserves the content
333 * of argv[] for the subsequent getopt_long() call.
335 * We use getopt_long() in both cases to ensure that we're using a routine
336 * whose permutation behavior we can control in the same fashion on all
337 * platforms, and so that, if we ever need to process a long argument before
338 * doing further initialization, we can do so.
340 * Glibc and Solaris libc document that a leading + disables permutation
341 * of options, regardless of whether POSIXLY_CORRECT is set or not; *BSD
342 * and macOS don't document it, but do so anyway.
344 * We do *not* use a leading - because the behavior of a leading - is
345 * platform-dependent.
347 #define OPTSTRING "+2C:d:e:E:hK:lo:O:qQr:R:S:t:T:u:vVxX:Y:z:"
349 static const char optstring[] = OPTSTRING;
351 /* Set the C-language locale to the native environment. */
352 setlocale(LC_ALL, "");
354 cmdarg_err_init(failure_warning_message, failure_message_cont);
357 create_app_running_mutex();
361 * Get credential information for later use, and drop privileges
362 * before doing anything else.
363 * Let the user know if anything happened.
365 init_process_policies();
366 relinquish_special_privs_perm();
367 print_current_user();
370 * Attempt to get the pathname of the directory containing the
373 init_progfile_dir_error = init_progfile_dir(argv[0]);
374 if (init_progfile_dir_error != NULL) {
376 "tfshark: Can't get pathname of directory containing the tfshark program: %s.\n",
377 init_progfile_dir_error);
378 g_free(init_progfile_dir_error);
381 initialize_funnel_ops();
383 /* Initialize the version information. */
384 ws_init_version_info("TFShark (Wireshark)", NULL,
385 epan_get_compiled_version_info,
386 get_tfshark_runtime_version_info);
389 * In order to have the -X opts assigned before the wslua machine starts
390 * we need to call getopts before epan_init() gets called.
392 * In order to handle, for example, -o options, we also need to call it
393 * *after* epan_init() gets called, so that the dissectors have had a
394 * chance to register their preferences.
396 * XXX - can we do this all with one getopt_long() call, saving the
397 * arguments we can't handle until after initializing libwireshark,
398 * and then process them after initializing libwireshark?
402 while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
404 case 'C': /* Configuration Profile */
405 if (profile_exists (optarg, FALSE)) {
406 set_profile_name (optarg);
408 cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
412 case 'O': /* Only output these protocols */
413 output_only = g_strdup(optarg);
415 case 'V': /* Verbose */
416 print_details = TRUE;
417 print_packet_info = TRUE;
419 case 'x': /* Print packet data in hex (and ASCII) */
421 /* The user asked for hex output, so let's ensure they get it,
422 * even if they're writing to a file.
424 print_packet_info = TRUE;
435 * Print packet summary information is the default, unless either -V or -x
436 * were specified. Note that this is new behavior, which
437 * allows for the possibility of printing only hex/ascii output without
438 * necessarily requiring that either the summary or details be printed too.
440 if (print_summary == -1)
441 print_summary = (print_details || print_hex) ? FALSE : TRUE;
443 /** Send All g_log messages to our own handler **/
447 G_LOG_LEVEL_CRITICAL|
452 G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
454 g_log_set_handler(NULL,
455 (GLogLevelFlags)log_flags,
456 tfshark_log_handler, NULL /* user_data */);
457 g_log_set_handler(LOG_DOMAIN_MAIN,
458 (GLogLevelFlags)log_flags,
459 tfshark_log_handler, NULL /* user_data */);
461 init_report_message(failure_warning_message, failure_warning_message,
462 open_failure_message, read_failure_message,
463 write_failure_message);
465 timestamp_set_type(TS_RELATIVE);
466 timestamp_set_precision(TS_PREC_AUTO);
467 timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
471 /* Register all dissectors; we must do this before checking for the
472 "-G" flag, as the "-G" flag dumps information registered by the
473 dissectors, and we must do it before we read the preferences, in
474 case any dissectors register preferences. */
475 if (!epan_init(NULL, NULL, TRUE)) {
476 exit_status = INIT_ERROR;
480 /* Register all tap listeners; we do this before we parse the arguments,
481 as the "-z" argument can specify a registered tap. */
483 /* we register the plugin taps before the other taps because
484 stats_tree taps plugins will be registered as tap listeners
485 by stats_tree_stat.c and need to registered before that */
487 /* XXX Disable tap registration for now until we can get tfshark set up with
488 * its own set of taps and the necessary registration function etc.
490 register_all_plugin_tap_listeners();
492 register_all_tap_listeners();
495 /* If invoked with the "-G" flag, we dump out information based on
496 the argument to the "-G" flag; if no argument is specified,
497 for backwards compatibility we dump out a glossary of display
500 XXX - we do this here, for now, to support "-G" with no arguments.
501 If none of our build or other processes uses "-G" with no arguments,
502 we can just process it with the other arguments. */
503 if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
504 proto_initialize_all_prefixes();
507 proto_registrar_dump_fields();
509 if (strcmp(argv[2], "column-formats") == 0)
510 column_dump_column_formats();
511 else if (strcmp(argv[2], "currentprefs") == 0) {
512 epan_load_settings();
515 else if (strcmp(argv[2], "decodes") == 0)
516 dissector_dump_decodes();
517 else if (strcmp(argv[2], "defaultprefs") == 0)
519 else if (strcmp(argv[2], "dissector-tables") == 0)
520 dissector_dump_dissector_tables();
521 else if (strcmp(argv[2], "fields") == 0)
522 proto_registrar_dump_fields();
523 else if (strcmp(argv[2], "ftypes") == 0)
524 proto_registrar_dump_ftypes();
525 else if (strcmp(argv[2], "heuristic-decodes") == 0)
526 dissector_dump_heur_decodes();
527 else if (strcmp(argv[2], "plugins") == 0) {
532 wslua_plugins_dump_all();
535 else if (strcmp(argv[2], "protocols") == 0)
536 proto_registrar_dump_protocols();
537 else if (strcmp(argv[2], "values") == 0)
538 proto_registrar_dump_values();
539 else if (strcmp(argv[2], "?") == 0)
540 glossary_option_help();
541 else if (strcmp(argv[2], "-?") == 0)
542 glossary_option_help();
544 cmdarg_err("Invalid \"%s\" option for -G flag, enter -G ? for more help.", argv[2]);
545 exit_status = INVALID_OPTION;
552 /* Load libwireshark settings from the current profile. */
553 prefs_p = epan_load_settings();
556 cap_file_init(&cfile);
558 /* Print format defaults to this. */
559 print_format = PR_FMT_TEXT;
561 output_fields = output_fields_new();
564 * To reset the options parser, set optreset to 1 on platforms that
565 * have optreset (documented in *BSD and macOS, apparently present but
566 * not documented in Solaris - the Illumos repository seems to
567 * suggest that the first Solaris getopt_long(), at least as of 2004,
568 * was based on the NetBSD one, it had optreset) and set optind to 1,
569 * and set optind to 0 otherwise (documented as working in the GNU
570 * getopt_long(). Setting optind to 0 didn't originally work in the
571 * NetBSD one, but that was added later - we don't want to depend on
572 * it if we have optreset).
574 * Also reset opterr to 1, so that error messages are printed by
585 /* Now get our args */
586 while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
588 case '2': /* Perform two pass analysis */
589 perform_two_pass_analysis = TRUE;
592 /* already processed; just ignore it now */
596 output_fields_add(output_fields, optarg);
600 if (!output_fields_set_option(output_fields, optarg)) {
601 cmdarg_err("\"%s\" is not a valid field output option=value pair.", optarg);
602 output_fields_list_options(stderr);
603 exit_status = INVALID_OPTION;
608 case 'h': /* Print help and exit */
609 show_help_header("Analyze file structure.");
613 case 'l': /* "Line-buffer" standard output */
614 /* The ANSI C standard does not appear to *require* that a line-buffered
615 stream be flushed to the host environment whenever a newline is
616 written, it just says that, on such a stream, characters "are
617 intended to be transmitted to or from the host environment as a
618 block when a new-line character is encountered".
620 The Visual C++ 6.0 C implementation doesn't do what is intended;
621 even if you set a stream to be line-buffered, it still doesn't
622 flush the buffer at the end of every line.
624 The whole reason for the "-l" flag in either tcpdump or TShark
625 is to allow the output of a live capture to be piped to a program
626 or script and to have that script see the information for the
627 packet as soon as it's printed, rather than having to wait until
628 a standard I/O buffer fills up.
630 So, if the "-l" flag is specified, we flush the standard output
631 at the end of a packet. This will do the right thing if we're
632 printing packet summary lines, and, as we print the entire protocol
633 tree for a single packet without waiting for anything to happen,
634 it should be as good as line-buffered mode if we're printing
635 protocol trees - arguably even better, as it may do fewer
637 line_buffered = TRUE;
639 case 'o': /* Override preference from command line */
643 switch (prefs_set_pref(optarg, &errmsg)) {
648 case PREFS_SET_SYNTAX_ERR:
649 cmdarg_err("Invalid -o flag \"%s\"%s%s", optarg,
650 errmsg ? ": " : "", errmsg ? errmsg : "");
655 case PREFS_SET_NO_SUCH_PREF:
656 case PREFS_SET_OBSOLETE:
657 cmdarg_err("-o flag \"%s\" specifies unknown preference", optarg);
658 exit_status = INVALID_OPTION;
664 case 'q': /* Quiet */
667 case 'Q': /* Really quiet */
671 case 'r': /* Read capture file x */
672 cf_name = g_strdup(optarg);
674 case 'R': /* Read file filter */
677 case 'S': /* Set the line Separator to be printed between packets */
678 separator = g_strdup(optarg);
680 case 'T': /* printing Type */
681 if (strcmp(optarg, "text") == 0) {
682 output_action = WRITE_TEXT;
683 print_format = PR_FMT_TEXT;
684 } else if (strcmp(optarg, "ps") == 0) {
685 output_action = WRITE_TEXT;
686 print_format = PR_FMT_PS;
687 } else if (strcmp(optarg, "pdml") == 0) {
688 output_action = WRITE_XML;
689 print_details = TRUE; /* Need details */
690 print_summary = FALSE; /* Don't allow summary */
691 } else if (strcmp(optarg, "psml") == 0) {
692 output_action = WRITE_XML;
693 print_details = FALSE; /* Don't allow details */
694 print_summary = TRUE; /* Need summary */
695 } else if (strcmp(optarg, "fields") == 0) {
696 output_action = WRITE_FIELDS;
697 print_details = TRUE; /* Need full tree info */
698 print_summary = FALSE; /* Don't allow summary */
700 cmdarg_err("Invalid -T parameter \"%s\"; it must be one of:", optarg); /* x */
701 cmdarg_err_cont("\t\"fields\" The values of fields specified with the -e option, in a form\n"
702 "\t specified by the -E option.\n"
703 "\t\"pdml\" Packet Details Markup Language, an XML-based format for the\n"
704 "\t details of a decoded packet. This information is equivalent to\n"
705 "\t the packet details printed with the -V flag.\n"
706 "\t\"ps\" PostScript for a human-readable one-line summary of each of\n"
707 "\t the packets, or a multi-line view of the details of each of\n"
708 "\t the packets, depending on whether the -V flag was specified.\n"
709 "\t\"psml\" Packet Summary Markup Language, an XML-based format for the\n"
710 "\t summary information of a decoded packet. This information is\n"
711 "\t equivalent to the information shown in the one-line summary\n"
712 "\t printed by default.\n"
713 "\t\"text\" Text of a human-readable one-line summary of each of the\n"
714 "\t packets, or a multi-line view of the details of each of the\n"
715 "\t packets, depending on whether the -V flag was specified.\n"
716 "\t This is the default.");
717 exit_status = INVALID_OPTION;
721 case 'v': /* Show version and exit */
724 case 'O': /* Only output these protocols */
725 /* already processed; just ignore it now */
727 case 'V': /* Verbose */
728 /* already processed; just ignore it now */
730 case 'x': /* Print packet data in hex (and ASCII) */
731 /* already processed; just ignore it now */
734 /* already processed; just ignore it now */
740 /* We won't call the init function for the stat this soon
741 as it would disallow MATE's fields (which are registered
742 by the preferences set callback) from being used as
743 part of a tap filter. Instead, we just add the argument
744 to a list of stat arguments. */
745 if (strcmp("help", optarg) == 0) {
746 fprintf(stderr, "tfshark: The available statistics for the \"-z\" option are:\n");
747 list_stat_cmd_args();
750 if (!process_stat_cmd_arg(optarg)) {
751 cmdarg_err("Invalid -z argument \"%s\"; it must be one of:", optarg);
752 list_stat_cmd_args();
753 exit_status = INVALID_OPTION;
757 case 'd': /* Decode as rule */
758 case 'K': /* Kerberos keytab file */
759 case 't': /* Time stamp type */
760 case 'u': /* Seconds type */
761 case LONGOPT_DISABLE_PROTOCOL: /* disable dissection of protocol */
762 case LONGOPT_ENABLE_HEURISTIC: /* enable heuristic dissection of protocol */
763 case LONGOPT_DISABLE_HEURISTIC: /* disable heuristic dissection of protocol */
764 case LONGOPT_ENABLE_PROTOCOL: /* enable dissection of protocol (that is disabled by default) */
765 if (!dissect_opts_handle_opt(opt, optarg)) {
766 exit_status = INVALID_OPTION;
771 case '?': /* Bad flag - print usage message */
773 exit_status = INVALID_OPTION;
779 /* If we specified output fields, but not the output field type... */
780 if (WRITE_FIELDS != output_action && 0 != output_fields_num_fields(output_fields)) {
781 cmdarg_err("Output fields were specified with \"-e\", "
782 "but \"-Tfields\" was not specified.");
784 } else if (WRITE_FIELDS == output_action && 0 == output_fields_num_fields(output_fields)) {
785 cmdarg_err("\"-Tfields\" was specified, but no fields were "
786 "specified with \"-e\".");
788 exit_status = INVALID_OPTION;
792 /* We require a -r flag specifying a file to read. */
793 if (cf_name == NULL) {
794 cmdarg_err("A file to read must be specified with \"-r\".");
795 exit_status = NO_FILE_SPECIFIED;
799 /* If no display filter has been specified, and there are still command-
800 line arguments, treat them as the tokens of a display filter. */
802 if (dfilter != NULL) {
803 cmdarg_err("Display filters were specified both with \"-d\" "
804 "and with additional command-line arguments.");
805 exit_status = INVALID_OPTION;
808 dfilter = get_args_as_string(argc, argv, optind);
811 /* if "-q" wasn't specified, we should print packet information */
813 print_packet_info = TRUE;
817 exit_status = INVALID_OPTION;
822 if (output_action != WRITE_TEXT) {
823 cmdarg_err("Raw packet hex data can only be printed as text or PostScript");
824 exit_status = INVALID_OPTION;
829 if (output_only != NULL) {
832 if (!print_details) {
833 cmdarg_err("-O requires -V");
834 exit_status = INVALID_OPTION;
838 output_only_tables = g_hash_table_new (g_str_hash, g_str_equal);
839 for (ps = strtok (output_only, ","); ps; ps = strtok (NULL, ",")) {
840 g_hash_table_insert(output_only_tables, (gpointer)ps, (gpointer)ps);
844 if (rfilter != NULL && !perform_two_pass_analysis) {
845 cmdarg_err("-R without -2 is deprecated. For single-pass filtering use -Y.");
846 exit_status = INVALID_OPTION;
850 /* Notify all registered modules that have had any of their preferences
851 changed either from one of the preferences file or from the command
852 line that their preferences have changed. */
856 * Enabled and disabled protocols and heuristic dissectors as per
857 * command-line options.
859 if (!setup_enabled_and_disabled_protocols()) {
860 exit_status = INVALID_OPTION;
864 /* Build the column format array */
865 build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
867 if (rfilter != NULL) {
868 if (!dfilter_compile(rfilter, &rfcode, &err_msg)) {
869 cmdarg_err("%s", err_msg);
871 exit_status = INVALID_FILTER;
875 cfile.rfcode = rfcode;
877 if (dfilter != NULL) {
878 if (!dfilter_compile(dfilter, &dfcode, &err_msg)) {
879 cmdarg_err("%s", err_msg);
881 exit_status = INVALID_FILTER;
885 cfile.dfcode = dfcode;
887 if (print_packet_info) {
888 /* If we're printing as text or PostScript, we have
889 to create a print stream. */
890 if (output_action == WRITE_TEXT) {
891 switch (print_format) {
894 print_stream = print_stream_text_stdio_new(stdout);
898 print_stream = print_stream_ps_stdio_new(stdout);
902 g_assert_not_reached();
907 /* We have to dissect each packet if:
909 we're printing information about each packet;
911 we're using a read filter on the packets;
913 we're using a display filter on the packets;
915 we're using any taps that need dissection. */
916 do_dissection = print_packet_info || rfcode || dfcode || tap_listeners_require_dissection();
922 /* TODO: if tfshark is ever changed to give the user a choice of which
923 open_routine reader to use, then the following needs to change. */
924 if (cf_open(&cfile, cf_name, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK) {
925 exit_status = OPEN_ERROR;
929 /* Start statistics taps; we do so after successfully opening the
930 capture file, so we know we have something to compute stats
931 on, and after registering all dissectors, so that MATE will
932 have registered its field array so we can have a tap filter
933 with one of MATE's late-registered fields as part of the
935 start_requested_stats();
937 /* Process the packets in the file */
939 /* XXX - for now there is only 1 packet */
940 success = process_file(&cfile, 1, 0);
942 CATCH(OutOfMemoryError) {
946 "Sorry, but TFShark has to terminate now.\n"
948 "Some infos / workarounds can be found at:\n"
949 "https://wiki.wireshark.org/KnownBugs/OutOfMemory\n");
955 /* We still dump out the results of taps, etc., as we might have
956 read some packets; however, we exit with an error status. */
962 if (cfile.provider.frames != NULL) {
963 free_frame_data_sequence(cfile.provider.frames);
964 cfile.provider.frames = NULL;
967 draw_tap_listeners(TRUE);
968 funnel_dump_all_text_windows();
971 destroy_print_stream(print_stream);
972 epan_free(cfile.epan);
976 output_fields_free(output_fields);
977 output_fields = NULL;
979 col_cleanup(&cfile.cinfo);
984 static const nstime_t *
985 tfshark_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num)
987 if (prov->ref && prov->ref->num == frame_num)
988 return &prov->ref->abs_ts;
990 if (prov->prev_dis && prov->prev_dis->num == frame_num)
991 return &prov->prev_dis->abs_ts;
993 if (prov->prev_cap && prov->prev_cap->num == frame_num)
994 return &prov->prev_cap->abs_ts;
997 frame_data *fd = frame_data_sequence_find(prov->frames, frame_num);
999 return (fd) ? &fd->abs_ts : NULL;
1006 no_interface_name(struct packet_provider_data *prov _U_, guint32 interface_id _U_)
1012 tfshark_epan_new(capture_file *cf)
1014 static const struct packet_provider_funcs funcs = {
1015 tfshark_get_frame_ts,
1021 return epan_new(&cf->provider, &funcs);
1025 process_packet_first_pass(capture_file *cf, epan_dissect_t *edt,
1026 gint64 offset, wtap_rec *rec,
1033 /* The frame number of this packet is one more than the count of
1034 frames in this packet. */
1035 framenum = cf->count + 1;
1037 /* If we're not running a display filter and we're not printing any
1038 packet information, we don't need to do a dissection. This means
1039 that all packets can be marked as 'passed'. */
1042 frame_data_init(&fdlocal, framenum, rec, offset, cum_bytes);
1044 /* If we're going to print packet information, or we're going to
1045 run a read filter, or display filter, or we're going to process taps, set up to
1046 do a dissection and do so. */
1048 /* If we're running a read filter, prime the epan_dissect_t with that
1051 epan_dissect_prime_with_dfilter(edt, cf->rfcode);
1053 /* This is the first pass, so prime the epan_dissect_t with the
1054 hfids postdissectors want on the first pass. */
1055 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1057 frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time,
1058 &cf->provider.ref, cf->provider.prev_dis);
1059 if (cf->provider.ref == &fdlocal) {
1060 ref_frame = fdlocal;
1061 cf->provider.ref = &ref_frame;
1064 epan_dissect_file_run(edt, rec,
1065 file_tvbuff_new(&cf->provider, &fdlocal, pd),
1068 /* Run the read filter if we have one. */
1070 passed = dfilter_apply_edt(cf->rfcode, edt);
1074 frame_data_set_after_dissect(&fdlocal, &cum_bytes);
1075 cf->provider.prev_cap = cf->provider.prev_dis = frame_data_sequence_add(cf->provider.frames, &fdlocal);
1077 /* If we're not doing dissection then there won't be any dependent frames.
1078 * More importantly, edt.pi.dependent_frames won't be initialized because
1079 * epan hasn't been initialized.
1082 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
1087 /* if we don't add it to the frame_data_sequence, clean it up right now
1089 frame_data_destroy(&fdlocal);
1093 epan_dissect_reset(edt);
1099 process_packet_second_pass(capture_file *cf, epan_dissect_t *edt,
1100 frame_data *fdata, wtap_rec *rec,
1101 Buffer *buf, guint tap_flags)
1106 /* If we're not running a display filter and we're not printing any
1107 packet information, we don't need to do a dissection. This means
1108 that all packets can be marked as 'passed'. */
1111 /* If we're going to print packet information, or we're going to
1112 run a read filter, or we're going to process taps, set up to
1113 do a dissection and do so. */
1116 /* If we're running a display filter, prime the epan_dissect_t with that
1119 epan_dissect_prime_with_dfilter(edt, cf->dfcode);
1121 /* This is the first and only pass, so prime the epan_dissect_t
1122 with the hfids postdissectors want on the first pass. */
1123 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1125 col_custom_prime_edt(edt, &cf->cinfo);
1127 /* We only need the columns if either
1128 1) some tap needs the columns
1130 2) we're printing packet info but we're *not* verbose; in verbose
1131 mode, we print the protocol tree, not the protocol summary.
1133 if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary))
1138 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1139 &cf->provider.ref, cf->provider.prev_dis);
1140 if (cf->provider.ref == fdata) {
1142 cf->provider.ref = &ref_frame;
1145 epan_dissect_file_run_with_taps(edt, rec,
1146 file_tvbuff_new_buffer(&cf->provider, fdata, buf), fdata, cinfo);
1148 /* Run the read/display filter if we have one. */
1150 passed = dfilter_apply_edt(cf->dfcode, edt);
1154 frame_data_set_after_dissect(fdata, &cum_bytes);
1155 /* Process this packet. */
1156 if (print_packet_info) {
1157 /* We're printing packet information; print the information for
1159 print_packet(cf, edt);
1161 /* If we're doing "line-buffering", flush the standard output
1162 after every packet. See the comment above, for the "-l"
1163 option, for an explanation of why we do that. */
1167 if (ferror(stdout)) {
1168 show_print_file_io_error(errno);
1172 cf->provider.prev_dis = fdata;
1174 cf->provider.prev_cap = fdata;
1177 epan_dissect_reset(edt);
1179 return passed || fdata->dependent_of_displayed;
1183 local_wtap_read(capture_file *cf, wtap_rec *file_rec _U_, int *err, gchar **err_info _U_, gint64 *data_offset _U_, guint8** data_buffer)
1185 /* int bytes_read; */
1186 gint64 packet_size = wtap_file_size(cf->provider.wth, err);
1188 *data_buffer = (guint8*)g_malloc((gsize)packet_size);
1189 /* bytes_read =*/ file_read(*data_buffer, (unsigned int)packet_size, cf->provider.wth->fh);
1191 #if 0 /* no more filetap */
1192 if (bytes_read < 0) {
1193 *err = file_error(cf->provider.wth->fh, err_info);
1195 *err = FTAP_ERR_SHORT_READ;
1197 } else if (bytes_read == 0) {
1198 /* Done with file, no error */
1203 /* XXX - SET FRAME SIZE EQUAL TO TOTAL FILE SIZE */
1204 file_rec->rec_header.packet_header.caplen = (guint32)packet_size;
1205 file_rec->rec_header.packet_header.len = (guint32)packet_size;
1208 * Set the packet encapsulation to the file's encapsulation
1209 * value; if that's not WTAP_ENCAP_PER_PACKET, it's the
1210 * right answer (and means that the read routine for this
1211 * capture file type doesn't have to set it), and if it
1212 * *is* WTAP_ENCAP_PER_PACKET, the caller needs to set it
1215 wth->rec.rec_header.packet_header.pkt_encap = wth->file_encap;
1217 if (!wth->subtype_read(wth, err, err_info, data_offset)) {
1219 * If we didn't get an error indication, we read
1220 * the last packet. See if there's any deferred
1221 * error, as might, for example, occur if we're
1222 * reading a compressed file, and we got an error
1223 * reading compressed data from the file, but
1224 * got enough compressed data to decompress the
1225 * last packet of the file.
1228 *err = file_error(wth->fh, err_info);
1229 return FALSE; /* failure */
1233 * It makes no sense for the captured data length to be bigger
1234 * than the actual data length.
1236 if (wth->rec.rec_header.packet_header.caplen > wth->rec.rec_header.packet_header.len)
1237 wth->rec.rec_header.packet_header.caplen = wth->rec.rec_header.packet_header.len;
1240 * Make sure that it's not WTAP_ENCAP_PER_PACKET, as that
1241 * probably means the file has that encapsulation type
1242 * but the read routine didn't set this packet's
1243 * encapsulation type.
1245 g_assert(wth->rec.rec_header.packet_header.pkt_encap != WTAP_ENCAP_PER_PACKET);
1248 return TRUE; /* success */
1252 process_file(capture_file *cf, int max_packet_count, gint64 max_byte_count)
1256 gchar *err_info = NULL;
1257 gint64 data_offset = 0;
1258 gboolean filtering_tap_listeners;
1261 epan_dissect_t *edt = NULL;
1265 if (print_packet_info) {
1266 if (!write_preamble(cf)) {
1268 show_print_file_io_error(err);
1273 /* Do we have any tap listeners with filters? */
1274 filtering_tap_listeners = have_filtering_tap_listeners();
1276 /* Get the union of the flags for all tap listeners. */
1277 tap_flags = union_of_tap_listener_flags();
1279 wtap_rec_init(&file_rec);
1281 /* XXX - TEMPORARY HACK TO ELF DISSECTOR */
1282 file_rec.rec_header.packet_header.pkt_encap = 1234;
1284 if (perform_two_pass_analysis) {
1287 /* Allocate a frame_data_sequence for all the frames. */
1288 cf->provider.frames = new_frame_data_sequence();
1290 if (do_dissection) {
1291 gboolean create_proto_tree;
1294 * Determine whether we need to create a protocol tree.
1297 * we're going to apply a read filter;
1299 * a postdissector wants field values or protocols
1300 * on the first pass.
1303 (cf->rfcode != NULL || postdissectors_want_hfids());
1305 /* We're not going to display the protocol tree on this pass,
1306 so it's not going to be "visible". */
1307 edt = epan_dissect_new(cf->epan, create_proto_tree, FALSE);
1309 while (local_wtap_read(cf, &file_rec, &err, &err_info, &data_offset, &raw_data)) {
1310 if (process_packet_first_pass(cf, edt, data_offset, &file_rec/*wtap_get_rec(cf->provider.wth)*/,
1311 wtap_get_buf_ptr(cf->provider.wth))) {
1313 /* Stop reading if we have the maximum number of packets;
1314 * When the -c option has not been used, max_packet_count
1315 * starts at 0, which practically means, never stop reading.
1316 * (unless we roll over max_packet_count ?)
1318 if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
1319 err = 0; /* This is not an error */
1326 epan_dissect_free(edt);
1331 /* Close the sequential I/O side, to free up memory it requires. */
1332 wtap_sequential_close(cf->provider.wth);
1335 /* Allow the protocol dissectors to free up memory that they
1336 * don't need after the sequential run-through of the packets. */
1337 postseq_cleanup_all_protocols();
1339 cf->provider.prev_dis = NULL;
1340 cf->provider.prev_cap = NULL;
1341 ws_buffer_init(&buf, 1500);
1343 if (do_dissection) {
1344 gboolean create_proto_tree;
1347 * Determine whether we need to create a protocol tree.
1350 * we're going to apply a display filter;
1352 * we're going to print the protocol tree;
1354 * one of the tap listeners requires a protocol tree;
1356 * we have custom columns (which require field values, which
1357 * currently requires that we build a protocol tree).
1360 (cf->dfcode || print_details || filtering_tap_listeners ||
1361 (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo));
1363 /* The protocol tree will be "visible", i.e., printed, only if we're
1364 printing packet details, which is true if we're printing stuff
1365 ("print_packet_info" is true) and we're in verbose mode
1366 ("packet_details" is true). */
1367 edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details);
1370 for (framenum = 1; err == 0 && framenum <= cf->count; framenum++) {
1371 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1373 if (wtap_seek_read(cf->provider.wth, fdata->file_off,
1374 &buf, fdata->cap_len, &err, &err_info)) {
1375 process_packet_second_pass(cf, edt, fdata, &cf->rec, &buf, tap_flags);
1378 if (!process_packet_second_pass(cf, edt, fdata, &cf->rec, &buf,
1385 epan_dissect_free(edt);
1389 ws_buffer_free(&buf);
1394 if (do_dissection) {
1395 gboolean create_proto_tree;
1398 * Determine whether we need to create a protocol tree.
1401 * we're going to apply a read filter;
1403 * we're going to apply a display filter;
1405 * we're going to print the protocol tree;
1407 * one of the tap listeners is going to apply a filter;
1409 * one of the tap listeners requires a protocol tree;
1411 * a postdissector wants field values or protocols
1412 * on the first pass;
1414 * we have custom columns (which require field values, which
1415 * currently requires that we build a protocol tree).
1418 (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners ||
1419 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids() ||
1420 have_custom_cols(&cf->cinfo));
1422 /* The protocol tree will be "visible", i.e., printed, only if we're
1423 printing packet details, which is true if we're printing stuff
1424 ("print_packet_info" is true) and we're in verbose mode
1425 ("packet_details" is true). */
1426 edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details);
1429 while (local_wtap_read(cf, &file_rec, &err, &err_info, &data_offset, &raw_data)) {
1433 if (!process_packet_single_pass(cf, edt, data_offset,
1434 &file_rec/*wtap_get_rec(cf->provider.wth)*/,
1435 raw_data, tap_flags))
1438 /* Stop reading if we have the maximum number of packets;
1439 * When the -c option has not been used, max_packet_count
1440 * starts at 0, which practically means, never stop reading.
1441 * (unless we roll over max_packet_count ?)
1443 if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
1444 err = 0; /* This is not an error */
1450 epan_dissect_free(edt);
1455 wtap_rec_cleanup(&file_rec);
1459 * Print a message noting that the read failed somewhere along the line.
1461 * If we're printing packet data, and the standard output and error are
1462 * going to the same place, flush the standard output, so everything
1463 * buffered up is written, and then print a newline to the standard error
1464 * before printing the error message, to separate it from the packet
1465 * data. (Alas, that only works on UN*X; st_dev is meaningless, and
1466 * the _fstat() documentation at Microsoft doesn't indicate whether
1467 * st_ino is even supported.)
1470 if (print_packet_info) {
1471 ws_statb64 stat_stdout, stat_stderr;
1473 if (ws_fstat64(1, &stat_stdout) == 0 && ws_fstat64(2, &stat_stderr) == 0) {
1474 if (stat_stdout.st_dev == stat_stderr.st_dev &&
1475 stat_stdout.st_ino == stat_stderr.st_ino) {
1477 fprintf(stderr, "\n");
1485 case FTAP_ERR_UNSUPPORTED:
1486 cmdarg_err("The file \"%s\" contains record data that TFShark doesn't support.\n(%s)",
1487 cf->filename, err_info);
1491 case FTAP_ERR_UNSUPPORTED_ENCAP:
1492 cmdarg_err("The file \"%s\" has a packet with a network type that TFShark doesn't support.\n(%s)",
1493 cf->filename, err_info);
1497 case FTAP_ERR_CANT_READ:
1498 cmdarg_err("An attempt to read from the file \"%s\" failed for some unknown reason.",
1502 case FTAP_ERR_SHORT_READ:
1503 cmdarg_err("The file \"%s\" appears to have been cut short in the middle of a packet.",
1507 case FTAP_ERR_BAD_FILE:
1508 cmdarg_err("The file \"%s\" appears to be damaged or corrupt.\n(%s)",
1509 cf->filename, err_info);
1513 case FTAP_ERR_DECOMPRESS:
1514 cmdarg_err("The compressed file \"%s\" appears to be damaged or corrupt.\n"
1515 "(%s)", cf->filename, err_info);
1519 cmdarg_err("An error occurred while reading the file \"%s\": %s.",
1520 cf->filename, ftap_strerror(err));
1525 if (print_packet_info) {
1526 if (!write_finale()) {
1528 show_print_file_io_error(err);
1534 wtap_close(cf->provider.wth);
1535 cf->provider.wth = NULL;
1541 process_packet_single_pass(capture_file *cf, epan_dissect_t *edt, gint64 offset,
1542 wtap_rec *rec, const guchar *pd,
1549 /* Count this packet. */
1552 /* If we're not running a display filter and we're not printing any
1553 packet information, we don't need to do a dissection. This means
1554 that all packets can be marked as 'passed'. */
1557 frame_data_init(&fdata, cf->count, rec, offset, cum_bytes);
1559 /* If we're going to print packet information, or we're going to
1560 run a read filter, or we're going to process taps, set up to
1561 do a dissection and do so. */
1563 /* If we're running a filter, prime the epan_dissect_t with that
1566 epan_dissect_prime_with_dfilter(edt, cf->dfcode);
1568 col_custom_prime_edt(edt, &cf->cinfo);
1570 /* We only need the columns if either
1571 1) some tap needs the columns
1573 2) we're printing packet info but we're *not* verbose; in verbose
1574 mode, we print the protocol tree, not the protocol summary.
1576 3) there is a column mapped as an individual field */
1577 if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary) || output_fields_has_cols(output_fields))
1582 frame_data_set_before_dissect(&fdata, &cf->elapsed_time,
1583 &cf->provider.ref, cf->provider.prev_dis);
1584 if (cf->provider.ref == &fdata) {
1586 cf->provider.ref = &ref_frame;
1589 epan_dissect_file_run_with_taps(edt, rec,
1590 frame_tvbuff_new(&cf->provider, &fdata, pd),
1593 /* Run the filter if we have it. */
1595 passed = dfilter_apply_edt(cf->dfcode, edt);
1599 frame_data_set_after_dissect(&fdata, &cum_bytes);
1601 /* Process this packet. */
1602 if (print_packet_info) {
1603 /* We're printing packet information; print the information for
1605 print_packet(cf, edt);
1607 /* If we're doing "line-buffering", flush the standard output
1608 after every packet. See the comment above, for the "-l"
1609 option, for an explanation of why we do that. */
1613 if (ferror(stdout)) {
1614 show_print_file_io_error(errno);
1619 /* this must be set after print_packet() [bug #8160] */
1620 prev_dis_frame = fdata;
1621 cf->provider.prev_dis = &prev_dis_frame;
1624 prev_cap_frame = fdata;
1625 cf->provider.prev_cap = &prev_cap_frame;
1628 epan_dissect_reset(edt);
1629 frame_data_destroy(&fdata);
1635 write_preamble(capture_file *cf)
1637 switch (output_action) {
1640 return print_preamble(print_stream, cf->filename, get_ws_vcs_version_info());
1644 write_pdml_preamble(stdout, cf->filename);
1646 write_psml_preamble(&cf->cinfo, stdout);
1647 return !ferror(stdout);
1650 write_fields_preamble(output_fields, stdout);
1651 return !ferror(stdout);
1654 g_assert_not_reached();
1660 get_line_buf(size_t len)
1662 static char *line_bufp = NULL;
1663 static size_t line_buf_len = 256;
1664 size_t new_line_buf_len;
1666 for (new_line_buf_len = line_buf_len; len > new_line_buf_len;
1667 new_line_buf_len *= 2)
1669 if (line_bufp == NULL) {
1670 line_buf_len = new_line_buf_len;
1671 line_bufp = (char *)g_malloc(line_buf_len + 1);
1673 if (new_line_buf_len > line_buf_len) {
1674 line_buf_len = new_line_buf_len;
1675 line_bufp = (char *)g_realloc(line_bufp, line_buf_len + 1);
1682 put_string(char *dest, const char *str, size_t str_len)
1684 memcpy(dest, str, str_len);
1685 dest[str_len] = '\0';
1689 put_spaces_string(char *dest, const char *str, size_t str_len, size_t str_with_spaces)
1693 for (i = str_len; i < str_with_spaces; i++)
1696 put_string(dest, str, str_len);
1700 put_string_spaces(char *dest, const char *str, size_t str_len, size_t str_with_spaces)
1704 memcpy(dest, str, str_len);
1705 for (i = str_len; i < str_with_spaces; i++)
1708 dest[str_with_spaces] = '\0';
1712 print_columns(capture_file *cf)
1719 col_item_t* col_item;
1721 line_bufp = get_line_buf(256);
1724 for (i = 0; i < cf->cinfo.num_cols; i++) {
1725 col_item = &cf->cinfo.columns[i];
1726 /* Skip columns not marked as visible. */
1727 if (!get_column_visible(i))
1729 switch (col_item->col_fmt) {
1731 column_len = col_len = strlen(col_item->col_data);
1734 line_bufp = get_line_buf(buf_offset + column_len);
1735 put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1741 case COL_ABS_YMD_TIME: /* XXX - wider */
1742 case COL_ABS_YDOY_TIME: /* XXX - wider */
1744 case COL_UTC_YMD_TIME: /* XXX - wider */
1745 case COL_UTC_YDOY_TIME: /* XXX - wider */
1746 column_len = col_len = strlen(col_item->col_data);
1747 if (column_len < 10)
1749 line_bufp = get_line_buf(buf_offset + column_len);
1750 put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1756 case COL_DEF_DL_SRC:
1757 case COL_RES_DL_SRC:
1758 case COL_UNRES_DL_SRC:
1759 case COL_DEF_NET_SRC:
1760 case COL_RES_NET_SRC:
1761 case COL_UNRES_NET_SRC:
1762 column_len = col_len = strlen(col_item->col_data);
1763 if (column_len < 12)
1765 line_bufp = get_line_buf(buf_offset + column_len);
1766 put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1772 case COL_DEF_DL_DST:
1773 case COL_RES_DL_DST:
1774 case COL_UNRES_DL_DST:
1775 case COL_DEF_NET_DST:
1776 case COL_RES_NET_DST:
1777 case COL_UNRES_NET_DST:
1778 column_len = col_len = strlen(col_item->col_data);
1779 if (column_len < 12)
1781 line_bufp = get_line_buf(buf_offset + column_len);
1782 put_string_spaces(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1786 column_len = strlen(col_item->col_data);
1787 line_bufp = get_line_buf(buf_offset + column_len);
1788 put_string(line_bufp + buf_offset, col_item->col_data, column_len);
1791 buf_offset += column_len;
1792 if (i != cf->cinfo.num_cols - 1) {
1794 * This isn't the last column, so we need to print a
1795 * separator between this column and the next.
1797 * If we printed a network source and are printing a
1798 * network destination of the same type next, separate
1799 * them with " -> "; if we printed a network destination
1800 * and are printing a network source of the same type
1801 * next, separate them with " <- "; otherwise separate them
1804 * We add enough space to the buffer for " <- " or " -> ",
1805 * even if we're only adding " ".
1807 line_bufp = get_line_buf(buf_offset + 4);
1808 switch (col_item->col_fmt) {
1813 switch (cf->cinfo.columns[i+1].col_fmt) {
1818 put_string(line_bufp + buf_offset, " -> ", 4);
1823 put_string(line_bufp + buf_offset, " ", 1);
1829 case COL_DEF_DL_SRC:
1830 case COL_RES_DL_SRC:
1831 case COL_UNRES_DL_SRC:
1832 switch (cf->cinfo.columns[i+1].col_fmt) {
1834 case COL_DEF_DL_DST:
1835 case COL_RES_DL_DST:
1836 case COL_UNRES_DL_DST:
1837 put_string(line_bufp + buf_offset, " -> ", 4);
1842 put_string(line_bufp + buf_offset, " ", 1);
1848 case COL_DEF_NET_SRC:
1849 case COL_RES_NET_SRC:
1850 case COL_UNRES_NET_SRC:
1851 switch (cf->cinfo.columns[i+1].col_fmt) {
1853 case COL_DEF_NET_DST:
1854 case COL_RES_NET_DST:
1855 case COL_UNRES_NET_DST:
1856 put_string(line_bufp + buf_offset, " -> ", 4);
1861 put_string(line_bufp + buf_offset, " ", 1);
1870 switch (cf->cinfo.columns[i+1].col_fmt) {
1875 put_string(line_bufp + buf_offset, " <- ", 4);
1880 put_string(line_bufp + buf_offset, " ", 1);
1886 case COL_DEF_DL_DST:
1887 case COL_RES_DL_DST:
1888 case COL_UNRES_DL_DST:
1889 switch (cf->cinfo.columns[i+1].col_fmt) {
1891 case COL_DEF_DL_SRC:
1892 case COL_RES_DL_SRC:
1893 case COL_UNRES_DL_SRC:
1894 put_string(line_bufp + buf_offset, " <- ", 4);
1899 put_string(line_bufp + buf_offset, " ", 1);
1905 case COL_DEF_NET_DST:
1906 case COL_RES_NET_DST:
1907 case COL_UNRES_NET_DST:
1908 switch (cf->cinfo.columns[i+1].col_fmt) {
1910 case COL_DEF_NET_SRC:
1911 case COL_RES_NET_SRC:
1912 case COL_UNRES_NET_SRC:
1913 put_string(line_bufp + buf_offset, " <- ", 4);
1918 put_string(line_bufp + buf_offset, " ", 1);
1925 put_string(line_bufp + buf_offset, " ", 1);
1931 return print_line(print_stream, 0, line_bufp);
1935 print_packet(capture_file *cf, epan_dissect_t *edt)
1937 if (print_summary || output_fields_has_cols(output_fields)) {
1938 /* Just fill in the columns. */
1939 epan_dissect_fill_in_columns(edt, FALSE, TRUE);
1941 if (print_summary) {
1942 /* Now print them. */
1943 switch (output_action) {
1946 if (!print_columns(cf))
1951 write_psml_columns(edt, stdout, FALSE);
1952 return !ferror(stdout);
1953 case WRITE_FIELDS: /*No non-verbose "fields" format */
1954 g_assert_not_reached();
1959 if (print_details) {
1960 /* Print the information in the protocol tree. */
1961 switch (output_action) {
1964 if (!proto_tree_print(print_details ? print_dissections_expanded : print_dissections_none,
1965 print_hex, edt, output_only_tables, print_stream))
1968 if (!print_line(print_stream, 0, separator))
1974 write_pdml_proto_tree(NULL, NULL, PF_NONE, edt, &cf->cinfo, stdout, FALSE);
1976 return !ferror(stdout);
1978 write_fields_proto_tree(output_fields, edt, &cf->cinfo, stdout);
1980 return !ferror(stdout);
1984 if (print_summary || print_details) {
1985 if (!print_line(print_stream, 0, ""))
1988 if (!print_hex_data(print_stream, edt))
1990 if (!print_line(print_stream, 0, separator))
1999 switch (output_action) {
2002 return print_finale(print_stream);
2006 write_pdml_finale(stdout);
2008 write_psml_finale(stdout);
2009 return !ferror(stdout);
2012 write_fields_finale(output_fields, stdout);
2013 return !ferror(stdout);
2016 g_assert_not_reached();
2022 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
2025 char err_msg[2048+1];
2027 /* The open isn't implemented yet. Fill in the information for this file. */
2029 /* Create new epan session for dissection. */
2030 epan_free(cf->epan);
2031 cf->epan = tfshark_epan_new(cf);
2033 cf->provider.wth = NULL; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2034 cf->f_datalen = 0; /* not used, but set it anyway */
2036 /* Set the file name because we need it to set the follow stream filter.
2037 XXX - is that still true? We need it for other reasons, though,
2039 cf->filename = g_strdup(fname);
2041 /* Indicate whether it's a permanent or temporary file. */
2042 cf->is_tempfile = is_tempfile;
2044 /* No user changes yet. */
2045 cf->unsaved_changes = FALSE;
2047 cf->cd_t = 0; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2048 cf->open_type = type;
2050 cf->drops_known = FALSE;
2052 cf->snap = 0; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2053 nstime_set_zero(&cf->elapsed_time);
2054 cf->provider.ref = NULL;
2055 cf->provider.prev_dis = NULL;
2056 cf->provider.prev_cap = NULL;
2058 cf->state = FILE_READ_IN_PROGRESS;
2063 g_snprintf(err_msg, sizeof err_msg,
2064 cf_open_error_message(*err, err_info, FALSE, cf->cd_t), fname);
2065 cmdarg_err("%s", err_msg);
2070 show_print_file_io_error(int err)
2075 cmdarg_err("Not all the packets could be printed because there is "
2076 "no space left on the file system.");
2081 cmdarg_err("Not all the packets could be printed because you are "
2082 "too close to, or over your disk quota.");
2087 cmdarg_err("An error occurred while printing packets: %s.",
2094 cf_open_error_message(int err, gchar *err_info _U_, gboolean for_writing,
2098 /* static char errmsg_errno[1024+1]; */
2102 /* Wiretap error. */
2105 case FTAP_ERR_NOT_REGULAR_FILE:
2106 errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
2109 case FTAP_ERR_RANDOM_OPEN_PIPE:
2110 /* Seen only when opening a capture file for reading. */
2111 errmsg = "The file \"%s\" is a pipe or FIFO; TFShark can't read pipe or FIFO files in two-pass mode.";
2114 case FTAP_ERR_FILE_UNKNOWN_FORMAT:
2115 /* Seen only when opening a capture file for reading. */
2116 errmsg = "The file \"%s\" isn't a capture file in a format TFShark understands.";
2119 case FTAP_ERR_UNSUPPORTED:
2120 /* Seen only when opening a capture file for reading. */
2121 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2122 "The file \"%%s\" isn't a capture file in a format TFShark understands.\n"
2125 errmsg = errmsg_errno;
2128 case FTAP_ERR_CANT_WRITE_TO_PIPE:
2129 /* Seen only when opening a capture file for writing. */
2130 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2131 "The file \"%%s\" is a pipe, and \"%s\" capture files can't be "
2132 "written to a pipe.", ftap_file_type_subtype_short_string(file_type));
2133 errmsg = errmsg_errno;
2136 case FTAP_ERR_UNSUPPORTED_FILE_TYPE:
2137 /* Seen only when opening a capture file for writing. */
2138 errmsg = "TFShark doesn't support writing capture files in that format.";
2141 case FTAP_ERR_UNSUPPORTED_ENCAP:
2143 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2144 "TFShark can't save this capture as a \"%s\" file.",
2145 ftap_file_type_subtype_short_string(file_type));
2147 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2148 "The file \"%%s\" is a capture for a network type that TFShark doesn't support.\n"
2152 errmsg = errmsg_errno;
2155 case FTAP_ERR_ENCAP_PER_RECORD_UNSUPPORTED:
2157 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2158 "TFShark can't save this capture as a \"%s\" file.",
2159 ftap_file_type_subtype_short_string(file_type));
2160 errmsg = errmsg_errno;
2162 errmsg = "The file \"%s\" is a capture for a network type that TFShark doesn't support.";
2165 case FTAP_ERR_BAD_FILE:
2166 /* Seen only when opening a capture file for reading. */
2167 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2168 "The file \"%%s\" appears to be damaged or corrupt.\n"
2171 errmsg = errmsg_errno;
2174 case FTAP_ERR_CANT_OPEN:
2176 errmsg = "The file \"%s\" could not be created for some unknown reason.";
2178 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
2181 case FTAP_ERR_SHORT_READ:
2182 errmsg = "The file \"%s\" appears to have been cut short"
2183 " in the middle of a packet or other data.";
2186 case FTAP_ERR_SHORT_WRITE:
2187 errmsg = "A full header couldn't be written to the file \"%s\".";
2190 case FTAP_ERR_COMPRESSION_NOT_SUPPORTED:
2191 errmsg = "This file type cannot be written as a compressed file.";
2194 case FTAP_ERR_DECOMPRESS:
2195 /* Seen only when opening a capture file for reading. */
2196 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2197 "The compressed file \"%%s\" appears to be damaged or corrupt.\n"
2200 errmsg = errmsg_errno;
2204 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2205 "The file \"%%s\" could not be %s: %s.",
2206 for_writing ? "created" : "opened",
2207 ftap_strerror(err));
2208 errmsg = errmsg_errno;
2213 errmsg = file_open_error_message(err, for_writing);
2218 * General errors and warnings are reported with an console message
2222 failure_warning_message(const char *msg_format, va_list ap)
2224 fprintf(stderr, "tfshark: ");
2225 vfprintf(stderr, msg_format, ap);
2226 fprintf(stderr, "\n");
2230 * Open/create errors are reported with an console message in TFShark.
2233 open_failure_message(const char *filename, int err, gboolean for_writing)
2235 fprintf(stderr, "tfshark: ");
2236 fprintf(stderr, file_open_error_message(err, for_writing), filename);
2237 fprintf(stderr, "\n");
2241 * Read errors are reported with an console message in TFShark.
2244 read_failure_message(const char *filename, int err)
2246 cmdarg_err("An error occurred while reading from the file \"%s\": %s.",
2247 filename, g_strerror(err));
2251 * Write errors are reported with an console message in TFShark.
2254 write_failure_message(const char *filename, int err)
2256 cmdarg_err("An error occurred while writing to the file \"%s\": %s.",
2257 filename, g_strerror(err));
2261 * Report additional information for an error in command-line arguments.
2264 failure_message_cont(const char *msg_format, va_list ap)
2266 vfprintf(stderr, msg_format, ap);
2267 fprintf(stderr, "\n");
2271 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2276 * indent-tabs-mode: nil
2279 * vi: set shiftwidth=2 tabstop=8 expandtab:
2280 * :indentSize=2:tabSize=8:noTabs=true: