1 /* tfshark.c
2  *
3  * Text-mode variant of Fileshark, based off of TShark,
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * SPDX-License-Identifier: GPL-2.0-or-later
10  */
11 
12 #include <config.h>
13 
14 #define WS_LOG_DOMAIN  LOG_DOMAIN_MAIN
15 
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <locale.h>
20 #include <limits.h>
21 
22 #include <wsutil/ws_getopt.h>
23 
24 #include <errno.h>
25 
26 #include <glib.h>
27 
28 #include <epan/exceptions.h>
29 #include <epan/epan.h>
30 
31 #include <ui/clopts_common.h>
32 #include <ui/cmdarg_err.h>
33 #include <ui/exit_codes.h>
34 #include <ui/urls.h>
35 #include <wsutil/filesystem.h>
36 #include <wsutil/file_util.h>
37 #include <wsutil/privileges.h>
38 #include <wsutil/report_message.h>
39 #include <wsutil/wslog.h>
40 #include <wsutil/ws_assert.h>
41 #include <cli_main.h>
42 #include <ui/version_info.h>
43 
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 "ui/failure_message.h"
61 #include <epan/epan_dissect.h>
62 #include <epan/tap.h>
63 #include <epan/stat_tap_ui.h>
64 #include <epan/ex-opt.h>
65 #include "extcap.h"
66 
67 #include <wiretap/wtap-int.h>
68 #include <wiretap/file_wrappers.h>
69 
70 #include <epan/funnel.h>
71 
72 #ifdef HAVE_PLUGINS
73 #include <wsutil/plugins.h>
74 #endif
75 
76 /* Additional exit codes */
77 #define NO_FILE_SPECIFIED 1
78 
79 capture_file cfile;
80 
81 static guint32 cum_bytes;
82 static frame_data ref_frame;
83 static frame_data prev_dis_frame;
84 static frame_data prev_cap_frame;
85 
86 static gboolean prefs_loaded = FALSE;
87 
88 static gboolean perform_two_pass_analysis;
89 
90 /*
91  * The way the packet decode is to be written.
92  */
93 typedef enum {
94   WRITE_TEXT,   /* summary or detail text */
95   WRITE_XML,    /* PDML or PSML */
96   WRITE_FIELDS  /* User defined list of fields */
97   /* Add CSV and the like here */
98 } output_action_e;
99 
100 static output_action_e output_action;
101 static gboolean do_dissection;     /* TRUE if we have to dissect each packet */
102 static gboolean print_packet_info; /* TRUE if we're to print packet information */
103 static gint print_summary = -1;    /* TRUE if we're to print packet summary information */
104 static gboolean print_details;     /* TRUE if we're to print packet details information */
105 static gboolean print_hex;         /* TRUE if we're to print hex/ascci information */
106 static gboolean line_buffered;
107 static gboolean really_quiet = FALSE;
108 
109 static print_format_e print_format = PR_FMT_TEXT;
110 static print_stream_t *print_stream;
111 
112 static output_fields_t* output_fields  = NULL;
113 
114 /* The line separator used between packets, changeable via the -S option */
115 static const char *separator = "";
116 
117 static gboolean process_file(capture_file *, int, gint64);
118 static gboolean process_packet_single_pass(capture_file *cf,
119     epan_dissect_t *edt, gint64 offset, wtap_rec *rec,
120     const guchar *pd, guint tap_flags);
121 static void show_print_file_io_error(int err);
122 static gboolean write_preamble(capture_file *cf);
123 static gboolean print_packet(capture_file *cf, epan_dissect_t *edt);
124 static gboolean write_finale(void);
125 static const char *cf_open_error_message(int err, gchar *err_info,
126     gboolean for_writing, int file_type);
127 
128 static void tfshark_cmdarg_err(const char *msg_format, va_list ap);
129 static void tfshark_cmdarg_err_cont(const char *msg_format, va_list ap);
130 
131 static GHashTable *output_only_tables = NULL;
132 
133 #if 0
134 struct string_elem {
135   const char *sstr;   /* The short string */
136   const char *lstr;   /* The long string */
137 };
138 
139 static gint
140 string_compare(gconstpointer a, gconstpointer b)
141 {
142   return strcmp(((const struct string_elem *)a)->sstr,
143                 ((const struct string_elem *)b)->sstr);
144 }
145 
146 static void
147 string_elem_print(gpointer data, gpointer not_used _U_)
148 {
149   fprintf(stderr, "    %s - %s\n",
150           ((struct string_elem *)data)->sstr,
151           ((struct string_elem *)data)->lstr);
152 }
153 #endif
154 
155 static void
print_usage(FILE * output)156 print_usage(FILE *output)
157 {
158   fprintf(output, "\n");
159   fprintf(output, "Usage: tfshark [options] ...\n");
160   fprintf(output, "\n");
161 
162   /*fprintf(output, "\n");*/
163   fprintf(output, "Input file:\n");
164   fprintf(output, "  -r <infile>              set the filename to read from (no pipes or stdin)\n");
165 
166   fprintf(output, "\n");
167   fprintf(output, "Processing:\n");
168   fprintf(output, "  -2                       perform a two-pass analysis\n");
169   fprintf(output, "  -R <read filter>         packet Read filter in Wireshark display filter syntax\n");
170   fprintf(output, "                           (requires -2)\n");
171   fprintf(output, "  -Y <display filter>      packet displaY filter in Wireshark display filter\n");
172   fprintf(output, "                           syntax\n");
173   fprintf(output, "  -d %s ...\n", DECODE_AS_ARG_TEMPLATE);
174   fprintf(output, "                           \"Decode As\", see the man page for details\n");
175   fprintf(output, "                           Example: tcp.port==8888,http\n");
176 
177   /*fprintf(output, "\n");*/
178   fprintf(output, "Output:\n");
179   fprintf(output, "  -C <config profile>      start with specified configuration profile\n");
180   fprintf(output, "  -V                       add output of packet tree        (Packet Details)\n");
181   fprintf(output, "  -O <protocols>           Only show packet details of these protocols, comma\n");
182   fprintf(output, "                           separated\n");
183   fprintf(output, "  -S <separator>           the line separator to print between packets\n");
184   fprintf(output, "  -x                       add output of hex and ASCII dump (Packet Bytes)\n");
185   fprintf(output, "  -T pdml|ps|psml|text|fields\n");
186   fprintf(output, "                           format of text output (def: text)\n");
187   fprintf(output, "  -e <field>               field to print if -Tfields selected (e.g. tcp.port,\n");
188   fprintf(output, "                           _ws.col.Info)\n");
189   fprintf(output, "                           this option can be repeated to print multiple fields\n");
190   fprintf(output, "  -E<fieldsoption>=<value> set options for output when -Tfields selected:\n");
191   fprintf(output, "     header=y|n            switch headers on and off\n");
192   fprintf(output, "     separator=/t|/s|<char> select tab, space, printable character as separator\n");
193   fprintf(output, "     occurrence=f|l|a      print first, last or all occurrences of each field\n");
194   fprintf(output, "     aggregator=,|/s|<char> select comma, space, printable character as\n");
195   fprintf(output, "                           aggregator\n");
196   fprintf(output, "     quote=d|s|n           select double, single, no quotes for values\n");
197   fprintf(output, "  -t a|ad|d|dd|e|r|u|ud    output format of time stamps (def: r: rel. to first)\n");
198   fprintf(output, "  -u s|hms                 output format of seconds (def: s: seconds)\n");
199   fprintf(output, "  -l                       flush standard output after each packet\n");
200   fprintf(output, "  -q                       be more quiet on stdout (e.g. when using statistics)\n");
201   fprintf(output, "  -Q                       only log true errors to stderr (quieter than -q)\n");
202   fprintf(output, "  -X <key>:<value>         eXtension options, see the man page for details\n");
203   fprintf(output, "  -z <statistics>          various statistics, see the man page for details\n");
204 
205   ws_log_print_usage(output);
206 
207   fprintf(output, "\n");
208   fprintf(output, "Miscellaneous:\n");
209   fprintf(output, "  -h                       display this help and exit\n");
210   fprintf(output, "  -v                       display version info and exit\n");
211   fprintf(output, "  -o <name>:<value> ...    override preference setting\n");
212   fprintf(output, "  -K <keytab>              keytab file to use for kerberos decryption\n");
213   fprintf(output, "  -G [report]              dump one of several available reports and exit\n");
214   fprintf(output, "                           default report=\"fields\"\n");
215   fprintf(output, "                           use \"-G ?\" for more help\n");
216 }
217 
218 static void
glossary_option_help(void)219 glossary_option_help(void)
220 {
221   FILE *output;
222 
223   output = stdout;
224 
225   fprintf(output, "%s\n", get_appname_and_version());
226 
227   fprintf(output, "\n");
228   fprintf(output, "Usage: tfshark -G [report]\n");
229   fprintf(output, "\n");
230   fprintf(output, "Glossary table reports:\n");
231   fprintf(output, "  -G column-formats        dump column format codes and exit\n");
232   fprintf(output, "  -G decodes               dump \"layer type\"/\"decode as\" associations and exit\n");
233   fprintf(output, "  -G dissector-tables      dump dissector table names, types, and properties\n");
234   fprintf(output, "  -G fields                dump fields glossary and exit\n");
235   fprintf(output, "  -G ftypes                dump field type basic and descriptive names\n");
236   fprintf(output, "  -G heuristic-decodes     dump heuristic dissector tables\n");
237   fprintf(output, "  -G plugins               dump installed plugins and exit\n");
238   fprintf(output, "  -G protocols             dump protocols in registration database and exit\n");
239   fprintf(output, "  -G values                dump value, range, true/false strings and exit\n");
240   fprintf(output, "\n");
241   fprintf(output, "Preference reports:\n");
242   fprintf(output, "  -G currentprefs          dump current preferences and exit\n");
243   fprintf(output, "  -G defaultprefs          dump default preferences and exit\n");
244   fprintf(output, "\n");
245 }
246 
247 static void
print_current_user(void)248 print_current_user(void) {
249   gchar *cur_user, *cur_group;
250 
251   if (started_with_special_privs()) {
252     cur_user = get_cur_username();
253     cur_group = get_cur_groupname();
254     fprintf(stderr, "Running as user \"%s\" and group \"%s\".",
255       cur_user, cur_group);
256     g_free(cur_user);
257     g_free(cur_group);
258     if (running_with_special_privs()) {
259       fprintf(stderr, " This could be dangerous.");
260     }
261     fprintf(stderr, "\n");
262   }
263 }
264 
265 static void
get_tfshark_runtime_version_info(GString * str)266 get_tfshark_runtime_version_info(GString *str)
267 {
268   /* stuff used by libwireshark */
269   epan_get_runtime_version_info(str);
270 }
271 
272 int
main(int argc,char * argv[])273 main(int argc, char *argv[])
274 {
275   char                *init_progfile_dir_error;
276   int                  opt;
277   static const struct ws_option long_options[] = {
278     {"help", ws_no_argument, NULL, 'h'},
279     {"version", ws_no_argument, NULL, 'v'},
280     {0, 0, 0, 0 }
281   };
282   gboolean             arg_error = FALSE;
283 
284   int                  err;
285   volatile gboolean    success;
286   volatile int         exit_status = 0;
287   gboolean             quiet = FALSE;
288   gchar               *volatile cf_name = NULL;
289   gchar               *rfilter = NULL;
290   gchar               *dfilter = NULL;
291   dfilter_t           *rfcode = NULL;
292   dfilter_t           *dfcode = NULL;
293   gchar               *err_msg;
294   e_prefs             *prefs_p;
295   gchar               *output_only = NULL;
296 
297 /*
298  * The leading + ensures that getopt_long() does not permute the argv[]
299  * entries.
300  *
301  * We have to make sure that the first getopt_long() preserves the content
302  * of argv[] for the subsequent getopt_long() call.
303  *
304  * We use getopt_long() in both cases to ensure that we're using a routine
305  * whose permutation behavior we can control in the same fashion on all
306  * platforms, and so that, if we ever need to process a long argument before
307  * doing further initialization, we can do so.
308  *
309  * Glibc and Solaris libc document that a leading + disables permutation
310  * of options, regardless of whether POSIXLY_CORRECT is set or not; *BSD
311  * and macOS don't document it, but do so anyway.
312  *
313  * We do *not* use a leading - because the behavior of a leading - is
314  * platform-dependent.
315  */
316 #define OPTSTRING "+2C:d:e:E:hK:lo:O:qQr:R:S:t:T:u:vVxX:Y:z:"
317 
318   static const char    optstring[] = OPTSTRING;
319   static const struct report_message_routines tfshark_report_routines = {
320     failure_message,
321     failure_message,
322     open_failure_message,
323     read_failure_message,
324     write_failure_message,
325     cfile_open_failure_message,
326     cfile_dump_open_failure_message,
327     cfile_read_failure_message,
328     cfile_write_failure_message,
329     cfile_close_failure_message
330   };
331 
332   /*
333    * Set the C-language locale to the native environment and set the
334    * code page to UTF-8 on Windows.
335    */
336 #ifdef _WIN32
337   setlocale(LC_ALL, ".UTF-8");
338 #else
339   setlocale(LC_ALL, "");
340 #endif
341 
342   cmdarg_err_init(tfshark_cmdarg_err, tfshark_cmdarg_err_cont);
343 
344   /* Initialize log handler early so we can have proper logging during startup. */
345   ws_log_init("tfshark", vcmdarg_err);
346 
347   /* Early logging command-line initialization. */
348   ws_log_parse_args(&argc, argv, vcmdarg_err, INVALID_OPTION);
349 
350 #ifdef _WIN32
351   create_app_running_mutex();
352 #endif /* _WIN32 */
353 
354   /*
355    * Get credential information for later use, and drop privileges
356    * before doing anything else.
357    * Let the user know if anything happened.
358    */
359   init_process_policies();
360   relinquish_special_privs_perm();
361   print_current_user();
362 
363   /*
364    * Attempt to get the pathname of the directory containing the
365    * executable file.
366    */
367   init_progfile_dir_error = init_progfile_dir(argv[0]);
368   if (init_progfile_dir_error != NULL) {
369     fprintf(stderr,
370             "tfshark: Can't get pathname of directory containing the tfshark program: %s.\n",
371             init_progfile_dir_error);
372     g_free(init_progfile_dir_error);
373   }
374 
375   initialize_funnel_ops();
376 
377   /* Initialize the version information. */
378   ws_init_version_info("TFShark (Wireshark)", NULL,
379                        epan_get_compiled_version_info,
380                        get_tfshark_runtime_version_info);
381 
382   /*
383    * In order to have the -X opts assigned before the wslua machine starts
384    * we need to call getopts before epan_init() gets called.
385    *
386    * In order to handle, for example, -o options, we also need to call it
387    * *after* epan_init() gets called, so that the dissectors have had a
388    * chance to register their preferences.
389    *
390    * XXX - can we do this all with one getopt_long() call, saving the
391    * arguments we can't handle until after initializing libwireshark,
392    * and then process them after initializing libwireshark?
393    */
394   ws_opterr = 0;
395 
396   while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
397     switch (opt) {
398     case 'C':        /* Configuration Profile */
399       if (profile_exists (ws_optarg, FALSE)) {
400         set_profile_name (ws_optarg);
401       } else {
402         cmdarg_err("Configuration Profile \"%s\" does not exist", ws_optarg);
403         return 1;
404       }
405       break;
406     case 'O':        /* Only output these protocols */
407       output_only = g_strdup(ws_optarg);
408       /* FALLTHROUGH */
409     case 'V':        /* Verbose */
410       print_details = TRUE;
411       print_packet_info = TRUE;
412       break;
413     case 'x':        /* Print packet data in hex (and ASCII) */
414       print_hex = TRUE;
415       /*  The user asked for hex output, so let's ensure they get it,
416        *  even if they're writing to a file.
417        */
418       print_packet_info = TRUE;
419       break;
420     case 'X':
421       ex_opt_add(ws_optarg);
422       break;
423     default:
424       break;
425     }
426   }
427 
428   /*
429    * Print packet summary information is the default, unless either -V or -x
430    * were specified.  Note that this is new behavior, which
431    * allows for the possibility of printing only hex/ascii output without
432    * necessarily requiring that either the summary or details be printed too.
433    */
434   if (print_summary == -1)
435     print_summary = (print_details || print_hex) ? FALSE : TRUE;
436 
437   init_report_message("tfshark", &tfshark_report_routines);
438 
439   timestamp_set_type(TS_RELATIVE);
440   timestamp_set_precision(TS_PREC_AUTO);
441   timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
442 
443   /*
444    * Libwiretap must be initialized before libwireshark is, so that
445    * dissection-time handlers for file-type-dependent blocks can
446    * register using the file type/subtype value for the file type.
447    *
448    * XXX - TFShark shouldn't use libwiretap, as it's a file dissector
449    * and should read all files as raw bytes and then try to dissect them.
450    * It needs to handle file types its own way, because we would want
451    * to support dissecting file-type-specific blocks when dissecting
452    * capture files, but that mechanism should support plugins for
453    * other files, too, if *their* formats are extensible.
454    */
455   wtap_init(TRUE);
456 
457   /* Register all dissectors; we must do this before checking for the
458      "-G" flag, as the "-G" flag dumps information registered by the
459      dissectors, and we must do it before we read the preferences, in
460      case any dissectors register preferences. */
461   if (!epan_init(NULL, NULL, TRUE)) {
462     exit_status = INIT_FAILED;
463     goto clean_exit;
464   }
465 
466   /* Register all tap listeners; we do this before we parse the arguments,
467      as the "-z" argument can specify a registered tap. */
468 
469   /* we register the plugin taps before the other taps because
470      stats_tree taps plugins will be registered as tap listeners
471      by stats_tree_stat.c and need to registered before that */
472 
473   /* XXX Disable tap registration for now until we can get tfshark set up with
474    * its own set of taps and the necessary registration function etc.
475   register_all_tap_listeners();
476   */
477 
478   /* If invoked with the "-G" flag, we dump out information based on
479      the argument to the "-G" flag; if no argument is specified,
480      for backwards compatibility we dump out a glossary of display
481      filter symbols.
482 
483      XXX - we do this here, for now, to support "-G" with no arguments.
484      If none of our build or other processes uses "-G" with no arguments,
485      we can just process it with the other arguments. */
486   if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
487     proto_initialize_all_prefixes();
488 
489     if (argc == 2)
490       proto_registrar_dump_fields();
491     else {
492       if (strcmp(argv[2], "column-formats") == 0)
493         column_dump_column_formats();
494       else if (strcmp(argv[2], "currentprefs") == 0) {
495         epan_load_settings();
496         write_prefs(NULL);
497       }
498       else if (strcmp(argv[2], "decodes") == 0)
499         dissector_dump_decodes();
500       else if (strcmp(argv[2], "defaultprefs") == 0)
501         write_prefs(NULL);
502       else if (strcmp(argv[2], "dissector-tables") == 0)
503         dissector_dump_dissector_tables();
504       else if (strcmp(argv[2], "fields") == 0)
505         proto_registrar_dump_fields();
506       else if (strcmp(argv[2], "ftypes") == 0)
507         proto_registrar_dump_ftypes();
508       else if (strcmp(argv[2], "heuristic-decodes") == 0)
509         dissector_dump_heur_decodes();
510       else if (strcmp(argv[2], "plugins") == 0) {
511 #ifdef HAVE_PLUGINS
512         plugins_dump_all();
513 #endif
514 #ifdef HAVE_LUA
515         wslua_plugins_dump_all();
516 #endif
517       }
518       else if (strcmp(argv[2], "protocols") == 0)
519         proto_registrar_dump_protocols();
520       else if (strcmp(argv[2], "values") == 0)
521         proto_registrar_dump_values();
522       else if (strcmp(argv[2], "?") == 0)
523         glossary_option_help();
524       else if (strcmp(argv[2], "-?") == 0)
525         glossary_option_help();
526       else {
527         cmdarg_err("Invalid \"%s\" option for -G flag, enter -G ? for more help.", argv[2]);
528         exit_status = INVALID_OPTION;
529         goto clean_exit;
530       }
531     }
532     goto clean_exit;
533   }
534 
535   /* Load libwireshark settings from the current profile. */
536   prefs_p = epan_load_settings();
537   prefs_loaded = TRUE;
538 
539   cap_file_init(&cfile);
540 
541   /* Print format defaults to this. */
542   print_format = PR_FMT_TEXT;
543 
544   output_fields = output_fields_new();
545 
546   /*
547    * To reset the options parser, set ws_optreset to 1 and set ws_optind to 1.
548    *
549    * Also reset ws_opterr to 1, so that error messages are printed by
550    * getopt_long().
551    */
552   ws_optreset = 1;
553   ws_optind = 1;
554   ws_opterr = 1;
555 
556   /* Now get our args */
557   while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
558     switch (opt) {
559     case '2':        /* Perform two pass analysis */
560       perform_two_pass_analysis = TRUE;
561       break;
562     case 'C':
563       /* already processed; just ignore it now */
564       break;
565     case 'e':
566       /* Field entry */
567       output_fields_add(output_fields, ws_optarg);
568       break;
569     case 'E':
570       /* Field option */
571       if (!output_fields_set_option(output_fields, ws_optarg)) {
572         cmdarg_err("\"%s\" is not a valid field output option=value pair.", ws_optarg);
573         output_fields_list_options(stderr);
574         exit_status = INVALID_OPTION;
575         goto clean_exit;
576       }
577       break;
578 
579     case 'h':        /* Print help and exit */
580       show_help_header("Analyze file structure.");
581       print_usage(stdout);
582       goto clean_exit;
583       break;
584     case 'l':        /* "Line-buffer" standard output */
585       /* The ANSI C standard does not appear to *require* that a line-buffered
586          stream be flushed to the host environment whenever a newline is
587          written, it just says that, on such a stream, characters "are
588          intended to be transmitted to or from the host environment as a
589          block when a new-line character is encountered".
590 
591          The Visual C++ 6.0 C implementation doesn't do what is intended;
592          even if you set a stream to be line-buffered, it still doesn't
593          flush the buffer at the end of every line.
594 
595          The whole reason for the "-l" flag in either tcpdump or TShark
596          is to allow the output of a live capture to be piped to a program
597          or script and to have that script see the information for the
598          packet as soon as it's printed, rather than having to wait until
599          a standard I/O buffer fills up.
600 
601          So, if the "-l" flag is specified, we flush the standard output
602          at the end of a packet.  This will do the right thing if we're
603          printing packet summary lines, and, as we print the entire protocol
604          tree for a single packet without waiting for anything to happen,
605          it should be as good as line-buffered mode if we're printing
606          protocol trees - arguably even better, as it may do fewer
607          writes. */
608       line_buffered = TRUE;
609       break;
610     case 'o':        /* Override preference from command line */
611     {
612       char *errmsg = NULL;
613 
614       switch (prefs_set_pref(ws_optarg, &errmsg)) {
615 
616       case PREFS_SET_OK:
617         break;
618 
619       case PREFS_SET_SYNTAX_ERR:
620         cmdarg_err("Invalid -o flag \"%s\"%s%s", ws_optarg,
621             errmsg ? ": " : "", errmsg ? errmsg : "");
622         g_free(errmsg);
623         exit_status = INVALID_OPTION;
624         goto clean_exit;
625         break;
626 
627       case PREFS_SET_NO_SUCH_PREF:
628         cmdarg_err("-o flag \"%s\" specifies unknown preference", ws_optarg);
629         exit_status = INVALID_OPTION;
630         goto clean_exit;
631         break;
632 
633       case PREFS_SET_OBSOLETE:
634         cmdarg_err("-o flag \"%s\" specifies obsolete preference", ws_optarg);
635         exit_status = INVALID_OPTION;
636         goto clean_exit;
637         break;
638       }
639       break;
640     }
641     case 'q':        /* Quiet */
642       quiet = TRUE;
643       break;
644     case 'Q':        /* Really quiet */
645       quiet = TRUE;
646       really_quiet = TRUE;
647       break;
648     case 'r':        /* Read capture file x */
649       cf_name = g_strdup(ws_optarg);
650       break;
651     case 'R':        /* Read file filter */
652       rfilter = ws_optarg;
653       break;
654     case 'S':        /* Set the line Separator to be printed between packets */
655       separator = g_strdup(ws_optarg);
656       break;
657     case 'T':        /* printing Type */
658       if (strcmp(ws_optarg, "text") == 0) {
659         output_action = WRITE_TEXT;
660         print_format = PR_FMT_TEXT;
661       } else if (strcmp(ws_optarg, "ps") == 0) {
662         output_action = WRITE_TEXT;
663         print_format = PR_FMT_PS;
664       } else if (strcmp(ws_optarg, "pdml") == 0) {
665         output_action = WRITE_XML;
666         print_details = TRUE;   /* Need details */
667         print_summary = FALSE;  /* Don't allow summary */
668       } else if (strcmp(ws_optarg, "psml") == 0) {
669         output_action = WRITE_XML;
670         print_details = FALSE;  /* Don't allow details */
671         print_summary = TRUE;   /* Need summary */
672       } else if (strcmp(ws_optarg, "fields") == 0) {
673         output_action = WRITE_FIELDS;
674         print_details = TRUE;   /* Need full tree info */
675         print_summary = FALSE;  /* Don't allow summary */
676       } else {
677         cmdarg_err("Invalid -T parameter \"%s\"; it must be one of:", ws_optarg);                   /* x */
678         cmdarg_err_cont("\t\"fields\" The values of fields specified with the -e option, in a form\n"
679                         "\t         specified by the -E option.\n"
680                         "\t\"pdml\"   Packet Details Markup Language, an XML-based format for the\n"
681                         "\t         details of a decoded packet. This information is equivalent to\n"
682                         "\t         the packet details printed with the -V flag.\n"
683                         "\t\"ps\"     PostScript for a human-readable one-line summary of each of\n"
684                         "\t         the packets, or a multi-line view of the details of each of\n"
685                         "\t         the packets, depending on whether the -V flag was specified.\n"
686                         "\t\"psml\"   Packet Summary Markup Language, an XML-based format for the\n"
687                         "\t         summary information of a decoded packet. This information is\n"
688                         "\t         equivalent to the information shown in the one-line summary\n"
689                         "\t         printed by default.\n"
690                         "\t\"text\"   Text of a human-readable one-line summary of each of the\n"
691                         "\t         packets, or a multi-line view of the details of each of the\n"
692                         "\t         packets, depending on whether the -V flag was specified.\n"
693                         "\t         This is the default.");
694         exit_status = INVALID_OPTION;
695         goto clean_exit;
696       }
697       break;
698     case 'v':         /* Show version and exit */
699       show_version();
700       goto clean_exit;
701     case 'O':        /* Only output these protocols */
702       /* already processed; just ignore it now */
703       break;
704     case 'V':        /* Verbose */
705       /* already processed; just ignore it now */
706       break;
707     case 'x':        /* Print packet data in hex (and ASCII) */
708       /* already processed; just ignore it now */
709       break;
710     case 'X':
711       /* already processed; just ignore it now */
712       break;
713     case 'Y':
714       dfilter = ws_optarg;
715       break;
716     case 'z':
717       /* We won't call the init function for the stat this soon
718          as it would disallow MATE's fields (which are registered
719          by the preferences set callback) from being used as
720          part of a tap filter.  Instead, we just add the argument
721          to a list of stat arguments. */
722       if (strcmp("help", ws_optarg) == 0) {
723         fprintf(stderr, "tfshark: The available statistics for the \"-z\" option are:\n");
724         list_stat_cmd_args();
725         goto clean_exit;
726       }
727       if (!process_stat_cmd_arg(ws_optarg)) {
728         cmdarg_err("Invalid -z argument \"%s\"; it must be one of:", ws_optarg);
729         list_stat_cmd_args();
730         exit_status = INVALID_OPTION;
731         goto clean_exit;
732       }
733       break;
734     case 'd':        /* Decode as rule */
735     case 'K':        /* Kerberos keytab file */
736     case 't':        /* Time stamp type */
737     case 'u':        /* Seconds type */
738     case LONGOPT_DISABLE_PROTOCOL: /* disable dissection of protocol */
739     case LONGOPT_ENABLE_HEURISTIC: /* enable heuristic dissection of protocol */
740     case LONGOPT_DISABLE_HEURISTIC: /* disable heuristic dissection of protocol */
741     case LONGOPT_ENABLE_PROTOCOL: /* enable dissection of protocol (that is disabled by default) */
742       if (!dissect_opts_handle_opt(opt, ws_optarg)) {
743         exit_status = INVALID_OPTION;
744         goto clean_exit;
745       }
746       break;
747     default:
748     case '?':        /* Bad flag - print usage message */
749       print_usage(stderr);
750       exit_status = INVALID_OPTION;
751       goto clean_exit;
752       break;
753     }
754   }
755 
756   /* If we specified output fields, but not the output field type... */
757   if (WRITE_FIELDS != output_action && 0 != output_fields_num_fields(output_fields)) {
758         cmdarg_err("Output fields were specified with \"-e\", "
759             "but \"-Tfields\" was not specified.");
760         return 1;
761   } else if (WRITE_FIELDS == output_action && 0 == output_fields_num_fields(output_fields)) {
762         cmdarg_err("\"-Tfields\" was specified, but no fields were "
763                     "specified with \"-e\".");
764 
765         exit_status = INVALID_OPTION;
766         goto clean_exit;
767   }
768 
769   /* We require a -r flag specifying a file to read. */
770   if (cf_name == NULL) {
771     cmdarg_err("A file to read must be specified with \"-r\".");
772     exit_status = NO_FILE_SPECIFIED;
773     goto clean_exit;
774   }
775 
776   /* If no display filter has been specified, and there are still command-
777      line arguments, treat them as the tokens of a display filter. */
778   if (ws_optind < argc) {
779     if (dfilter != NULL) {
780       cmdarg_err("Display filters were specified both with \"-Y\" "
781           "and with additional command-line arguments.");
782       exit_status = INVALID_OPTION;
783       goto clean_exit;
784     }
785     dfilter = get_args_as_string(argc, argv, ws_optind);
786   }
787 
788   /* if "-q" wasn't specified, we should print packet information */
789   if (!quiet)
790     print_packet_info = TRUE;
791 
792   if (arg_error) {
793     print_usage(stderr);
794     exit_status = INVALID_OPTION;
795     goto clean_exit;
796   }
797 
798   if (print_hex) {
799     if (output_action != WRITE_TEXT) {
800       cmdarg_err("Raw packet hex data can only be printed as text or PostScript");
801       exit_status = INVALID_OPTION;
802       goto clean_exit;
803     }
804   }
805 
806   if (output_only != NULL) {
807     char *ps;
808 
809     if (!print_details) {
810       cmdarg_err("-O requires -V");
811       exit_status = INVALID_OPTION;
812       goto clean_exit;
813     }
814 
815     output_only_tables = g_hash_table_new (g_str_hash, g_str_equal);
816     for (ps = strtok (output_only, ","); ps; ps = strtok (NULL, ",")) {
817       g_hash_table_insert(output_only_tables, (gpointer)ps, (gpointer)ps);
818     }
819   }
820 
821   if (rfilter != NULL && !perform_two_pass_analysis) {
822     cmdarg_err("-R without -2 is deprecated. For single-pass filtering use -Y.");
823     exit_status = INVALID_OPTION;
824     goto clean_exit;
825   }
826 
827   /* Notify all registered modules that have had any of their preferences
828      changed either from one of the preferences file or from the command
829      line that their preferences have changed. */
830   prefs_apply_all();
831 
832   /*
833    * Enabled and disabled protocols and heuristic dissectors as per
834    * command-line options.
835    */
836   if (!setup_enabled_and_disabled_protocols()) {
837     exit_status = INVALID_OPTION;
838     goto clean_exit;
839   }
840 
841   /* Build the column format array */
842   build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
843 
844   if (rfilter != NULL) {
845     if (!dfilter_compile(rfilter, &rfcode, &err_msg)) {
846       cmdarg_err("%s", err_msg);
847       g_free(err_msg);
848       exit_status = INVALID_FILTER;
849       goto clean_exit;
850     }
851   }
852   cfile.rfcode = rfcode;
853 
854   if (dfilter != NULL) {
855     if (!dfilter_compile(dfilter, &dfcode, &err_msg)) {
856       cmdarg_err("%s", err_msg);
857       g_free(err_msg);
858       exit_status = INVALID_FILTER;
859       goto clean_exit;
860     }
861   }
862   cfile.dfcode = dfcode;
863 
864   if (print_packet_info) {
865     /* If we're printing as text or PostScript, we have
866        to create a print stream. */
867     if (output_action == WRITE_TEXT) {
868       switch (print_format) {
869 
870       case PR_FMT_TEXT:
871         print_stream = print_stream_text_stdio_new(stdout);
872         break;
873 
874       case PR_FMT_PS:
875         print_stream = print_stream_ps_stdio_new(stdout);
876         break;
877 
878       default:
879         ws_assert_not_reached();
880       }
881     }
882   }
883 
884   /* We have to dissect each packet if:
885 
886         we're printing information about each packet;
887 
888         we're using a read filter on the packets;
889 
890         we're using a display filter on the packets;
891 
892         we're using any taps that need dissection. */
893   do_dissection = print_packet_info || rfcode || dfcode || tap_listeners_require_dissection();
894 
895   /*
896    * Read the file.
897    */
898 
899   /* TODO: if tfshark is ever changed to give the user a choice of which
900      open_routine reader to use, then the following needs to change. */
901   if (cf_open(&cfile, cf_name, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK) {
902     exit_status = OPEN_ERROR;
903     goto clean_exit;
904   }
905 
906   /* Start statistics taps; we do so after successfully opening the
907      capture file, so we know we have something to compute stats
908      on, and after registering all dissectors, so that MATE will
909      have registered its field array so we can have a tap filter
910      with one of MATE's late-registered fields as part of the
911      filter. */
912   start_requested_stats();
913 
914   /* Process the packets in the file */
915   TRY {
916     /* XXX - for now there is only 1 packet */
917     success = process_file(&cfile, 1, 0);
918   }
919   CATCH(OutOfMemoryError) {
920     fprintf(stderr,
921             "Out Of Memory.\n"
922             "\n"
923             "Sorry, but TFShark has to terminate now.\n"
924             "\n"
925             "Some infos / workarounds can be found at:\n"
926              WS_WIKI_URL("KnownBugs/OutOfMemory") "\n");
927     success = FALSE;
928   }
929   ENDTRY;
930 
931   if (!success) {
932     /* We still dump out the results of taps, etc., as we might have
933        read some packets; however, we exit with an error status. */
934     exit_status = 2;
935   }
936 
937   g_free(cf_name);
938 
939   if (cfile.provider.frames != NULL) {
940     free_frame_data_sequence(cfile.provider.frames);
941     cfile.provider.frames = NULL;
942   }
943 
944   draw_tap_listeners(TRUE);
945   funnel_dump_all_text_windows();
946 
947 clean_exit:
948   destroy_print_stream(print_stream);
949   epan_free(cfile.epan);
950   epan_cleanup();
951   extcap_cleanup();
952 
953   output_fields_free(output_fields);
954   output_fields = NULL;
955 
956   col_cleanup(&cfile.cinfo);
957   wtap_cleanup();
958   return exit_status;
959 }
960 
961 static const nstime_t *
tfshark_get_frame_ts(struct packet_provider_data * prov,guint32 frame_num)962 tfshark_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num)
963 {
964   if (prov->ref && prov->ref->num == frame_num)
965     return &prov->ref->abs_ts;
966 
967   if (prov->prev_dis && prov->prev_dis->num == frame_num)
968     return &prov->prev_dis->abs_ts;
969 
970   if (prov->prev_cap && prov->prev_cap->num == frame_num)
971     return &prov->prev_cap->abs_ts;
972 
973   if (prov->frames) {
974      frame_data *fd = frame_data_sequence_find(prov->frames, frame_num);
975 
976      return (fd) ? &fd->abs_ts : NULL;
977   }
978 
979   return NULL;
980 }
981 
982 static const char *
no_interface_name(struct packet_provider_data * prov _U_,guint32 interface_id _U_)983 no_interface_name(struct packet_provider_data *prov _U_, guint32 interface_id _U_)
984 {
985     return "";
986 }
987 
988 static epan_t *
tfshark_epan_new(capture_file * cf)989 tfshark_epan_new(capture_file *cf)
990 {
991   static const struct packet_provider_funcs funcs = {
992     tfshark_get_frame_ts,
993     no_interface_name,
994     NULL,
995     NULL,
996   };
997 
998   return epan_new(&cf->provider, &funcs);
999 }
1000 
1001 static gboolean
process_packet_first_pass(capture_file * cf,epan_dissect_t * edt,gint64 offset,wtap_rec * rec,const guchar * pd)1002 process_packet_first_pass(capture_file *cf, epan_dissect_t *edt,
1003                           gint64 offset, wtap_rec *rec,
1004                           const guchar *pd)
1005 {
1006   frame_data     fdlocal;
1007   guint32        framenum;
1008   gboolean       passed;
1009 
1010   /* The frame number of this packet is one more than the count of
1011      frames in this packet. */
1012   framenum = cf->count + 1;
1013 
1014   /* If we're not running a display filter and we're not printing any
1015      packet information, we don't need to do a dissection. This means
1016      that all packets can be marked as 'passed'. */
1017   passed = TRUE;
1018 
1019   frame_data_init(&fdlocal, framenum, rec, offset, cum_bytes);
1020 
1021   /* If we're going to print packet information, or we're going to
1022      run a read filter, or display filter, or we're going to process taps, set up to
1023      do a dissection and do so. */
1024   if (edt) {
1025     /* If we're running a read filter, prime the epan_dissect_t with that
1026        filter. */
1027     if (cf->rfcode)
1028       epan_dissect_prime_with_dfilter(edt, cf->rfcode);
1029 
1030     /* This is the first pass, so prime the epan_dissect_t with the
1031        hfids postdissectors want on the first pass. */
1032     prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1033 
1034     frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time,
1035                                   &cf->provider.ref, cf->provider.prev_dis);
1036     if (cf->provider.ref == &fdlocal) {
1037       ref_frame = fdlocal;
1038       cf->provider.ref = &ref_frame;
1039     }
1040 
1041     epan_dissect_file_run(edt, rec,
1042                           file_tvbuff_new(&cf->provider, &fdlocal, pd),
1043                           &fdlocal, NULL);
1044 
1045     /* Run the read filter if we have one. */
1046     if (cf->rfcode)
1047       passed = dfilter_apply_edt(cf->rfcode, edt);
1048   }
1049 
1050   if (passed) {
1051     frame_data_set_after_dissect(&fdlocal, &cum_bytes);
1052     cf->provider.prev_cap = cf->provider.prev_dis = frame_data_sequence_add(cf->provider.frames, &fdlocal);
1053 
1054     /* If we're not doing dissection then there won't be any dependent frames.
1055      * More importantly, edt.pi.dependent_frames won't be initialized because
1056      * epan hasn't been initialized.
1057      */
1058     if (edt) {
1059       g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
1060     }
1061 
1062     cf->count++;
1063   } else {
1064     /* if we don't add it to the frame_data_sequence, clean it up right now
1065      * to avoid leaks */
1066     frame_data_destroy(&fdlocal);
1067   }
1068 
1069   if (edt)
1070     epan_dissect_reset(edt);
1071 
1072   return passed;
1073 }
1074 
1075 static gboolean
process_packet_second_pass(capture_file * cf,epan_dissect_t * edt,frame_data * fdata,wtap_rec * rec,Buffer * buf,guint tap_flags)1076 process_packet_second_pass(capture_file *cf, epan_dissect_t *edt,
1077                            frame_data *fdata, wtap_rec *rec,
1078                            Buffer *buf, guint tap_flags)
1079 {
1080   column_info    *cinfo;
1081   gboolean        passed;
1082 
1083   /* If we're not running a display filter and we're not printing any
1084      packet information, we don't need to do a dissection. This means
1085      that all packets can be marked as 'passed'. */
1086   passed = TRUE;
1087 
1088   /* If we're going to print packet information, or we're going to
1089      run a read filter, or we're going to process taps, set up to
1090      do a dissection and do so. */
1091   if (edt) {
1092 
1093     /* If we're running a display filter, prime the epan_dissect_t with that
1094        filter. */
1095     if (cf->dfcode)
1096       epan_dissect_prime_with_dfilter(edt, cf->dfcode);
1097 
1098     /* This is the first and only pass, so prime the epan_dissect_t
1099        with the hfids postdissectors want on the first pass. */
1100     prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1101 
1102     col_custom_prime_edt(edt, &cf->cinfo);
1103 
1104     /* We only need the columns if either
1105          1) some tap needs the columns
1106        or
1107          2) we're printing packet info but we're *not* verbose; in verbose
1108             mode, we print the protocol tree, not the protocol summary.
1109      */
1110     if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary))
1111       cinfo = &cf->cinfo;
1112     else
1113       cinfo = NULL;
1114 
1115     frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1116                                   &cf->provider.ref, cf->provider.prev_dis);
1117     if (cf->provider.ref == fdata) {
1118       ref_frame = *fdata;
1119       cf->provider.ref = &ref_frame;
1120     }
1121 
1122     epan_dissect_file_run_with_taps(edt, rec,
1123         file_tvbuff_new_buffer(&cf->provider, fdata, buf), fdata, cinfo);
1124 
1125     /* Run the read/display filter if we have one. */
1126     if (cf->dfcode)
1127       passed = dfilter_apply_edt(cf->dfcode, edt);
1128   }
1129 
1130   if (passed) {
1131     frame_data_set_after_dissect(fdata, &cum_bytes);
1132     /* Process this packet. */
1133     if (print_packet_info) {
1134       /* We're printing packet information; print the information for
1135          this packet. */
1136       print_packet(cf, edt);
1137 
1138       /* If we're doing "line-buffering", flush the standard output
1139          after every packet.  See the comment above, for the "-l"
1140          option, for an explanation of why we do that. */
1141       if (line_buffered)
1142         fflush(stdout);
1143 
1144       if (ferror(stdout)) {
1145         show_print_file_io_error(errno);
1146         return FALSE;
1147       }
1148     }
1149     cf->provider.prev_dis = fdata;
1150   }
1151   cf->provider.prev_cap = fdata;
1152 
1153   if (edt) {
1154     epan_dissect_reset(edt);
1155   }
1156   return passed || fdata->dependent_of_displayed;
1157 }
1158 
1159 static gboolean
local_wtap_read(capture_file * cf,wtap_rec * file_rec _U_,int * err,gchar ** err_info _U_,gint64 * data_offset _U_,guint8 ** data_buffer)1160 local_wtap_read(capture_file *cf, wtap_rec *file_rec _U_, int *err, gchar **err_info _U_, gint64 *data_offset _U_, guint8** data_buffer)
1161 {
1162     /* int bytes_read; */
1163     gint64 packet_size = wtap_file_size(cf->provider.wth, err);
1164 
1165     *data_buffer = (guint8*)g_malloc((gsize)packet_size);
1166     /* bytes_read =*/ file_read(*data_buffer, (unsigned int)packet_size, cf->provider.wth->fh);
1167 
1168 #if 0 /* no more filetap */
1169     if (bytes_read < 0) {
1170         *err = file_error(cf->provider.wth->fh, err_info);
1171         if (*err == 0)
1172             *err = FTAP_ERR_SHORT_READ;
1173         return FALSE;
1174     } else if (bytes_read == 0) {
1175         /* Done with file, no error */
1176         return FALSE;
1177     }
1178 
1179 
1180     /* XXX - SET FRAME SIZE EQUAL TO TOTAL FILE SIZE */
1181     file_rec->rec_header.packet_header.caplen = (guint32)packet_size;
1182     file_rec->rec_header.packet_header.len = (guint32)packet_size;
1183 
1184     /*
1185      * Set the packet encapsulation to the file's encapsulation
1186      * value; if that's not WTAP_ENCAP_PER_PACKET, it's the
1187      * right answer (and means that the read routine for this
1188      * capture file type doesn't have to set it), and if it
1189      * *is* WTAP_ENCAP_PER_PACKET, the caller needs to set it
1190      * anyway.
1191      */
1192     wth->rec.rec_header.packet_header.pkt_encap = wth->file_encap;
1193 
1194     if (!wth->subtype_read(wth, err, err_info, data_offset)) {
1195         /*
1196          * If we didn't get an error indication, we read
1197          * the last packet.  See if there's any deferred
1198          * error, as might, for example, occur if we're
1199          * reading a compressed file, and we got an error
1200          * reading compressed data from the file, but
1201          * got enough compressed data to decompress the
1202          * last packet of the file.
1203          */
1204         if (*err == 0)
1205             *err = file_error(wth->fh, err_info);
1206         return FALSE;    /* failure */
1207     }
1208 
1209     /*
1210      * It makes no sense for the captured data length to be bigger
1211      * than the actual data length.
1212      */
1213     if (wth->rec.rec_header.packet_header.caplen > wth->rec.rec_header.packet_header.len)
1214         wth->rec.rec_header.packet_header.caplen = wth->rec.rec_header.packet_header.len;
1215 
1216     /*
1217      * Make sure that it's not WTAP_ENCAP_PER_PACKET, as that
1218      * probably means the file has that encapsulation type
1219      * but the read routine didn't set this packet's
1220      * encapsulation type.
1221      */
1222     ws_assert(wth->rec.rec_header.packet_header.pkt_encap != WTAP_ENCAP_PER_PACKET);
1223 #endif
1224 
1225     return TRUE; /* success */
1226 }
1227 
1228 static gboolean
process_file(capture_file * cf,int max_packet_count,gint64 max_byte_count)1229 process_file(capture_file *cf, int max_packet_count, gint64 max_byte_count)
1230 {
1231   guint32      framenum;
1232   int          err;
1233   gchar       *err_info = NULL;
1234   gint64       data_offset = 0;
1235   gboolean     filtering_tap_listeners;
1236   guint        tap_flags;
1237   Buffer       buf;
1238   epan_dissect_t *edt = NULL;
1239   wtap_rec     file_rec;
1240   guint8* raw_data;
1241 
1242   if (print_packet_info) {
1243     if (!write_preamble(cf)) {
1244       err = errno;
1245       show_print_file_io_error(err);
1246       goto out;
1247     }
1248   }
1249 
1250   /* Do we have any tap listeners with filters? */
1251   filtering_tap_listeners = have_filtering_tap_listeners();
1252 
1253   /* Get the union of the flags for all tap listeners. */
1254   tap_flags = union_of_tap_listener_flags();
1255 
1256   wtap_rec_init(&file_rec);
1257 
1258   /* XXX - TEMPORARY HACK TO ELF DISSECTOR */
1259   file_rec.rec_header.packet_header.pkt_encap = 1234;
1260 
1261   if (perform_two_pass_analysis) {
1262     frame_data *fdata;
1263 
1264     /* Allocate a frame_data_sequence for all the frames. */
1265     cf->provider.frames = new_frame_data_sequence();
1266 
1267     if (do_dissection) {
1268       gboolean create_proto_tree;
1269 
1270       /*
1271        * Determine whether we need to create a protocol tree.
1272        * We do if:
1273        *
1274        *    we're going to apply a read filter;
1275        *
1276        *    a postdissector wants field values or protocols
1277        *    on the first pass.
1278        */
1279       create_proto_tree =
1280         (cf->rfcode != NULL || postdissectors_want_hfids());
1281 
1282       /* We're not going to display the protocol tree on this pass,
1283          so it's not going to be "visible". */
1284       edt = epan_dissect_new(cf->epan, create_proto_tree, FALSE);
1285     }
1286     while (local_wtap_read(cf, &file_rec, &err, &err_info, &data_offset, &raw_data)) {
1287       if (process_packet_first_pass(cf, edt, data_offset, &file_rec, raw_data)) {
1288 
1289         /* Stop reading if we have the maximum number of packets;
1290          * When the -c option has not been used, max_packet_count
1291          * starts at 0, which practically means, never stop reading.
1292          * (unless we roll over max_packet_count ?)
1293          */
1294         if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
1295           err = 0; /* This is not an error */
1296           break;
1297         }
1298       }
1299     }
1300 
1301     if (edt) {
1302       epan_dissect_free(edt);
1303       edt = NULL;
1304     }
1305 
1306 #if 0
1307     /* Close the sequential I/O side, to free up memory it requires. */
1308     wtap_sequential_close(cf->provider.wth);
1309 #endif
1310 
1311     /* Allow the protocol dissectors to free up memory that they
1312      * don't need after the sequential run-through of the packets. */
1313     postseq_cleanup_all_protocols();
1314 
1315     cf->provider.prev_dis = NULL;
1316     cf->provider.prev_cap = NULL;
1317     ws_buffer_init(&buf, 1514);
1318 
1319     if (do_dissection) {
1320       gboolean create_proto_tree;
1321 
1322       /*
1323        * Determine whether we need to create a protocol tree.
1324        * We do if:
1325        *
1326        *    we're going to apply a display filter;
1327        *
1328        *    we're going to print the protocol tree;
1329        *
1330        *    one of the tap listeners requires a protocol tree;
1331        *
1332        *    we have custom columns (which require field values, which
1333        *    currently requires that we build a protocol tree).
1334        */
1335       create_proto_tree =
1336         (cf->dfcode || print_details || filtering_tap_listeners ||
1337          (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo));
1338 
1339       /* The protocol tree will be "visible", i.e., printed, only if we're
1340          printing packet details, which is true if we're printing stuff
1341          ("print_packet_info" is true) and we're in verbose mode
1342          ("packet_details" is true). */
1343       edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details);
1344     }
1345 
1346     for (framenum = 1; err == 0 && framenum <= cf->count; framenum++) {
1347       fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1348 #if 0
1349       if (wtap_seek_read(cf->provider.wth, fdata->file_off,
1350           &buf, fdata->cap_len, &err, &err_info)) {
1351         process_packet_second_pass(cf, edt, fdata, &cf->rec, &buf, tap_flags);
1352       }
1353 #else
1354       if (!process_packet_second_pass(cf, edt, fdata, &cf->rec, &buf,
1355                                        tap_flags))
1356         return FALSE;
1357 #endif
1358     }
1359 
1360     if (edt) {
1361       epan_dissect_free(edt);
1362       edt = NULL;
1363     }
1364 
1365     ws_buffer_free(&buf);
1366   }
1367   else {
1368     framenum = 0;
1369 
1370     if (do_dissection) {
1371       gboolean create_proto_tree;
1372 
1373       /*
1374        * Determine whether we need to create a protocol tree.
1375        * We do if:
1376        *
1377        *    we're going to apply a read filter;
1378        *
1379        *    we're going to apply a display filter;
1380        *
1381        *    we're going to print the protocol tree;
1382        *
1383        *    one of the tap listeners is going to apply a filter;
1384        *
1385        *    one of the tap listeners requires a protocol tree;
1386        *
1387        *    a postdissector wants field values or protocols
1388        *    on the first pass;
1389        *
1390        *    we have custom columns (which require field values, which
1391        *    currently requires that we build a protocol tree).
1392        */
1393       create_proto_tree =
1394         (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners ||
1395           (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids() ||
1396           have_custom_cols(&cf->cinfo));
1397 
1398       /* The protocol tree will be "visible", i.e., printed, only if we're
1399          printing packet details, which is true if we're printing stuff
1400          ("print_packet_info" is true) and we're in verbose mode
1401          ("packet_details" is true). */
1402       edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details);
1403     }
1404 
1405     while (local_wtap_read(cf, &file_rec, &err, &err_info, &data_offset, &raw_data)) {
1406 
1407       framenum++;
1408 
1409       if (!process_packet_single_pass(cf, edt, data_offset,
1410                                       &file_rec/*wtap_get_rec(cf->provider.wth)*/,
1411                                       raw_data, tap_flags))
1412         return FALSE;
1413 
1414       /* Stop reading if we have the maximum number of packets;
1415       * When the -c option has not been used, max_packet_count
1416       * starts at 0, which practically means, never stop reading.
1417       * (unless we roll over max_packet_count ?)
1418       */
1419       if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
1420         err = 0; /* This is not an error */
1421         break;
1422       }
1423     }
1424 
1425     if (edt) {
1426       epan_dissect_free(edt);
1427       edt = NULL;
1428     }
1429   }
1430 
1431   wtap_rec_cleanup(&file_rec);
1432 
1433   if (err != 0) {
1434     /*
1435      * Print a message noting that the read failed somewhere along the line.
1436      *
1437      * If we're printing packet data, and the standard output and error are
1438      * going to the same place, flush the standard output, so everything
1439      * buffered up is written, and then print a newline to the standard error
1440      * before printing the error message, to separate it from the packet
1441      * data.  (Alas, that only works on UN*X; st_dev is meaningless, and
1442      * the _fstat() documentation at Microsoft doesn't indicate whether
1443      * st_ino is even supported.)
1444      */
1445 #ifndef _WIN32
1446     if (print_packet_info) {
1447       ws_statb64 stat_stdout, stat_stderr;
1448 
1449       if (ws_fstat64(1, &stat_stdout) == 0 && ws_fstat64(2, &stat_stderr) == 0) {
1450         if (stat_stdout.st_dev == stat_stderr.st_dev &&
1451             stat_stdout.st_ino == stat_stderr.st_ino) {
1452           fflush(stdout);
1453           fprintf(stderr, "\n");
1454         }
1455       }
1456     }
1457 #endif
1458 #if 0
1459     switch (err) {
1460 
1461     case FTAP_ERR_UNSUPPORTED:
1462       cmdarg_err("The file \"%s\" contains record data that TFShark doesn't support.\n(%s)",
1463                  cf->filename, err_info);
1464       g_free(err_info);
1465       break;
1466 
1467     case FTAP_ERR_UNSUPPORTED_ENCAP:
1468       cmdarg_err("The file \"%s\" has a packet with a network type that TFShark doesn't support.\n(%s)",
1469                  cf->filename, err_info);
1470       g_free(err_info);
1471       break;
1472 
1473     case FTAP_ERR_CANT_READ:
1474       cmdarg_err("An attempt to read from the file \"%s\" failed for some unknown reason.",
1475                  cf->filename);
1476       break;
1477 
1478     case FTAP_ERR_SHORT_READ:
1479       cmdarg_err("The file \"%s\" appears to have been cut short in the middle of a packet.",
1480                  cf->filename);
1481       break;
1482 
1483     case FTAP_ERR_BAD_FILE:
1484       cmdarg_err("The file \"%s\" appears to be damaged or corrupt.\n(%s)",
1485                  cf->filename, err_info);
1486       g_free(err_info);
1487       break;
1488 
1489     case FTAP_ERR_DECOMPRESS:
1490       cmdarg_err("The compressed file \"%s\" appears to be damaged or corrupt.\n"
1491                  "(%s)", cf->filename, err_info);
1492       break;
1493 
1494     default:
1495       cmdarg_err("An error occurred while reading the file \"%s\": %s.",
1496                  cf->filename, ftap_strerror(err));
1497       break;
1498     }
1499 #endif
1500   } else {
1501     if (print_packet_info) {
1502       if (!write_finale()) {
1503         err = errno;
1504         show_print_file_io_error(err);
1505       }
1506     }
1507   }
1508 
1509 out:
1510   wtap_close(cf->provider.wth);
1511   cf->provider.wth = NULL;
1512 
1513   return (err != 0);
1514 }
1515 
1516 static gboolean
process_packet_single_pass(capture_file * cf,epan_dissect_t * edt,gint64 offset,wtap_rec * rec,const guchar * pd,guint tap_flags)1517 process_packet_single_pass(capture_file *cf, epan_dissect_t *edt, gint64 offset,
1518                            wtap_rec *rec, const guchar *pd,
1519                            guint tap_flags)
1520 {
1521   frame_data      fdata;
1522   column_info    *cinfo;
1523   gboolean        passed;
1524 
1525   /* Count this packet. */
1526   cf->count++;
1527 
1528   /* If we're not running a display filter and we're not printing any
1529      packet information, we don't need to do a dissection. This means
1530      that all packets can be marked as 'passed'. */
1531   passed = TRUE;
1532 
1533   frame_data_init(&fdata, cf->count, rec, offset, cum_bytes);
1534 
1535   /* If we're going to print packet information, or we're going to
1536      run a read filter, or we're going to process taps, set up to
1537      do a dissection and do so. */
1538   if (edt) {
1539     /* If we're running a filter, prime the epan_dissect_t with that
1540        filter. */
1541     if (cf->dfcode)
1542       epan_dissect_prime_with_dfilter(edt, cf->dfcode);
1543 
1544     col_custom_prime_edt(edt, &cf->cinfo);
1545 
1546     /* We only need the columns if either
1547          1) some tap needs the columns
1548        or
1549          2) we're printing packet info but we're *not* verbose; in verbose
1550             mode, we print the protocol tree, not the protocol summary.
1551        or
1552          3) there is a column mapped as an individual field */
1553     if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary) || output_fields_has_cols(output_fields))
1554       cinfo = &cf->cinfo;
1555     else
1556       cinfo = NULL;
1557 
1558     frame_data_set_before_dissect(&fdata, &cf->elapsed_time,
1559                                   &cf->provider.ref, cf->provider.prev_dis);
1560     if (cf->provider.ref == &fdata) {
1561       ref_frame = fdata;
1562       cf->provider.ref = &ref_frame;
1563     }
1564 
1565     epan_dissect_file_run_with_taps(edt, rec,
1566                                     frame_tvbuff_new(&cf->provider, &fdata, pd),
1567                                     &fdata, cinfo);
1568 
1569     /* Run the filter if we have it. */
1570     if (cf->dfcode)
1571       passed = dfilter_apply_edt(cf->dfcode, edt);
1572   }
1573 
1574   if (passed) {
1575     frame_data_set_after_dissect(&fdata, &cum_bytes);
1576 
1577     /* Process this packet. */
1578     if (print_packet_info) {
1579       /* We're printing packet information; print the information for
1580          this packet. */
1581       print_packet(cf, edt);
1582 
1583       /* If we're doing "line-buffering", flush the standard output
1584          after every packet.  See the comment above, for the "-l"
1585          option, for an explanation of why we do that. */
1586       if (line_buffered)
1587         fflush(stdout);
1588 
1589       if (ferror(stdout)) {
1590         show_print_file_io_error(errno);
1591         return FALSE;
1592       }
1593     }
1594 
1595     /* this must be set after print_packet() [bug #8160] */
1596     prev_dis_frame = fdata;
1597     cf->provider.prev_dis = &prev_dis_frame;
1598   }
1599 
1600   prev_cap_frame = fdata;
1601   cf->provider.prev_cap = &prev_cap_frame;
1602 
1603   if (edt) {
1604     epan_dissect_reset(edt);
1605     frame_data_destroy(&fdata);
1606   }
1607   return passed;
1608 }
1609 
1610 static gboolean
write_preamble(capture_file * cf)1611 write_preamble(capture_file *cf)
1612 {
1613   switch (output_action) {
1614 
1615   case WRITE_TEXT:
1616     return print_preamble(print_stream, cf->filename, get_ws_vcs_version_info());
1617 
1618   case WRITE_XML:
1619     if (print_details)
1620       write_pdml_preamble(stdout, cf->filename);
1621     else
1622       write_psml_preamble(&cf->cinfo, stdout);
1623     return !ferror(stdout);
1624 
1625   case WRITE_FIELDS:
1626     write_fields_preamble(output_fields, stdout);
1627     return !ferror(stdout);
1628 
1629   default:
1630     ws_assert_not_reached();
1631     return FALSE;
1632   }
1633 }
1634 
1635 static char *
get_line_buf(size_t len)1636 get_line_buf(size_t len)
1637 {
1638   static char   *line_bufp    = NULL;
1639   static size_t  line_buf_len = 256;
1640   size_t         new_line_buf_len;
1641 
1642   for (new_line_buf_len = line_buf_len; len > new_line_buf_len;
1643        new_line_buf_len *= 2)
1644     ;
1645   if (line_bufp == NULL) {
1646     line_buf_len = new_line_buf_len;
1647     line_bufp = (char *)g_malloc(line_buf_len + 1);
1648   } else {
1649     if (new_line_buf_len > line_buf_len) {
1650       line_buf_len = new_line_buf_len;
1651       line_bufp = (char *)g_realloc(line_bufp, line_buf_len + 1);
1652     }
1653   }
1654   return line_bufp;
1655 }
1656 
1657 static inline void
put_string(char * dest,const char * str,size_t str_len)1658 put_string(char *dest, const char *str, size_t str_len)
1659 {
1660   memcpy(dest, str, str_len);
1661   dest[str_len] = '\0';
1662 }
1663 
1664 static inline void
put_spaces_string(char * dest,const char * str,size_t str_len,size_t str_with_spaces)1665 put_spaces_string(char *dest, const char *str, size_t str_len, size_t str_with_spaces)
1666 {
1667   size_t i;
1668 
1669   for (i = str_len; i < str_with_spaces; i++)
1670     *dest++ = ' ';
1671 
1672   put_string(dest, str, str_len);
1673 }
1674 
1675 static inline void
put_string_spaces(char * dest,const char * str,size_t str_len,size_t str_with_spaces)1676 put_string_spaces(char *dest, const char *str, size_t str_len, size_t str_with_spaces)
1677 {
1678   size_t i;
1679 
1680   memcpy(dest, str, str_len);
1681   for (i = str_len; i < str_with_spaces; i++)
1682     dest[i] = ' ';
1683 
1684   dest[str_with_spaces] = '\0';
1685 }
1686 
1687 static gboolean
print_columns(capture_file * cf)1688 print_columns(capture_file *cf)
1689 {
1690   char   *line_bufp;
1691   int     i;
1692   size_t  buf_offset;
1693   size_t  column_len;
1694   size_t  col_len;
1695   col_item_t* col_item;
1696 
1697   line_bufp = get_line_buf(256);
1698   buf_offset = 0;
1699   *line_bufp = '\0';
1700   for (i = 0; i < cf->cinfo.num_cols; i++) {
1701     col_item = &cf->cinfo.columns[i];
1702     /* Skip columns not marked as visible. */
1703     if (!get_column_visible(i))
1704       continue;
1705     switch (col_item->col_fmt) {
1706     case COL_NUMBER:
1707       column_len = col_len = strlen(col_item->col_data);
1708       if (column_len < 3)
1709         column_len = 3;
1710       line_bufp = get_line_buf(buf_offset + column_len);
1711       put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1712       break;
1713 
1714     case COL_CLS_TIME:
1715     case COL_REL_TIME:
1716     case COL_ABS_TIME:
1717     case COL_ABS_YMD_TIME:  /* XXX - wider */
1718     case COL_ABS_YDOY_TIME: /* XXX - wider */
1719     case COL_UTC_TIME:
1720     case COL_UTC_YMD_TIME:  /* XXX - wider */
1721     case COL_UTC_YDOY_TIME: /* XXX - wider */
1722       column_len = col_len = strlen(col_item->col_data);
1723       if (column_len < 10)
1724         column_len = 10;
1725       line_bufp = get_line_buf(buf_offset + column_len);
1726       put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1727       break;
1728 
1729     case COL_DEF_SRC:
1730     case COL_RES_SRC:
1731     case COL_UNRES_SRC:
1732     case COL_DEF_DL_SRC:
1733     case COL_RES_DL_SRC:
1734     case COL_UNRES_DL_SRC:
1735     case COL_DEF_NET_SRC:
1736     case COL_RES_NET_SRC:
1737     case COL_UNRES_NET_SRC:
1738       column_len = col_len = strlen(col_item->col_data);
1739       if (column_len < 12)
1740         column_len = 12;
1741       line_bufp = get_line_buf(buf_offset + column_len);
1742       put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1743       break;
1744 
1745     case COL_DEF_DST:
1746     case COL_RES_DST:
1747     case COL_UNRES_DST:
1748     case COL_DEF_DL_DST:
1749     case COL_RES_DL_DST:
1750     case COL_UNRES_DL_DST:
1751     case COL_DEF_NET_DST:
1752     case COL_RES_NET_DST:
1753     case COL_UNRES_NET_DST:
1754       column_len = col_len = strlen(col_item->col_data);
1755       if (column_len < 12)
1756         column_len = 12;
1757       line_bufp = get_line_buf(buf_offset + column_len);
1758       put_string_spaces(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
1759       break;
1760 
1761     default:
1762       column_len = strlen(col_item->col_data);
1763       line_bufp = get_line_buf(buf_offset + column_len);
1764       put_string(line_bufp + buf_offset, col_item->col_data, column_len);
1765       break;
1766     }
1767     buf_offset += column_len;
1768     if (i != cf->cinfo.num_cols - 1) {
1769       /*
1770        * This isn't the last column, so we need to print a
1771        * separator between this column and the next.
1772        *
1773        * If we printed a network source and are printing a
1774        * network destination of the same type next, separate
1775        * them with " -> "; if we printed a network destination
1776        * and are printing a network source of the same type
1777        * next, separate them with " <- "; otherwise separate them
1778        * with a space.
1779        *
1780        * We add enough space to the buffer for " <- " or " -> ",
1781        * even if we're only adding " ".
1782        */
1783       line_bufp = get_line_buf(buf_offset + 4);
1784       switch (col_item->col_fmt) {
1785 
1786       case COL_DEF_SRC:
1787       case COL_RES_SRC:
1788       case COL_UNRES_SRC:
1789         switch (cf->cinfo.columns[i+1].col_fmt) {
1790 
1791         case COL_DEF_DST:
1792         case COL_RES_DST:
1793         case COL_UNRES_DST:
1794           put_string(line_bufp + buf_offset, " -> ", 4);
1795           buf_offset += 4;
1796           break;
1797 
1798         default:
1799           put_string(line_bufp + buf_offset, " ", 1);
1800           buf_offset += 1;
1801           break;
1802         }
1803         break;
1804 
1805       case COL_DEF_DL_SRC:
1806       case COL_RES_DL_SRC:
1807       case COL_UNRES_DL_SRC:
1808         switch (cf->cinfo.columns[i+1].col_fmt) {
1809 
1810         case COL_DEF_DL_DST:
1811         case COL_RES_DL_DST:
1812         case COL_UNRES_DL_DST:
1813           put_string(line_bufp + buf_offset, " -> ", 4);
1814           buf_offset += 4;
1815           break;
1816 
1817         default:
1818           put_string(line_bufp + buf_offset, " ", 1);
1819           buf_offset += 1;
1820           break;
1821         }
1822         break;
1823 
1824       case COL_DEF_NET_SRC:
1825       case COL_RES_NET_SRC:
1826       case COL_UNRES_NET_SRC:
1827         switch (cf->cinfo.columns[i+1].col_fmt) {
1828 
1829         case COL_DEF_NET_DST:
1830         case COL_RES_NET_DST:
1831         case COL_UNRES_NET_DST:
1832           put_string(line_bufp + buf_offset, " -> ", 4);
1833           buf_offset += 4;
1834           break;
1835 
1836         default:
1837           put_string(line_bufp + buf_offset, " ", 1);
1838           buf_offset += 1;
1839           break;
1840         }
1841         break;
1842 
1843       case COL_DEF_DST:
1844       case COL_RES_DST:
1845       case COL_UNRES_DST:
1846         switch (cf->cinfo.columns[i+1].col_fmt) {
1847 
1848         case COL_DEF_SRC:
1849         case COL_RES_SRC:
1850         case COL_UNRES_SRC:
1851           put_string(line_bufp + buf_offset, " <- ", 4);
1852           buf_offset += 4;
1853           break;
1854 
1855         default:
1856           put_string(line_bufp + buf_offset, " ", 1);
1857           buf_offset += 1;
1858           break;
1859         }
1860         break;
1861 
1862       case COL_DEF_DL_DST:
1863       case COL_RES_DL_DST:
1864       case COL_UNRES_DL_DST:
1865         switch (cf->cinfo.columns[i+1].col_fmt) {
1866 
1867         case COL_DEF_DL_SRC:
1868         case COL_RES_DL_SRC:
1869         case COL_UNRES_DL_SRC:
1870           put_string(line_bufp + buf_offset, " <- ", 4);
1871           buf_offset += 4;
1872           break;
1873 
1874         default:
1875           put_string(line_bufp + buf_offset, " ", 1);
1876           buf_offset += 1;
1877           break;
1878         }
1879         break;
1880 
1881       case COL_DEF_NET_DST:
1882       case COL_RES_NET_DST:
1883       case COL_UNRES_NET_DST:
1884         switch (cf->cinfo.columns[i+1].col_fmt) {
1885 
1886         case COL_DEF_NET_SRC:
1887         case COL_RES_NET_SRC:
1888         case COL_UNRES_NET_SRC:
1889           put_string(line_bufp + buf_offset, " <- ", 4);
1890           buf_offset += 4;
1891           break;
1892 
1893         default:
1894           put_string(line_bufp + buf_offset, " ", 1);
1895           buf_offset += 1;
1896           break;
1897         }
1898         break;
1899 
1900       default:
1901         put_string(line_bufp + buf_offset, " ", 1);
1902         buf_offset += 1;
1903         break;
1904       }
1905     }
1906   }
1907   return print_line(print_stream, 0, line_bufp);
1908 }
1909 
1910 static gboolean
print_packet(capture_file * cf,epan_dissect_t * edt)1911 print_packet(capture_file *cf, epan_dissect_t *edt)
1912 {
1913   if (print_summary || output_fields_has_cols(output_fields)) {
1914     /* Just fill in the columns. */
1915     epan_dissect_fill_in_columns(edt, FALSE, TRUE);
1916 
1917     if (print_summary) {
1918       /* Now print them. */
1919       switch (output_action) {
1920 
1921       case WRITE_TEXT:
1922         if (!print_columns(cf))
1923           return FALSE;
1924         break;
1925 
1926       case WRITE_XML:
1927         write_psml_columns(edt, stdout, FALSE);
1928         return !ferror(stdout);
1929       case WRITE_FIELDS: /*No non-verbose "fields" format */
1930         ws_assert_not_reached();
1931         break;
1932       }
1933     }
1934   }
1935   if (print_details) {
1936     /* Print the information in the protocol tree. */
1937     switch (output_action) {
1938 
1939     case WRITE_TEXT:
1940       if (!proto_tree_print(print_details ? print_dissections_expanded : print_dissections_none,
1941                             print_hex, edt, output_only_tables, print_stream))
1942         return FALSE;
1943       if (!print_hex) {
1944         if (!print_line(print_stream, 0, separator))
1945           return FALSE;
1946       }
1947       break;
1948 
1949     case WRITE_XML:
1950       write_pdml_proto_tree(NULL, NULL, PF_NONE, edt, &cf->cinfo, stdout, FALSE);
1951       printf("\n");
1952       return !ferror(stdout);
1953     case WRITE_FIELDS:
1954       write_fields_proto_tree(output_fields, edt, &cf->cinfo, stdout);
1955       printf("\n");
1956       return !ferror(stdout);
1957     }
1958   }
1959   if (print_hex) {
1960     if (print_summary || print_details) {
1961       if (!print_line(print_stream, 0, ""))
1962         return FALSE;
1963     }
1964     if (!print_hex_data(print_stream, edt))
1965       return FALSE;
1966     if (!print_line(print_stream, 0, separator))
1967       return FALSE;
1968   }
1969   return TRUE;
1970 }
1971 
1972 static gboolean
write_finale(void)1973 write_finale(void)
1974 {
1975   switch (output_action) {
1976 
1977   case WRITE_TEXT:
1978     return print_finale(print_stream);
1979 
1980   case WRITE_XML:
1981     if (print_details)
1982       write_pdml_finale(stdout);
1983     else
1984       write_psml_finale(stdout);
1985     return !ferror(stdout);
1986 
1987   case WRITE_FIELDS:
1988     write_fields_finale(output_fields, stdout);
1989     return !ferror(stdout);
1990 
1991   default:
1992     ws_assert_not_reached();
1993     return FALSE;
1994   }
1995 }
1996 
1997 cf_status_t
cf_open(capture_file * cf,const char * fname,unsigned int type,gboolean is_tempfile,int * err)1998 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
1999 {
2000   gchar *err_info;
2001   char   err_msg[2048+1];
2002 
2003   /* The open isn't implemented yet.  Fill in the information for this file. */
2004 
2005   /* Create new epan session for dissection. */
2006   epan_free(cf->epan);
2007   cf->epan = tfshark_epan_new(cf);
2008 
2009   cf->provider.wth = NULL; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2010   cf->f_datalen = 0; /* not used, but set it anyway */
2011 
2012   /* Set the file name because we need it to set the follow stream filter.
2013      XXX - is that still true?  We need it for other reasons, though,
2014      in any case. */
2015   cf->filename = g_strdup(fname);
2016 
2017   /* Indicate whether it's a permanent or temporary file. */
2018   cf->is_tempfile = is_tempfile;
2019 
2020   /* No user changes yet. */
2021   cf->unsaved_changes = FALSE;
2022 
2023   cf->cd_t      = 0; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2024   cf->open_type = type;
2025   cf->count     = 0;
2026   cf->drops_known = FALSE;
2027   cf->drops     = 0;
2028   cf->snap      = 0; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */
2029   nstime_set_zero(&cf->elapsed_time);
2030   cf->provider.ref = NULL;
2031   cf->provider.prev_dis = NULL;
2032   cf->provider.prev_cap = NULL;
2033 
2034   cf->state = FILE_READ_IN_PROGRESS;
2035 
2036   return CF_OK;
2037 
2038 /* fail: */
2039   g_snprintf(err_msg, sizeof err_msg,
2040              cf_open_error_message(*err, err_info, FALSE, cf->cd_t), fname);
2041   cmdarg_err("%s", err_msg);
2042   return CF_ERROR;
2043 }
2044 
2045 static void
show_print_file_io_error(int err)2046 show_print_file_io_error(int err)
2047 {
2048   switch (err) {
2049 
2050   case ENOSPC:
2051     cmdarg_err("Not all the packets could be printed because there is "
2052 "no space left on the file system.");
2053     break;
2054 
2055 #ifdef EDQUOT
2056   case EDQUOT:
2057     cmdarg_err("Not all the packets could be printed because you are "
2058 "too close to, or over your disk quota.");
2059   break;
2060 #endif
2061 
2062   default:
2063     cmdarg_err("An error occurred while printing packets: %s.",
2064       g_strerror(err));
2065     break;
2066   }
2067 }
2068 
2069 static const char *
cf_open_error_message(int err,gchar * err_info _U_,gboolean for_writing,int file_type _U_)2070 cf_open_error_message(int err, gchar *err_info _U_, gboolean for_writing,
2071                       int file_type _U_)
2072 {
2073   const char *errmsg;
2074   /* static char errmsg_errno[1024+1]; */
2075 
2076 #if 0
2077   if (err < 0) {
2078     /* Wiretap error. */
2079     switch (err) {
2080 
2081     case FTAP_ERR_NOT_REGULAR_FILE:
2082       errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
2083       break;
2084 
2085     case FTAP_ERR_RANDOM_OPEN_PIPE:
2086       /* Seen only when opening a capture file for reading. */
2087       errmsg = "The file \"%s\" is a pipe or FIFO; TFShark can't read pipe or FIFO files in two-pass mode.";
2088       break;
2089 
2090     case FTAP_ERR_FILE_UNKNOWN_FORMAT:
2091       /* Seen only when opening a capture file for reading. */
2092       errmsg = "The file \"%s\" isn't a capture file in a format TFShark understands.";
2093       break;
2094 
2095     case FTAP_ERR_UNSUPPORTED:
2096       /* Seen only when opening a capture file for reading. */
2097       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2098                "The file \"%%s\" isn't a capture file in a format TFShark understands.\n"
2099                "(%s)", err_info);
2100       g_free(err_info);
2101       errmsg = errmsg_errno;
2102       break;
2103 
2104     case FTAP_ERR_CANT_WRITE_TO_PIPE:
2105       /* Seen only when opening a capture file for writing. */
2106       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2107                  "The file \"%%s\" is a pipe, and \"%s\" capture files can't be "
2108                  "written to a pipe.", ftap_file_type_subtype_short_string(file_type));
2109       errmsg = errmsg_errno;
2110       break;
2111 
2112     case FTAP_ERR_UNSUPPORTED_FILE_TYPE:
2113       /* Seen only when opening a capture file for writing. */
2114       errmsg = "TFShark doesn't support writing capture files in that format.";
2115       break;
2116 
2117     case FTAP_ERR_UNSUPPORTED_ENCAP:
2118       if (for_writing) {
2119         g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2120                    "TFShark can't save this capture as a \"%s\" file.",
2121                    ftap_file_type_subtype_short_string(file_type));
2122       } else {
2123         g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2124                  "The file \"%%s\" is a capture for a network type that TFShark doesn't support.\n"
2125                  "(%s)", err_info);
2126         g_free(err_info);
2127       }
2128       errmsg = errmsg_errno;
2129       break;
2130 
2131     case FTAP_ERR_ENCAP_PER_RECORD_UNSUPPORTED:
2132       if (for_writing) {
2133         g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2134                    "TFShark can't save this capture as a \"%s\" file.",
2135                    ftap_file_type_subtype_short_string(file_type));
2136         errmsg = errmsg_errno;
2137       } else
2138         errmsg = "The file \"%s\" is a capture for a network type that TFShark doesn't support.";
2139       break;
2140 
2141     case FTAP_ERR_BAD_FILE:
2142       /* Seen only when opening a capture file for reading. */
2143       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2144                "The file \"%%s\" appears to be damaged or corrupt.\n"
2145                "(%s)", err_info);
2146       g_free(err_info);
2147       errmsg = errmsg_errno;
2148       break;
2149 
2150     case FTAP_ERR_CANT_OPEN:
2151       if (for_writing)
2152         errmsg = "The file \"%s\" could not be created for some unknown reason.";
2153       else
2154         errmsg = "The file \"%s\" could not be opened for some unknown reason.";
2155       break;
2156 
2157     case FTAP_ERR_SHORT_READ:
2158       errmsg = "The file \"%s\" appears to have been cut short"
2159                " in the middle of a packet or other data.";
2160       break;
2161 
2162     case FTAP_ERR_SHORT_WRITE:
2163       errmsg = "A full header couldn't be written to the file \"%s\".";
2164       break;
2165 
2166     case FTAP_ERR_COMPRESSION_NOT_SUPPORTED:
2167       errmsg = "This file type cannot be written as a compressed file.";
2168       break;
2169 
2170     case FTAP_ERR_DECOMPRESS:
2171       /* Seen only when opening a capture file for reading. */
2172       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2173                  "The compressed file \"%%s\" appears to be damaged or corrupt.\n"
2174                  "(%s)", err_info);
2175       g_free(err_info);
2176       errmsg = errmsg_errno;
2177       break;
2178 
2179     default:
2180       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
2181                  "The file \"%%s\" could not be %s: %s.",
2182                  for_writing ? "created" : "opened",
2183                  ftap_strerror(err));
2184       errmsg = errmsg_errno;
2185       break;
2186     }
2187   } else
2188 #endif
2189     errmsg = file_open_error_message(err, for_writing);
2190   return errmsg;
2191 }
2192 
2193 /*
2194  * Report an error in command-line arguments.
2195  */
2196 static void
tfshark_cmdarg_err(const char * msg_format,va_list ap)2197 tfshark_cmdarg_err(const char *msg_format, va_list ap)
2198 {
2199   fprintf(stderr, "tfshark: ");
2200   vfprintf(stderr, msg_format, ap);
2201   fprintf(stderr, "\n");
2202 }
2203 
2204 /*
2205  * Report additional information for an error in command-line arguments.
2206  */
2207 static void
tfshark_cmdarg_err_cont(const char * msg_format,va_list ap)2208 tfshark_cmdarg_err_cont(const char *msg_format, va_list ap)
2209 {
2210   vfprintf(stderr, msg_format, ap);
2211   fprintf(stderr, "\n");
2212 }
2213 
2214 /*
2215  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2216  *
2217  * Local variables:
2218  * c-basic-offset: 2
2219  * tab-width: 8
2220  * indent-tabs-mode: nil
2221  * End:
2222  *
2223  * vi: set shiftwidth=2 tabstop=8 expandtab:
2224  * :indentSize=2:tabSize=8:noTabs=true:
2225  */
2226