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>
38 #include <wsutil/filesystem.h>
39 #include <wsutil/file_util.h>
40 #include <wsutil/privileges.h>
41 #include <wsutil/report_message.h>
43 #include <version_info.h>
46 #include <epan/timestamp.h>
47 #include <epan/packet.h>
49 #include <epan/wslua/init_wslua.h>
52 #include "frame_tvbuff.h"
53 #include <epan/disabled_protos.h>
54 #include <epan/prefs.h>
55 #include <epan/column.h>
56 #include <epan/print.h>
57 #include <epan/addr_resolv.h>
59 #include "ui/decode_as_utils.h"
60 #include "ui/dissect_opts.h"
61 #include <epan/epan_dissect.h>
63 #include <epan/stat_tap_ui.h>
64 #include <epan/ex-opt.h>
67 #include <wiretap/wtap-int.h>
68 #include <wiretap/file_wrappers.h>
71 #include <epan/funnel.h>
74 #include <wsutil/plugins.h>
77 #define INVALID_OPTION 1
78 #define NO_FILE_SPECIFIED 1
80 #define INVALID_FILTER 2
85 static guint32 cum_bytes;
86 static frame_data ref_frame;
87 static frame_data prev_dis_frame;
88 static frame_data prev_cap_frame;
90 static gboolean prefs_loaded = FALSE;
92 static gboolean perform_two_pass_analysis;
95 * The way the packet decode is to be written.
98 WRITE_TEXT, /* summary or detail text */
99 WRITE_XML, /* PDML or PSML */
100 WRITE_FIELDS /* User defined list of fields */
101 /* Add CSV and the like here */
104 static output_action_e output_action;
105 static gboolean do_dissection; /* TRUE if we have to dissect each packet */
106 static gboolean print_packet_info; /* TRUE if we're to print packet information */
107 static gint print_summary = -1; /* TRUE if we're to print packet summary information */
108 static gboolean print_details; /* TRUE if we're to print packet details information */
109 static gboolean print_hex; /* TRUE if we're to print hex/ascci information */
110 static gboolean line_buffered;
111 static gboolean really_quiet = FALSE;
113 static print_format_e print_format = PR_FMT_TEXT;
114 static print_stream_t *print_stream;
116 static output_fields_t* output_fields = NULL;
118 /* The line separator used between packets, changeable via the -S option */
119 static const char *separator = "";
121 static gboolean process_file(capture_file *, int, gint64);
122 static gboolean process_packet_single_pass(capture_file *cf,
123 epan_dissect_t *edt, gint64 offset, wtap_rec *rec,
124 const guchar *pd, guint tap_flags);
125 static void show_print_file_io_error(int err);
126 static gboolean write_preamble(capture_file *cf);
127 static gboolean print_packet(capture_file *cf, epan_dissect_t *edt);
128 static gboolean write_finale(void);
129 static const char *cf_open_error_message(int err, gchar *err_info,
130 gboolean for_writing, int file_type);
132 static void failure_warning_message(const char *msg_format, va_list ap);
133 static void open_failure_message(const char *filename, int err,
134 gboolean for_writing);
135 static void read_failure_message(const char *filename, int err);
136 static void write_failure_message(const char *filename, int err);
137 static void failure_message_cont(const char *msg_format, va_list ap);
139 static GHashTable *output_only_tables = NULL;
143 const char *sstr; /* The short string */
144 const char *lstr; /* The long string */
148 string_compare(gconstpointer a, gconstpointer b)
150 return strcmp(((const struct string_elem *)a)->sstr,
151 ((const struct string_elem *)b)->sstr);
155 string_elem_print(gpointer data, gpointer not_used _U_)
157 fprintf(stderr, " %s - %s\n",
158 ((struct string_elem *)data)->sstr,
159 ((struct string_elem *)data)->lstr);
164 print_usage(FILE *output)
166 fprintf(output, "\n");
167 fprintf(output, "Usage: tfshark [options] ...\n");
168 fprintf(output, "\n");
170 /*fprintf(output, "\n");*/
171 fprintf(output, "Input file:\n");
172 fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin)\n");
174 fprintf(output, "\n");
175 fprintf(output, "Processing:\n");
176 fprintf(output, " -2 perform a two-pass analysis\n");
177 fprintf(output, " -R <read filter> packet Read filter in Wireshark display filter syntax\n");
178 fprintf(output, " (requires -2)\n");
179 fprintf(output, " -Y <display filter> packet displaY filter in Wireshark display filter\n");
180 fprintf(output, " syntax\n");
181 fprintf(output, " -d %s ...\n", DECODE_AS_ARG_TEMPLATE);
182 fprintf(output, " \"Decode As\", see the man page for details\n");
183 fprintf(output, " Example: tcp.port==8888,http\n");
185 /*fprintf(output, "\n");*/
186 fprintf(output, "Output:\n");
187 fprintf(output, " -C <config profile> start with specified configuration profile\n");
188 fprintf(output, " -V add output of packet tree (Packet Details)\n");
189 fprintf(output, " -O <protocols> Only show packet details of these protocols, comma\n");
190 fprintf(output, " separated\n");
191 fprintf(output, " -S <separator> the line separator to print between packets\n");
192 fprintf(output, " -x add output of hex and ASCII dump (Packet Bytes)\n");
193 fprintf(output, " -T pdml|ps|psml|text|fields\n");
194 fprintf(output, " format of text output (def: text)\n");
195 fprintf(output, " -e <field> field to print if -Tfields selected (e.g. tcp.port,\n");
196 fprintf(output, " _ws.col.Info)\n");
197 fprintf(output, " this option can be repeated to print multiple fields\n");
198 fprintf(output, " -E<fieldsoption>=<value> set options for output when -Tfields selected:\n");
199 fprintf(output, " header=y|n switch headers on and off\n");
200 fprintf(output, " separator=/t|/s|<char> select tab, space, printable character as separator\n");
201 fprintf(output, " occurrence=f|l|a print first, last or all occurrences of each field\n");
202 fprintf(output, " aggregator=,|/s|<char> select comma, space, printable character as\n");
203 fprintf(output, " aggregator\n");
204 fprintf(output, " quote=d|s|n select double, single, no quotes for values\n");
205 fprintf(output, " -t a|ad|d|dd|e|r|u|ud output format of time stamps (def: r: rel. to first)\n");
206 fprintf(output, " -u s|hms output format of seconds (def: s: seconds)\n");
207 fprintf(output, " -l flush standard output after each packet\n");
208 fprintf(output, " -q be more quiet on stdout (e.g. when using statistics)\n");
209 fprintf(output, " -Q only log true errors to stderr (quieter than -q)\n");
210 fprintf(output, " -X <key>:<value> eXtension options, see the man page for details\n");
211 fprintf(output, " -z <statistics> various statistics, see the man page for details\n");
213 fprintf(output, "\n");
214 fprintf(output, "Miscellaneous:\n");
215 fprintf(output, " -h display this help and exit\n");
216 fprintf(output, " -v display version info and exit\n");
217 fprintf(output, " -o <name>:<value> ... override preference setting\n");
218 fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
219 fprintf(output, " -G [report] dump one of several available reports and exit\n");
220 fprintf(output, " default report=\"fields\"\n");
221 fprintf(output, " use \"-G ?\" for more help\n");
225 glossary_option_help(void)
231 fprintf(output, "%s\n", get_appname_and_version());
233 fprintf(output, "\n");
234 fprintf(output, "Usage: tfshark -G [report]\n");
235 fprintf(output, "\n");
236 fprintf(output, "Glossary table reports:\n");
237 fprintf(output, " -G column-formats dump column format codes and exit\n");
238 fprintf(output, " -G decodes dump \"layer type\"/\"decode as\" associations and exit\n");
239 fprintf(output, " -G dissector-tables dump dissector table names, types, and properties\n");
240 fprintf(output, " -G fields dump fields glossary and exit\n");
241 fprintf(output, " -G ftypes dump field type basic and descriptive names\n");
242 fprintf(output, " -G heuristic-decodes dump heuristic dissector tables\n");
243 fprintf(output, " -G plugins dump installed plugins and exit\n");
244 fprintf(output, " -G protocols dump protocols in registration database and exit\n");
245 fprintf(output, " -G values dump value, range, true/false strings and exit\n");
246 fprintf(output, "\n");
247 fprintf(output, "Preference reports:\n");
248 fprintf(output, " -G currentprefs dump current preferences and exit\n");
249 fprintf(output, " -G defaultprefs dump default preferences and exit\n");
250 fprintf(output, "\n");
254 tfshark_log_handler (const gchar *log_domain, GLogLevelFlags log_level,
255 const gchar *message, gpointer user_data)
257 /* ignore log message, if log_level isn't interesting based
258 upon the console log preferences.
259 If the preferences haven't been loaded yet, display the
262 The default console_log_level preference value is such that only
263 ERROR, CRITICAL and WARNING level messages are processed;
264 MESSAGE, INFO and DEBUG level messages are ignored.
266 XXX: Aug 07, 2009: Prior tshark g_log code was hardwired to process only
267 ERROR and CRITICAL level messages so the current code is a behavioral
268 change. The current behavior is the same as in Wireshark.
270 if (prefs_loaded && (log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0) {
274 g_log_default_handler(log_domain, log_level, message, user_data);
279 print_current_user(void) {
280 gchar *cur_user, *cur_group;
282 if (started_with_special_privs()) {
283 cur_user = get_cur_username();
284 cur_group = get_cur_groupname();
285 fprintf(stderr, "Running as user \"%s\" and group \"%s\".",
286 cur_user, cur_group);
289 if (running_with_special_privs()) {
290 fprintf(stderr, " This could be dangerous.");
292 fprintf(stderr, "\n");
297 get_tfshark_runtime_version_info(GString *str)
299 /* stuff used by libwireshark */
300 epan_get_runtime_version_info(str);
304 main(int argc, char *argv[])
306 char *init_progfile_dir_error;
308 static const struct option long_options[] = {
309 {"help", no_argument, NULL, 'h'},
310 {"version", no_argument, NULL, 'v'},
313 gboolean arg_error = FALSE;
316 volatile gboolean success;
317 volatile int exit_status = 0;
318 gboolean quiet = FALSE;
319 gchar *volatile cf_name = NULL;
320 gchar *rfilter = NULL;
321 gchar *dfilter = NULL;
322 dfilter_t *rfcode = NULL;
323 dfilter_t *dfcode = NULL;
327 gchar *output_only = NULL;
330 * The leading + ensures that getopt_long() does not permute the argv[]
333 * We have to make sure that the first getopt_long() preserves the content
334 * of argv[] for the subsequent getopt_long() call.
336 * We use getopt_long() in both cases to ensure that we're using a routine
337 * whose permutation behavior we can control in the same fashion on all
338 * platforms, and so that, if we ever need to process a long argument before
339 * doing further initialization, we can do so.
341 * Glibc and Solaris libc document that a leading + disables permutation
342 * of options, regardless of whether POSIXLY_CORRECT is set or not; *BSD
343 * and macOS don't document it, but do so anyway.
345 * We do *not* use a leading - because the behavior of a leading - is
346 * platform-dependent.
348 #define OPTSTRING "+2C:d:e:E:hK:lo:O:qQr:R:S:t:T:u:vVxX:Y:z:"
350 static const char optstring[] = OPTSTRING;
353 * Set the C-language locale to the native environment and set the
354 * code page to UTF-8 on Windows.
357 setlocale(LC_ALL, ".UTF-8");
359 setlocale(LC_ALL, "");
362 cmdarg_err_init(failure_warning_message, failure_message_cont);
365 create_app_running_mutex();
369 * Get credential information for later use, and drop privileges
370 * before doing anything else.
371 * Let the user know if anything happened.
373 init_process_policies();
374 relinquish_special_privs_perm();
375 print_current_user();
378 * Attempt to get the pathname of the directory containing the
381 init_progfile_dir_error = init_progfile_dir(argv[0]);
382 if (init_progfile_dir_error != NULL) {
384 "tfshark: Can't get pathname of directory containing the tfshark program: %s.\n",
385 init_progfile_dir_error);
386 g_free(init_progfile_dir_error);
389 initialize_funnel_ops();
391 /* Initialize the version information. */
392 ws_init_version_info("TFShark (Wireshark)", NULL,
393 epan_get_compiled_version_info,
394 get_tfshark_runtime_version_info);
397 * In order to have the -X opts assigned before the wslua machine starts
398 * we need to call getopts before epan_init() gets called.
400 * In order to handle, for example, -o options, we also need to call it
401 * *after* epan_init() gets called, so that the dissectors have had a
402 * chance to register their preferences.
404 * XXX - can we do this all with one getopt_long() call, saving the
405 * arguments we can't handle until after initializing libwireshark,
406 * and then process them after initializing libwireshark?
410 while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
412 case 'C': /* Configuration Profile */
413 if (profile_exists (optarg, FALSE)) {
414 set_profile_name (optarg);
416 cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
420 case 'O': /* Only output these protocols */
421 output_only = g_strdup(optarg);
423 case 'V': /* Verbose */
424 print_details = TRUE;
425 print_packet_info = TRUE;
427 case 'x': /* Print packet data in hex (and ASCII) */
429 /* The user asked for hex output, so let's ensure they get it,
430 * even if they're writing to a file.
432 print_packet_info = TRUE;
443 * Print packet summary information is the default, unless either -V or -x
444 * were specified. Note that this is new behavior, which
445 * allows for the possibility of printing only hex/ascii output without
446 * necessarily requiring that either the summary or details be printed too.
448 if (print_summary == -1)
449 print_summary = (print_details || print_hex) ? FALSE : TRUE;
451 /** Send All g_log messages to our own handler **/
455 G_LOG_LEVEL_CRITICAL|
460 G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
462 g_log_set_handler(NULL,
463 (GLogLevelFlags)log_flags,
464 tfshark_log_handler, NULL /* user_data */);
465 g_log_set_handler(LOG_DOMAIN_MAIN,
466 (GLogLevelFlags)log_flags,
467 tfshark_log_handler, NULL /* user_data */);
469 init_report_message(failure_warning_message, failure_warning_message,
470 open_failure_message, read_failure_message,
471 write_failure_message);
473 timestamp_set_type(TS_RELATIVE);
474 timestamp_set_precision(TS_PREC_AUTO);
475 timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
479 /* Register all dissectors; we must do this before checking for the
480 "-G" flag, as the "-G" flag dumps information registered by the
481 dissectors, and we must do it before we read the preferences, in
482 case any dissectors register preferences. */
483 if (!epan_init(NULL, NULL, TRUE)) {
484 exit_status = INIT_ERROR;
488 /* Register all tap listeners; we do this before we parse the arguments,
489 as the "-z" argument can specify a registered tap. */
491 /* we register the plugin taps before the other taps because
492 stats_tree taps plugins will be registered as tap listeners
493 by stats_tree_stat.c and need to registered before that */
495 /* XXX Disable tap registration for now until we can get tfshark set up with
496 * its own set of taps and the necessary registration function etc.
498 register_all_plugin_tap_listeners();
500 register_all_tap_listeners();
503 /* If invoked with the "-G" flag, we dump out information based on
504 the argument to the "-G" flag; if no argument is specified,
505 for backwards compatibility we dump out a glossary of display
508 XXX - we do this here, for now, to support "-G" with no arguments.
509 If none of our build or other processes uses "-G" with no arguments,
510 we can just process it with the other arguments. */
511 if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
512 proto_initialize_all_prefixes();
515 proto_registrar_dump_fields();
517 if (strcmp(argv[2], "column-formats") == 0)
518 column_dump_column_formats();
519 else if (strcmp(argv[2], "currentprefs") == 0) {
520 epan_load_settings();
523 else if (strcmp(argv[2], "decodes") == 0)
524 dissector_dump_decodes();
525 else if (strcmp(argv[2], "defaultprefs") == 0)
527 else if (strcmp(argv[2], "dissector-tables") == 0)
528 dissector_dump_dissector_tables();
529 else if (strcmp(argv[2], "fields") == 0)
530 proto_registrar_dump_fields();
531 else if (strcmp(argv[2], "ftypes") == 0)
532 proto_registrar_dump_ftypes();
533 else if (strcmp(argv[2], "heuristic-decodes") == 0)
534 dissector_dump_heur_decodes();
535 else if (strcmp(argv[2], "plugins") == 0) {
540 wslua_plugins_dump_all();
543 else if (strcmp(argv[2], "protocols") == 0)
544 proto_registrar_dump_protocols();
545 else if (strcmp(argv[2], "values") == 0)
546 proto_registrar_dump_values();
547 else if (strcmp(argv[2], "?") == 0)
548 glossary_option_help();
549 else if (strcmp(argv[2], "-?") == 0)
550 glossary_option_help();
552 cmdarg_err("Invalid \"%s\" option for -G flag, enter -G ? for more help.", argv[2]);
553 exit_status = INVALID_OPTION;
560 /* Load libwireshark settings from the current profile. */
561 prefs_p = epan_load_settings();
564 cap_file_init(&cfile);
566 /* Print format defaults to this. */
567 print_format = PR_FMT_TEXT;
569 output_fields = output_fields_new();
572 * To reset the options parser, set optreset to 1 on platforms that
573 * have optreset (documented in *BSD and macOS, apparently present but
574 * not documented in Solaris - the Illumos repository seems to
575 * suggest that the first Solaris getopt_long(), at least as of 2004,
576 * was based on the NetBSD one, it had optreset) and set optind to 1,
577 * and set optind to 0 otherwise (documented as working in the GNU
578 * getopt_long(). Setting optind to 0 didn't originally work in the
579 * NetBSD one, but that was added later - we don't want to depend on
580 * it if we have optreset).
582 * Also reset opterr to 1, so that error messages are printed by
593 /* Now get our args */
594 while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
596 case '2': /* Perform two pass analysis */
597 perform_two_pass_analysis = TRUE;
600 /* already processed; just ignore it now */
604 output_fields_add(output_fields, optarg);
608 if (!output_fields_set_option(output_fields, optarg)) {
609 cmdarg_err("\"%s\" is not a valid field output option=value pair.", optarg);
610 output_fields_list_options(stderr);
611 exit_status = INVALID_OPTION;
616 case 'h': /* Print help and exit */
617 show_help_header("Analyze file structure.");
621 case 'l': /* "Line-buffer" standard output */
622 /* The ANSI C standard does not appear to *require* that a line-buffered
623 stream be flushed to the host environment whenever a newline is
624 written, it just says that, on such a stream, characters "are
625 intended to be transmitted to or from the host environment as a
626 block when a new-line character is encountered".
628 The Visual C++ 6.0 C implementation doesn't do what is intended;
629 even if you set a stream to be line-buffered, it still doesn't
630 flush the buffer at the end of every line.
632 The whole reason for the "-l" flag in either tcpdump or TShark
633 is to allow the output of a live capture to be piped to a program
634 or script and to have that script see the information for the
635 packet as soon as it's printed, rather than having to wait until
636 a standard I/O buffer fills up.
638 So, if the "-l" flag is specified, we flush the standard output
639 at the end of a packet. This will do the right thing if we're
640 printing packet summary lines, and, as we print the entire protocol
641 tree for a single packet without waiting for anything to happen,
642 it should be as good as line-buffered mode if we're printing
643 protocol trees - arguably even better, as it may do fewer
645 line_buffered = TRUE;
647 case 'o': /* Override preference from command line */
651 switch (prefs_set_pref(optarg, &errmsg)) {
656 case PREFS_SET_SYNTAX_ERR:
657 cmdarg_err("Invalid -o flag \"%s\"%s%s", optarg,
658 errmsg ? ": " : "", errmsg ? errmsg : "");
663 case PREFS_SET_NO_SUCH_PREF:
664 case PREFS_SET_OBSOLETE:
665 cmdarg_err("-o flag \"%s\" specifies unknown preference", optarg);
666 exit_status = INVALID_OPTION;
672 case 'q': /* Quiet */
675 case 'Q': /* Really quiet */
679 case 'r': /* Read capture file x */
680 cf_name = g_strdup(optarg);
682 case 'R': /* Read file filter */
685 case 'S': /* Set the line Separator to be printed between packets */
686 separator = g_strdup(optarg);
688 case 'T': /* printing Type */
689 if (strcmp(optarg, "text") == 0) {
690 output_action = WRITE_TEXT;
691 print_format = PR_FMT_TEXT;
692 } else if (strcmp(optarg, "ps") == 0) {
693 output_action = WRITE_TEXT;
694 print_format = PR_FMT_PS;
695 } else if (strcmp(optarg, "pdml") == 0) {
696 output_action = WRITE_XML;
697 print_details = TRUE; /* Need details */
698 print_summary = FALSE; /* Don't allow summary */
699 } else if (strcmp(optarg, "psml") == 0) {
700 output_action = WRITE_XML;
701 print_details = FALSE; /* Don't allow details */
702 print_summary = TRUE; /* Need summary */
703 } else if (strcmp(optarg, "fields") == 0) {
704 output_action = WRITE_FIELDS;
705 print_details = TRUE; /* Need full tree info */
706 print_summary = FALSE; /* Don't allow summary */
708 cmdarg_err("Invalid -T parameter \"%s\"; it must be one of:", optarg); /* x */
709 cmdarg_err_cont("\t\"fields\" The values of fields specified with the -e option, in a form\n"
710 "\t specified by the -E option.\n"
711 "\t\"pdml\" Packet Details Markup Language, an XML-based format for the\n"
712 "\t details of a decoded packet. This information is equivalent to\n"
713 "\t the packet details printed with the -V flag.\n"
714 "\t\"ps\" PostScript for a human-readable one-line summary of each of\n"
715 "\t the packets, or a multi-line view of the details of each of\n"
716 "\t the packets, depending on whether the -V flag was specified.\n"
717 "\t\"psml\" Packet Summary Markup Language, an XML-based format for the\n"
718 "\t summary information of a decoded packet. This information is\n"
719 "\t equivalent to the information shown in the one-line summary\n"
720 "\t printed by default.\n"
721 "\t\"text\" Text of a human-readable one-line summary of each of the\n"
722 "\t packets, or a multi-line view of the details of each of the\n"
723 "\t packets, depending on whether the -V flag was specified.\n"
724 "\t This is the default.");
725 exit_status = INVALID_OPTION;
729 case 'v': /* Show version and exit */
732 case 'O': /* Only output these protocols */
733 /* already processed; just ignore it now */
735 case 'V': /* Verbose */
736 /* already processed; just ignore it now */
738 case 'x': /* Print packet data in hex (and ASCII) */
739 /* already processed; just ignore it now */
742 /* already processed; just ignore it now */
748 /* We won't call the init function for the stat this soon
749 as it would disallow MATE's fields (which are registered
750 by the preferences set callback) from being used as
751 part of a tap filter. Instead, we just add the argument
752 to a list of stat arguments. */
753 if (strcmp("help", optarg) == 0) {
754 fprintf(stderr, "tfshark: The available statistics for the \"-z\" option are:\n");
755 list_stat_cmd_args();
758 if (!process_stat_cmd_arg(optarg)) {
759 cmdarg_err("Invalid -z argument \"%s\"; it must be one of:", optarg);
760 list_stat_cmd_args();
761 exit_status = INVALID_OPTION;
765 case 'd': /* Decode as rule */
766 case 'K': /* Kerberos keytab file */
767 case 't': /* Time stamp type */
768 case 'u': /* Seconds type */
769 case LONGOPT_DISABLE_PROTOCOL: /* disable dissection of protocol */
770 case LONGOPT_ENABLE_HEURISTIC: /* enable heuristic dissection of protocol */
771 case LONGOPT_DISABLE_HEURISTIC: /* disable heuristic dissection of protocol */
772 case LONGOPT_ENABLE_PROTOCOL: /* enable dissection of protocol (that is disabled by default) */
773 if (!dissect_opts_handle_opt(opt, optarg)) {
774 exit_status = INVALID_OPTION;
779 case '?': /* Bad flag - print usage message */
781 exit_status = INVALID_OPTION;
787 /* If we specified output fields, but not the output field type... */
788 if (WRITE_FIELDS != output_action && 0 != output_fields_num_fields(output_fields)) {
789 cmdarg_err("Output fields were specified with \"-e\", "
790 "but \"-Tfields\" was not specified.");
792 } else if (WRITE_FIELDS == output_action && 0 == output_fields_num_fields(output_fields)) {
793 cmdarg_err("\"-Tfields\" was specified, but no fields were "
794 "specified with \"-e\".");
796 exit_status = INVALID_OPTION;
800 /* We require a -r flag specifying a file to read. */
801 if (cf_name == NULL) {
802 cmdarg_err("A file to read must be specified with \"-r\".");
803 exit_status = NO_FILE_SPECIFIED;
807 /* If no display filter has been specified, and there are still command-
808 line arguments, treat them as the tokens of a display filter. */
810 if (dfilter != NULL) {
811 cmdarg_err("Display filters were specified both with \"-Y\" "
812 "and with additional command-line arguments.");
813 exit_status = INVALID_OPTION;
816 dfilter = get_args_as_string(argc, argv, optind);
819 /* if "-q" wasn't specified, we should print packet information */
821 print_packet_info = TRUE;
825 exit_status = INVALID_OPTION;
830 if (output_action != WRITE_TEXT) {
831 cmdarg_err("Raw packet hex data can only be printed as text or PostScript");
832 exit_status = INVALID_OPTION;
837 if (output_only != NULL) {
840 if (!print_details) {
841 cmdarg_err("-O requires -V");
842 exit_status = INVALID_OPTION;
846 output_only_tables = g_hash_table_new (g_str_hash, g_str_equal);
847 for (ps = strtok (output_only, ","); ps; ps = strtok (NULL, ",")) {
848 g_hash_table_insert(output_only_tables, (gpointer)ps, (gpointer)ps);
852 if (rfilter != NULL && !perform_two_pass_analysis) {
853 cmdarg_err("-R without -2 is deprecated. For single-pass filtering use -Y.");
854 exit_status = INVALID_OPTION;
858 /* Notify all registered modules that have had any of their preferences
859 changed either from one of the preferences file or from the command
860 line that their preferences have changed. */
864 * Enabled and disabled protocols and heuristic dissectors as per
865 * command-line options.
867 if (!setup_enabled_and_disabled_protocols()) {
868 exit_status = INVALID_OPTION;
872 /* Build the column format array */
873 build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
875 if (rfilter != NULL) {
876 if (!dfilter_compile(rfilter, &rfcode, &err_msg)) {
877 cmdarg_err("%s", err_msg);
879 exit_status = INVALID_FILTER;
883 cfile.rfcode = rfcode;
885 if (dfilter != NULL) {
886 if (!dfilter_compile(dfilter, &dfcode, &err_msg)) {
887 cmdarg_err("%s", err_msg);
889 exit_status = INVALID_FILTER;
893 cfile.dfcode = dfcode;
895 if (print_packet_info) {
896 /* If we're printing as text or PostScript, we have
897 to create a print stream. */
898 if (output_action == WRITE_TEXT) {
899 switch (print_format) {
902 print_stream = print_stream_text_stdio_new(stdout);
906 print_stream = print_stream_ps_stdio_new(stdout);
910 g_assert_not_reached();
915 /* We have to dissect each packet if:
917 we're printing information about each packet;
919 we're using a read filter on the packets;
921 we're using a display filter on the packets;
923 we're using any taps that need dissection. */
924 do_dissection = print_packet_info || rfcode || dfcode || tap_listeners_require_dissection();
930 /* TODO: if tfshark is ever changed to give the user a choice of which
931 open_routine reader to use, then the following needs to change. */
932 if (cf_open(&cfile, cf_name, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK) {
933 exit_status = OPEN_ERROR;
937 /* Start statistics taps; we do so after successfully opening the
938 capture file, so we know we have something to compute stats
939 on, and after registering all dissectors, so that MATE will
940 have registered its field array so we can have a tap filter
941 with one of MATE's late-registered fields as part of the
943 start_requested_stats();
945 /* Process the packets in the file */
947 /* XXX - for now there is only 1 packet */
948 success = process_file(&cfile, 1, 0);
950 CATCH(OutOfMemoryError) {
954 "Sorry, but TFShark has to terminate now.\n"
956 "Some infos / workarounds can be found at:\n"
957 WS_WIKI_URL("KnownBugs/OutOfMemory") "\n");
963 /* We still dump out the results of taps, etc., as we might have
964 read some packets; however, we exit with an error status. */
970 if (cfile.provider.frames != NULL) {
971 free_frame_data_sequence(cfile.provider.frames);
972 cfile.provider.frames = NULL;
975 draw_tap_listeners(TRUE);
976 funnel_dump_all_text_windows();
979 destroy_print_stream(print_stream);
980 epan_free(cfile.epan);
984 output_fields_free(output_fields);
985 output_fields = NULL;
987 col_cleanup(&cfile.cinfo);
992 static const nstime_t *
993 tfshark_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num)
995 if (prov->ref && prov->ref->num == frame_num)
996 return &prov->ref->abs_ts;
998 if (prov->prev_dis && prov->prev_dis->num == frame_num)
999 return &prov->prev_dis->abs_ts;
1001 if (prov->prev_cap && prov->prev_cap->num == frame_num)
1002 return &prov->prev_cap->abs_ts;
1005 frame_data *fd = frame_data_sequence_find(prov->frames, frame_num);
1007 return (fd) ? &fd->abs_ts : NULL;
1014 no_interface_name(struct packet_provider_data *prov _U_, guint32 interface_id _U_)
1020 tfshark_epan_new(capture_file *cf)
1022 static const struct packet_provider_funcs funcs = {
1023 tfshark_get_frame_ts,
1029 return epan_new(&cf->provider, &funcs);
1033 process_packet_first_pass(capture_file *cf, epan_dissect_t *edt,
1034 gint64 offset, wtap_rec *rec,
1041 /* The frame number of this packet is one more than the count of
1042 frames in this packet. */
1043 framenum = cf->count + 1;
1045 /* If we're not running a display filter and we're not printing any
1046 packet information, we don't need to do a dissection. This means
1047 that all packets can be marked as 'passed'. */
1050 frame_data_init(&fdlocal, framenum, rec, offset, cum_bytes);
1052 /* If we're going to print packet information, or we're going to
1053 run a read filter, or display filter, or we're going to process taps, set up to
1054 do a dissection and do so. */
1056 /* If we're running a read filter, prime the epan_dissect_t with that
1059 epan_dissect_prime_with_dfilter(edt, cf->rfcode);
1061 /* This is the first pass, so prime the epan_dissect_t with the
1062 hfids postdissectors want on the first pass. */
1063 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1065 frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time,
1066 &cf->provider.ref, cf->provider.prev_dis);
1067 if (cf->provider.ref == &fdlocal) {
1068 ref_frame = fdlocal;
1069 cf->provider.ref = &ref_frame;
1072 epan_dissect_file_run(edt, rec,
1073 file_tvbuff_new(&cf->provider, &fdlocal, pd),
1076 /* Run the read filter if we have one. */
1078 passed = dfilter_apply_edt(cf->rfcode, edt);
1082 frame_data_set_after_dissect(&fdlocal, &cum_bytes);
1083 cf->provider.prev_cap = cf->provider.prev_dis = frame_data_sequence_add(cf->provider.frames, &fdlocal);
1085 /* If we're not doing dissection then there won't be any dependent frames.
1086 * More importantly, edt.pi.dependent_frames won't be initialized because
1087 * epan hasn't been initialized.
1090 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
1095 /* if we don't add it to the frame_data_sequence, clean it up right now
1097 frame_data_destroy(&fdlocal);
1101 epan_dissect_reset(edt);
1107 process_packet_second_pass(capture_file *cf, epan_dissect_t *edt,
1108 frame_data *fdata, wtap_rec *rec,
1109 Buffer *buf, guint tap_flags)
1114 /* If we're not running a display filter and we're not printing any
1115 packet information, we don't need to do a dissection. This means
1116 that all packets can be marked as 'passed'. */
1119 /* If we're going to print packet information, or we're going to
1120 run a read filter, or we're going to process taps, set up to
1121 do a dissection and do so. */
1124 /* If we're running a display filter, prime the epan_dissect_t with that
1127 epan_dissect_prime_with_dfilter(edt, cf->dfcode);
1129 /* This is the first and only pass, so prime the epan_dissect_t
1130 with the hfids postdissectors want on the first pass. */
1131 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1133 col_custom_prime_edt(edt, &cf->cinfo);
1135 /* We only need the columns if either
1136 1) some tap needs the columns
1138 2) we're printing packet info but we're *not* verbose; in verbose
1139 mode, we print the protocol tree, not the protocol summary.
1141 if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary))
1146 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1147 &cf->provider.ref, cf->provider.prev_dis);
1148 if (cf->provider.ref == fdata) {
1150 cf->provider.ref = &ref_frame;
1153 epan_dissect_file_run_with_taps(edt, rec,
1154 file_tvbuff_new_buffer(&cf->provider, fdata, buf), fdata, cinfo);
1156 /* Run the read/display filter if we have one. */
1158 passed = dfilter_apply_edt(cf->dfcode, edt);
1162 frame_data_set_after_dissect(fdata, &cum_bytes);
1163 /* Process this packet. */
1164 if (print_packet_info) {
1165 /* We're printing packet information; print the information for
1167 print_packet(cf, edt);
1169 /* If we're doing "line-buffering", flush the standard output
1170 after every packet. See the comment above, for the "-l"
1171 option, for an explanation of why we do that. */
1175 if (ferror(stdout)) {
1176 show_print_file_io_error(errno);
1180 cf->provider.prev_dis = fdata;
1182 cf->provider.prev_cap = fdata;
1185 epan_dissect_reset(edt);
1187 return passed || fdata->dependent_of_displayed;
1191 local_wtap_read(capture_file *cf, wtap_rec *file_rec _U_, int *err, gchar **err_info _U_, gint64 *data_offset _U_, guint8** data_buffer)
1193 /* int bytes_read; */
1194 gint64 packet_size = wtap_file_size(cf->provider.wth, err);
1196 *data_buffer = (guint8*)g_malloc((gsize)packet_size);
1197 /* bytes_read =*/ file_read(*data_buffer, (unsigned int)packet_size, cf->provider.wth->fh);
1199 #if 0 /* no more filetap */
1200 if (bytes_read < 0) {
1201 *err = file_error(cf->provider.wth->fh, err_info);
1203 *err = FTAP_ERR_SHORT_READ;
1205 } else if (bytes_read == 0) {
1206 /* Done with file, no error */
1211 /* XXX - SET FRAME SIZE EQUAL TO TOTAL FILE SIZE */
1212 file_rec->rec_header.packet_header.caplen = (guint32)packet_size;
1213 file_rec->rec_header.packet_header.len = (guint32)packet_size;
1216 * Set the packet encapsulation to the file's encapsulation
1217 * value; if that's not WTAP_ENCAP_PER_PACKET, it's the
1218 * right answer (and means that the read routine for this
1219 * capture file type doesn't have to set it), and if it
1220 * *is* WTAP_ENCAP_PER_PACKET, the caller needs to set it
1223 wth->rec.rec_header.packet_header.pkt_encap = wth->file_encap;
1225 if (!wth->subtype_read(wth, err, err_info, data_offset)) {
1227 * If we didn't get an error indication, we read
1228 * the last packet. See if there's any deferred
1229 * error, as might, for example, occur if we're
1230 * reading a compressed file, and we got an error
1231 * reading compressed data from the file, but
1232 * got enough compressed data to decompress the
1233 * last packet of the file.
1236 *err = file_error(wth->fh, err_info);
1237 return FALSE; /* failure */
1241 * It makes no sense for the captured data length to be bigger
1242 * than the actual data length.
1244 if (wth->rec.rec_header.packet_header.caplen > wth->rec.rec_header.packet_header.len)
1245 wth->rec.rec_header.packet_header.caplen = wth->rec.rec_header.packet_header.len;
1248 * Make sure that it's not WTAP_ENCAP_PER_PACKET, as that
1249 * probably means the file has that encapsulation type
1250 * but the read routine didn't set this packet's
1251 * encapsulation type.
1253 g_assert(wth->rec.rec_header.packet_header.pkt_encap != WTAP_ENCAP_PER_PACKET);
1256 return TRUE; /* success */
1260 process_file(capture_file *cf, int max_packet_count, gint64 max_byte_count)
1264 gchar *err_info = NULL;
1265 gint64 data_offset = 0;
1266 gboolean filtering_tap_listeners;
1269 epan_dissect_t *edt = NULL;
1273 if (print_packet_info) {
1274 if (!write_preamble(cf)) {
1276 show_print_file_io_error(err);
1281 /* Do we have any tap listeners with filters? */
1282 filtering_tap_listeners = have_filtering_tap_listeners();
1284 /* Get the union of the flags for all tap listeners. */
1285 tap_flags = union_of_tap_listener_flags();
1287 wtap_rec_init(&file_rec);
1289 /* XXX - TEMPORARY HACK TO ELF DISSECTOR */
1290 file_rec.rec_header.packet_header.pkt_encap = 1234;
1292 if (perform_two_pass_analysis) {
1295 /* Allocate a frame_data_sequence for all the frames. */
1296 cf->provider.frames = new_frame_data_sequence();
1298 if (do_dissection) {
1299 gboolean create_proto_tree;
1302 * Determine whether we need to create a protocol tree.
1305 * we're going to apply a read filter;
1307 * a postdissector wants field values or protocols
1308 * on the first pass.
1311 (cf->rfcode != NULL || postdissectors_want_hfids());
1313 /* We're not going to display the protocol tree on this pass,
1314 so it's not going to be "visible". */
1315 edt = epan_dissect_new(cf->epan, create_proto_tree, FALSE);
1317 while (local_wtap_read(cf, &file_rec, &err, &err_info, &data_offset, &raw_data)) {
1318 if (process_packet_first_pass(cf, edt, data_offset, &file_rec, raw_data)) {
1320 /* Stop reading if we have the maximum number of packets;
1321 * When the -c option has not been used, max_packet_count
1322 * starts at 0, which practically means, never stop reading.
1323 * (unless we roll over max_packet_count ?)
1325 if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
1326 err = 0; /* This is not an error */
1333 epan_dissect_free(edt);
1338 /* Close the sequential I/O side, to free up memory it requires. */
1339 wtap_sequential_close(cf->provider.wth);
1342 /* Allow the protocol dissectors to free up memory that they
1343 * don't need after the sequential run-through of the packets. */
1344 postseq_cleanup_all_protocols();
1346 cf->provider.prev_dis = NULL;
1347 cf->provider.prev_cap = NULL;
1348 ws_buffer_init(&buf, 1514);
1350 if (do_dissection) {
1351 gboolean create_proto_tree;
1354 * Determine whether we need to create a protocol tree.
1357 * we're going to apply a display filter;
1359 * we're going to print the protocol tree;
1361 * one of the tap listeners requires a protocol tree;
1363 * we have custom columns (which require field values, which
1364 * currently requires that we build a protocol tree).
1367 (cf->dfcode || print_details || filtering_tap_listeners ||
1368 (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo));
1370 /* The protocol tree will be "visible", i.e., printed, only if we're
1371 printing packet details, which is true if we're printing stuff
1372 ("print_packet_info" is true) and we're in verbose mode
1373 ("packet_details" is true). */
1374 edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details);
1377 for (framenum = 1; err == 0 && framenum <= cf->count; framenum++) {
1378 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1380 if (wtap_seek_read(cf->provider.wth, fdata->file_off,
1381 &buf, fdata->cap_len, &err, &err_info)) {
1382 process_packet_second_pass(cf, edt, fdata, &cf->rec, &buf, tap_flags);
1385 if (!process_packet_second_pass(cf, edt, fdata, &cf->rec, &buf,
1392 epan_dissect_free(edt);
1396 ws_buffer_free(&buf);
1401 if (do_dissection) {
1402 gboolean create_proto_tree;
1405 * Determine whether we need to create a protocol tree.
1408 * we're going to apply a read filter;
1410 * we're going to apply a display filter;
1412 * we're going to print the protocol tree;
1414 * one of the tap listeners is going to apply a filter;
1416 * one of the tap listeners requires a protocol tree;
1418 * a postdissector wants field values or protocols
1419 * on the first pass;
1421 * we have custom columns (which require field values, which
1422 * currently requires that we build a protocol tree).
1425 (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners ||
1426 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids() ||
1427 have_custom_cols(&cf->cinfo));
1429 /* The protocol tree will be "visible", i.e., printed, only if we're
1430 printing packet details, which is true if we're printing stuff
1431 ("print_packet_info" is true) and we're in verbose mode
1432 ("packet_details" is true). */
1433 edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details);
1436 while (local_wtap_read(cf, &file_rec, &err, &err_info, &data_offset, &raw_data)) {
1440 if (!process_packet_single_pass(cf, edt, data_offset,
1441 &file_rec/*wtap_get_rec(cf->provider.wth)*/,
1442 raw_data, tap_flags))
1445 /* Stop reading if we have the maximum number of packets;
1446 * When the -c option has not been used, max_packet_count
1447 * starts at 0, which practically means, never stop reading.
1448 * (unless we roll over max_packet_count ?)
1450 if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
1451 err = 0; /* This is not an error */
1457 epan_dissect_free(edt);
1462 wtap_rec_cleanup(&file_rec);
1466 * Print a message noting that the read failed somewhere along the line.
1468 * If we're printing packet data, and the standard output and error are
1469 * going to the same place, flush the standard output, so everything
1470 * buffered up is written, and then print a newline to the standard error
1471 * before printing the error message, to separate it from the packet
1472 * data. (Alas, that only works on UN*X; st_dev is meaningless, and
1473 * the _fstat() documentation at Microsoft doesn't indicate whether
1474 * st_ino is even supported.)
1477 if (print_packet_info) {
1478 ws_statb64 stat_stdout, stat_stderr;
1480 if (ws_fstat64(1, &stat_stdout) == 0 && ws_fstat64(2, &stat_stderr) == 0) {
1481 if (stat_stdout.st_dev == stat_stderr.st_dev &&
1482 stat_stdout.st_ino == stat_stderr.st_ino) {
1484 fprintf(stderr, "\n");
1492 case FTAP_ERR_UNSUPPORTED:
1493 cmdarg_err("The file \"%s\" contains record data that TFShark doesn't support.\n(%s)",
1494 cf->filename, err_info);
1498 case FTAP_ERR_UNSUPPORTED_ENCAP:
1499 cmdarg_err("The file \"%s\" has a packet with a network type that TFShark doesn't support.\n(%s)",
1500 cf->filename, err_info);
1504 case FTAP_ERR_CANT_READ:
1505 cmdarg_err("An attempt to read from the file \"%s\" failed for some unknown reason.",
1509 case FTAP_ERR_SHORT_READ:
1510 cmdarg_err("The file \"%s\" appears to have been cut short in the middle of a packet.",
1514 case FTAP_ERR_BAD_FILE:
1515 cmdarg_err("The file \"%s\" appears to be damaged or corrupt.\n(%s)",
1516 cf->filename, err_info);
1520 case FTAP_ERR_DECOMPRESS:
1521 cmdarg_err("The compressed file \"%s\" appears to be damaged or corrupt.\n"
1522 "(%s)", cf->filename, err_info);
1526 cmdarg_err("An error occurred while reading the file \"%s\": %s.",
1527 cf->filename, ftap_strerror(err));
1532 if (print_packet_info) {
1533 if (!write_finale()) {
1535 show_print_file_io_error(err);
1541 wtap_close(cf->provider.wth);
1542 cf->provider.wth = NULL;
1548 process_packet_single_pass(capture_file *cf, epan_dissect_t *edt, gint64 offset,
1549 wtap_rec *rec, const guchar *pd,
1556 /* Count this packet. */
1559 /* If we're not running a display filter and we're not printing any
1560 packet information, we don't need to do a dissection. This means
1561 that all packets can be marked as 'passed'. */
1564 frame_data_init(&fdata, cf->count, rec, offset, cum_bytes);
1566 /* If we're going to print packet information, or we're going to
1567 run a read filter, or we're going to process taps, set up to
1568 do a dissection and do so. */
1570 /* If we're running a filter, prime the epan_dissect_t with that
1573 epan_dissect_prime_with_dfilter(edt, cf->dfcode);
1575 col_custom_prime_edt(edt, &cf->cinfo);
1577 /* We only need the columns if either
1578 1) some tap needs the columns
1580 2) we're printing packet info but we're *not* verbose; in verbose
1581 mode, we print the protocol tree, not the protocol summary.
1583 3) there is a column mapped as an individual field */
1584 if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary) || output_fields_has_cols(output_fields))
1589 frame_data_set_before_dissect(&fdata, &cf->elapsed_time,
1590 &cf->provider.ref, cf->provider.prev_dis);
1591 if (cf->provider.ref == &fdata) {
1593 cf->provider.ref = &ref_frame;
1596 epan_dissect_file_run_with_taps(edt, rec,
1597 frame_tvbuff_new(&cf->provider, &fdata, pd),
1600 /* Run the filter if we have it. */
1602 passed = dfilter_apply_edt(cf->dfcode, edt);
1606 frame_data_set_after_dissect(&fdata, &cum_bytes);
1608 /* Process this packet. */
1609 if (print_packet_info) {
1610 /* We're printing packet information; print the information for
1612 print_packet(cf, edt);
1614 /* If we're doing "line-buffering", flush the standard output
1615 after every packet. See the comment above, for the "-l"
1616 option, for an explanation of why we do that. */
1620 if (ferror(stdout)) {
1621 show_print_file_io_error(errno);
1626 /* this must be set after print_packet() [bug #8160] */
1627 prev_dis_frame = fdata;
1628 cf->provider.prev_dis = &prev_dis_frame;
1631 prev_cap_frame = fdata;
1632 cf->provider.prev_cap = &prev_cap_frame;
1635 epan_dissect_reset(edt);
1636 frame_data_destroy(&fdata);
1642 write_preamble(capture_file *cf)
1644 switch (output_action) {
1647 return print_preamble(print_stream, cf->filename, get_ws_vcs_version_info());
1651 write_pdml_preamble(stdout, cf->filename);
1653 write_psml_preamble(&cf->cinfo, stdout);
1654 return !ferror(stdout);
1657 write_fields_preamble(output_fields, stdout);
1658 return !ferror(stdout);
1661 g_assert_not_reached();
1667 get_line_buf(size_t len)
1669 static char *line_bufp = NULL;
1670 static size_t line_buf_len = 256;
1671 size_t new_line_buf_len;
1673 for (new_line_buf_len = line_buf_len; len > new_line_buf_len;
1674 new_line_buf_len *= 2)
1676 if (line_bufp == NULL) {
1677 line_buf_len = new_line_buf_len;
1678 line_bufp = (char *)g_malloc(line_buf_len + 1);
1680 if (new_line_buf_len > line_buf_len) {
1681 line_buf_len = new_line_buf_len;
1682 line_bufp = (char *)g_realloc(line_bufp, line_buf_len + 1);
1689 put_string(char *dest, const char *str, size_t str_len)
1691 memcpy(dest, str, str_len);
1692 dest[str_len] = '\0';
1696 put_spaces_string(char *dest, const char *str, size_t str_len, size_t str_with_spaces)
1700 for (i = str_len; i < str_with_spaces; i++)
1703 put_string(dest, str, str_len);
1707 put_string_spaces(char *dest, const char *str, size_t str_len, size_t str_with_spaces)
1711 memcpy(dest, str, str_len);
1712 for (i = str_len; i < str_with_spaces; i++)
1715 dest[str_with_spaces] = '\0';
1719 print_columns(capture_file *cf)
1726 col_item_t* col_item;
1728 line_bufp = get_line_buf(256);
1731 for (i = 0; i < cf->cinfo.num_cols; i++) {
1732 col_item = &cf->cinfo.columns[i];
1733 /* Skip columns not marked as visible. */
1734 if (!get_column_visible(i))
1736 switch (col_item->col_fmt) {
1738 column_len = col_len = strlen(col_item->col_data);
1741 line_bufp = get_line_buf(buf_offset + column_len);
1742 put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1748 case COL_ABS_YMD_TIME: /* XXX - wider */
1749 case COL_ABS_YDOY_TIME: /* XXX - wider */
1751 case COL_UTC_YMD_TIME: /* XXX - wider */
1752 case COL_UTC_YDOY_TIME: /* XXX - wider */
1753 column_len = col_len = strlen(col_item->col_data);
1754 if (column_len < 10)
1756 line_bufp = get_line_buf(buf_offset + column_len);
1757 put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1763 case COL_DEF_DL_SRC:
1764 case COL_RES_DL_SRC:
1765 case COL_UNRES_DL_SRC:
1766 case COL_DEF_NET_SRC:
1767 case COL_RES_NET_SRC:
1768 case COL_UNRES_NET_SRC:
1769 column_len = col_len = strlen(col_item->col_data);
1770 if (column_len < 12)
1772 line_bufp = get_line_buf(buf_offset + column_len);
1773 put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1779 case COL_DEF_DL_DST:
1780 case COL_RES_DL_DST:
1781 case COL_UNRES_DL_DST:
1782 case COL_DEF_NET_DST:
1783 case COL_RES_NET_DST:
1784 case COL_UNRES_NET_DST:
1785 column_len = col_len = strlen(col_item->col_data);
1786 if (column_len < 12)
1788 line_bufp = get_line_buf(buf_offset + column_len);
1789 put_string_spaces(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1793 column_len = strlen(col_item->col_data);
1794 line_bufp = get_line_buf(buf_offset + column_len);
1795 put_string(line_bufp + buf_offset, col_item->col_data, column_len);
1798 buf_offset += column_len;
1799 if (i != cf->cinfo.num_cols - 1) {
1801 * This isn't the last column, so we need to print a
1802 * separator between this column and the next.
1804 * If we printed a network source and are printing a
1805 * network destination of the same type next, separate
1806 * them with " -> "; if we printed a network destination
1807 * and are printing a network source of the same type
1808 * next, separate them with " <- "; otherwise separate them
1811 * We add enough space to the buffer for " <- " or " -> ",
1812 * even if we're only adding " ".
1814 line_bufp = get_line_buf(buf_offset + 4);
1815 switch (col_item->col_fmt) {
1820 switch (cf->cinfo.columns[i+1].col_fmt) {
1825 put_string(line_bufp + buf_offset, " -> ", 4);
1830 put_string(line_bufp + buf_offset, " ", 1);
1836 case COL_DEF_DL_SRC:
1837 case COL_RES_DL_SRC:
1838 case COL_UNRES_DL_SRC:
1839 switch (cf->cinfo.columns[i+1].col_fmt) {
1841 case COL_DEF_DL_DST:
1842 case COL_RES_DL_DST:
1843 case COL_UNRES_DL_DST:
1844 put_string(line_bufp + buf_offset, " -> ", 4);
1849 put_string(line_bufp + buf_offset, " ", 1);
1855 case COL_DEF_NET_SRC:
1856 case COL_RES_NET_SRC:
1857 case COL_UNRES_NET_SRC:
1858 switch (cf->cinfo.columns[i+1].col_fmt) {
1860 case COL_DEF_NET_DST:
1861 case COL_RES_NET_DST:
1862 case COL_UNRES_NET_DST:
1863 put_string(line_bufp + buf_offset, " -> ", 4);
1868 put_string(line_bufp + buf_offset, " ", 1);
1877 switch (cf->cinfo.columns[i+1].col_fmt) {
1882 put_string(line_bufp + buf_offset, " <- ", 4);
1887 put_string(line_bufp + buf_offset, " ", 1);
1893 case COL_DEF_DL_DST:
1894 case COL_RES_DL_DST:
1895 case COL_UNRES_DL_DST:
1896 switch (cf->cinfo.columns[i+1].col_fmt) {
1898 case COL_DEF_DL_SRC:
1899 case COL_RES_DL_SRC:
1900 case COL_UNRES_DL_SRC:
1901 put_string(line_bufp + buf_offset, " <- ", 4);
1906 put_string(line_bufp + buf_offset, " ", 1);
1912 case COL_DEF_NET_DST:
1913 case COL_RES_NET_DST:
1914 case COL_UNRES_NET_DST:
1915 switch (cf->cinfo.columns[i+1].col_fmt) {
1917 case COL_DEF_NET_SRC:
1918 case COL_RES_NET_SRC:
1919 case COL_UNRES_NET_SRC:
1920 put_string(line_bufp + buf_offset, " <- ", 4);
1925 put_string(line_bufp + buf_offset, " ", 1);
1932 put_string(line_bufp + buf_offset, " ", 1);
1938 return print_line(print_stream, 0, line_bufp);
1942 print_packet(capture_file *cf, epan_dissect_t *edt)
1944 if (print_summary || output_fields_has_cols(output_fields)) {
1945 /* Just fill in the columns. */
1946 epan_dissect_fill_in_columns(edt, FALSE, TRUE);
1948 if (print_summary) {
1949 /* Now print them. */
1950 switch (output_action) {
1953 if (!print_columns(cf))
1958 write_psml_columns(edt, stdout, FALSE);
1959 return !ferror(stdout);
1960 case WRITE_FIELDS: /*No non-verbose "fields" format */
1961 g_assert_not_reached();
1966 if (print_details) {
1967 /* Print the information in the protocol tree. */
1968 switch (output_action) {
1971 if (!proto_tree_print(print_details ? print_dissections_expanded : print_dissections_none,
1972 print_hex, edt, output_only_tables, print_stream))
1975 if (!print_line(print_stream, 0, separator))
1981 write_pdml_proto_tree(NULL, NULL, PF_NONE, edt, &cf->cinfo, stdout, FALSE);
1983 return !ferror(stdout);
1985 write_fields_proto_tree(output_fields, edt, &cf->cinfo, stdout);
1987 return !ferror(stdout);
1991 if (print_summary || print_details) {
1992 if (!print_line(print_stream, 0, ""))
1995 if (!print_hex_data(print_stream, edt))
1997 if (!print_line(print_stream, 0, separator))
2006 switch (output_action) {
2009 return print_finale(print_stream);
2013 write_pdml_finale(stdout);
2015 write_psml_finale(stdout);
2016 return !ferror(stdout);
2019 write_fields_finale(output_fields, stdout);
2020 return !ferror(stdout);
2023 g_assert_not_reached();
2029 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
2032 char err_msg[2048+1];
2034 /* The open isn't implemented yet. Fill in the information for this file. */
2036 /* Create new epan session for dissection. */
2037 epan_free(cf->epan);
2038 cf->epan = tfshark_epan_new(cf);
2040 cf->provider.wth = NULL; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2041 cf->f_datalen = 0; /* not used, but set it anyway */
2043 /* Set the file name because we need it to set the follow stream filter.
2044 XXX - is that still true? We need it for other reasons, though,
2046 cf->filename = g_strdup(fname);
2048 /* Indicate whether it's a permanent or temporary file. */
2049 cf->is_tempfile = is_tempfile;
2051 /* No user changes yet. */
2052 cf->unsaved_changes = FALSE;
2054 cf->cd_t = 0; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2055 cf->open_type = type;
2057 cf->drops_known = FALSE;
2059 cf->snap = 0; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2060 nstime_set_zero(&cf->elapsed_time);
2061 cf->provider.ref = NULL;
2062 cf->provider.prev_dis = NULL;
2063 cf->provider.prev_cap = NULL;
2065 cf->state = FILE_READ_IN_PROGRESS;
2070 g_snprintf(err_msg, sizeof err_msg,
2071 cf_open_error_message(*err, err_info, FALSE, cf->cd_t), fname);
2072 cmdarg_err("%s", err_msg);
2077 show_print_file_io_error(int err)
2082 cmdarg_err("Not all the packets could be printed because there is "
2083 "no space left on the file system.");
2088 cmdarg_err("Not all the packets could be printed because you are "
2089 "too close to, or over your disk quota.");
2094 cmdarg_err("An error occurred while printing packets: %s.",
2101 cf_open_error_message(int err, gchar *err_info _U_, gboolean for_writing,
2105 /* static char errmsg_errno[1024+1]; */
2109 /* Wiretap error. */
2112 case FTAP_ERR_NOT_REGULAR_FILE:
2113 errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
2116 case FTAP_ERR_RANDOM_OPEN_PIPE:
2117 /* Seen only when opening a capture file for reading. */
2118 errmsg = "The file \"%s\" is a pipe or FIFO; TFShark can't read pipe or FIFO files in two-pass mode.";
2121 case FTAP_ERR_FILE_UNKNOWN_FORMAT:
2122 /* Seen only when opening a capture file for reading. */
2123 errmsg = "The file \"%s\" isn't a capture file in a format TFShark understands.";
2126 case FTAP_ERR_UNSUPPORTED:
2127 /* Seen only when opening a capture file for reading. */
2128 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2129 "The file \"%%s\" isn't a capture file in a format TFShark understands.\n"
2132 errmsg = errmsg_errno;
2135 case FTAP_ERR_CANT_WRITE_TO_PIPE:
2136 /* Seen only when opening a capture file for writing. */
2137 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2138 "The file \"%%s\" is a pipe, and \"%s\" capture files can't be "
2139 "written to a pipe.", ftap_file_type_subtype_short_string(file_type));
2140 errmsg = errmsg_errno;
2143 case FTAP_ERR_UNSUPPORTED_FILE_TYPE:
2144 /* Seen only when opening a capture file for writing. */
2145 errmsg = "TFShark doesn't support writing capture files in that format.";
2148 case FTAP_ERR_UNSUPPORTED_ENCAP:
2150 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2151 "TFShark can't save this capture as a \"%s\" file.",
2152 ftap_file_type_subtype_short_string(file_type));
2154 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2155 "The file \"%%s\" is a capture for a network type that TFShark doesn't support.\n"
2159 errmsg = errmsg_errno;
2162 case FTAP_ERR_ENCAP_PER_RECORD_UNSUPPORTED:
2164 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2165 "TFShark can't save this capture as a \"%s\" file.",
2166 ftap_file_type_subtype_short_string(file_type));
2167 errmsg = errmsg_errno;
2169 errmsg = "The file \"%s\" is a capture for a network type that TFShark doesn't support.";
2172 case FTAP_ERR_BAD_FILE:
2173 /* Seen only when opening a capture file for reading. */
2174 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2175 "The file \"%%s\" appears to be damaged or corrupt.\n"
2178 errmsg = errmsg_errno;
2181 case FTAP_ERR_CANT_OPEN:
2183 errmsg = "The file \"%s\" could not be created for some unknown reason.";
2185 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
2188 case FTAP_ERR_SHORT_READ:
2189 errmsg = "The file \"%s\" appears to have been cut short"
2190 " in the middle of a packet or other data.";
2193 case FTAP_ERR_SHORT_WRITE:
2194 errmsg = "A full header couldn't be written to the file \"%s\".";
2197 case FTAP_ERR_COMPRESSION_NOT_SUPPORTED:
2198 errmsg = "This file type cannot be written as a compressed file.";
2201 case FTAP_ERR_DECOMPRESS:
2202 /* Seen only when opening a capture file for reading. */
2203 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2204 "The compressed file \"%%s\" appears to be damaged or corrupt.\n"
2207 errmsg = errmsg_errno;
2211 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2212 "The file \"%%s\" could not be %s: %s.",
2213 for_writing ? "created" : "opened",
2214 ftap_strerror(err));
2215 errmsg = errmsg_errno;
2220 errmsg = file_open_error_message(err, for_writing);
2225 * General errors and warnings are reported with an console message
2229 failure_warning_message(const char *msg_format, va_list ap)
2231 fprintf(stderr, "tfshark: ");
2232 vfprintf(stderr, msg_format, ap);
2233 fprintf(stderr, "\n");
2237 * Open/create errors are reported with an console message in TFShark.
2240 open_failure_message(const char *filename, int err, gboolean for_writing)
2242 fprintf(stderr, "tfshark: ");
2243 fprintf(stderr, file_open_error_message(err, for_writing), filename);
2244 fprintf(stderr, "\n");
2248 * Read errors are reported with an console message in TFShark.
2251 read_failure_message(const char *filename, int err)
2253 cmdarg_err("An error occurred while reading from the file \"%s\": %s.",
2254 filename, g_strerror(err));
2258 * Write errors are reported with an console message in TFShark.
2261 write_failure_message(const char *filename, int err)
2263 cmdarg_err("An error occurred while writing to the file \"%s\": %s.",
2264 filename, g_strerror(err));
2268 * Report additional information for an error in command-line arguments.
2271 failure_message_cont(const char *msg_format, va_list ap)
2273 vfprintf(stderr, msg_format, ap);
2274 fprintf(stderr, "\n");
2278 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2283 * indent-tabs-mode: nil
2286 * vi: set shiftwidth=2 tabstop=8 expandtab:
2287 * :indentSize=2:tabSize=8:noTabs=true: