Add the packet number to the packet_info structure, and use it.
[metze/wireshark/wip.git] / tfshark.c
index 04923f8800e679338e318ca2eee41e33286f74d2..fea110c1e55bb817a3bc274619c63e3be53f4264 100644 (file)
--- a/tfshark.c
+++ b/tfshark.c
 #include <locale.h>
 #include <limits.h>
 
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
 #ifdef HAVE_GETOPT_H
 #include <getopt.h>
 #endif
 
 #include <errno.h>
 
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-#include <signal.h>
-
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-
 #ifdef HAVE_LIBZ
 #include <zlib.h>      /* to get the libz version number */
 #endif
 
-#ifndef HAVE_GETOPT
+#ifndef HAVE_GETOPT_LONG
 #include "wsutil/wsgetopt.h"
 #endif
 
 #include <wsutil/clopts_common.h>
 #include <wsutil/cmdarg_err.h>
 #include <wsutil/crash_info.h>
-#include <wsutil/privileges.h>
-#include <wsutil/file_util.h>
 #include <wsutil/filesystem.h>
+#include <wsutil/file_util.h>
+#include <wsutil/privileges.h>
 #include <wsutil/report_err.h>
-#include <wsutil/copyright_info.h>
+#include <wsutil/ws_diag_control.h>
 #include <wsutil/ws_version_info.h>
 
 #include "globals.h"
 #include <epan/print.h>
 #include <epan/addr_resolv.h>
 #include "ui/util.h"
-#include "version_info.h"
 #include "register.h"
 #include <epan/epan_dissect.h>
 #include <epan/tap.h>
 #include <epan/stat_tap_ui.h>
-#include <epan/timestamp.h>
 #include <epan/ex-opt.h>
+
+#if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
+#include <epan/asn1.h>
+#include <epan/dissectors/packet-kerberos.h>
+#endif
+
 #include <wiretap/wtap-int.h>
 #include <wiretap/file_wrappers.h>
 
@@ -172,6 +162,8 @@ static void failure_message_cont(const char *msg_format, va_list ap);
 
 capture_file cfile;
 
+static GHashTable *output_only_tables = NULL;
+
 #if 0
 struct string_elem {
   const char *sstr;   /* The short string */
@@ -734,20 +726,6 @@ print_current_user(void) {
   }
 }
 
-static void
-show_version(GString *comp_info_str, GString *runtime_info_str)
-{
-  printf("TFShark (Wireshark) %s\n"
-         "\n"
-         "%s"
-         "\n"
-         "%s"
-         "\n"
-         "%s",
-         get_ws_vcs_version_info(), get_copyright_info(), comp_info_str->str,
-         runtime_info_str->str);
-}
-
 static void
 get_tfshark_compiled_version_info(GString *str)
 {
@@ -784,8 +762,8 @@ main(int argc, char *argv[])
   char                *init_progfile_dir_error;
   int                  opt;
   static const struct option long_options[] = {
-    {(char *)"help", no_argument, NULL, 'h'},
-    {(char *)"version", no_argument, NULL, 'v'},
+    {"help", no_argument, NULL, 'h'},
+    {"version", no_argument, NULL, 'v'},
     {0, 0, 0, 0 }
   };
   gboolean             arg_error = FALSE;
@@ -804,18 +782,37 @@ main(int argc, char *argv[])
   gchar               *dfilter = NULL;
   dfilter_t           *rfcode = NULL;
   dfilter_t           *dfcode = NULL;
+  gchar               *err_msg;
   e_prefs             *prefs_p;
   int                  log_flags;
-  int                  optind_initial;
   gchar               *output_only = NULL;
 
-/* the leading - ensures that getopt() does not permute the argv[] entries
-   we have to make sure that the first getopt() preserves the content of argv[]
-   for the subsequent getopt_long() call */
-#define OPTSTRING "-2C:d:e:E:hK:lo:O:qQr:R:S:t:T:u:vVxX:Y:z:"
+/*
+ * The leading + ensures that getopt_long() does not permute the argv[]
+ * entries.
+ *
+ * We have to make sure that the first getopt_long() preserves the content
+ * of argv[] for the subsequent getopt_long() call.
+ *
+ * We use getopt_long() in both cases to ensure that we're using a routine
+ * whose permutation behavior we can control in the same fashion on all
+ * platforms, and so that, if we ever need to process a long argument before
+ * doing further initialization, we can do so.
+ *
+ * Glibc and Solaris libc document that a leading + disables permutation
+ * of options, regardless of whether POSIXLY_CORRECT is set or not; *BSD
+ * and OS X don't document it, but do so anyway.
+ *
+ * We do *not* use a leading - because the behavior of a leading - is
+ * platform-dependent.
+ */
+#define OPTSTRING "+2C:d:e:E:hK:lo:O:qQr:R:S:t:T:u:vVxX:Y:z:"
 
   static const char    optstring[] = OPTSTRING;
 
+  /* Set the C-language locale to the native environment. */
+  setlocale(LC_ALL, "");
+
   cmdarg_err_init(failure_message, failure_message_cont);
 
 #ifdef _WIN32
@@ -846,14 +843,12 @@ main(int argc, char *argv[])
 
   initialize_funnel_ops();
 
-  /* Assemble the compile-time version information string */
-  comp_info_str = g_string_new("Compiled ");
-  get_compiled_version_info(comp_info_str, get_tfshark_compiled_version_info,
-                            epan_get_compiled_version_info);
+  /* Get the compile-time version information string */
+  comp_info_str = get_compiled_version_info(get_tfshark_compiled_version_info,
+                                            epan_get_compiled_version_info);
 
-  /* Assemble the run-time version information string */
-  runtime_info_str = g_string_new("Running ");
-  get_runtime_version_info(runtime_info_str, get_tfshark_runtime_version_info);
+  /* Get the run-time version information string */
+  runtime_info_str = get_runtime_version_info(get_tfshark_runtime_version_info);
 
   /* Add it to the information to be reported on a crash. */
   ws_add_crash_info("TFShark (Wireshark) %s\n"
@@ -866,11 +861,18 @@ main(int argc, char *argv[])
   /*
    * In order to have the -X opts assigned before the wslua machine starts
    * we need to call getopts before epan_init() gets called.
+   *
+   * In order to handle, for example, -o options, we also need to call it
+   * *after* epan_init() gets called, so that the dissectors have had a
+   * chance to register their preferences.
+   *
+   * XXX - can we do this all with one getopt_long() call, saving the
+   * arguments we can't handle until after initializing libwireshark,
+   * and then process them after initializing libwireshark?
    */
   opterr = 0;
-  optind_initial = optind;
 
-  while ((opt = getopt(argc, argv, optstring)) != -1) {
+  while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
     switch (opt) {
     case 'C':        /* Configuration Profile */
       if (profile_exists (optarg, FALSE)) {
@@ -911,11 +913,6 @@ main(int argc, char *argv[])
   if (print_summary == -1)
     print_summary = (print_details || print_hex) ? FALSE : TRUE;
 
-  optind = optind_initial;
-  opterr = 1;
-
-
-
 /** Send All g_log messages to our own handler **/
 
   log_flags =
@@ -957,7 +954,9 @@ main(int argc, char *argv[])
      "-G" flag, as the "-G" flag dumps information registered by the
      dissectors, and we must do it before we read the preferences, in
      case any dissectors register preferences. */
-  epan_init(register_all_protocols, register_all_protocol_handoffs, NULL, NULL);
+  if (!epan_init(register_all_protocols, register_all_protocol_handoffs, NULL,
+                 NULL))
+    return 2;
 
   /* Register all tap listeners; we do this before we parse the arguments,
      as the "-z" argument can specify a registered tap. */
@@ -1031,9 +1030,6 @@ main(int argc, char *argv[])
     return 0;
   }
 
-  /* Set the C-language locale to the native environment. */
-  setlocale(LC_ALL, "");
-
   prefs_p = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
                      &pf_open_errno, &pf_read_errno, &pf_path);
   if (gpf_path != NULL) {
@@ -1062,6 +1058,8 @@ main(int argc, char *argv[])
   /* Read the disabled protocols file. */
   read_disabled_protos_list(&gdp_path, &gdp_open_errno, &gdp_read_errno,
                             &dp_path, &dp_open_errno, &dp_read_errno);
+  read_disabled_heur_dissector_list(&gdp_path, &gdp_open_errno, &gdp_read_errno,
+                            &dp_path, &dp_open_errno, &dp_read_errno);
   if (gdp_path != NULL) {
     if (gdp_open_errno != 0) {
       cmdarg_err("Could not open global disabled protocols file\n\"%s\": %s.",
@@ -1094,6 +1092,28 @@ main(int argc, char *argv[])
 
   output_fields = output_fields_new();
 
+  /*
+   * To reset the options parser, set optreset to 1 on platforms that
+   * have optreset (documented in *BSD and OS X, apparently present but
+   * not documented in Solaris - the Illumos repository seems to
+   * suggest that the first Solaris getopt_long(), at least as of 2004,
+   * was based on the NetBSD one, it had optreset) and set optind to 1,
+   * and set optind to 0 otherwise (documented as working in the GNU
+   * getopt_long().  Setting optind to 0 didn't originally work in the
+   * NetBSD one, but that was added later - we don't want to depend on
+   * it if we have optreset).
+   *
+   * Also reset opterr to 1, so that error messages are printed by
+   * getopt_long().
+   */
+#ifdef HAVE_OPTRESET
+  optreset = 1;
+  optind = 1;
+#else
+  optind = 0;
+#endif
+  opterr = 1;
+
   /* Now get our args */
   while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
     switch (opt) {
@@ -1101,7 +1121,7 @@ main(int argc, char *argv[])
       perform_two_pass_analysis = TRUE;
       break;
     case 'C':
-      /* Configuration profile settings were already processed just ignore them this time*/
+      /* already processed; just ignore it now */
       break;
     case 'd':        /* Decode as rule */
       if (!add_decode_as(optarg))
@@ -1128,7 +1148,7 @@ main(int argc, char *argv[])
     case 'h':        /* Print help and exit */
       printf("TFShark (Wireshark) %s\n"
              "Dump and analyze network traffic.\n"
-             "See http://www.wireshark.org for more information.\n",
+             "See https://www.wireshark.org for more information.\n",
              get_ws_vcs_version_info());
       print_usage(stdout);
       return 0;
@@ -1272,7 +1292,7 @@ main(int argc, char *argv[])
       break;
     case 'v':         /* Show version and exit */
     {
-      show_version(comp_info_str, runtime_info_str);
+      show_version("TFShark (Wireshark)", comp_info_str, runtime_info_str);
       g_string_free(comp_info_str, TRUE);
       g_string_free(runtime_info_str, TRUE);
       /* We don't really have to cleanup here, but it's a convenient way to test
@@ -1293,6 +1313,7 @@ main(int argc, char *argv[])
       /* already processed; just ignore it now */
       break;
     case 'X':
+      /* already processed; just ignore it now */
       break;
     case 'Y':
       dfilter = optarg;
@@ -1397,14 +1418,16 @@ main(int argc, char *argv[])
   /* disabled protocols as per configuration file */
   if (gdp_path == NULL && dp_path == NULL) {
     set_disabled_protos_list();
+    set_disabled_heur_dissector_list();
   }
 
   /* Build the column format array */
   build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
 
   if (rfilter != NULL) {
-    if (!dfilter_compile(rfilter, &rfcode)) {
-      cmdarg_err("%s", dfilter_error_msg);
+    if (!dfilter_compile(rfilter, &rfcode, &err_msg)) {
+      cmdarg_err("%s", err_msg);
+      g_free(err_msg);
       epan_cleanup();
       return 2;
     }
@@ -1412,8 +1435,9 @@ main(int argc, char *argv[])
   cfile.rfcode = rfcode;
 
   if (dfilter != NULL) {
-    if (!dfilter_compile(dfilter, &dfcode)) {
-      cmdarg_err("%s", dfilter_error_msg);
+    if (!dfilter_compile(dfilter, &dfcode, &err_msg)) {
+      cmdarg_err("%s", err_msg);
+      g_free(err_msg);
       epan_cleanup();
       return 2;
     }
@@ -1475,7 +1499,7 @@ main(int argc, char *argv[])
               "Sorry, but TFShark has to terminate now!\n"
               "\n"
               "Some infos / workarounds can be found at:\n"
-              "http://wiki.wireshark.org/KnownBugs/OutOfMemory\n");
+              "https://wiki.wireshark.org/KnownBugs/OutOfMemory\n");
       err = ENOMEM;
     }
     ENDTRY;
@@ -1711,7 +1735,7 @@ process_packet_second_pass(capture_file *cf, epan_dissect_t *edt, frame_data *fd
   return passed || fdata->flags.dependent_of_displayed;
 }
 
-gboolean
+static gboolean
 local_wtap_read(capture_file *cf, struct wtap_pkthdr* file_phdr _U_, int *err, gchar **err_info _U_, gint64 *data_offset _U_, guint8** data_buffer)
 {
     /* int bytes_read; */
@@ -1808,7 +1832,7 @@ load_cap_file(capture_file *cf, int max_packet_count, gint64 max_byte_count)
   /* Get the union of the flags for all tap listeners. */
   tap_flags = union_of_tap_listener_flags();
 
-  memset(&file_phdr, 0, sizeof(file_phdr));
+  wtap_phdr_init(&file_phdr);
 
   /* XXX - TEMPORARY HACK TO ELF DISSECTOR */
   file_phdr.pkt_encap = 1234;
@@ -1943,6 +1967,8 @@ load_cap_file(capture_file *cf, int max_packet_count, gint64 max_byte_count)
     }
   }
 
+  wtap_phdr_cleanup(&file_phdr);
+
   if (err != 0) {
     /*
      * Print a message noting that the read failed somewhere along the line.
@@ -2140,13 +2166,13 @@ write_preamble(capture_file *cf)
   switch (output_action) {
 
   case WRITE_TEXT:
-    return print_preamble(print_stream, cf ? cf->filename : NULL, get_ws_vcs_version_info());
+    return print_preamble(print_stream, cf->filename, get_ws_vcs_version_info());
 
   case WRITE_XML:
     if (print_details)
-      write_pdml_preamble(stdout, cf ? cf->filename : NULL);
+      write_pdml_preamble(stdout, cf->filename);
     else
-      write_psml_preamble(stdout);
+      write_psml_preamble(&cf->cinfo, stdout);
     return !ferror(stdout);
 
   case WRITE_FIELDS:
@@ -2219,21 +2245,23 @@ print_columns(capture_file *cf)
   size_t  buf_offset;
   size_t  column_len;
   size_t  col_len;
+  col_item_t* col_item;
 
   line_bufp = get_line_buf(256);
   buf_offset = 0;
   *line_bufp = '\0';
   for (i = 0; i < cf->cinfo.num_cols; i++) {
+    col_item = &cf->cinfo.columns[i];
     /* Skip columns not marked as visible. */
     if (!get_column_visible(i))
       continue;
-    switch (cf->cinfo.col_fmt[i]) {
+    switch (col_item->col_fmt) {
     case COL_NUMBER:
-      column_len = col_len = strlen(cf->cinfo.col_data[i]);
+      column_len = col_len = strlen(col_item->col_data);
       if (column_len < 3)
         column_len = 3;
       line_bufp = get_line_buf(buf_offset + column_len);
-      put_spaces_string(line_bufp + buf_offset, cf->cinfo.col_data[i], col_len, column_len);
+      put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
       break;
 
     case COL_CLS_TIME:
@@ -2244,11 +2272,11 @@ print_columns(capture_file *cf)
     case COL_UTC_TIME:
     case COL_UTC_YMD_TIME:  /* XXX - wider */
     case COL_UTC_YDOY_TIME: /* XXX - wider */
-      column_len = col_len = strlen(cf->cinfo.col_data[i]);
+      column_len = col_len = strlen(col_item->col_data);
       if (column_len < 10)
         column_len = 10;
       line_bufp = get_line_buf(buf_offset + column_len);
-      put_spaces_string(line_bufp + buf_offset, cf->cinfo.col_data[i], col_len, column_len);
+      put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
       break;
 
     case COL_DEF_SRC:
@@ -2260,11 +2288,11 @@ print_columns(capture_file *cf)
     case COL_DEF_NET_SRC:
     case COL_RES_NET_SRC:
     case COL_UNRES_NET_SRC:
-      column_len = col_len = strlen(cf->cinfo.col_data[i]);
+      column_len = col_len = strlen(col_item->col_data);
       if (column_len < 12)
         column_len = 12;
       line_bufp = get_line_buf(buf_offset + column_len);
-      put_spaces_string(line_bufp + buf_offset, cf->cinfo.col_data[i], col_len, column_len);
+      put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
       break;
 
     case COL_DEF_DST:
@@ -2276,17 +2304,17 @@ print_columns(capture_file *cf)
     case COL_DEF_NET_DST:
     case COL_RES_NET_DST:
     case COL_UNRES_NET_DST:
-      column_len = col_len = strlen(cf->cinfo.col_data[i]);
+      column_len = col_len = strlen(col_item->col_data);
       if (column_len < 12)
         column_len = 12;
       line_bufp = get_line_buf(buf_offset + column_len);
-      put_string_spaces(line_bufp + buf_offset, cf->cinfo.col_data[i], col_len, column_len);
+      put_string_spaces(line_bufp + buf_offset, col_item->col_data, col_len, column_len);
       break;
 
     default:
-      column_len = strlen(cf->cinfo.col_data[i]);
+      column_len = strlen(col_item->col_data);
       line_bufp = get_line_buf(buf_offset + column_len);
-      put_string(line_bufp + buf_offset, cf->cinfo.col_data[i], column_len);
+      put_string(line_bufp + buf_offset, col_item->col_data, column_len);
       break;
     }
     buf_offset += column_len;
@@ -2306,12 +2334,12 @@ print_columns(capture_file *cf)
        * even if we're only adding " ".
        */
       line_bufp = get_line_buf(buf_offset + 4);
-      switch (cf->cinfo.col_fmt[i]) {
+      switch (col_item->col_fmt) {
 
       case COL_DEF_SRC:
       case COL_RES_SRC:
       case COL_UNRES_SRC:
-        switch (cf->cinfo.col_fmt[i + 1]) {
+        switch (cf->cinfo.columns[i+1].col_fmt) {
 
         case COL_DEF_DST:
         case COL_RES_DST:
@@ -2330,7 +2358,7 @@ print_columns(capture_file *cf)
       case COL_DEF_DL_SRC:
       case COL_RES_DL_SRC:
       case COL_UNRES_DL_SRC:
-        switch (cf->cinfo.col_fmt[i + 1]) {
+        switch (cf->cinfo.columns[i+1].col_fmt) {
 
         case COL_DEF_DL_DST:
         case COL_RES_DL_DST:
@@ -2349,7 +2377,7 @@ print_columns(capture_file *cf)
       case COL_DEF_NET_SRC:
       case COL_RES_NET_SRC:
       case COL_UNRES_NET_SRC:
-        switch (cf->cinfo.col_fmt[i + 1]) {
+        switch (cf->cinfo.columns[i+1].col_fmt) {
 
         case COL_DEF_NET_DST:
         case COL_RES_NET_DST:
@@ -2368,7 +2396,7 @@ print_columns(capture_file *cf)
       case COL_DEF_DST:
       case COL_RES_DST:
       case COL_UNRES_DST:
-        switch (cf->cinfo.col_fmt[i + 1]) {
+        switch (cf->cinfo.columns[i+1].col_fmt) {
 
         case COL_DEF_SRC:
         case COL_RES_SRC:
@@ -2387,7 +2415,7 @@ print_columns(capture_file *cf)
       case COL_DEF_DL_DST:
       case COL_RES_DL_DST:
       case COL_UNRES_DL_DST:
-        switch (cf->cinfo.col_fmt[i + 1]) {
+        switch (cf->cinfo.columns[i+1].col_fmt) {
 
         case COL_DEF_DL_SRC:
         case COL_RES_DL_SRC:
@@ -2406,7 +2434,7 @@ print_columns(capture_file *cf)
       case COL_DEF_NET_DST:
       case COL_RES_NET_DST:
       case COL_UNRES_NET_DST:
-        switch (cf->cinfo.col_fmt[i + 1]) {
+        switch (cf->cinfo.columns[i+1].col_fmt) {
 
         case COL_DEF_NET_SRC:
         case COL_RES_NET_SRC:
@@ -2451,7 +2479,7 @@ print_packet(capture_file *cf, epan_dissect_t *edt)
         break;
 
       case WRITE_XML:
-        proto_tree_write_psml(edt, stdout);
+        write_psml_columns(edt, stdout);
         return !ferror(stdout);
       case WRITE_FIELDS: /*No non-verbose "fields" format */
         g_assert_not_reached();
@@ -2476,7 +2504,7 @@ print_packet(capture_file *cf, epan_dissect_t *edt)
       print_args.print_hex = print_hex;
       print_args.print_dissections = print_details ? print_dissections_expanded : print_dissections_none;
 
-      if (!proto_tree_print(&print_args, edt, print_stream))
+      if (!proto_tree_print(&print_args, edt, output_only_tables, print_stream))
         return FALSE;
       if (!print_hex) {
         if (!print_line(print_stream, 0, separator))
@@ -2485,11 +2513,11 @@ print_packet(capture_file *cf, epan_dissect_t *edt)
       break;
 
     case WRITE_XML:
-      proto_tree_write_pdml(edt, stdout);
+      write_pdml_proto_tree(edt, stdout);
       printf("\n");
       return !ferror(stdout);
     case WRITE_FIELDS:
-      proto_tree_write_fields(output_fields, edt, &cf->cinfo, stdout);
+      write_fields_proto_tree(output_fields, edt, &cf->cinfo, stdout);
       printf("\n");
       return !ferror(stdout);
     }
@@ -2617,9 +2645,9 @@ cf_open_error_message(int err, gchar *err_info _U_, gboolean for_writing,
   const char *errmsg;
   /* static char errmsg_errno[1024+1]; */
 
+#if 0
   if (err < 0) {
     /* Wiretap error. */
-#if 0
     switch (err) {
 
     case FTAP_ERR_NOT_REGULAR_FILE:
@@ -2728,8 +2756,8 @@ cf_open_error_message(int err, gchar *err_info _U_, gboolean for_writing,
       errmsg = errmsg_errno;
       break;
     }
-#endif
   } else
+#endif
     errmsg = file_open_error_message(err, for_writing);
   return errmsg;
 }
@@ -2788,7 +2816,7 @@ failure_message_cont(const char *msg_format, va_list ap)
 }
 
 /*
- * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
+ * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
  *
  * Local variables:
  * c-basic-offset: 2