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
14 #define WS_LOG_DOMAIN LOG_DOMAIN_MAIN
22 #include <ws_exit_codes.h>
23 #include <wsutil/ws_getopt.h>
29 #include <epan/exceptions.h>
30 #include <epan/epan.h>
32 #include <wsutil/clopts_common.h>
33 #include <wsutil/cmdarg_err.h>
35 #include <wsutil/filesystem.h>
36 #include <wsutil/file_util.h>
37 #include <wsutil/privileges.h>
38 #include <wsutil/wslog.h>
39 #include <wsutil/ws_assert.h>
41 #include <wsutil/version_info.h>
44 #include <epan/timestamp.h>
45 #include <epan/packet.h>
47 #include <epan/wslua/init_wslua.h>
50 #include <epan/disabled_protos.h>
51 #include <epan/prefs.h>
52 #include <epan/column.h>
53 #include <epan/print.h>
54 #include <epan/addr_resolv.h>
56 #include "ui/decode_as_utils.h"
57 #include "ui/dissect_opts.h"
58 #include "ui/failure_message.h"
59 #include <epan/epan_dissect.h>
61 #include <epan/stat_tap_ui.h>
62 #include <epan/ex-opt.h>
64 #include <wiretap/wtap-int.h>
65 #include <wiretap/file_wrappers.h>
67 #include <epan/funnel.h>
70 #include <wsutil/plugins.h>
73 /* Additional exit codes */
74 #define NO_FILE_SPECIFIED 1
78 static uint32_t cum_bytes
;
79 static frame_data ref_frame
;
80 static frame_data prev_dis_frame
;
81 static frame_data prev_cap_frame
;
83 static bool prefs_loaded
;
85 static bool perform_two_pass_analysis
;
88 * The way the packet decode is to be written.
91 WRITE_TEXT
, /* summary or detail text */
92 WRITE_XML
, /* PDML or PSML */
93 WRITE_FIELDS
/* User defined list of fields */
94 /* Add CSV and the like here */
97 static output_action_e output_action
;
98 static bool do_dissection
; /* true if we have to dissect each packet */
99 static bool print_packet_info
; /* true if we're to print packet information */
100 static int print_summary
= -1; /* true if we're to print packet summary information */
101 static bool print_details
; /* true if we're to print packet details information */
102 static bool print_hex
; /* true if we're to print hex/ascii information */
103 static bool line_buffered
;
104 static bool really_quiet
;
106 static print_format_e print_format
= PR_FMT_TEXT
;
107 static print_stream_t
*print_stream
;
109 static output_fields_t
* output_fields
;
111 /* The line separator used between packets, changeable via the -S option */
112 static const char *separator
= "";
114 static bool process_file(capture_file
*, int, int64_t);
115 static bool process_packet_single_pass(capture_file
*cf
,
116 epan_dissect_t
*edt
, int64_t offset
, wtap_rec
*rec
,
117 const unsigned char *pd
);
118 static void show_print_file_io_error(int err
);
119 static bool write_preamble(capture_file
*cf
);
120 static bool print_packet(capture_file
*cf
, epan_dissect_t
*edt
);
121 static bool write_finale(void);
123 static GHashTable
*output_only_tables
;
127 const char *sstr
; /* The short string */
128 const char *lstr
; /* The long string */
132 string_compare(const void *a
, const void *b
)
134 return strcmp(((const struct string_elem
*)a
)->sstr
,
135 ((const struct string_elem
*)b
)->sstr
);
139 string_elem_print(void *data
, void *not_used _U_
)
141 fprintf(stderr
, " %s - %s\n",
142 ((struct string_elem
*)data
)->sstr
,
143 ((struct string_elem
*)data
)->lstr
);
148 print_usage(FILE *output
)
150 fprintf(output
, "\n");
151 fprintf(output
, "Usage: tfshark [options] ...\n");
152 fprintf(output
, "\n");
154 /*fprintf(output, "\n");*/
155 fprintf(output
, "Input file:\n");
156 fprintf(output
, " -r <infile> set the filename to read from (no pipes or stdin)\n");
158 fprintf(output
, "\n");
159 fprintf(output
, "Processing:\n");
160 fprintf(output
, " -2 perform a two-pass analysis\n");
161 fprintf(output
, " -R <read filter> packet Read filter in Wireshark display filter syntax\n");
162 fprintf(output
, " (requires -2)\n");
163 fprintf(output
, " -Y <display filter> packet displaY filter in Wireshark display filter\n");
164 fprintf(output
, " syntax\n");
165 fprintf(output
, " -d %s ...\n", DECODE_AS_ARG_TEMPLATE
);
166 fprintf(output
, " \"Decode As\", see the man page for details\n");
167 fprintf(output
, " Example: tcp.port==8888,http\n");
169 /*fprintf(output, "\n");*/
170 fprintf(output
, "Output:\n");
171 fprintf(output
, " -C <config profile> start with specified configuration profile\n");
172 fprintf(output
, " -V add output of packet tree (Packet Details)\n");
173 fprintf(output
, " -O <protocols> Only show packet details of these protocols, comma\n");
174 fprintf(output
, " separated\n");
175 fprintf(output
, " -S <separator> the line separator to print between packets\n");
176 fprintf(output
, " -x add output of hex and ASCII dump (Packet Bytes)\n");
177 fprintf(output
, " -T pdml|ps|psml|text|fields\n");
178 fprintf(output
, " format of text output (def: text)\n");
179 fprintf(output
, " -e <field> field to print if -Tfields selected (e.g. tcp.port,\n");
180 fprintf(output
, " _ws.col.info)\n");
181 fprintf(output
, " this option can be repeated to print multiple fields\n");
182 fprintf(output
, " -E<fieldsoption>=<value> set options for output when -Tfields selected:\n");
183 fprintf(output
, " header=y|n switch headers on and off\n");
184 fprintf(output
, " separator=/t|/s|<char> select tab, space, printable character as separator\n");
185 fprintf(output
, " occurrence=f|l|a print first, last or all occurrences of each field\n");
186 fprintf(output
, " aggregator=,|/s|<char> select comma, space, printable character as\n");
187 fprintf(output
, " aggregator\n");
188 fprintf(output
, " quote=d|s|n select double, single, no quotes for values\n");
189 fprintf(output
, " -t a|ad|d|dd|e|r|u|ud output format of time stamps (def: r: rel. to first)\n");
190 fprintf(output
, " -u s|hms output format of seconds (def: s: seconds)\n");
191 fprintf(output
, " -l flush standard output after each packet\n");
192 fprintf(output
, " -q be more quiet on stdout (e.g. when using statistics)\n");
193 fprintf(output
, " -Q only log true errors to stderr (quieter than -q)\n");
194 fprintf(output
, " -X <key>:<value> eXtension options, see the man page for details\n");
195 fprintf(output
, " -z <statistics> various statistics, see the man page for details\n");
196 fprintf(output
, "\n");
198 ws_log_print_usage(output
);
199 fprintf(output
, "\n");
201 fprintf(output
, "Miscellaneous:\n");
202 fprintf(output
, " -h display this help and exit\n");
203 fprintf(output
, " -v display version info and exit\n");
204 fprintf(output
, " -o <name>:<value> ... override preference setting\n");
205 fprintf(output
, " -K <keytab> keytab file to use for kerberos decryption\n");
206 fprintf(output
, " -G [report] dump one of several available reports and exit\n");
207 fprintf(output
, " default report=\"fields\"\n");
208 fprintf(output
, " use \"-G ?\" for more help\n");
212 glossary_option_help(void)
218 fprintf(output
, "%s\n", get_appname_and_version());
220 fprintf(output
, "\n");
221 fprintf(output
, "Usage: tfshark -G [report]\n");
222 fprintf(output
, "\n");
223 fprintf(output
, "Glossary table reports:\n");
224 fprintf(output
, " -G column-formats dump column format codes and exit\n");
225 fprintf(output
, " -G decodes dump \"layer type\"/\"decode as\" associations and exit\n");
226 fprintf(output
, " -G dissector-tables dump dissector table names, types, and properties\n");
227 fprintf(output
, " -G fields dump fields glossary and exit\n");
228 fprintf(output
, " -G ftypes dump field type basic and descriptive names\n");
229 fprintf(output
, " -G heuristic-decodes dump heuristic dissector tables\n");
230 fprintf(output
, " -G plugins dump installed plugins and exit\n");
231 fprintf(output
, " -G protocols dump protocols in registration database and exit\n");
232 fprintf(output
, " -G values dump value, range, true/false strings and exit\n");
233 fprintf(output
, "\n");
234 fprintf(output
, "Preference reports:\n");
235 fprintf(output
, " -G currentprefs dump current preferences and exit\n");
236 fprintf(output
, " -G defaultprefs dump default preferences and exit\n");
237 fprintf(output
, "\n");
241 print_current_user(void)
243 char *cur_user
, *cur_group
;
245 if (started_with_special_privs()) {
246 cur_user
= get_cur_username();
247 cur_group
= get_cur_groupname();
248 fprintf(stderr
, "Running as user \"%s\" and group \"%s\".",
249 cur_user
, cur_group
);
252 if (running_with_special_privs()) {
253 fprintf(stderr
, " This could be dangerous.");
255 fprintf(stderr
, "\n");
260 main(int argc
, char *argv
[])
262 char *configuration_init_error
;
264 static const struct ws_option long_options
[] = {
265 {"help", ws_no_argument
, NULL
, 'h'},
266 {"version", ws_no_argument
, NULL
, 'v'},
269 bool arg_error
= false;
272 volatile bool success
;
273 volatile int exit_status
= 0;
275 char *volatile cf_name
= NULL
;
276 char *rfilter
= NULL
;
277 char *dfilter
= NULL
;
278 dfilter_t
*rfcode
= NULL
;
279 dfilter_t
*dfcode
= NULL
;
282 char *output_only
= NULL
;
285 * The leading + ensures that getopt_long() does not permute the argv[]
288 * We have to make sure that the first getopt_long() preserves the content
289 * of argv[] for the subsequent getopt_long() call.
291 * We use getopt_long() in both cases to ensure that we're using a routine
292 * whose permutation behavior we can control in the same fashion on all
293 * platforms, and so that, if we ever need to process a long argument before
294 * doing further initialization, we can do so.
296 * Glibc and Solaris libc document that a leading + disables permutation
297 * of options, regardless of whether POSIXLY_CORRECT is set or not; *BSD
298 * and macOS don't document it, but do so anyway.
300 * We do *not* use a leading - because the behavior of a leading - is
301 * platform-dependent.
303 #define OPTSTRING "+2C:d:e:E:hK:lo:O:qQr:R:S:t:T:u:vVxX:Y:z:"
305 static const char optstring
[] = OPTSTRING
;
307 /* Set the program name. */
308 g_set_prgname("tfshark");
311 * Set the C-language locale to the native environment and set the
312 * code page to UTF-8 on Windows.
315 setlocale(LC_ALL
, ".UTF-8");
317 setlocale(LC_ALL
, "");
320 cmdarg_err_init(stderr_cmdarg_err
, stderr_cmdarg_err_cont
);
322 /* Initialize log handler early so we can have proper logging during startup. */
323 ws_log_init(vcmdarg_err
);
325 /* Early logging command-line initialization. */
326 ws_log_parse_args(&argc
, argv
, vcmdarg_err
, WS_EXIT_INVALID_OPTION
);
328 ws_noisy("Finished log init and parsing command line log arguments");
331 create_app_running_mutex();
335 * Get credential information for later use, and drop privileges
336 * before doing anything else.
337 * Let the user know if anything happened.
339 init_process_policies();
340 relinquish_special_privs_perm();
341 print_current_user();
344 * Attempt to get the pathname of the directory containing the
347 configuration_init_error
= configuration_init(argv
[0]);
348 if (configuration_init_error
!= NULL
) {
350 "tfshark: Can't get pathname of directory containing the tfshark program: %s.\n",
351 configuration_init_error
);
352 g_free(configuration_init_error
);
355 initialize_funnel_ops();
357 /* Initialize the version information. */
358 ws_init_version_info("TFShark",
359 epan_gather_compile_info
,
360 epan_gather_runtime_info
);
362 * In order to have the -X opts assigned before the wslua machine starts
363 * we need to call getopts before epan_init() gets called.
365 * In order to handle, for example, -o options, we also need to call it
366 * *after* epan_init() gets called, so that the dissectors have had a
367 * chance to register their preferences.
369 * XXX - can we do this all with one getopt_long() call, saving the
370 * arguments we can't handle until after initializing libwireshark,
371 * and then process them after initializing libwireshark?
375 while ((opt
= ws_getopt_long(argc
, argv
, optstring
, long_options
, NULL
)) != -1) {
377 case 'C': /* Configuration Profile */
378 if (profile_exists (ws_optarg
, false)) {
379 set_profile_name (ws_optarg
);
380 } else if (profile_exists (ws_optarg
, true)) {
381 char *pf_dir_path
, *pf_dir_path2
, *pf_filename
;
382 /* Copy from global profile */
383 if (create_persconffile_profile(ws_optarg
, &pf_dir_path
) == -1) {
384 cmdarg_err("Can't create directory\n\"%s\":\n%s.",
385 pf_dir_path
, g_strerror(errno
));
388 exit_status
= WS_EXIT_INVALID_FILE
;
391 if (copy_persconffile_profile(ws_optarg
, ws_optarg
, true, &pf_filename
,
392 &pf_dir_path
, &pf_dir_path2
) == -1) {
393 cmdarg_err("Can't copy file \"%s\" in directory\n\"%s\" to\n\"%s\":\n%s.",
394 pf_filename
, pf_dir_path2
, pf_dir_path
, g_strerror(errno
));
398 g_free(pf_dir_path2
);
399 exit_status
= WS_EXIT_INVALID_FILE
;
402 set_profile_name (ws_optarg
);
404 cmdarg_err("Configuration Profile \"%s\" does not exist", ws_optarg
);
408 case 'O': /* Only output these protocols */
409 output_only
= g_strdup(ws_optarg
);
411 case 'V': /* Verbose */
412 print_details
= true;
413 print_packet_info
= true;
415 case 'x': /* Print packet data in hex (and ASCII) */
417 /* The user asked for hex output, so let's ensure they get it,
418 * even if they're writing to a file.
420 print_packet_info
= true;
423 ex_opt_add(ws_optarg
);
431 * Print packet summary information is the default, unless either -V or -x
432 * were specified. Note that this is new behavior, which
433 * allows for the possibility of printing only hex/ascii output without
434 * necessarily requiring that either the summary or details be printed too.
436 if (print_summary
== -1)
437 print_summary
= (print_details
|| print_hex
) ? false : true;
439 init_report_failure_message("tfshark");
441 timestamp_set_type(TS_RELATIVE
);
442 timestamp_set_precision(TS_PREC_AUTO
);
443 timestamp_set_seconds_type(TS_SECONDS_DEFAULT
);
446 * Libwiretap must be initialized before libwireshark is, so that
447 * dissection-time handlers for file-type-dependent blocks can
448 * register using the file type/subtype value for the file type.
450 * XXX - TFShark shouldn't use libwiretap, as it's a file dissector
451 * and should read all files as raw bytes and then try to dissect them.
452 * It needs to handle file types its own way, because we would want
453 * to support dissecting file-type-specific blocks when dissecting
454 * capture files, but that mechanism should support plugins for
455 * other files, too, if *their* formats are extensible.
459 /* Register all dissectors; we must do this before checking for the
460 "-G" flag, as the "-G" flag dumps information registered by the
461 dissectors, and we must do it before we read the preferences, in
462 case any dissectors register preferences. */
463 if (!epan_init(NULL
, NULL
, true)) {
464 exit_status
= WS_EXIT_INIT_FAILED
;
468 /* Register all tap listeners; we do this before we parse the arguments,
469 as the "-z" argument can specify a registered tap. */
471 /* we register the plugin taps before the other taps because
472 stats_tree taps plugins will be registered as tap listeners
473 by stats_tree_stat.c and need to registered before that */
475 /* XXX Disable tap registration for now until we can get tfshark set up with
476 * its own set of taps and the necessary registration function etc.
477 register_all_tap_listeners();
480 /* If invoked with the "-G" flag, we dump out information based on
481 the argument to the "-G" flag; if no argument is specified,
482 for backwards compatibility we dump out a glossary of display
485 XXX - we do this here, for now, to support "-G" with no arguments.
486 If none of our build or other processes uses "-G" with no arguments,
487 we can just process it with the other arguments. */
488 if (argc
>= 2 && strcmp(argv
[1], "-G") == 0) {
489 proto_initialize_all_prefixes();
492 proto_registrar_dump_fields();
494 if (strcmp(argv
[2], "column-formats") == 0)
495 column_dump_column_formats();
496 else if (strcmp(argv
[2], "currentprefs") == 0) {
497 epan_load_settings();
500 else if (strcmp(argv
[2], "decodes") == 0)
501 dissector_dump_decodes();
502 else if (strcmp(argv
[2], "defaultprefs") == 0)
504 else if (strcmp(argv
[2], "dissector-tables") == 0)
505 dissector_dump_dissector_tables();
506 else if (strcmp(argv
[2], "fields") == 0)
507 proto_registrar_dump_fields();
508 else if (strcmp(argv
[2], "ftypes") == 0)
509 proto_registrar_dump_ftypes();
510 else if (strcmp(argv
[2], "heuristic-decodes") == 0)
511 dissector_dump_heur_decodes();
512 else if (strcmp(argv
[2], "plugins") == 0) {
517 wslua_plugins_dump_all();
520 else if (strcmp(argv
[2], "protocols") == 0)
521 proto_registrar_dump_protocols();
522 else if (strcmp(argv
[2], "values") == 0)
523 proto_registrar_dump_values();
524 else if (strcmp(argv
[2], "?") == 0)
525 glossary_option_help();
526 else if (strcmp(argv
[2], "-?") == 0)
527 glossary_option_help();
529 cmdarg_err("Invalid \"%s\" option for -G flag, enter -G ? for more help.", argv
[2]);
530 exit_status
= WS_EXIT_INVALID_OPTION
;
537 /* Load libwireshark settings from the current profile. */
538 prefs_p
= epan_load_settings();
541 cap_file_init(&cfile
);
543 /* Print format defaults to this. */
544 print_format
= PR_FMT_TEXT
;
546 output_fields
= output_fields_new();
549 * To reset the options parser, set ws_optreset to 1 and set ws_optind to 1.
551 * Also reset ws_opterr to 1, so that error messages are printed by
558 /* Now get our args */
559 while ((opt
= ws_getopt_long(argc
, argv
, optstring
, long_options
, NULL
)) != -1) {
561 case '2': /* Perform two-pass analysis */
562 perform_two_pass_analysis
= true;
565 /* already processed; just ignore it now */
569 output_fields_add(output_fields
, ws_optarg
);
573 if (!output_fields_set_option(output_fields
, ws_optarg
)) {
574 cmdarg_err("\"%s\" is not a valid field output option=value pair.", ws_optarg
);
575 output_fields_list_options(stderr
);
576 exit_status
= WS_EXIT_INVALID_OPTION
;
581 case 'h': /* Print help and exit */
582 show_help_header("Analyze file structure.");
586 case 'l': /* "Line-buffer" standard output */
587 /* The ANSI C standard does not appear to *require* that a
588 line-buffered stream be flushed to the host environment
589 whenever a newline is written, it just says that, on such a
590 stream, characters "are intended to be transmitted to or
591 from the host environment as a block when a new-line
592 character is encountered".
594 The Visual C++ 6.0 C implementation doesn't do what is
595 intended; even if you set a stream to be line-buffered, it
596 still doesn't flush the buffer at the end of every line.
598 The whole reason for the "-l" flag in either tcpdump or
599 TShark is to allow the output of a live capture to be piped
600 to a program or script and to have that script see the
601 information for the packet as soon as it's printed, rather
602 than having to wait until a standard I/O buffer fills up.
604 So, if the "-l" flag is specified, we flush the standard
605 output at the end of a packet. This will do the right thing
606 if we're printing packet summary lines, and, as we print the
607 entire protocol tree for a single packet without waiting for
608 anything to happen, it should be as good as line-buffered
609 mode if we're printing protocol trees - arguably even
610 better, as it may do fewer writes. */
611 line_buffered
= true;
613 case 'o': /* Override preference from command line */
617 switch (prefs_set_pref(ws_optarg
, &errmsg
)) {
622 case PREFS_SET_SYNTAX_ERR
:
623 cmdarg_err("Invalid -o flag \"%s\"%s%s", ws_optarg
,
624 errmsg
? ": " : "", errmsg
? errmsg
: "");
626 exit_status
= WS_EXIT_INVALID_OPTION
;
630 case PREFS_SET_NO_SUCH_PREF
:
631 cmdarg_err("-o flag \"%s\" specifies unknown preference", ws_optarg
);
632 exit_status
= WS_EXIT_INVALID_OPTION
;
636 case PREFS_SET_OBSOLETE
:
637 cmdarg_err("-o flag \"%s\" specifies obsolete preference", ws_optarg
);
638 exit_status
= WS_EXIT_INVALID_OPTION
;
644 case 'q': /* Quiet */
647 case 'Q': /* Really quiet */
651 case 'r': /* Read capture file x */
652 cf_name
= g_strdup(ws_optarg
);
654 case 'R': /* Read file filter */
657 case 'S': /* Set the line Separator to be printed between packets */
658 separator
= g_strdup(ws_optarg
);
660 case 'T': /* printing Type */
661 if (strcmp(ws_optarg
, "text") == 0) {
662 output_action
= WRITE_TEXT
;
663 print_format
= PR_FMT_TEXT
;
664 } else if (strcmp(ws_optarg
, "ps") == 0) {
665 output_action
= WRITE_TEXT
;
666 print_format
= PR_FMT_PS
;
667 } else if (strcmp(ws_optarg
, "pdml") == 0) {
668 output_action
= WRITE_XML
;
669 print_details
= true; /* Need details */
670 print_summary
= false; /* Don't allow summary */
671 } else if (strcmp(ws_optarg
, "psml") == 0) {
672 output_action
= WRITE_XML
;
673 print_details
= false; /* Don't allow details */
674 print_summary
= true; /* Need summary */
675 } else if (strcmp(ws_optarg
, "fields") == 0) {
676 output_action
= WRITE_FIELDS
;
677 print_details
= true; /* Need full tree info */
678 print_summary
= false; /* Don't allow summary */
680 cmdarg_err("Invalid -T parameter \"%s\"; it must be one of:", ws_optarg
); /* x */
681 cmdarg_err_cont("\t\"fields\" The values of fields specified with the -e option, in a form\n"
682 "\t specified by the -E option.\n"
683 "\t\"pdml\" Packet Details Markup Language, an XML-based format for the\n"
684 "\t details of a decoded packet. This information is equivalent to\n"
685 "\t the packet details printed with the -V flag.\n"
686 "\t\"ps\" PostScript for a human-readable one-line summary of each of\n"
687 "\t the packets, or a multi-line view of the details of each of\n"
688 "\t the packets, depending on whether the -V flag was specified.\n"
689 "\t\"psml\" Packet Summary Markup Language, an XML-based format for the\n"
690 "\t summary information of a decoded packet. This information is\n"
691 "\t equivalent to the information shown in the one-line summary\n"
692 "\t printed by default.\n"
693 "\t\"text\" Text of a human-readable one-line summary of each of the\n"
694 "\t packets, or a multi-line view of the details of each of the\n"
695 "\t packets, depending on whether the -V flag was specified.\n"
696 "\t This is the default.");
697 exit_status
= WS_EXIT_INVALID_OPTION
;
701 case 'v': /* Show version and exit */
704 case 'O': /* Only output these protocols */
705 /* already processed; just ignore it now */
707 case 'V': /* Verbose */
708 /* already processed; just ignore it now */
710 case 'x': /* Print packet data in hex (and ASCII) */
711 /* already processed; just ignore it now */
714 /* already processed; just ignore it now */
720 /* We won't call the init function for the stat this soon
721 as it would disallow MATE's fields (which are registered
722 by the preferences set callback) from being used as
723 part of a tap filter. Instead, we just add the argument
724 to a list of stat arguments. */
725 if (strcmp("help", ws_optarg
) == 0) {
726 fprintf(stderr
, "tfshark: The available statistics for the \"-z\" option are:\n");
727 list_stat_cmd_args();
730 if (!process_stat_cmd_arg(ws_optarg
)) {
731 cmdarg_err("Invalid -z argument \"%s\"; it must be one of:", ws_optarg
);
732 list_stat_cmd_args();
733 exit_status
= WS_EXIT_INVALID_OPTION
;
737 case 'd': /* Decode as rule */
738 case 'K': /* Kerberos keytab file */
739 case 't': /* Time stamp type */
740 case 'u': /* Seconds type */
741 case LONGOPT_DISABLE_PROTOCOL
: /* disable dissection of protocol */
742 case LONGOPT_ENABLE_HEURISTIC
: /* enable heuristic dissection of protocol */
743 case LONGOPT_DISABLE_HEURISTIC
: /* disable heuristic dissection of protocol */
744 case LONGOPT_ENABLE_PROTOCOL
: /* enable dissection of protocol (that is disabled by default) */
745 if (!dissect_opts_handle_opt(opt
, ws_optarg
)) {
746 exit_status
= WS_EXIT_INVALID_OPTION
;
751 case '?': /* Bad flag - print usage message */
753 exit_status
= WS_EXIT_INVALID_OPTION
;
759 /* If we specified output fields, but not the output field type... */
760 if (WRITE_FIELDS
!= output_action
&& 0 != output_fields_num_fields(output_fields
)) {
761 cmdarg_err("Output fields were specified with \"-e\", "
762 "but \"-Tfields\" was not specified.");
764 } else if (WRITE_FIELDS
== output_action
&& 0 == output_fields_num_fields(output_fields
)) {
765 cmdarg_err("\"-Tfields\" was specified, but no fields were "
766 "specified with \"-e\".");
768 exit_status
= WS_EXIT_INVALID_OPTION
;
772 /* We require a -r flag specifying a file to read. */
773 if (cf_name
== NULL
) {
774 cmdarg_err("A file to read must be specified with \"-r\".");
775 exit_status
= NO_FILE_SPECIFIED
;
779 /* If no display filter has been specified, and there are still command-
780 line arguments, treat them as the tokens of a display filter. */
781 if (ws_optind
< argc
) {
782 if (dfilter
!= NULL
) {
783 cmdarg_err("Display filters were specified both with \"-Y\" "
784 "and with additional command-line arguments.");
785 exit_status
= WS_EXIT_INVALID_OPTION
;
788 dfilter
= get_args_as_string(argc
, argv
, ws_optind
);
791 /* if "-q" wasn't specified, we should print packet information */
793 print_packet_info
= true;
797 exit_status
= WS_EXIT_INVALID_OPTION
;
802 if (output_action
!= WRITE_TEXT
) {
803 cmdarg_err("Raw packet hex data can only be printed as text or PostScript");
804 exit_status
= WS_EXIT_INVALID_OPTION
;
809 if (output_only
!= NULL
) {
812 if (!print_details
) {
813 cmdarg_err("-O requires -V");
814 exit_status
= WS_EXIT_INVALID_OPTION
;
818 output_only_tables
= g_hash_table_new (g_str_hash
, g_str_equal
);
819 for (ps
= strtok (output_only
, ","); ps
; ps
= strtok (NULL
, ",")) {
820 g_hash_table_insert(output_only_tables
, (void *)ps
, (void *)ps
);
824 if (rfilter
!= NULL
&& !perform_two_pass_analysis
) {
825 cmdarg_err("-R without -2 is deprecated. For single-pass filtering use -Y.");
826 exit_status
= WS_EXIT_INVALID_OPTION
;
830 /* Notify all registered modules that have had any of their preferences
831 changed either from one of the preferences file or from the command
832 line that their preferences have changed. */
836 * Enabled and disabled protocols and heuristic dissectors as per
837 * command-line options.
839 if (!setup_enabled_and_disabled_protocols()) {
840 exit_status
= WS_EXIT_INVALID_OPTION
;
844 /* Build the column format array */
845 build_column_format_array(&cfile
.cinfo
, prefs_p
->num_cols
, true);
847 if (rfilter
!= NULL
) {
848 if (!dfilter_compile(rfilter
, &rfcode
, &df_err
)) {
849 cmdarg_err("%s", df_err
->msg
);
850 df_error_free(&df_err
);
851 exit_status
= WS_EXIT_INVALID_FILTER
;
855 cfile
.rfcode
= rfcode
;
857 if (dfilter
!= NULL
) {
858 if (!dfilter_compile(dfilter
, &dfcode
, &df_err
)) {
859 cmdarg_err("%s", df_err
->msg
);
860 df_error_free(&df_err
);
861 exit_status
= WS_EXIT_INVALID_FILTER
;
865 cfile
.dfcode
= dfcode
;
867 if (print_packet_info
) {
868 /* If we're printing as text or PostScript, we have
869 to create a print stream. */
870 if (output_action
== WRITE_TEXT
) {
871 switch (print_format
) {
874 print_stream
= print_stream_text_stdio_new(stdout
);
878 print_stream
= print_stream_ps_stdio_new(stdout
);
882 ws_assert_not_reached();
887 /* We have to dissect each packet if:
889 we're printing information about each packet;
891 we're using a read filter on the packets;
893 we're using a display filter on the packets;
895 we're using any taps that need dissection. */
896 do_dissection
= print_packet_info
|| rfcode
|| dfcode
|| tap_listeners_require_dissection();
902 /* TODO: if tfshark is ever changed to give the user a choice of which
903 open_routine reader to use, then the following needs to change. */
904 if (cf_open(&cfile
, cf_name
, WTAP_TYPE_AUTO
, false, &err
) != CF_OK
) {
905 exit_status
= WS_EXIT_OPEN_ERROR
;
909 /* Start statistics taps; we do so after successfully opening the
910 capture file, so we know we have something to compute stats
911 on, and after registering all dissectors, so that MATE will
912 have registered its field array so we can have a tap filter
913 with one of MATE's late-registered fields as part of the
915 start_requested_stats();
917 /* Process the packets in the file */
919 /* XXX - for now there is only 1 packet */
920 success
= process_file(&cfile
, 1, 0);
922 CATCH(OutOfMemoryError
) {
926 "Sorry, but TFShark has to terminate now.\n"
928 "Some infos / workarounds can be found at:\n"
929 WS_WIKI_URL("KnownBugs/OutOfMemory") "\n");
935 /* We still dump out the results of taps, etc., as we might have
936 read some packets; however, we exit with an error status. */
942 if (cfile
.provider
.frames
!= NULL
) {
943 free_frame_data_sequence(cfile
.provider
.frames
);
944 cfile
.provider
.frames
= NULL
;
947 draw_tap_listeners(true);
948 funnel_dump_all_text_windows();
951 destroy_print_stream(print_stream
);
952 epan_free(cfile
.epan
);
955 output_fields_free(output_fields
);
956 output_fields
= NULL
;
958 col_cleanup(&cfile
.cinfo
);
964 no_interface_name(struct packet_provider_data
*prov _U_
, uint32_t interface_id _U_
, unsigned section_number _U_
)
970 tfshark_epan_new(capture_file
*cf
)
972 static const struct packet_provider_funcs funcs
= {
973 /* XXX - there should be no need for time stamps */
974 cap_file_provider_get_frame_ts
,
980 return epan_new(&cf
->provider
, &funcs
);
984 process_packet_first_pass(capture_file
*cf
, epan_dissect_t
*edt
,
985 int64_t offset
, wtap_rec
*rec
,
986 const unsigned char *pd
)
992 /* The frame number of this packet is one more than the count of
993 frames in this packet. */
994 framenum
= cf
->count
+ 1;
996 /* If we're not running a display filter and we're not printing any
997 packet information, we don't need to do a dissection. This means
998 that all packets can be marked as 'passed'. */
1001 frame_data_init(&fdlocal
, framenum
, rec
, offset
, cum_bytes
);
1003 /* If we're going to print packet information, or we're going to
1004 run a read filter, or display filter, or we're going to process taps, set up to
1005 do a dissection and do so. */
1007 /* If we're running a read filter, prime the epan_dissect_t with that
1010 epan_dissect_prime_with_dfilter(edt
, cf
->rfcode
);
1012 /* This is the first pass, so prime the epan_dissect_t with the
1013 hfids postdissectors want on the first pass. */
1014 prime_epan_dissect_with_postdissector_wanted_hfids(edt
);
1016 frame_data_set_before_dissect(&fdlocal
, &cf
->elapsed_time
,
1017 &cf
->provider
.ref
, cf
->provider
.prev_dis
);
1018 if (cf
->provider
.ref
== &fdlocal
) {
1019 ref_frame
= fdlocal
;
1020 cf
->provider
.ref
= &ref_frame
;
1023 epan_dissect_file_run(edt
, rec
,
1027 /* Run the read filter if we have one. */
1029 passed
= dfilter_apply_edt(cf
->rfcode
, edt
);
1033 frame_data_set_after_dissect(&fdlocal
, &cum_bytes
);
1034 cf
->provider
.prev_cap
= cf
->provider
.prev_dis
= frame_data_sequence_add(cf
->provider
.frames
, &fdlocal
);
1036 /* If we're not doing dissection then there won't be any dependent frames.
1037 * More importantly, edt.pi.fd.dependent_frames won't be initialized because
1038 * epan hasn't been initialized.
1040 if (edt
&& edt
->pi
.fd
->dependent_frames
) {
1041 g_hash_table_foreach(edt
->pi
.fd
->dependent_frames
, find_and_mark_frame_depended_upon
, cf
->provider
.frames
);
1046 /* if we don't add it to the frame_data_sequence, clean it up right now
1048 frame_data_destroy(&fdlocal
);
1052 epan_dissect_reset(edt
);
1058 process_packet_second_pass(capture_file
*cf
, epan_dissect_t
*edt
,
1059 frame_data
*fdata
, wtap_rec
*rec
,
1065 /* If we're not running a display filter and we're not printing any
1066 packet information, we don't need to do a dissection. This means
1067 that all packets can be marked as 'passed'. */
1070 /* If we're going to print packet information, or we're going to
1071 run a read filter, or we're going to process taps, set up to
1072 do a dissection and do so. */
1075 /* If we're running a display filter, prime the epan_dissect_t with that
1078 epan_dissect_prime_with_dfilter(edt
, cf
->dfcode
);
1080 /* This is the first and only pass, so prime the epan_dissect_t
1081 with the hfids postdissectors want on the first pass. */
1082 prime_epan_dissect_with_postdissector_wanted_hfids(edt
);
1084 col_custom_prime_edt(edt
, &cf
->cinfo
);
1086 /* We only need the columns if either
1087 1) some tap needs the columns
1089 2) we're printing packet info but we're *not* verbose; in verbose
1090 mode, we print the protocol tree, not the protocol summary.
1092 if ((tap_listeners_require_columns()) || (print_packet_info
&& print_summary
))
1097 frame_data_set_before_dissect(fdata
, &cf
->elapsed_time
,
1098 &cf
->provider
.ref
, cf
->provider
.prev_dis
);
1099 if (cf
->provider
.ref
== fdata
) {
1101 cf
->provider
.ref
= &ref_frame
;
1104 epan_dissect_file_run_with_taps(edt
, rec
,
1105 ws_buffer_start_ptr(buf
), fdata
, cinfo
);
1107 /* Run the read/display filter if we have one. */
1109 passed
= dfilter_apply_edt(cf
->dfcode
, edt
);
1113 frame_data_set_after_dissect(fdata
, &cum_bytes
);
1114 /* Process this packet. */
1115 if (print_packet_info
) {
1116 /* We're printing packet information; print the information for
1118 print_packet(cf
, edt
);
1120 /* If we're doing "line-buffering", flush the standard output
1121 after every packet. See the comment above, for the "-l"
1122 option, for an explanation of why we do that. */
1126 if (ferror(stdout
)) {
1127 show_print_file_io_error(errno
);
1131 cf
->provider
.prev_dis
= fdata
;
1133 cf
->provider
.prev_cap
= fdata
;
1136 epan_dissect_reset(edt
);
1138 return passed
|| fdata
->dependent_of_displayed
;
1142 local_wtap_read(capture_file
*cf
, wtap_rec
*file_rec _U_
, int *err
, char **err_info _U_
, int64_t *data_offset _U_
, uint8_t** data_buffer
)
1144 /* int bytes_read; */
1145 int64_t packet_size
= wtap_file_size(cf
->provider
.wth
, err
);
1147 *data_buffer
= (uint8_t*)g_malloc((size_t)packet_size
);
1148 /* bytes_read =*/ file_read(*data_buffer
, (unsigned int)packet_size
, cf
->provider
.wth
->fh
);
1150 #if 0 /* no more filetap */
1151 if (bytes_read
< 0) {
1152 *err
= file_error(cf
->provider
.wth
->fh
, err_info
);
1154 *err
= FTAP_ERR_SHORT_READ
;
1156 } else if (bytes_read
== 0) {
1157 /* Done with file, no error */
1162 /* XXX - SET FRAME SIZE EQUAL TO TOTAL FILE SIZE */
1163 file_rec
->rec_header
.packet_header
.caplen
= (uint32_t)packet_size
;
1164 file_rec
->rec_header
.packet_header
.len
= (uint32_t)packet_size
;
1167 * Set the packet encapsulation to the file's encapsulation
1168 * value; if that's not WTAP_ENCAP_PER_PACKET, it's the
1169 * right answer (and means that the read routine for this
1170 * capture file type doesn't have to set it), and if it
1171 * *is* WTAP_ENCAP_PER_PACKET, the caller needs to set it
1174 wth
->rec
.rec_header
.packet_header
.pkt_encap
= wth
->file_encap
;
1176 if (!wth
->subtype_read(wth
, err
, err_info
, data_offset
)) {
1178 * If we didn't get an error indication, we read
1179 * the last packet. See if there's any deferred
1180 * error, as might, for example, occur if we're
1181 * reading a compressed file, and we got an error
1182 * reading compressed data from the file, but
1183 * got enough compressed data to decompress the
1184 * last packet of the file.
1187 *err
= file_error(wth
->fh
, err_info
);
1188 return false; /* failure */
1192 * It makes no sense for the captured data length to be bigger
1193 * than the actual data length.
1195 if (wth
->rec
.rec_header
.packet_header
.caplen
> wth
->rec
.rec_header
.packet_header
.len
)
1196 wth
->rec
.rec_header
.packet_header
.caplen
= wth
->rec
.rec_header
.packet_header
.len
;
1199 * Make sure that it's not WTAP_ENCAP_PER_PACKET, as that
1200 * probably means the file has that encapsulation type
1201 * but the read routine didn't set this packet's
1202 * encapsulation type.
1204 ws_assert(wth
->rec
.rec_header
.packet_header
.pkt_encap
!= WTAP_ENCAP_PER_PACKET
);
1207 return true; /* success */
1211 process_file(capture_file
*cf
, int max_packet_count
, int64_t max_byte_count
)
1215 char *err_info
= NULL
;
1216 int64_t data_offset
= 0;
1217 bool filtering_tap_listeners
;
1220 epan_dissect_t
*edt
= NULL
;
1224 if (print_packet_info
) {
1225 if (!write_preamble(cf
)) {
1227 show_print_file_io_error(err
);
1232 /* Do we have any tap listeners with filters? */
1233 filtering_tap_listeners
= have_filtering_tap_listeners();
1235 /* Get the union of the flags for all tap listeners. */
1236 tap_flags
= union_of_tap_listener_flags();
1238 wtap_rec_init(&file_rec
);
1240 /* XXX - TEMPORARY HACK TO ELF DISSECTOR */
1241 file_rec
.rec_header
.packet_header
.pkt_encap
= 1234;
1243 if (perform_two_pass_analysis
) {
1246 /* Allocate a frame_data_sequence for all the frames. */
1247 cf
->provider
.frames
= new_frame_data_sequence();
1249 if (do_dissection
) {
1250 bool create_proto_tree
;
1253 * Determine whether we need to create a protocol tree.
1256 * we're going to apply a read filter;
1258 * a postdissector wants field values or protocols
1259 * on the first pass.
1262 (cf
->rfcode
!= NULL
|| postdissectors_want_hfids());
1264 /* We're not going to display the protocol tree on this pass,
1265 so it's not going to be "visible". */
1266 edt
= epan_dissect_new(cf
->epan
, create_proto_tree
, false);
1268 while (local_wtap_read(cf
, &file_rec
, &err
, &err_info
, &data_offset
, &raw_data
)) {
1269 if (process_packet_first_pass(cf
, edt
, data_offset
, &file_rec
, raw_data
)) {
1271 /* Stop reading if we have the maximum number of packets;
1272 * When the -c option has not been used, max_packet_count
1273 * starts at 0, which practically means, never stop reading.
1274 * (unless we roll over max_packet_count ?)
1276 if ( (--max_packet_count
== 0) || (max_byte_count
!= 0 && data_offset
>= max_byte_count
)) {
1277 err
= 0; /* This is not an error */
1284 epan_dissect_free(edt
);
1289 /* Close the sequential I/O side, to free up memory it requires. */
1290 wtap_sequential_close(cf
->provider
.wth
);
1293 /* Allow the protocol dissectors to free up memory that they
1294 * don't need after the sequential run-through of the packets. */
1295 postseq_cleanup_all_protocols();
1297 cf
->provider
.prev_dis
= NULL
;
1298 cf
->provider
.prev_cap
= NULL
;
1299 ws_buffer_init(&buf
, 1514);
1301 if (do_dissection
) {
1302 bool create_proto_tree
;
1305 * Determine whether we need to create a protocol tree.
1308 * we're going to apply a display filter;
1310 * we're going to print the protocol tree;
1312 * one of the tap listeners requires a protocol tree;
1314 * we have custom columns (which require field values, which
1315 * currently requires that we build a protocol tree).
1318 (cf
->dfcode
|| print_details
|| filtering_tap_listeners
||
1319 (tap_flags
& TL_REQUIRES_PROTO_TREE
) || have_custom_cols(&cf
->cinfo
));
1321 /* The protocol tree will be "visible", i.e., printed, only if we're
1322 printing packet details, which is true if we're printing stuff
1323 ("print_packet_info" is true) and we're in verbose mode
1324 ("packet_details" is true). */
1325 edt
= epan_dissect_new(cf
->epan
, create_proto_tree
, print_packet_info
&& print_details
);
1328 for (framenum
= 1; err
== 0 && framenum
<= cf
->count
; framenum
++) {
1329 fdata
= frame_data_sequence_find(cf
->provider
.frames
, framenum
);
1331 if (wtap_seek_read(cf
->provider
.wth
, fdata
->file_off
,
1332 &buf
, fdata
->cap_len
, &err
, &err_info
)) {
1333 process_packet_second_pass(cf
, edt
, fdata
, &cf
->rec
, &buf
, tap_flags
);
1336 if (!process_packet_second_pass(cf
, edt
, fdata
, &cf
->rec
, &buf
))
1342 epan_dissect_free(edt
);
1346 ws_buffer_free(&buf
);
1351 if (do_dissection
) {
1352 bool create_proto_tree
;
1355 * Determine whether we need to create a protocol tree.
1358 * we're going to apply a read filter;
1360 * we're going to apply a display filter;
1362 * we're going to print the protocol tree;
1364 * one of the tap listeners is going to apply a filter;
1366 * one of the tap listeners requires a protocol tree;
1368 * a postdissector wants field values or protocols
1369 * on the first pass;
1371 * we have custom columns (which require field values, which
1372 * currently requires that we build a protocol tree).
1375 (cf
->rfcode
|| cf
->dfcode
|| print_details
|| filtering_tap_listeners
||
1376 (tap_flags
& TL_REQUIRES_PROTO_TREE
) || postdissectors_want_hfids() ||
1377 have_custom_cols(&cf
->cinfo
));
1379 /* The protocol tree will be "visible", i.e., printed, only if we're
1380 printing packet details, which is true if we're printing stuff
1381 ("print_packet_info" is true) and we're in verbose mode
1382 ("packet_details" is true). */
1383 edt
= epan_dissect_new(cf
->epan
, create_proto_tree
, print_packet_info
&& print_details
);
1386 while (local_wtap_read(cf
, &file_rec
, &err
, &err_info
, &data_offset
, &raw_data
)) {
1390 if (!process_packet_single_pass(cf
, edt
, data_offset
,
1391 &file_rec
/*wtap_get_rec(cf->provider.wth)*/,
1395 /* Stop reading if we have the maximum number of packets;
1396 * When the -c option has not been used, max_packet_count
1397 * starts at 0, which practically means, never stop reading.
1398 * (unless we roll over max_packet_count ?)
1400 if ( (--max_packet_count
== 0) || (max_byte_count
!= 0 && data_offset
>= max_byte_count
)) {
1401 err
= 0; /* This is not an error */
1407 epan_dissect_free(edt
);
1412 wtap_rec_cleanup(&file_rec
);
1416 * Print a message noting that the read failed somewhere along the line.
1418 * If we're printing packet data, and the standard output and error are
1419 * going to the same place, flush the standard output, so everything
1420 * buffered up is written, and then print a newline to the standard error
1421 * before printing the error message, to separate it from the packet
1422 * data. (Alas, that only works on UN*X; st_dev is meaningless, and
1423 * the _fstat() documentation at Microsoft doesn't indicate whether
1424 * st_ino is even supported.)
1427 if (print_packet_info
) {
1428 ws_statb64 stat_stdout
, stat_stderr
;
1430 if (ws_fstat64(1, &stat_stdout
) == 0 && ws_fstat64(2, &stat_stderr
) == 0) {
1431 if (stat_stdout
.st_dev
== stat_stderr
.st_dev
&&
1432 stat_stdout
.st_ino
== stat_stderr
.st_ino
) {
1434 fprintf(stderr
, "\n");
1442 case FTAP_ERR_UNSUPPORTED
:
1443 cmdarg_err("The file \"%s\" contains record data that TFShark doesn't support.\n(%s)",
1444 cf
->filename
, err_info
);
1448 case FTAP_ERR_UNSUPPORTED_ENCAP
:
1449 cmdarg_err("The file \"%s\" has a packet with a network type that TFShark doesn't support.\n(%s)",
1450 cf
->filename
, err_info
);
1454 case FTAP_ERR_CANT_READ
:
1455 cmdarg_err("An attempt to read from the file \"%s\" failed for some unknown reason.",
1459 case FTAP_ERR_SHORT_READ
:
1460 cmdarg_err("The file \"%s\" appears to have been cut short in the middle of a packet.",
1464 case FTAP_ERR_BAD_FILE
:
1465 cmdarg_err("The file \"%s\" appears to be damaged or corrupt.\n(%s)",
1466 cf
->filename
, err_info
);
1470 case FTAP_ERR_DECOMPRESS
:
1471 cmdarg_err("The compressed file \"%s\" appears to be damaged or corrupt.\n"
1472 "(%s)", cf
->filename
, err_info
);
1476 cmdarg_err("An error occurred while reading the file \"%s\": %s.",
1477 cf
->filename
, ftap_strerror(err
));
1482 if (print_packet_info
) {
1483 if (!write_finale()) {
1485 show_print_file_io_error(err
);
1491 wtap_close(cf
->provider
.wth
);
1492 cf
->provider
.wth
= NULL
;
1498 process_packet_single_pass(capture_file
*cf
, epan_dissect_t
*edt
, int64_t offset
,
1499 wtap_rec
*rec
, const unsigned char *pd
)
1505 /* Count this packet. */
1508 /* If we're not running a display filter and we're not printing any
1509 packet information, we don't need to do a dissection. This means
1510 that all packets can be marked as 'passed'. */
1513 frame_data_init(&fdata
, cf
->count
, rec
, offset
, cum_bytes
);
1515 /* If we're going to print packet information, or we're going to
1516 run a read filter, or we're going to process taps, set up to
1517 do a dissection and do so. */
1519 /* If we're running a filter, prime the epan_dissect_t with that
1522 epan_dissect_prime_with_dfilter(edt
, cf
->dfcode
);
1524 col_custom_prime_edt(edt
, &cf
->cinfo
);
1526 /* We only need the columns if either
1527 1) some tap needs the columns
1529 2) we're printing packet info but we're *not* verbose; in verbose
1530 mode, we print the protocol tree, not the protocol summary.
1532 3) there is a column mapped as an individual field */
1533 if ((tap_listeners_require_columns()) || (print_packet_info
&& print_summary
) || output_fields_has_cols(output_fields
))
1538 frame_data_set_before_dissect(&fdata
, &cf
->elapsed_time
,
1539 &cf
->provider
.ref
, cf
->provider
.prev_dis
);
1540 if (cf
->provider
.ref
== &fdata
) {
1542 cf
->provider
.ref
= &ref_frame
;
1545 epan_dissect_file_run_with_taps(edt
, rec
,
1549 /* Run the filter if we have it. */
1551 passed
= dfilter_apply_edt(cf
->dfcode
, edt
);
1555 frame_data_set_after_dissect(&fdata
, &cum_bytes
);
1557 /* Process this packet. */
1558 if (print_packet_info
) {
1559 /* We're printing packet information; print the information for
1561 print_packet(cf
, edt
);
1563 /* If we're doing "line-buffering", flush the standard output
1564 after every packet. See the comment above, for the "-l"
1565 option, for an explanation of why we do that. */
1569 if (ferror(stdout
)) {
1570 show_print_file_io_error(errno
);
1575 /* this must be set after print_packet() [bug #8160] */
1576 prev_dis_frame
= fdata
;
1577 cf
->provider
.prev_dis
= &prev_dis_frame
;
1580 prev_cap_frame
= fdata
;
1581 cf
->provider
.prev_cap
= &prev_cap_frame
;
1584 epan_dissect_reset(edt
);
1585 frame_data_destroy(&fdata
);
1591 write_preamble(capture_file
*cf
)
1593 switch (output_action
) {
1596 return print_preamble(print_stream
, cf
->filename
, get_ws_vcs_version_info());
1600 write_pdml_preamble(stdout
, cf
->filename
);
1602 write_psml_preamble(&cf
->cinfo
, stdout
);
1603 return !ferror(stdout
);
1606 write_fields_preamble(output_fields
, stdout
);
1607 return !ferror(stdout
);
1610 ws_assert_not_reached();
1616 get_line_buf(size_t len
)
1618 static char *line_bufp
= NULL
;
1619 static size_t line_buf_len
= 256;
1620 size_t new_line_buf_len
;
1622 for (new_line_buf_len
= line_buf_len
; len
> new_line_buf_len
;
1623 new_line_buf_len
*= 2)
1625 if (line_bufp
== NULL
) {
1626 line_buf_len
= new_line_buf_len
;
1627 line_bufp
= (char *)g_malloc(line_buf_len
+ 1);
1629 if (new_line_buf_len
> line_buf_len
) {
1630 line_buf_len
= new_line_buf_len
;
1631 line_bufp
= (char *)g_realloc(line_bufp
, line_buf_len
+ 1);
1638 put_string(char *dest
, const char *str
, size_t str_len
)
1640 memcpy(dest
, str
, str_len
);
1641 dest
[str_len
] = '\0';
1645 put_spaces_string(char *dest
, const char *str
, size_t str_len
, size_t str_with_spaces
)
1649 for (i
= str_len
; i
< str_with_spaces
; i
++)
1652 put_string(dest
, str
, str_len
);
1656 put_string_spaces(char *dest
, const char *str
, size_t str_len
, size_t str_with_spaces
)
1660 memcpy(dest
, str
, str_len
);
1661 for (i
= str_len
; i
< str_with_spaces
; i
++)
1664 dest
[str_with_spaces
] = '\0';
1668 print_columns(capture_file
*cf
)
1675 col_item_t
* col_item
;
1677 line_bufp
= get_line_buf(256);
1680 for (i
= 0; i
< cf
->cinfo
.num_cols
; i
++) {
1681 col_item
= &cf
->cinfo
.columns
[i
];
1682 /* Skip columns not marked as visible. */
1683 if (!get_column_visible(i
))
1685 const char* col_text
= get_column_text(&cf
->cinfo
, i
);
1686 switch (col_item
->col_fmt
) {
1688 case COL_NUMBER_DIS
:
1689 column_len
= col_len
= strlen(col_text
);
1692 line_bufp
= get_line_buf(buf_offset
+ column_len
);
1693 put_spaces_string(line_bufp
+ buf_offset
, col_text
, col_len
, column_len
);
1699 case COL_ABS_YMD_TIME
: /* XXX - wider */
1700 case COL_ABS_YDOY_TIME
: /* XXX - wider */
1702 case COL_UTC_YMD_TIME
: /* XXX - wider */
1703 case COL_UTC_YDOY_TIME
: /* XXX - wider */
1704 column_len
= col_len
= strlen(col_text
);
1705 if (column_len
< 10)
1707 line_bufp
= get_line_buf(buf_offset
+ column_len
);
1708 put_spaces_string(line_bufp
+ buf_offset
, col_text
, col_len
, column_len
);
1714 case COL_DEF_DL_SRC
:
1715 case COL_RES_DL_SRC
:
1716 case COL_UNRES_DL_SRC
:
1717 case COL_DEF_NET_SRC
:
1718 case COL_RES_NET_SRC
:
1719 case COL_UNRES_NET_SRC
:
1720 column_len
= col_len
= strlen(col_text
);
1721 if (column_len
< 12)
1723 line_bufp
= get_line_buf(buf_offset
+ column_len
);
1724 put_spaces_string(line_bufp
+ buf_offset
, col_text
, col_len
, column_len
);
1730 case COL_DEF_DL_DST
:
1731 case COL_RES_DL_DST
:
1732 case COL_UNRES_DL_DST
:
1733 case COL_DEF_NET_DST
:
1734 case COL_RES_NET_DST
:
1735 case COL_UNRES_NET_DST
:
1736 column_len
= col_len
= strlen(col_text
);
1737 if (column_len
< 12)
1739 line_bufp
= get_line_buf(buf_offset
+ column_len
);
1740 put_string_spaces(line_bufp
+ buf_offset
, col_text
, col_len
, column_len
);
1744 column_len
= strlen(col_text
);
1745 line_bufp
= get_line_buf(buf_offset
+ column_len
);
1746 put_string(line_bufp
+ buf_offset
, col_text
, column_len
);
1749 buf_offset
+= column_len
;
1750 if (i
!= cf
->cinfo
.num_cols
- 1) {
1752 * This isn't the last column, so we need to print a
1753 * separator between this column and the next.
1755 * If we printed a network source and are printing a
1756 * network destination of the same type next, separate
1757 * them with " -> "; if we printed a network destination
1758 * and are printing a network source of the same type
1759 * next, separate them with " <- "; otherwise separate them
1762 * We add enough space to the buffer for " <- " or " -> ",
1763 * even if we're only adding " ".
1765 line_bufp
= get_line_buf(buf_offset
+ 4);
1766 switch (col_item
->col_fmt
) {
1771 switch (cf
->cinfo
.columns
[i
+1].col_fmt
) {
1776 put_string(line_bufp
+ buf_offset
, " -> ", 4);
1781 put_string(line_bufp
+ buf_offset
, " ", 1);
1787 case COL_DEF_DL_SRC
:
1788 case COL_RES_DL_SRC
:
1789 case COL_UNRES_DL_SRC
:
1790 switch (cf
->cinfo
.columns
[i
+1].col_fmt
) {
1792 case COL_DEF_DL_DST
:
1793 case COL_RES_DL_DST
:
1794 case COL_UNRES_DL_DST
:
1795 put_string(line_bufp
+ buf_offset
, " -> ", 4);
1800 put_string(line_bufp
+ buf_offset
, " ", 1);
1806 case COL_DEF_NET_SRC
:
1807 case COL_RES_NET_SRC
:
1808 case COL_UNRES_NET_SRC
:
1809 switch (cf
->cinfo
.columns
[i
+1].col_fmt
) {
1811 case COL_DEF_NET_DST
:
1812 case COL_RES_NET_DST
:
1813 case COL_UNRES_NET_DST
:
1814 put_string(line_bufp
+ buf_offset
, " -> ", 4);
1819 put_string(line_bufp
+ buf_offset
, " ", 1);
1828 switch (cf
->cinfo
.columns
[i
+1].col_fmt
) {
1833 put_string(line_bufp
+ buf_offset
, " <- ", 4);
1838 put_string(line_bufp
+ buf_offset
, " ", 1);
1844 case COL_DEF_DL_DST
:
1845 case COL_RES_DL_DST
:
1846 case COL_UNRES_DL_DST
:
1847 switch (cf
->cinfo
.columns
[i
+1].col_fmt
) {
1849 case COL_DEF_DL_SRC
:
1850 case COL_RES_DL_SRC
:
1851 case COL_UNRES_DL_SRC
:
1852 put_string(line_bufp
+ buf_offset
, " <- ", 4);
1857 put_string(line_bufp
+ buf_offset
, " ", 1);
1863 case COL_DEF_NET_DST
:
1864 case COL_RES_NET_DST
:
1865 case COL_UNRES_NET_DST
:
1866 switch (cf
->cinfo
.columns
[i
+1].col_fmt
) {
1868 case COL_DEF_NET_SRC
:
1869 case COL_RES_NET_SRC
:
1870 case COL_UNRES_NET_SRC
:
1871 put_string(line_bufp
+ buf_offset
, " <- ", 4);
1876 put_string(line_bufp
+ buf_offset
, " ", 1);
1883 put_string(line_bufp
+ buf_offset
, " ", 1);
1889 return print_line(print_stream
, 0, line_bufp
);
1893 print_packet(capture_file
*cf
, epan_dissect_t
*edt
)
1895 if (print_summary
|| output_fields_has_cols(output_fields
)) {
1896 /* Just fill in the columns. */
1897 epan_dissect_fill_in_columns(edt
, false, true);
1899 if (print_summary
) {
1900 /* Now print them. */
1901 switch (output_action
) {
1904 if (!print_columns(cf
))
1909 write_psml_columns(edt
, stdout
, false);
1910 return !ferror(stdout
);
1911 case WRITE_FIELDS
: /*No non-verbose "fields" format */
1912 ws_assert_not_reached();
1917 if (print_details
) {
1918 /* Print the information in the protocol tree. */
1919 switch (output_action
) {
1922 if (!proto_tree_print(print_details
? print_dissections_expanded
: print_dissections_none
,
1923 print_hex
, edt
, output_only_tables
, print_stream
))
1926 if (!print_line(print_stream
, 0, separator
))
1932 write_pdml_proto_tree(NULL
, edt
, &cf
->cinfo
, stdout
, false);
1934 return !ferror(stdout
);
1936 write_fields_proto_tree(output_fields
, edt
, &cf
->cinfo
, stdout
);
1938 return !ferror(stdout
);
1942 if (print_summary
|| print_details
) {
1943 if (!print_line(print_stream
, 0, ""))
1946 if (!print_hex_data(print_stream
, edt
, HEXDUMP_SOURCE_MULTI
| HEXDUMP_ASCII_INCLUDE
))
1948 if (!print_line(print_stream
, 0, separator
))
1957 switch (output_action
) {
1960 return print_finale(print_stream
);
1964 write_pdml_finale(stdout
);
1966 write_psml_finale(stdout
);
1967 return !ferror(stdout
);
1970 write_fields_finale(output_fields
, stdout
);
1971 return !ferror(stdout
);
1974 ws_assert_not_reached();
1980 cf_open(capture_file
*cf
, const char *fname
, unsigned int type
, bool is_tempfile
, int *err _U_
)
1982 /* The open isn't implemented yet. Fill in the information for this file. */
1984 /* Create new epan session for dissection. */
1985 epan_free(cf
->epan
);
1986 cf
->epan
= tfshark_epan_new(cf
);
1988 cf
->provider
.wth
= NULL
; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
1989 cf
->f_datalen
= 0; /* not used, but set it anyway */
1991 /* Set the file name because we need it to set the follow stream filter.
1992 XXX - is that still true? We need it for other reasons, though,
1994 cf
->filename
= g_strdup(fname
);
1996 /* Indicate whether it's a permanent or temporary file. */
1997 cf
->is_tempfile
= is_tempfile
;
1999 /* No user changes yet. */
2000 cf
->unsaved_changes
= false;
2002 cf
->cd_t
= 0; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2003 cf
->open_type
= type
;
2005 cf
->drops_known
= false;
2007 cf
->snap
= 0; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2008 nstime_set_zero(&cf
->elapsed_time
);
2009 cf
->provider
.ref
= NULL
;
2010 cf
->provider
.prev_dis
= NULL
;
2011 cf
->provider
.prev_cap
= NULL
;
2013 cf
->state
= FILE_READ_IN_PROGRESS
;
2020 char err_msg[2048+1];
2021 snprintf(err_msg, sizeof err_msg,
2022 cf_open_error_message(*err, err_info, false, cf->cd_t), fname);
2023 cmdarg_err("%s", err_msg);
2029 show_print_file_io_error(int err
)
2034 cmdarg_err("Not all the packets could be printed because there is "
2035 "no space left on the file system.");
2040 cmdarg_err("Not all the packets could be printed because you are "
2041 "too close to, or over your disk quota.");
2046 cmdarg_err("An error occurred while printing packets: %s.",