SMB2: dissect new signing capability negotiate context
[wireshark-sm.git] / tfshark.c
blobfcd1f6b520007d82c6928a3bd42362037eb266c0
1 /* tfshark.c
3 * Text-mode variant of Fileshark, based off of TShark,
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include <config.h>
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <locale.h>
18 #include <limits.h>
20 #ifdef HAVE_GETOPT_H
21 #include <getopt.h>
22 #endif
24 #include <errno.h>
26 #ifndef HAVE_GETOPT_LONG
27 #include "wsutil/wsgetopt.h"
28 #endif
30 #include <glib.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>
41 #include <cli_main.h>
42 #include <version_info.h>
44 #include "globals.h"
45 #include <epan/timestamp.h>
46 #include <epan/packet.h>
47 #ifdef HAVE_LUA
48 #include <epan/wslua/init_wslua.h>
49 #endif
50 #include "file.h"
51 #include "frame_tvbuff.h"
52 #include <epan/disabled_protos.h>
53 #include <epan/prefs.h>
54 #include <epan/column.h>
55 #include <epan/print.h>
56 #include <epan/addr_resolv.h>
57 #include "ui/util.h"
58 #include "ui/decode_as_utils.h"
59 #include "ui/dissect_opts.h"
60 #include <epan/epan_dissect.h>
61 #include <epan/tap.h>
62 #include <epan/stat_tap_ui.h>
63 #include <epan/ex-opt.h>
64 #include "extcap.h"
66 #include <wiretap/wtap-int.h>
67 #include <wiretap/file_wrappers.h>
69 #include "log.h"
70 #include <epan/funnel.h>
72 #ifdef HAVE_PLUGINS
73 #include <wsutil/plugins.h>
74 #endif
76 #define INVALID_OPTION 1
77 #define NO_FILE_SPECIFIED 1
78 #define INIT_ERROR 2
79 #define INVALID_FILTER 2
80 #define OPEN_ERROR 2
82 capture_file cfile;
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.
96 typedef enum {
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 */
101 } output_action_e;
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;
140 #if 0
141 struct string_elem {
142 const char *sstr; /* The short string */
143 const char *lstr; /* The long string */
146 static gint
147 string_compare(gconstpointer a, gconstpointer b)
149 return strcmp(((const struct string_elem *)a)->sstr,
150 ((const struct string_elem *)b)->sstr);
153 static void
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);
160 #endif
162 static void
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");
223 static void
224 glossary_option_help(void)
226 FILE *output;
228 output = stdout;
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");
252 static void
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
259 message anyway.
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) {
270 return;
273 g_log_default_handler(log_domain, log_level, message, user_data);
277 static void
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);
286 g_free(cur_user);
287 g_free(cur_group);
288 if (running_with_special_privs()) {
289 fprintf(stderr, " This could be dangerous.");
291 fprintf(stderr, "\n");
295 static void
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;
306 int opt;
307 static const struct option long_options[] = {
308 {"help", no_argument, NULL, 'h'},
309 {"version", no_argument, NULL, 'v'},
310 {0, 0, 0, 0 }
312 gboolean arg_error = FALSE;
314 int err;
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;
323 gchar *err_msg;
324 e_prefs *prefs_p;
325 int log_flags;
326 gchar *output_only = NULL;
329 * The leading + ensures that getopt_long() does not permute the argv[]
330 * entries.
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;
352 * Set the C-language locale to the native environment and set the
353 * code page to UTF-8 on Windows.
355 #ifdef _WIN32
356 setlocale(LC_ALL, ".UTF-8");
357 #else
358 setlocale(LC_ALL, "");
359 #endif
361 cmdarg_err_init(failure_warning_message, failure_message_cont);
363 #ifdef _WIN32
364 create_app_running_mutex();
365 #endif /* _WIN32 */
368 * Get credential information for later use, and drop privileges
369 * before doing anything else.
370 * Let the user know if anything happened.
372 init_process_policies();
373 relinquish_special_privs_perm();
374 print_current_user();
377 * Attempt to get the pathname of the directory containing the
378 * executable file.
380 init_progfile_dir_error = init_progfile_dir(argv[0]);
381 if (init_progfile_dir_error != NULL) {
382 fprintf(stderr,
383 "tfshark: Can't get pathname of directory containing the tfshark program: %s.\n",
384 init_progfile_dir_error);
385 g_free(init_progfile_dir_error);
388 initialize_funnel_ops();
390 /* Initialize the version information. */
391 ws_init_version_info("TFShark (Wireshark)", NULL,
392 epan_get_compiled_version_info,
393 get_tfshark_runtime_version_info);
396 * In order to have the -X opts assigned before the wslua machine starts
397 * we need to call getopts before epan_init() gets called.
399 * In order to handle, for example, -o options, we also need to call it
400 * *after* epan_init() gets called, so that the dissectors have had a
401 * chance to register their preferences.
403 * XXX - can we do this all with one getopt_long() call, saving the
404 * arguments we can't handle until after initializing libwireshark,
405 * and then process them after initializing libwireshark?
407 opterr = 0;
409 while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
410 switch (opt) {
411 case 'C': /* Configuration Profile */
412 if (profile_exists (optarg, FALSE)) {
413 set_profile_name (optarg);
414 } else {
415 cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
416 return 1;
418 break;
419 case 'O': /* Only output these protocols */
420 output_only = g_strdup(optarg);
421 /* FALLTHROUGH */
422 case 'V': /* Verbose */
423 print_details = TRUE;
424 print_packet_info = TRUE;
425 break;
426 case 'x': /* Print packet data in hex (and ASCII) */
427 print_hex = TRUE;
428 /* The user asked for hex output, so let's ensure they get it,
429 * even if they're writing to a file.
431 print_packet_info = TRUE;
432 break;
433 case 'X':
434 ex_opt_add(optarg);
435 break;
436 default:
437 break;
442 * Print packet summary information is the default, unless either -V or -x
443 * were specified. Note that this is new behavior, which
444 * allows for the possibility of printing only hex/ascii output without
445 * necessarily requiring that either the summary or details be printed too.
447 if (print_summary == -1)
448 print_summary = (print_details || print_hex) ? FALSE : TRUE;
450 /** Send All g_log messages to our own handler **/
452 log_flags =
453 G_LOG_LEVEL_ERROR|
454 G_LOG_LEVEL_CRITICAL|
455 G_LOG_LEVEL_WARNING|
456 G_LOG_LEVEL_MESSAGE|
457 G_LOG_LEVEL_INFO|
458 G_LOG_LEVEL_DEBUG|
459 G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
461 g_log_set_handler(NULL,
462 (GLogLevelFlags)log_flags,
463 tfshark_log_handler, NULL /* user_data */);
464 g_log_set_handler(LOG_DOMAIN_MAIN,
465 (GLogLevelFlags)log_flags,
466 tfshark_log_handler, NULL /* user_data */);
468 init_report_message(failure_warning_message, failure_warning_message,
469 open_failure_message, read_failure_message,
470 write_failure_message);
472 timestamp_set_type(TS_RELATIVE);
473 timestamp_set_precision(TS_PREC_AUTO);
474 timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
476 wtap_init(TRUE);
478 /* Register all dissectors; we must do this before checking for the
479 "-G" flag, as the "-G" flag dumps information registered by the
480 dissectors, and we must do it before we read the preferences, in
481 case any dissectors register preferences. */
482 if (!epan_init(NULL, NULL, TRUE)) {
483 exit_status = INIT_ERROR;
484 goto clean_exit;
487 /* Register all tap listeners; we do this before we parse the arguments,
488 as the "-z" argument can specify a registered tap. */
490 /* we register the plugin taps before the other taps because
491 stats_tree taps plugins will be registered as tap listeners
492 by stats_tree_stat.c and need to registered before that */
494 /* XXX Disable tap registration for now until we can get tfshark set up with
495 * its own set of taps and the necessary registration function etc.
496 #ifdef HAVE_PLUGINS
497 register_all_plugin_tap_listeners();
498 #endif
499 register_all_tap_listeners();
502 /* If invoked with the "-G" flag, we dump out information based on
503 the argument to the "-G" flag; if no argument is specified,
504 for backwards compatibility we dump out a glossary of display
505 filter symbols.
507 XXX - we do this here, for now, to support "-G" with no arguments.
508 If none of our build or other processes uses "-G" with no arguments,
509 we can just process it with the other arguments. */
510 if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
511 proto_initialize_all_prefixes();
513 if (argc == 2)
514 proto_registrar_dump_fields();
515 else {
516 if (strcmp(argv[2], "column-formats") == 0)
517 column_dump_column_formats();
518 else if (strcmp(argv[2], "currentprefs") == 0) {
519 epan_load_settings();
520 write_prefs(NULL);
522 else if (strcmp(argv[2], "decodes") == 0)
523 dissector_dump_decodes();
524 else if (strcmp(argv[2], "defaultprefs") == 0)
525 write_prefs(NULL);
526 else if (strcmp(argv[2], "dissector-tables") == 0)
527 dissector_dump_dissector_tables();
528 else if (strcmp(argv[2], "fields") == 0)
529 proto_registrar_dump_fields();
530 else if (strcmp(argv[2], "ftypes") == 0)
531 proto_registrar_dump_ftypes();
532 else if (strcmp(argv[2], "heuristic-decodes") == 0)
533 dissector_dump_heur_decodes();
534 else if (strcmp(argv[2], "plugins") == 0) {
535 #ifdef HAVE_PLUGINS
536 plugins_dump_all();
537 #endif
538 #ifdef HAVE_LUA
539 wslua_plugins_dump_all();
540 #endif
542 else if (strcmp(argv[2], "protocols") == 0)
543 proto_registrar_dump_protocols();
544 else if (strcmp(argv[2], "values") == 0)
545 proto_registrar_dump_values();
546 else if (strcmp(argv[2], "?") == 0)
547 glossary_option_help();
548 else if (strcmp(argv[2], "-?") == 0)
549 glossary_option_help();
550 else {
551 cmdarg_err("Invalid \"%s\" option for -G flag, enter -G ? for more help.", argv[2]);
552 exit_status = INVALID_OPTION;
553 goto clean_exit;
556 goto clean_exit;
559 /* Load libwireshark settings from the current profile. */
560 prefs_p = epan_load_settings();
561 prefs_loaded = TRUE;
563 cap_file_init(&cfile);
565 /* Print format defaults to this. */
566 print_format = PR_FMT_TEXT;
568 output_fields = output_fields_new();
571 * To reset the options parser, set optreset to 1 on platforms that
572 * have optreset (documented in *BSD and macOS, apparently present but
573 * not documented in Solaris - the Illumos repository seems to
574 * suggest that the first Solaris getopt_long(), at least as of 2004,
575 * was based on the NetBSD one, it had optreset) and set optind to 1,
576 * and set optind to 0 otherwise (documented as working in the GNU
577 * getopt_long(). Setting optind to 0 didn't originally work in the
578 * NetBSD one, but that was added later - we don't want to depend on
579 * it if we have optreset).
581 * Also reset opterr to 1, so that error messages are printed by
582 * getopt_long().
584 #ifdef HAVE_OPTRESET
585 optreset = 1;
586 optind = 1;
587 #else
588 optind = 0;
589 #endif
590 opterr = 1;
592 /* Now get our args */
593 while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
594 switch (opt) {
595 case '2': /* Perform two pass analysis */
596 perform_two_pass_analysis = TRUE;
597 break;
598 case 'C':
599 /* already processed; just ignore it now */
600 break;
601 case 'e':
602 /* Field entry */
603 output_fields_add(output_fields, optarg);
604 break;
605 case 'E':
606 /* Field option */
607 if (!output_fields_set_option(output_fields, optarg)) {
608 cmdarg_err("\"%s\" is not a valid field output option=value pair.", optarg);
609 output_fields_list_options(stderr);
610 exit_status = INVALID_OPTION;
611 goto clean_exit;
613 break;
615 case 'h': /* Print help and exit */
616 show_help_header("Analyze file structure.");
617 print_usage(stdout);
618 goto clean_exit;
619 break;
620 case 'l': /* "Line-buffer" standard output */
621 /* The ANSI C standard does not appear to *require* that a line-buffered
622 stream be flushed to the host environment whenever a newline is
623 written, it just says that, on such a stream, characters "are
624 intended to be transmitted to or from the host environment as a
625 block when a new-line character is encountered".
627 The Visual C++ 6.0 C implementation doesn't do what is intended;
628 even if you set a stream to be line-buffered, it still doesn't
629 flush the buffer at the end of every line.
631 The whole reason for the "-l" flag in either tcpdump or TShark
632 is to allow the output of a live capture to be piped to a program
633 or script and to have that script see the information for the
634 packet as soon as it's printed, rather than having to wait until
635 a standard I/O buffer fills up.
637 So, if the "-l" flag is specified, we flush the standard output
638 at the end of a packet. This will do the right thing if we're
639 printing packet summary lines, and, as we print the entire protocol
640 tree for a single packet without waiting for anything to happen,
641 it should be as good as line-buffered mode if we're printing
642 protocol trees - arguably even better, as it may do fewer
643 writes. */
644 line_buffered = TRUE;
645 break;
646 case 'o': /* Override preference from command line */
648 char *errmsg = NULL;
650 switch (prefs_set_pref(optarg, &errmsg)) {
652 case PREFS_SET_OK:
653 break;
655 case PREFS_SET_SYNTAX_ERR:
656 cmdarg_err("Invalid -o flag \"%s\"%s%s", optarg,
657 errmsg ? ": " : "", errmsg ? errmsg : "");
658 g_free(errmsg);
659 return 1;
660 break;
662 case PREFS_SET_NO_SUCH_PREF:
663 case PREFS_SET_OBSOLETE:
664 cmdarg_err("-o flag \"%s\" specifies unknown preference", optarg);
665 exit_status = INVALID_OPTION;
666 goto clean_exit;
667 break;
669 break;
671 case 'q': /* Quiet */
672 quiet = TRUE;
673 break;
674 case 'Q': /* Really quiet */
675 quiet = TRUE;
676 really_quiet = TRUE;
677 break;
678 case 'r': /* Read capture file x */
679 cf_name = g_strdup(optarg);
680 break;
681 case 'R': /* Read file filter */
682 rfilter = optarg;
683 break;
684 case 'S': /* Set the line Separator to be printed between packets */
685 separator = g_strdup(optarg);
686 break;
687 case 'T': /* printing Type */
688 if (strcmp(optarg, "text") == 0) {
689 output_action = WRITE_TEXT;
690 print_format = PR_FMT_TEXT;
691 } else if (strcmp(optarg, "ps") == 0) {
692 output_action = WRITE_TEXT;
693 print_format = PR_FMT_PS;
694 } else if (strcmp(optarg, "pdml") == 0) {
695 output_action = WRITE_XML;
696 print_details = TRUE; /* Need details */
697 print_summary = FALSE; /* Don't allow summary */
698 } else if (strcmp(optarg, "psml") == 0) {
699 output_action = WRITE_XML;
700 print_details = FALSE; /* Don't allow details */
701 print_summary = TRUE; /* Need summary */
702 } else if (strcmp(optarg, "fields") == 0) {
703 output_action = WRITE_FIELDS;
704 print_details = TRUE; /* Need full tree info */
705 print_summary = FALSE; /* Don't allow summary */
706 } else {
707 cmdarg_err("Invalid -T parameter \"%s\"; it must be one of:", optarg); /* x */
708 cmdarg_err_cont("\t\"fields\" The values of fields specified with the -e option, in a form\n"
709 "\t specified by the -E option.\n"
710 "\t\"pdml\" Packet Details Markup Language, an XML-based format for the\n"
711 "\t details of a decoded packet. This information is equivalent to\n"
712 "\t the packet details printed with the -V flag.\n"
713 "\t\"ps\" PostScript for a human-readable one-line summary of each of\n"
714 "\t the packets, or a multi-line view of the details of each of\n"
715 "\t the packets, depending on whether the -V flag was specified.\n"
716 "\t\"psml\" Packet Summary Markup Language, an XML-based format for the\n"
717 "\t summary information of a decoded packet. This information is\n"
718 "\t equivalent to the information shown in the one-line summary\n"
719 "\t printed by default.\n"
720 "\t\"text\" Text of a human-readable one-line summary of each of the\n"
721 "\t packets, or a multi-line view of the details of each of the\n"
722 "\t packets, depending on whether the -V flag was specified.\n"
723 "\t This is the default.");
724 exit_status = INVALID_OPTION;
725 goto clean_exit;
727 break;
728 case 'v': /* Show version and exit */
729 show_version();
730 goto clean_exit;
731 case 'O': /* Only output these protocols */
732 /* already processed; just ignore it now */
733 break;
734 case 'V': /* Verbose */
735 /* already processed; just ignore it now */
736 break;
737 case 'x': /* Print packet data in hex (and ASCII) */
738 /* already processed; just ignore it now */
739 break;
740 case 'X':
741 /* already processed; just ignore it now */
742 break;
743 case 'Y':
744 dfilter = optarg;
745 break;
746 case 'z':
747 /* We won't call the init function for the stat this soon
748 as it would disallow MATE's fields (which are registered
749 by the preferences set callback) from being used as
750 part of a tap filter. Instead, we just add the argument
751 to a list of stat arguments. */
752 if (strcmp("help", optarg) == 0) {
753 fprintf(stderr, "tfshark: The available statistics for the \"-z\" option are:\n");
754 list_stat_cmd_args();
755 goto clean_exit;
757 if (!process_stat_cmd_arg(optarg)) {
758 cmdarg_err("Invalid -z argument \"%s\"; it must be one of:", optarg);
759 list_stat_cmd_args();
760 exit_status = INVALID_OPTION;
761 goto clean_exit;
763 break;
764 case 'd': /* Decode as rule */
765 case 'K': /* Kerberos keytab file */
766 case 't': /* Time stamp type */
767 case 'u': /* Seconds type */
768 case LONGOPT_DISABLE_PROTOCOL: /* disable dissection of protocol */
769 case LONGOPT_ENABLE_HEURISTIC: /* enable heuristic dissection of protocol */
770 case LONGOPT_DISABLE_HEURISTIC: /* disable heuristic dissection of protocol */
771 case LONGOPT_ENABLE_PROTOCOL: /* enable dissection of protocol (that is disabled by default) */
772 if (!dissect_opts_handle_opt(opt, optarg)) {
773 exit_status = INVALID_OPTION;
774 goto clean_exit;
776 break;
777 default:
778 case '?': /* Bad flag - print usage message */
779 print_usage(stderr);
780 exit_status = INVALID_OPTION;
781 goto clean_exit;
782 break;
786 /* If we specified output fields, but not the output field type... */
787 if (WRITE_FIELDS != output_action && 0 != output_fields_num_fields(output_fields)) {
788 cmdarg_err("Output fields were specified with \"-e\", "
789 "but \"-Tfields\" was not specified.");
790 return 1;
791 } else if (WRITE_FIELDS == output_action && 0 == output_fields_num_fields(output_fields)) {
792 cmdarg_err("\"-Tfields\" was specified, but no fields were "
793 "specified with \"-e\".");
795 exit_status = INVALID_OPTION;
796 goto clean_exit;
799 /* We require a -r flag specifying a file to read. */
800 if (cf_name == NULL) {
801 cmdarg_err("A file to read must be specified with \"-r\".");
802 exit_status = NO_FILE_SPECIFIED;
803 goto clean_exit;
806 /* If no display filter has been specified, and there are still command-
807 line arguments, treat them as the tokens of a display filter. */
808 if (optind < argc) {
809 if (dfilter != NULL) {
810 cmdarg_err("Display filters were specified both with \"-Y\" "
811 "and with additional command-line arguments.");
812 exit_status = INVALID_OPTION;
813 goto clean_exit;
815 dfilter = get_args_as_string(argc, argv, optind);
818 /* if "-q" wasn't specified, we should print packet information */
819 if (!quiet)
820 print_packet_info = TRUE;
822 if (arg_error) {
823 print_usage(stderr);
824 exit_status = INVALID_OPTION;
825 goto clean_exit;
828 if (print_hex) {
829 if (output_action != WRITE_TEXT) {
830 cmdarg_err("Raw packet hex data can only be printed as text or PostScript");
831 exit_status = INVALID_OPTION;
832 goto clean_exit;
836 if (output_only != NULL) {
837 char *ps;
839 if (!print_details) {
840 cmdarg_err("-O requires -V");
841 exit_status = INVALID_OPTION;
842 goto clean_exit;
845 output_only_tables = g_hash_table_new (g_str_hash, g_str_equal);
846 for (ps = strtok (output_only, ","); ps; ps = strtok (NULL, ",")) {
847 g_hash_table_insert(output_only_tables, (gpointer)ps, (gpointer)ps);
851 if (rfilter != NULL && !perform_two_pass_analysis) {
852 cmdarg_err("-R without -2 is deprecated. For single-pass filtering use -Y.");
853 exit_status = INVALID_OPTION;
854 goto clean_exit;
857 /* Notify all registered modules that have had any of their preferences
858 changed either from one of the preferences file or from the command
859 line that their preferences have changed. */
860 prefs_apply_all();
863 * Enabled and disabled protocols and heuristic dissectors as per
864 * command-line options.
866 if (!setup_enabled_and_disabled_protocols()) {
867 exit_status = INVALID_OPTION;
868 goto clean_exit;
871 /* Build the column format array */
872 build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
874 if (rfilter != NULL) {
875 if (!dfilter_compile(rfilter, &rfcode, &err_msg)) {
876 cmdarg_err("%s", err_msg);
877 g_free(err_msg);
878 exit_status = INVALID_FILTER;
879 goto clean_exit;
882 cfile.rfcode = rfcode;
884 if (dfilter != NULL) {
885 if (!dfilter_compile(dfilter, &dfcode, &err_msg)) {
886 cmdarg_err("%s", err_msg);
887 g_free(err_msg);
888 exit_status = INVALID_FILTER;
889 goto clean_exit;
892 cfile.dfcode = dfcode;
894 if (print_packet_info) {
895 /* If we're printing as text or PostScript, we have
896 to create a print stream. */
897 if (output_action == WRITE_TEXT) {
898 switch (print_format) {
900 case PR_FMT_TEXT:
901 print_stream = print_stream_text_stdio_new(stdout);
902 break;
904 case PR_FMT_PS:
905 print_stream = print_stream_ps_stdio_new(stdout);
906 break;
908 default:
909 g_assert_not_reached();
914 /* We have to dissect each packet if:
916 we're printing information about each packet;
918 we're using a read filter on the packets;
920 we're using a display filter on the packets;
922 we're using any taps that need dissection. */
923 do_dissection = print_packet_info || rfcode || dfcode || tap_listeners_require_dissection();
926 * Read the file.
929 /* TODO: if tfshark is ever changed to give the user a choice of which
930 open_routine reader to use, then the following needs to change. */
931 if (cf_open(&cfile, cf_name, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK) {
932 exit_status = OPEN_ERROR;
933 goto clean_exit;
936 /* Start statistics taps; we do so after successfully opening the
937 capture file, so we know we have something to compute stats
938 on, and after registering all dissectors, so that MATE will
939 have registered its field array so we can have a tap filter
940 with one of MATE's late-registered fields as part of the
941 filter. */
942 start_requested_stats();
944 /* Process the packets in the file */
945 TRY {
946 /* XXX - for now there is only 1 packet */
947 success = process_file(&cfile, 1, 0);
949 CATCH(OutOfMemoryError) {
950 fprintf(stderr,
951 "Out Of Memory.\n"
952 "\n"
953 "Sorry, but TFShark has to terminate now.\n"
954 "\n"
955 "Some infos / workarounds can be found at:\n"
956 "https://wiki.wireshark.org/KnownBugs/OutOfMemory\n");
957 success = FALSE;
959 ENDTRY;
961 if (!success) {
962 /* We still dump out the results of taps, etc., as we might have
963 read some packets; however, we exit with an error status. */
964 exit_status = 2;
967 g_free(cf_name);
969 if (cfile.provider.frames != NULL) {
970 free_frame_data_sequence(cfile.provider.frames);
971 cfile.provider.frames = NULL;
974 draw_tap_listeners(TRUE);
975 funnel_dump_all_text_windows();
977 clean_exit:
978 destroy_print_stream(print_stream);
979 epan_free(cfile.epan);
980 epan_cleanup();
981 extcap_cleanup();
983 output_fields_free(output_fields);
984 output_fields = NULL;
986 col_cleanup(&cfile.cinfo);
987 wtap_cleanup();
988 return exit_status;
991 static const nstime_t *
992 tfshark_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num)
994 if (prov->ref && prov->ref->num == frame_num)
995 return &prov->ref->abs_ts;
997 if (prov->prev_dis && prov->prev_dis->num == frame_num)
998 return &prov->prev_dis->abs_ts;
1000 if (prov->prev_cap && prov->prev_cap->num == frame_num)
1001 return &prov->prev_cap->abs_ts;
1003 if (prov->frames) {
1004 frame_data *fd = frame_data_sequence_find(prov->frames, frame_num);
1006 return (fd) ? &fd->abs_ts : NULL;
1009 return NULL;
1012 static const char *
1013 no_interface_name(struct packet_provider_data *prov _U_, guint32 interface_id _U_)
1015 return "";
1018 static epan_t *
1019 tfshark_epan_new(capture_file *cf)
1021 static const struct packet_provider_funcs funcs = {
1022 tfshark_get_frame_ts,
1023 no_interface_name,
1024 NULL,
1025 NULL,
1028 return epan_new(&cf->provider, &funcs);
1031 static gboolean
1032 process_packet_first_pass(capture_file *cf, epan_dissect_t *edt,
1033 gint64 offset, wtap_rec *rec,
1034 const guchar *pd)
1036 frame_data fdlocal;
1037 guint32 framenum;
1038 gboolean passed;
1040 /* The frame number of this packet is one more than the count of
1041 frames in this packet. */
1042 framenum = cf->count + 1;
1044 /* If we're not running a display filter and we're not printing any
1045 packet information, we don't need to do a dissection. This means
1046 that all packets can be marked as 'passed'. */
1047 passed = TRUE;
1049 frame_data_init(&fdlocal, framenum, rec, offset, cum_bytes);
1051 /* If we're going to print packet information, or we're going to
1052 run a read filter, or display filter, or we're going to process taps, set up to
1053 do a dissection and do so. */
1054 if (edt) {
1055 /* If we're running a read filter, prime the epan_dissect_t with that
1056 filter. */
1057 if (cf->rfcode)
1058 epan_dissect_prime_with_dfilter(edt, cf->rfcode);
1060 /* This is the first pass, so prime the epan_dissect_t with the
1061 hfids postdissectors want on the first pass. */
1062 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1064 frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time,
1065 &cf->provider.ref, cf->provider.prev_dis);
1066 if (cf->provider.ref == &fdlocal) {
1067 ref_frame = fdlocal;
1068 cf->provider.ref = &ref_frame;
1071 epan_dissect_file_run(edt, rec,
1072 file_tvbuff_new(&cf->provider, &fdlocal, pd),
1073 &fdlocal, NULL);
1075 /* Run the read filter if we have one. */
1076 if (cf->rfcode)
1077 passed = dfilter_apply_edt(cf->rfcode, edt);
1080 if (passed) {
1081 frame_data_set_after_dissect(&fdlocal, &cum_bytes);
1082 cf->provider.prev_cap = cf->provider.prev_dis = frame_data_sequence_add(cf->provider.frames, &fdlocal);
1084 /* If we're not doing dissection then there won't be any dependent frames.
1085 * More importantly, edt.pi.dependent_frames won't be initialized because
1086 * epan hasn't been initialized.
1088 if (edt) {
1089 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
1092 cf->count++;
1093 } else {
1094 /* if we don't add it to the frame_data_sequence, clean it up right now
1095 * to avoid leaks */
1096 frame_data_destroy(&fdlocal);
1099 if (edt)
1100 epan_dissect_reset(edt);
1102 return passed;
1105 static gboolean
1106 process_packet_second_pass(capture_file *cf, epan_dissect_t *edt,
1107 frame_data *fdata, wtap_rec *rec,
1108 Buffer *buf, guint tap_flags)
1110 column_info *cinfo;
1111 gboolean passed;
1113 /* If we're not running a display filter and we're not printing any
1114 packet information, we don't need to do a dissection. This means
1115 that all packets can be marked as 'passed'. */
1116 passed = TRUE;
1118 /* If we're going to print packet information, or we're going to
1119 run a read filter, or we're going to process taps, set up to
1120 do a dissection and do so. */
1121 if (edt) {
1123 /* If we're running a display filter, prime the epan_dissect_t with that
1124 filter. */
1125 if (cf->dfcode)
1126 epan_dissect_prime_with_dfilter(edt, cf->dfcode);
1128 /* This is the first and only pass, so prime the epan_dissect_t
1129 with the hfids postdissectors want on the first pass. */
1130 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1132 col_custom_prime_edt(edt, &cf->cinfo);
1134 /* We only need the columns if either
1135 1) some tap needs the columns
1137 2) we're printing packet info but we're *not* verbose; in verbose
1138 mode, we print the protocol tree, not the protocol summary.
1140 if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary))
1141 cinfo = &cf->cinfo;
1142 else
1143 cinfo = NULL;
1145 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1146 &cf->provider.ref, cf->provider.prev_dis);
1147 if (cf->provider.ref == fdata) {
1148 ref_frame = *fdata;
1149 cf->provider.ref = &ref_frame;
1152 epan_dissect_file_run_with_taps(edt, rec,
1153 file_tvbuff_new_buffer(&cf->provider, fdata, buf), fdata, cinfo);
1155 /* Run the read/display filter if we have one. */
1156 if (cf->dfcode)
1157 passed = dfilter_apply_edt(cf->dfcode, edt);
1160 if (passed) {
1161 frame_data_set_after_dissect(fdata, &cum_bytes);
1162 /* Process this packet. */
1163 if (print_packet_info) {
1164 /* We're printing packet information; print the information for
1165 this packet. */
1166 print_packet(cf, edt);
1168 /* If we're doing "line-buffering", flush the standard output
1169 after every packet. See the comment above, for the "-l"
1170 option, for an explanation of why we do that. */
1171 if (line_buffered)
1172 fflush(stdout);
1174 if (ferror(stdout)) {
1175 show_print_file_io_error(errno);
1176 return FALSE;
1179 cf->provider.prev_dis = fdata;
1181 cf->provider.prev_cap = fdata;
1183 if (edt) {
1184 epan_dissect_reset(edt);
1186 return passed || fdata->dependent_of_displayed;
1189 static gboolean
1190 local_wtap_read(capture_file *cf, wtap_rec *file_rec _U_, int *err, gchar **err_info _U_, gint64 *data_offset _U_, guint8** data_buffer)
1192 /* int bytes_read; */
1193 gint64 packet_size = wtap_file_size(cf->provider.wth, err);
1195 *data_buffer = (guint8*)g_malloc((gsize)packet_size);
1196 /* bytes_read =*/ file_read(*data_buffer, (unsigned int)packet_size, cf->provider.wth->fh);
1198 #if 0 /* no more filetap */
1199 if (bytes_read < 0) {
1200 *err = file_error(cf->provider.wth->fh, err_info);
1201 if (*err == 0)
1202 *err = FTAP_ERR_SHORT_READ;
1203 return FALSE;
1204 } else if (bytes_read == 0) {
1205 /* Done with file, no error */
1206 return FALSE;
1210 /* XXX - SET FRAME SIZE EQUAL TO TOTAL FILE SIZE */
1211 file_rec->rec_header.packet_header.caplen = (guint32)packet_size;
1212 file_rec->rec_header.packet_header.len = (guint32)packet_size;
1215 * Set the packet encapsulation to the file's encapsulation
1216 * value; if that's not WTAP_ENCAP_PER_PACKET, it's the
1217 * right answer (and means that the read routine for this
1218 * capture file type doesn't have to set it), and if it
1219 * *is* WTAP_ENCAP_PER_PACKET, the caller needs to set it
1220 * anyway.
1222 wth->rec.rec_header.packet_header.pkt_encap = wth->file_encap;
1224 if (!wth->subtype_read(wth, err, err_info, data_offset)) {
1226 * If we didn't get an error indication, we read
1227 * the last packet. See if there's any deferred
1228 * error, as might, for example, occur if we're
1229 * reading a compressed file, and we got an error
1230 * reading compressed data from the file, but
1231 * got enough compressed data to decompress the
1232 * last packet of the file.
1234 if (*err == 0)
1235 *err = file_error(wth->fh, err_info);
1236 return FALSE; /* failure */
1240 * It makes no sense for the captured data length to be bigger
1241 * than the actual data length.
1243 if (wth->rec.rec_header.packet_header.caplen > wth->rec.rec_header.packet_header.len)
1244 wth->rec.rec_header.packet_header.caplen = wth->rec.rec_header.packet_header.len;
1247 * Make sure that it's not WTAP_ENCAP_PER_PACKET, as that
1248 * probably means the file has that encapsulation type
1249 * but the read routine didn't set this packet's
1250 * encapsulation type.
1252 g_assert(wth->rec.rec_header.packet_header.pkt_encap != WTAP_ENCAP_PER_PACKET);
1253 #endif
1255 return TRUE; /* success */
1258 static gboolean
1259 process_file(capture_file *cf, int max_packet_count, gint64 max_byte_count)
1261 guint32 framenum;
1262 int err;
1263 gchar *err_info = NULL;
1264 gint64 data_offset = 0;
1265 gboolean filtering_tap_listeners;
1266 guint tap_flags;
1267 Buffer buf;
1268 epan_dissect_t *edt = NULL;
1269 wtap_rec file_rec;
1270 guint8* raw_data;
1272 if (print_packet_info) {
1273 if (!write_preamble(cf)) {
1274 err = errno;
1275 show_print_file_io_error(err);
1276 goto out;
1280 /* Do we have any tap listeners with filters? */
1281 filtering_tap_listeners = have_filtering_tap_listeners();
1283 /* Get the union of the flags for all tap listeners. */
1284 tap_flags = union_of_tap_listener_flags();
1286 wtap_rec_init(&file_rec);
1288 /* XXX - TEMPORARY HACK TO ELF DISSECTOR */
1289 file_rec.rec_header.packet_header.pkt_encap = 1234;
1291 if (perform_two_pass_analysis) {
1292 frame_data *fdata;
1294 /* Allocate a frame_data_sequence for all the frames. */
1295 cf->provider.frames = new_frame_data_sequence();
1297 if (do_dissection) {
1298 gboolean create_proto_tree;
1301 * Determine whether we need to create a protocol tree.
1302 * We do if:
1304 * we're going to apply a read filter;
1306 * a postdissector wants field values or protocols
1307 * on the first pass.
1309 create_proto_tree =
1310 (cf->rfcode != NULL || postdissectors_want_hfids());
1312 /* We're not going to display the protocol tree on this pass,
1313 so it's not going to be "visible". */
1314 edt = epan_dissect_new(cf->epan, create_proto_tree, FALSE);
1316 while (local_wtap_read(cf, &file_rec, &err, &err_info, &data_offset, &raw_data)) {
1317 if (process_packet_first_pass(cf, edt, data_offset, &file_rec, raw_data)) {
1319 /* Stop reading if we have the maximum number of packets;
1320 * When the -c option has not been used, max_packet_count
1321 * starts at 0, which practically means, never stop reading.
1322 * (unless we roll over max_packet_count ?)
1324 if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
1325 err = 0; /* This is not an error */
1326 break;
1331 if (edt) {
1332 epan_dissect_free(edt);
1333 edt = NULL;
1336 #if 0
1337 /* Close the sequential I/O side, to free up memory it requires. */
1338 wtap_sequential_close(cf->provider.wth);
1339 #endif
1341 /* Allow the protocol dissectors to free up memory that they
1342 * don't need after the sequential run-through of the packets. */
1343 postseq_cleanup_all_protocols();
1345 cf->provider.prev_dis = NULL;
1346 cf->provider.prev_cap = NULL;
1347 ws_buffer_init(&buf, 1514);
1349 if (do_dissection) {
1350 gboolean create_proto_tree;
1353 * Determine whether we need to create a protocol tree.
1354 * We do if:
1356 * we're going to apply a display filter;
1358 * we're going to print the protocol tree;
1360 * one of the tap listeners requires a protocol tree;
1362 * we have custom columns (which require field values, which
1363 * currently requires that we build a protocol tree).
1365 create_proto_tree =
1366 (cf->dfcode || print_details || filtering_tap_listeners ||
1367 (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo));
1369 /* The protocol tree will be "visible", i.e., printed, only if we're
1370 printing packet details, which is true if we're printing stuff
1371 ("print_packet_info" is true) and we're in verbose mode
1372 ("packet_details" is true). */
1373 edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details);
1376 for (framenum = 1; err == 0 && framenum <= cf->count; framenum++) {
1377 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1378 #if 0
1379 if (wtap_seek_read(cf->provider.wth, fdata->file_off,
1380 &buf, fdata->cap_len, &err, &err_info)) {
1381 process_packet_second_pass(cf, edt, fdata, &cf->rec, &buf, tap_flags);
1383 #else
1384 if (!process_packet_second_pass(cf, edt, fdata, &cf->rec, &buf,
1385 tap_flags))
1386 return FALSE;
1387 #endif
1390 if (edt) {
1391 epan_dissect_free(edt);
1392 edt = NULL;
1395 ws_buffer_free(&buf);
1397 else {
1398 framenum = 0;
1400 if (do_dissection) {
1401 gboolean create_proto_tree;
1404 * Determine whether we need to create a protocol tree.
1405 * We do if:
1407 * we're going to apply a read filter;
1409 * we're going to apply a display filter;
1411 * we're going to print the protocol tree;
1413 * one of the tap listeners is going to apply a filter;
1415 * one of the tap listeners requires a protocol tree;
1417 * a postdissector wants field values or protocols
1418 * on the first pass;
1420 * we have custom columns (which require field values, which
1421 * currently requires that we build a protocol tree).
1423 create_proto_tree =
1424 (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners ||
1425 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids() ||
1426 have_custom_cols(&cf->cinfo));
1428 /* The protocol tree will be "visible", i.e., printed, only if we're
1429 printing packet details, which is true if we're printing stuff
1430 ("print_packet_info" is true) and we're in verbose mode
1431 ("packet_details" is true). */
1432 edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details);
1435 while (local_wtap_read(cf, &file_rec, &err, &err_info, &data_offset, &raw_data)) {
1437 framenum++;
1439 if (!process_packet_single_pass(cf, edt, data_offset,
1440 &file_rec/*wtap_get_rec(cf->provider.wth)*/,
1441 raw_data, tap_flags))
1442 return FALSE;
1444 /* Stop reading if we have the maximum number of packets;
1445 * When the -c option has not been used, max_packet_count
1446 * starts at 0, which practically means, never stop reading.
1447 * (unless we roll over max_packet_count ?)
1449 if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
1450 err = 0; /* This is not an error */
1451 break;
1455 if (edt) {
1456 epan_dissect_free(edt);
1457 edt = NULL;
1461 wtap_rec_cleanup(&file_rec);
1463 if (err != 0) {
1465 * Print a message noting that the read failed somewhere along the line.
1467 * If we're printing packet data, and the standard output and error are
1468 * going to the same place, flush the standard output, so everything
1469 * buffered up is written, and then print a newline to the standard error
1470 * before printing the error message, to separate it from the packet
1471 * data. (Alas, that only works on UN*X; st_dev is meaningless, and
1472 * the _fstat() documentation at Microsoft doesn't indicate whether
1473 * st_ino is even supported.)
1475 #ifndef _WIN32
1476 if (print_packet_info) {
1477 ws_statb64 stat_stdout, stat_stderr;
1479 if (ws_fstat64(1, &stat_stdout) == 0 && ws_fstat64(2, &stat_stderr) == 0) {
1480 if (stat_stdout.st_dev == stat_stderr.st_dev &&
1481 stat_stdout.st_ino == stat_stderr.st_ino) {
1482 fflush(stdout);
1483 fprintf(stderr, "\n");
1487 #endif
1488 #if 0
1489 switch (err) {
1491 case FTAP_ERR_UNSUPPORTED:
1492 cmdarg_err("The file \"%s\" contains record data that TFShark doesn't support.\n(%s)",
1493 cf->filename, err_info);
1494 g_free(err_info);
1495 break;
1497 case FTAP_ERR_UNSUPPORTED_ENCAP:
1498 cmdarg_err("The file \"%s\" has a packet with a network type that TFShark doesn't support.\n(%s)",
1499 cf->filename, err_info);
1500 g_free(err_info);
1501 break;
1503 case FTAP_ERR_CANT_READ:
1504 cmdarg_err("An attempt to read from the file \"%s\" failed for some unknown reason.",
1505 cf->filename);
1506 break;
1508 case FTAP_ERR_SHORT_READ:
1509 cmdarg_err("The file \"%s\" appears to have been cut short in the middle of a packet.",
1510 cf->filename);
1511 break;
1513 case FTAP_ERR_BAD_FILE:
1514 cmdarg_err("The file \"%s\" appears to be damaged or corrupt.\n(%s)",
1515 cf->filename, err_info);
1516 g_free(err_info);
1517 break;
1519 case FTAP_ERR_DECOMPRESS:
1520 cmdarg_err("The compressed file \"%s\" appears to be damaged or corrupt.\n"
1521 "(%s)", cf->filename, err_info);
1522 break;
1524 default:
1525 cmdarg_err("An error occurred while reading the file \"%s\": %s.",
1526 cf->filename, ftap_strerror(err));
1527 break;
1529 #endif
1530 } else {
1531 if (print_packet_info) {
1532 if (!write_finale()) {
1533 err = errno;
1534 show_print_file_io_error(err);
1539 out:
1540 wtap_close(cf->provider.wth);
1541 cf->provider.wth = NULL;
1543 return (err != 0);
1546 static gboolean
1547 process_packet_single_pass(capture_file *cf, epan_dissect_t *edt, gint64 offset,
1548 wtap_rec *rec, const guchar *pd,
1549 guint tap_flags)
1551 frame_data fdata;
1552 column_info *cinfo;
1553 gboolean passed;
1555 /* Count this packet. */
1556 cf->count++;
1558 /* If we're not running a display filter and we're not printing any
1559 packet information, we don't need to do a dissection. This means
1560 that all packets can be marked as 'passed'. */
1561 passed = TRUE;
1563 frame_data_init(&fdata, cf->count, rec, offset, cum_bytes);
1565 /* If we're going to print packet information, or we're going to
1566 run a read filter, or we're going to process taps, set up to
1567 do a dissection and do so. */
1568 if (edt) {
1569 /* If we're running a filter, prime the epan_dissect_t with that
1570 filter. */
1571 if (cf->dfcode)
1572 epan_dissect_prime_with_dfilter(edt, cf->dfcode);
1574 col_custom_prime_edt(edt, &cf->cinfo);
1576 /* We only need the columns if either
1577 1) some tap needs the columns
1579 2) we're printing packet info but we're *not* verbose; in verbose
1580 mode, we print the protocol tree, not the protocol summary.
1582 3) there is a column mapped as an individual field */
1583 if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary) || output_fields_has_cols(output_fields))
1584 cinfo = &cf->cinfo;
1585 else
1586 cinfo = NULL;
1588 frame_data_set_before_dissect(&fdata, &cf->elapsed_time,
1589 &cf->provider.ref, cf->provider.prev_dis);
1590 if (cf->provider.ref == &fdata) {
1591 ref_frame = fdata;
1592 cf->provider.ref = &ref_frame;
1595 epan_dissect_file_run_with_taps(edt, rec,
1596 frame_tvbuff_new(&cf->provider, &fdata, pd),
1597 &fdata, cinfo);
1599 /* Run the filter if we have it. */
1600 if (cf->dfcode)
1601 passed = dfilter_apply_edt(cf->dfcode, edt);
1604 if (passed) {
1605 frame_data_set_after_dissect(&fdata, &cum_bytes);
1607 /* Process this packet. */
1608 if (print_packet_info) {
1609 /* We're printing packet information; print the information for
1610 this packet. */
1611 print_packet(cf, edt);
1613 /* If we're doing "line-buffering", flush the standard output
1614 after every packet. See the comment above, for the "-l"
1615 option, for an explanation of why we do that. */
1616 if (line_buffered)
1617 fflush(stdout);
1619 if (ferror(stdout)) {
1620 show_print_file_io_error(errno);
1621 return FALSE;
1625 /* this must be set after print_packet() [bug #8160] */
1626 prev_dis_frame = fdata;
1627 cf->provider.prev_dis = &prev_dis_frame;
1630 prev_cap_frame = fdata;
1631 cf->provider.prev_cap = &prev_cap_frame;
1633 if (edt) {
1634 epan_dissect_reset(edt);
1635 frame_data_destroy(&fdata);
1637 return passed;
1640 static gboolean
1641 write_preamble(capture_file *cf)
1643 switch (output_action) {
1645 case WRITE_TEXT:
1646 return print_preamble(print_stream, cf->filename, get_ws_vcs_version_info());
1648 case WRITE_XML:
1649 if (print_details)
1650 write_pdml_preamble(stdout, cf->filename);
1651 else
1652 write_psml_preamble(&cf->cinfo, stdout);
1653 return !ferror(stdout);
1655 case WRITE_FIELDS:
1656 write_fields_preamble(output_fields, stdout);
1657 return !ferror(stdout);
1659 default:
1660 g_assert_not_reached();
1661 return FALSE;
1665 static char *
1666 get_line_buf(size_t len)
1668 static char *line_bufp = NULL;
1669 static size_t line_buf_len = 256;
1670 size_t new_line_buf_len;
1672 for (new_line_buf_len = line_buf_len; len > new_line_buf_len;
1673 new_line_buf_len *= 2)
1675 if (line_bufp == NULL) {
1676 line_buf_len = new_line_buf_len;
1677 line_bufp = (char *)g_malloc(line_buf_len + 1);
1678 } else {
1679 if (new_line_buf_len > line_buf_len) {
1680 line_buf_len = new_line_buf_len;
1681 line_bufp = (char *)g_realloc(line_bufp, line_buf_len + 1);
1684 return line_bufp;
1687 static inline void
1688 put_string(char *dest, const char *str, size_t str_len)
1690 memcpy(dest, str, str_len);
1691 dest[str_len] = '\0';
1694 static inline void
1695 put_spaces_string(char *dest, const char *str, size_t str_len, size_t str_with_spaces)
1697 size_t i;
1699 for (i = str_len; i < str_with_spaces; i++)
1700 *dest++ = ' ';
1702 put_string(dest, str, str_len);
1705 static inline void
1706 put_string_spaces(char *dest, const char *str, size_t str_len, size_t str_with_spaces)
1708 size_t i;
1710 memcpy(dest, str, str_len);
1711 for (i = str_len; i < str_with_spaces; i++)
1712 dest[i] = ' ';
1714 dest[str_with_spaces] = '\0';
1717 static gboolean
1718 print_columns(capture_file *cf)
1720 char *line_bufp;
1721 int i;
1722 size_t buf_offset;
1723 size_t column_len;
1724 size_t col_len;
1725 col_item_t* col_item;
1727 line_bufp = get_line_buf(256);
1728 buf_offset = 0;
1729 *line_bufp = '\0';
1730 for (i = 0; i < cf->cinfo.num_cols; i++) {
1731 col_item = &cf->cinfo.columns[i];
1732 /* Skip columns not marked as visible. */
1733 if (!get_column_visible(i))
1734 continue;
1735 switch (col_item->col_fmt) {
1736 case COL_NUMBER:
1737 column_len = col_len = strlen(col_item->col_data);
1738 if (column_len < 3)
1739 column_len = 3;
1740 line_bufp = get_line_buf(buf_offset + column_len);
1741 put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1742 break;
1744 case COL_CLS_TIME:
1745 case COL_REL_TIME:
1746 case COL_ABS_TIME:
1747 case COL_ABS_YMD_TIME: /* XXX - wider */
1748 case COL_ABS_YDOY_TIME: /* XXX - wider */
1749 case COL_UTC_TIME:
1750 case COL_UTC_YMD_TIME: /* XXX - wider */
1751 case COL_UTC_YDOY_TIME: /* XXX - wider */
1752 column_len = col_len = strlen(col_item->col_data);
1753 if (column_len < 10)
1754 column_len = 10;
1755 line_bufp = get_line_buf(buf_offset + column_len);
1756 put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1757 break;
1759 case COL_DEF_SRC:
1760 case COL_RES_SRC:
1761 case COL_UNRES_SRC:
1762 case COL_DEF_DL_SRC:
1763 case COL_RES_DL_SRC:
1764 case COL_UNRES_DL_SRC:
1765 case COL_DEF_NET_SRC:
1766 case COL_RES_NET_SRC:
1767 case COL_UNRES_NET_SRC:
1768 column_len = col_len = strlen(col_item->col_data);
1769 if (column_len < 12)
1770 column_len = 12;
1771 line_bufp = get_line_buf(buf_offset + column_len);
1772 put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1773 break;
1775 case COL_DEF_DST:
1776 case COL_RES_DST:
1777 case COL_UNRES_DST:
1778 case COL_DEF_DL_DST:
1779 case COL_RES_DL_DST:
1780 case COL_UNRES_DL_DST:
1781 case COL_DEF_NET_DST:
1782 case COL_RES_NET_DST:
1783 case COL_UNRES_NET_DST:
1784 column_len = col_len = strlen(col_item->col_data);
1785 if (column_len < 12)
1786 column_len = 12;
1787 line_bufp = get_line_buf(buf_offset + column_len);
1788 put_string_spaces(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1789 break;
1791 default:
1792 column_len = strlen(col_item->col_data);
1793 line_bufp = get_line_buf(buf_offset + column_len);
1794 put_string(line_bufp + buf_offset, col_item->col_data, column_len);
1795 break;
1797 buf_offset += column_len;
1798 if (i != cf->cinfo.num_cols - 1) {
1800 * This isn't the last column, so we need to print a
1801 * separator between this column and the next.
1803 * If we printed a network source and are printing a
1804 * network destination of the same type next, separate
1805 * them with " -> "; if we printed a network destination
1806 * and are printing a network source of the same type
1807 * next, separate them with " <- "; otherwise separate them
1808 * with a space.
1810 * We add enough space to the buffer for " <- " or " -> ",
1811 * even if we're only adding " ".
1813 line_bufp = get_line_buf(buf_offset + 4);
1814 switch (col_item->col_fmt) {
1816 case COL_DEF_SRC:
1817 case COL_RES_SRC:
1818 case COL_UNRES_SRC:
1819 switch (cf->cinfo.columns[i+1].col_fmt) {
1821 case COL_DEF_DST:
1822 case COL_RES_DST:
1823 case COL_UNRES_DST:
1824 put_string(line_bufp + buf_offset, " -> ", 4);
1825 buf_offset += 4;
1826 break;
1828 default:
1829 put_string(line_bufp + buf_offset, " ", 1);
1830 buf_offset += 1;
1831 break;
1833 break;
1835 case COL_DEF_DL_SRC:
1836 case COL_RES_DL_SRC:
1837 case COL_UNRES_DL_SRC:
1838 switch (cf->cinfo.columns[i+1].col_fmt) {
1840 case COL_DEF_DL_DST:
1841 case COL_RES_DL_DST:
1842 case COL_UNRES_DL_DST:
1843 put_string(line_bufp + buf_offset, " -> ", 4);
1844 buf_offset += 4;
1845 break;
1847 default:
1848 put_string(line_bufp + buf_offset, " ", 1);
1849 buf_offset += 1;
1850 break;
1852 break;
1854 case COL_DEF_NET_SRC:
1855 case COL_RES_NET_SRC:
1856 case COL_UNRES_NET_SRC:
1857 switch (cf->cinfo.columns[i+1].col_fmt) {
1859 case COL_DEF_NET_DST:
1860 case COL_RES_NET_DST:
1861 case COL_UNRES_NET_DST:
1862 put_string(line_bufp + buf_offset, " -> ", 4);
1863 buf_offset += 4;
1864 break;
1866 default:
1867 put_string(line_bufp + buf_offset, " ", 1);
1868 buf_offset += 1;
1869 break;
1871 break;
1873 case COL_DEF_DST:
1874 case COL_RES_DST:
1875 case COL_UNRES_DST:
1876 switch (cf->cinfo.columns[i+1].col_fmt) {
1878 case COL_DEF_SRC:
1879 case COL_RES_SRC:
1880 case COL_UNRES_SRC:
1881 put_string(line_bufp + buf_offset, " <- ", 4);
1882 buf_offset += 4;
1883 break;
1885 default:
1886 put_string(line_bufp + buf_offset, " ", 1);
1887 buf_offset += 1;
1888 break;
1890 break;
1892 case COL_DEF_DL_DST:
1893 case COL_RES_DL_DST:
1894 case COL_UNRES_DL_DST:
1895 switch (cf->cinfo.columns[i+1].col_fmt) {
1897 case COL_DEF_DL_SRC:
1898 case COL_RES_DL_SRC:
1899 case COL_UNRES_DL_SRC:
1900 put_string(line_bufp + buf_offset, " <- ", 4);
1901 buf_offset += 4;
1902 break;
1904 default:
1905 put_string(line_bufp + buf_offset, " ", 1);
1906 buf_offset += 1;
1907 break;
1909 break;
1911 case COL_DEF_NET_DST:
1912 case COL_RES_NET_DST:
1913 case COL_UNRES_NET_DST:
1914 switch (cf->cinfo.columns[i+1].col_fmt) {
1916 case COL_DEF_NET_SRC:
1917 case COL_RES_NET_SRC:
1918 case COL_UNRES_NET_SRC:
1919 put_string(line_bufp + buf_offset, " <- ", 4);
1920 buf_offset += 4;
1921 break;
1923 default:
1924 put_string(line_bufp + buf_offset, " ", 1);
1925 buf_offset += 1;
1926 break;
1928 break;
1930 default:
1931 put_string(line_bufp + buf_offset, " ", 1);
1932 buf_offset += 1;
1933 break;
1937 return print_line(print_stream, 0, line_bufp);
1940 static gboolean
1941 print_packet(capture_file *cf, epan_dissect_t *edt)
1943 if (print_summary || output_fields_has_cols(output_fields)) {
1944 /* Just fill in the columns. */
1945 epan_dissect_fill_in_columns(edt, FALSE, TRUE);
1947 if (print_summary) {
1948 /* Now print them. */
1949 switch (output_action) {
1951 case WRITE_TEXT:
1952 if (!print_columns(cf))
1953 return FALSE;
1954 break;
1956 case WRITE_XML:
1957 write_psml_columns(edt, stdout, FALSE);
1958 return !ferror(stdout);
1959 case WRITE_FIELDS: /*No non-verbose "fields" format */
1960 g_assert_not_reached();
1961 break;
1965 if (print_details) {
1966 /* Print the information in the protocol tree. */
1967 switch (output_action) {
1969 case WRITE_TEXT:
1970 if (!proto_tree_print(print_details ? print_dissections_expanded : print_dissections_none,
1971 print_hex, edt, output_only_tables, print_stream))
1972 return FALSE;
1973 if (!print_hex) {
1974 if (!print_line(print_stream, 0, separator))
1975 return FALSE;
1977 break;
1979 case WRITE_XML:
1980 write_pdml_proto_tree(NULL, NULL, PF_NONE, edt, &cf->cinfo, stdout, FALSE);
1981 printf("\n");
1982 return !ferror(stdout);
1983 case WRITE_FIELDS:
1984 write_fields_proto_tree(output_fields, edt, &cf->cinfo, stdout);
1985 printf("\n");
1986 return !ferror(stdout);
1989 if (print_hex) {
1990 if (print_summary || print_details) {
1991 if (!print_line(print_stream, 0, ""))
1992 return FALSE;
1994 if (!print_hex_data(print_stream, edt))
1995 return FALSE;
1996 if (!print_line(print_stream, 0, separator))
1997 return FALSE;
1999 return TRUE;
2002 static gboolean
2003 write_finale(void)
2005 switch (output_action) {
2007 case WRITE_TEXT:
2008 return print_finale(print_stream);
2010 case WRITE_XML:
2011 if (print_details)
2012 write_pdml_finale(stdout);
2013 else
2014 write_psml_finale(stdout);
2015 return !ferror(stdout);
2017 case WRITE_FIELDS:
2018 write_fields_finale(output_fields, stdout);
2019 return !ferror(stdout);
2021 default:
2022 g_assert_not_reached();
2023 return FALSE;
2027 cf_status_t
2028 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
2030 gchar *err_info;
2031 char err_msg[2048+1];
2033 /* The open isn't implemented yet. Fill in the information for this file. */
2035 /* Create new epan session for dissection. */
2036 epan_free(cf->epan);
2037 cf->epan = tfshark_epan_new(cf);
2039 cf->provider.wth = NULL; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2040 cf->f_datalen = 0; /* not used, but set it anyway */
2042 /* Set the file name because we need it to set the follow stream filter.
2043 XXX - is that still true? We need it for other reasons, though,
2044 in any case. */
2045 cf->filename = g_strdup(fname);
2047 /* Indicate whether it's a permanent or temporary file. */
2048 cf->is_tempfile = is_tempfile;
2050 /* No user changes yet. */
2051 cf->unsaved_changes = FALSE;
2053 cf->cd_t = 0; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2054 cf->open_type = type;
2055 cf->count = 0;
2056 cf->drops_known = FALSE;
2057 cf->drops = 0;
2058 cf->snap = 0; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2059 nstime_set_zero(&cf->elapsed_time);
2060 cf->provider.ref = NULL;
2061 cf->provider.prev_dis = NULL;
2062 cf->provider.prev_cap = NULL;
2064 cf->state = FILE_READ_IN_PROGRESS;
2066 return CF_OK;
2068 /* fail: */
2069 g_snprintf(err_msg, sizeof err_msg,
2070 cf_open_error_message(*err, err_info, FALSE, cf->cd_t), fname);
2071 cmdarg_err("%s", err_msg);
2072 return CF_ERROR;
2075 static void
2076 show_print_file_io_error(int err)
2078 switch (err) {
2080 case ENOSPC:
2081 cmdarg_err("Not all the packets could be printed because there is "
2082 "no space left on the file system.");
2083 break;
2085 #ifdef EDQUOT
2086 case EDQUOT:
2087 cmdarg_err("Not all the packets could be printed because you are "
2088 "too close to, or over your disk quota.");
2089 break;
2090 #endif
2092 default:
2093 cmdarg_err("An error occurred while printing packets: %s.",
2094 g_strerror(err));
2095 break;
2099 static const char *
2100 cf_open_error_message(int err, gchar *err_info _U_, gboolean for_writing,
2101 int file_type _U_)
2103 const char *errmsg;
2104 /* static char errmsg_errno[1024+1]; */
2106 #if 0
2107 if (err < 0) {
2108 /* Wiretap error. */
2109 switch (err) {
2111 case FTAP_ERR_NOT_REGULAR_FILE:
2112 errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
2113 break;
2115 case FTAP_ERR_RANDOM_OPEN_PIPE:
2116 /* Seen only when opening a capture file for reading. */
2117 errmsg = "The file \"%s\" is a pipe or FIFO; TFShark can't read pipe or FIFO files in two-pass mode.";
2118 break;
2120 case FTAP_ERR_FILE_UNKNOWN_FORMAT:
2121 /* Seen only when opening a capture file for reading. */
2122 errmsg = "The file \"%s\" isn't a capture file in a format TFShark understands.";
2123 break;
2125 case FTAP_ERR_UNSUPPORTED:
2126 /* Seen only when opening a capture file for reading. */
2127 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2128 "The file \"%%s\" isn't a capture file in a format TFShark understands.\n"
2129 "(%s)", err_info);
2130 g_free(err_info);
2131 errmsg = errmsg_errno;
2132 break;
2134 case FTAP_ERR_CANT_WRITE_TO_PIPE:
2135 /* Seen only when opening a capture file for writing. */
2136 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2137 "The file \"%%s\" is a pipe, and \"%s\" capture files can't be "
2138 "written to a pipe.", ftap_file_type_subtype_short_string(file_type));
2139 errmsg = errmsg_errno;
2140 break;
2142 case FTAP_ERR_UNSUPPORTED_FILE_TYPE:
2143 /* Seen only when opening a capture file for writing. */
2144 errmsg = "TFShark doesn't support writing capture files in that format.";
2145 break;
2147 case FTAP_ERR_UNSUPPORTED_ENCAP:
2148 if (for_writing) {
2149 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2150 "TFShark can't save this capture as a \"%s\" file.",
2151 ftap_file_type_subtype_short_string(file_type));
2152 } else {
2153 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2154 "The file \"%%s\" is a capture for a network type that TFShark doesn't support.\n"
2155 "(%s)", err_info);
2156 g_free(err_info);
2158 errmsg = errmsg_errno;
2159 break;
2161 case FTAP_ERR_ENCAP_PER_RECORD_UNSUPPORTED:
2162 if (for_writing) {
2163 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2164 "TFShark can't save this capture as a \"%s\" file.",
2165 ftap_file_type_subtype_short_string(file_type));
2166 errmsg = errmsg_errno;
2167 } else
2168 errmsg = "The file \"%s\" is a capture for a network type that TFShark doesn't support.";
2169 break;
2171 case FTAP_ERR_BAD_FILE:
2172 /* Seen only when opening a capture file for reading. */
2173 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2174 "The file \"%%s\" appears to be damaged or corrupt.\n"
2175 "(%s)", err_info);
2176 g_free(err_info);
2177 errmsg = errmsg_errno;
2178 break;
2180 case FTAP_ERR_CANT_OPEN:
2181 if (for_writing)
2182 errmsg = "The file \"%s\" could not be created for some unknown reason.";
2183 else
2184 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
2185 break;
2187 case FTAP_ERR_SHORT_READ:
2188 errmsg = "The file \"%s\" appears to have been cut short"
2189 " in the middle of a packet or other data.";
2190 break;
2192 case FTAP_ERR_SHORT_WRITE:
2193 errmsg = "A full header couldn't be written to the file \"%s\".";
2194 break;
2196 case FTAP_ERR_COMPRESSION_NOT_SUPPORTED:
2197 errmsg = "This file type cannot be written as a compressed file.";
2198 break;
2200 case FTAP_ERR_DECOMPRESS:
2201 /* Seen only when opening a capture file for reading. */
2202 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2203 "The compressed file \"%%s\" appears to be damaged or corrupt.\n"
2204 "(%s)", err_info);
2205 g_free(err_info);
2206 errmsg = errmsg_errno;
2207 break;
2209 default:
2210 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2211 "The file \"%%s\" could not be %s: %s.",
2212 for_writing ? "created" : "opened",
2213 ftap_strerror(err));
2214 errmsg = errmsg_errno;
2215 break;
2217 } else
2218 #endif
2219 errmsg = file_open_error_message(err, for_writing);
2220 return errmsg;
2224 * General errors and warnings are reported with an console message
2225 * in TFShark.
2227 static void
2228 failure_warning_message(const char *msg_format, va_list ap)
2230 fprintf(stderr, "tfshark: ");
2231 vfprintf(stderr, msg_format, ap);
2232 fprintf(stderr, "\n");
2236 * Open/create errors are reported with an console message in TFShark.
2238 static void
2239 open_failure_message(const char *filename, int err, gboolean for_writing)
2241 fprintf(stderr, "tfshark: ");
2242 fprintf(stderr, file_open_error_message(err, for_writing), filename);
2243 fprintf(stderr, "\n");
2247 * Read errors are reported with an console message in TFShark.
2249 static void
2250 read_failure_message(const char *filename, int err)
2252 cmdarg_err("An error occurred while reading from the file \"%s\": %s.",
2253 filename, g_strerror(err));
2257 * Write errors are reported with an console message in TFShark.
2259 static void
2260 write_failure_message(const char *filename, int err)
2262 cmdarg_err("An error occurred while writing to the file \"%s\": %s.",
2263 filename, g_strerror(err));
2267 * Report additional information for an error in command-line arguments.
2269 static void
2270 failure_message_cont(const char *msg_format, va_list ap)
2272 vfprintf(stderr, msg_format, ap);
2273 fprintf(stderr, "\n");
2277 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2279 * Local variables:
2280 * c-basic-offset: 2
2281 * tab-width: 8
2282 * indent-tabs-mode: nil
2283 * End:
2285 * vi: set shiftwidth=2 tabstop=8 expandtab:
2286 * :indentSize=2:tabSize=8:noTabs=true: