Fix typo s/ENCNA/ENC_NA/
[metze/wireshark/wip.git] / tshark.c
index c6a42782ee4137ebc9e5240a9e9e343aa677df71..2481db9817c0177fcaf52d5a8090b0e240ea2ab8 100644 (file)
--- a/tshark.c
+++ b/tshark.c
@@ -71,7 +71,6 @@
 #include <epan/addr_resolv.h>
 #include "ui/util.h"
 #include "clopts_common.h"
-#include "console_io.h"
 #include "cmdarg_err.h"
 #include "version_info.h"
 #include <epan/plugins.h>
@@ -167,8 +166,8 @@ static void report_counts_siginfo(int);
 
 static int load_cap_file(capture_file *, char *, int, gboolean, int, gint64);
 static gboolean process_packet(capture_file *cf, gint64 offset,
-    struct wtap_pkthdr *whdr,
-    const guchar *pd, gboolean filtering_tap_listeners, guint tap_flags);
+    struct wtap_pkthdr *whdr, const guchar *pd,
+    gboolean filtering_tap_listeners, guint tap_flags);
 static void show_capture_file_io_error(const char *, int, gboolean);
 static void show_print_file_io_error(int err);
 static gboolean write_preamble(capture_file *cf);
@@ -211,7 +210,7 @@ list_capture_types(void) {
   struct string_elem *captypes;
   GSList             *list = NULL;
 
-  captypes = g_malloc(sizeof(struct string_elem) * WTAP_NUM_FILE_TYPES);
+  captypes = g_new(struct string_elem, WTAP_NUM_FILE_TYPES);
 
   fprintf(stderr, "tshark: The available capture file types for the \"-F\" flag are:\n");
   for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
@@ -257,7 +256,7 @@ print_usage(gboolean print_ver)
   fprintf(output, "  -I                       capture in monitor mode, if available\n");
 #endif
 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-  fprintf(output, "  -B <buffer size>         size of kernel buffer (def: 1MB)\n");
+  fprintf(output, "  -B <buffer size>         size of kernel buffer (def: %dMB)\n", DEFAULT_CAPTURE_BUFFER_SIZE);
 #endif
   fprintf(output, "  -y <link type>           link layer type (def: first appropriate)\n");
   fprintf(output, "  -D                       print list of interfaces and exit\n");
@@ -285,7 +284,8 @@ print_usage(gboolean print_ver)
   fprintf(output, "\n");
   fprintf(output, "Processing:\n");
   fprintf(output, "  -2                       perform a two-pass analysis\n");
-  fprintf(output, "  -R <read filter>         packet filter in Wireshark display filter syntax\n");
+  fprintf(output, "  -R <read filter>         packet Read filter in Wireshark display filter syntax\n");
+  fprintf(output, "  -Y <display filter>      packet displaY filter in Wireshark display filter syntax\n");
   fprintf(output, "  -n                       disable all name resolutions (def: all enabled)\n");
   fprintf(output, "  -N <name resolve flags>  enable specific name resolution(s): \"mntC\"\n");
   fprintf(output, "  -d %s ...\n", decode_as_arg_template);
@@ -353,9 +353,7 @@ glossary_option_help(void)
   fprintf(output, "Usage: tshark -G [report]\n");
   fprintf(output, "\n");
   fprintf(output, "Glossary table reports:\n");
-  fprintf(output, "  -G [fields]              dump glossary in original format and exit\n");
-  fprintf(output, "  -G fields2               dump glossary in format 2 and exit\n");
-  fprintf(output, "  -G fields3               dump glossary in format 3 and exit\n");
+  fprintf(output, "  -G fields                dump fields glossary and exit\n");
   fprintf(output, "  -G protocols             dump protocols in registration database and exit\n");
   fprintf(output, "  -G values                dump value, range, true/false strings and exit\n");
   fprintf(output, "  -G ftypes                dump field type basic and descriptive names\n");
@@ -366,7 +364,6 @@ glossary_option_help(void)
   fprintf(output, "  -G defaultprefs          dump default preferences and exit\n");
   fprintf(output, "  -G currentprefs          dump current preferences and exit\n");
   fprintf(output, "\n");
-
 }
 
 /*
@@ -897,13 +894,15 @@ main(int argc, char *argv[])
   volatile gboolean    out_file_name_res = FALSE;
   gchar               *volatile cf_name = NULL;
   gchar               *rfilter = NULL;
+  gchar               *dfilter = NULL;
 #ifdef HAVE_PCAP_OPEN_DEAD
   struct bpf_program   fcode;
 #endif
   dfilter_t           *rfcode = NULL;
+  dfilter_t           *dfcode = NULL;
   e_prefs             *prefs_p;
   char                 badopt;
-  GLogLevelFlags       log_flags;
+  int                  log_flags;
   int                  optind_initial;
   gchar               *output_only = NULL;
 
@@ -928,7 +927,7 @@ main(int argc, char *argv[])
 #define OPTSTRING_I ""
 #endif
 
-#define OPTSTRING "2a:" OPTSTRING_A "b:" OPTSTRING_B "c:C:d:De:E:f:F:gG:hH:i:" OPTSTRING_I "K:lLnN:o:O:pPqQr:R:s:S:t:T:u:vVw:W:xX:y:z:"
+#define OPTSTRING "2a:" OPTSTRING_A "b:" OPTSTRING_B "c:C:d:De:E:f:F:gG:hH:i:" OPTSTRING_I "K:lLnN:o:O:pPqQr:R:s:S:t:T:u:vVw:W:xX:y:Y:z:"
 
   static const char    optstring[] = OPTSTRING;
 
@@ -1039,18 +1038,18 @@ main(int argc, char *argv[])
                     G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
 
   g_log_set_handler(NULL,
-                    log_flags,
+                    (GLogLevelFlags)log_flags,
                     tshark_log_handler, NULL /* user_data */);
   g_log_set_handler(LOG_DOMAIN_MAIN,
-                    log_flags,
+                    (GLogLevelFlags)log_flags,
                     tshark_log_handler, NULL /* user_data */);
 
 #ifdef HAVE_LIBPCAP
   g_log_set_handler(LOG_DOMAIN_CAPTURE,
-                    log_flags,
+                    (GLogLevelFlags)log_flags,
                     tshark_log_handler, NULL /* user_data */);
   g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
-                    log_flags,
+                    (GLogLevelFlags)log_flags,
                     tshark_log_handler, NULL /* user_data */);
 #endif
 
@@ -1095,14 +1094,10 @@ main(int argc, char *argv[])
     proto_initialize_all_prefixes();
 
     if (argc == 2)
-      proto_registrar_dump_fields(1);
+      proto_registrar_dump_fields();
     else {
       if (strcmp(argv[2], "fields") == 0)
-        proto_registrar_dump_fields(1);
-      else if (strcmp(argv[2], "fields2") == 0)
-        proto_registrar_dump_fields(2);
-      else if (strcmp(argv[2], "fields3") == 0)
-        proto_registrar_dump_fields(3);
+        proto_registrar_dump_fields();
       else if (strcmp(argv[2], "protocols") == 0)
         proto_registrar_dump_protocols();
       else if (strcmp(argv[2], "values") == 0)
@@ -1472,6 +1467,9 @@ main(int argc, char *argv[])
       break;
     case 'X':
       break;
+    case 'Y':
+      dfilter = optarg;
+      break;
     case 'z':
       /* We won't call the init function for the stat this soon
          as it would disallow MATE's fields (which are registered
@@ -1479,6 +1477,11 @@ main(int argc, char *argv[])
          part of a tap filter.  Instead, we just add the argument
          to a list of stat arguments. */
       if (!process_stat_cmd_arg(optarg)) {
+        if (strcmp("help", optarg)==0) {
+          fprintf(stderr, "tshark: The available statistics for the \"-z\" option are:\n");
+          list_stat_cmd_args();
+          return 0;
+        }
         cmdarg_err("Invalid -z argument \"%s\".", optarg);
         cmdarg_err_cont("  -z argument must be one of :");
         list_stat_cmd_args();
@@ -1511,18 +1514,18 @@ main(int argc, char *argv[])
         return 1;
   }
 
-  /* If no capture filter or read filter has been specified, and there are
+  /* If no capture filter or display filter has been specified, and there are
      still command-line arguments, treat them as the tokens of a capture
-     filter (if no "-r" flag was specified) or a read filter (if a "-r"
+     filter (if no "-r" flag was specified) or a display filter (if a "-r"
      flag was specified. */
   if (optind < argc) {
     if (cf_name != NULL) {
-      if (rfilter != NULL) {
-        cmdarg_err("Read filters were specified both with \"-R\" "
+      if (dfilter != NULL) {
+        cmdarg_err("Display filters were specified both with \"-d\" "
             "and with additional command-line arguments.");
         return 1;
       }
-      rfilter = get_args_as_string(argc, argv, optind);
+      dfilter = get_args_as_string(argc, argv, optind);
     } else {
 #ifdef HAVE_LIBPCAP
       guint i;
@@ -1620,6 +1623,11 @@ main(int argc, char *argv[])
     }
   }
 
+  if (rfilter != NULL && !perform_two_pass_analysis) {
+    /* Just a warning, so we don't return */
+    cmdarg_err("-R without -2 is deprecated. For single-pass filtering use -Y.");
+  }
+
 #ifdef HAVE_LIBPCAP
   if (list_link_layer_types) {
     /* We're supposed to list the link-layer types for an interface;
@@ -1704,12 +1712,16 @@ main(int argc, char *argv[])
             return 1;
           }
         }
-        /* Currently, we don't support read filters when capturing
+        /* Currently, we don't support read or display filters when capturing
            and saving the packets. */
         if (rfilter != NULL) {
           cmdarg_err("Read filters aren't supported when capturing and saving the captured packets.");
           return 1;
         }
+        if (dfilter != NULL) {
+          cmdarg_err("Display filters aren't supported when capturing and saving the captured packets.");
+          return 1;
+        }
       } else {
         /* They didn't specify a "-w" flag, so we won't be saving to a
            capture file.  Check for options that only make sense if
@@ -1785,7 +1797,7 @@ main(int argc, char *argv[])
         if (pc != NULL) {
           if (pcap_compile(pc, &fcode, rfilter, 0, 0) != -1) {
             cmdarg_err_cont(
-              "  Note: That display filter code looks like a valid capture filter;");
+              "  Note: That read filter code looks like a valid capture filter;");
             cmdarg_err_cont(
               "        maybe you mixed them up?");
           }
@@ -1798,6 +1810,31 @@ main(int argc, char *argv[])
   }
   cfile.rfcode = rfcode;
 
+  if (dfilter != NULL) {
+    if (!dfilter_compile(dfilter, &dfcode)) {
+      cmdarg_err("%s", dfilter_error_msg);
+      epan_cleanup();
+#ifdef HAVE_PCAP_OPEN_DEAD
+      {
+        pcap_t *pc;
+
+        pc = pcap_open_dead(DLT_EN10MB, MIN_PACKET_SIZE);
+        if (pc != NULL) {
+          if (pcap_compile(pc, &fcode, dfilter, 0, 0) != -1) {
+            cmdarg_err_cont(
+              "  Note: That display filter code looks like a valid capture filter;");
+            cmdarg_err_cont(
+              "        maybe you mixed them up?");
+          }
+          pcap_close(pc);
+        }
+      }
+#endif
+      return 2;
+    }
+  }
+  cfile.dfcode = dfcode;
+
   if (print_packet_info) {
     /* If we're printing as text or PostScript, we have
        to create a print stream. */
@@ -1824,8 +1861,10 @@ main(int argc, char *argv[])
 
         we're using a read filter on the packets;
 
+        we're using a display filter on the packets;
+
         we're using any taps that need dissection. */
-  do_dissection = print_packet_info || rfcode || tap_listeners_require_dissection();
+  do_dissection = print_packet_info || rfcode || dfcode || tap_listeners_require_dissection();
 
   if (cf_name) {
     /*
@@ -2387,7 +2426,7 @@ capture_input_new_file(capture_options *capture_opts, gchar *new_file)
   /* if we are in real-time mode, open the new file now */
   if (do_dissection) {
     /* Attempt to open the capture file and set up to read from it. */
-    switch(cf_open(capture_opts->cf, capture_opts->save_file, is_tempfile, &err)) {
+    switch(cf_open((capture_file *)capture_opts->cf, capture_opts->save_file, is_tempfile, &err)) {
     case CF_OK:
       break;
     case CF_ERROR:
@@ -2413,7 +2452,7 @@ capture_input_new_packets(capture_options *capture_opts, int to_read)
   int           err;
   gchar        *err_info;
   gint64        data_offset;
-  capture_file *cf = capture_opts->cf;
+  capture_file *cf = (capture_file *)capture_opts->cf;
   gboolean      filtering_tap_listeners;
   guint         tap_flags;
 
@@ -2633,7 +2672,7 @@ process_packet_first_pass(capture_file *cf,
   frame_data_init(&fdlocal, framenum, whdr, offset, cum_bytes);
 
   /* If we're going to print packet information, or we're going to
-     run a read filter, or we're going to process taps, set up to
+     run a read filter, or display filter, or we're going to process taps, set up to
      do a dissection and do so. */
   if (do_dissection) {
     if (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
@@ -2641,7 +2680,7 @@ process_packet_first_pass(capture_file *cf,
       /* Grab any resolved addresses */
       host_name_lookup_process();
 
-    /* If we're going to be applying a read filter, we'll need to
+    /* If we're going to be applying a filter, we'll need to
        create a protocol tree against which to apply the filter. */
     if (cf->rfcode)
       create_proto_tree = TRUE;
@@ -2667,15 +2706,22 @@ process_packet_first_pass(capture_file *cf,
 
   if (passed) {
     frame_data_set_after_dissect(&fdlocal, &cum_bytes);
-    prev_dis_frame = fdlocal;
-    prev_dis = &prev_dis_frame;
-    frame_data_sequence_add(cf->frames, &fdlocal);
+    prev_cap = prev_dis = frame_data_sequence_add(cf->frames, &fdlocal);
+
+    g_slist_foreach(edt.pi.dependent_frames, find_and_mark_frame_depended_upon, cf->frames);
+
     cf->count++;
+  } else {
+    /* if we don't add it to the frame_data_sequence, clean it up right now
+     * to avoid leaks */
+    frame_data_destroy(&fdlocal);
+    /* TODO, bug #8160 */
+    /*
+    prev_cap_frame = fdlocal;
+    prev_cap = &prev_cap_frame;
+     */
   }
 
-  prev_cap_frame = fdlocal;
-  prev_cap = &prev_cap_frame;
-
   if (do_dissection)
     epan_dissect_cleanup(&edt);
 
@@ -2706,7 +2752,7 @@ process_packet_second_pass(capture_file *cf, frame_data *fdata,
       /* Grab any resolved addresses */
       host_name_lookup_process();
 
-    if (cf->rfcode || print_details || filtering_tap_listeners ||
+    if (cf->dfcode || print_details || filtering_tap_listeners ||
         (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo))
       create_proto_tree = TRUE;
     else
@@ -2718,10 +2764,10 @@ process_packet_second_pass(capture_file *cf, frame_data *fdata,
        ("packet_details" is true). */
     epan_dissect_init(&edt, create_proto_tree, print_packet_info && print_details);
 
-    /* If we're running a read filter, prime the epan_dissect_t with that
+    /* If we're running a display filter, prime the epan_dissect_t with that
        filter. */
-    if (cf->rfcode)
-      epan_dissect_prime_dfilter(&edt, cf->rfcode);
+    if (cf->dfcode)
+      epan_dissect_prime_dfilter(&edt, cf->dfcode);
 
     col_custom_prime_edt(&edt, &cf->cinfo);
 
@@ -2738,9 +2784,9 @@ process_packet_second_pass(capture_file *cf, frame_data *fdata,
 
     epan_dissect_run_with_taps(&edt, phdr, pd, fdata, cinfo);
 
-    /* Run the read filter if we have one. */
-    if (cf->rfcode)
-      passed = dfilter_apply_edt(cf->rfcode, &edt);
+    /* Run the read/display filter if we have one. */
+    if (cf->dfcode)
+      passed = dfilter_apply_edt(cf->dfcode, &edt);
   }
 
   if (passed) {
@@ -2786,7 +2832,7 @@ process_packet_second_pass(capture_file *cf, frame_data *fdata,
   if (do_dissection) {
     epan_dissect_cleanup(&edt);
   }
-  return passed;
+  return passed || fdata->flags.dependent_of_displayed;
 }
 
 static int
@@ -2937,7 +2983,7 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
              filter, so, if we're writing to a capture file, write
              this packet out. */
           if (pdh != NULL) {
-            if (!wtap_dump(pdh, &cf->phdr, wtap_buf_ptr(cf->wth), &err)) {
+            if (!wtap_dump(pdh, &cf->phdr, cf->pd, &err)) {
               /* Error writing to a capture file */
               switch (err) {
 
@@ -3151,7 +3197,7 @@ process_packet(capture_file *cf, gint64 offset, struct wtap_pkthdr *whdr,
       /* Grab any resolved addresses */
       host_name_lookup_process();
 
-    if (cf->rfcode || print_details || filtering_tap_listeners ||
+    if (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners ||
         (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo))
       create_proto_tree = TRUE;
     else
@@ -3163,10 +3209,12 @@ process_packet(capture_file *cf, gint64 offset, struct wtap_pkthdr *whdr,
        ("packet_details" is true). */
     epan_dissect_init(&edt, create_proto_tree, print_packet_info && print_details);
 
-    /* If we're running a read filter, prime the epan_dissect_t with that
+    /* If we're running a filter, prime the epan_dissect_t with that
        filter. */
     if (cf->rfcode)
       epan_dissect_prime_dfilter(&edt, cf->rfcode);
+    if (cf->dfcode)
+      epan_dissect_prime_dfilter(&edt, cf->dfcode);
 
     col_custom_prime_edt(&edt, &cf->cinfo);
 
@@ -3187,15 +3235,15 @@ process_packet(capture_file *cf, gint64 offset, struct wtap_pkthdr *whdr,
 
     epan_dissect_run_with_taps(&edt, whdr, pd, &fdata, cinfo);
 
-    /* Run the read filter if we have one. */
+    /* Run the filters if we have them. */
     if (cf->rfcode)
       passed = dfilter_apply_edt(cf->rfcode, &edt);
+    if (passed && cf->dfcode)
+      passed = dfilter_apply_edt(cf->dfcode, &edt);
   }
 
   if (passed) {
     frame_data_set_after_dissect(&fdata, &cum_bytes);
-    prev_dis_frame = fdata;
-    prev_dis = &prev_dis_frame;
 
     /* Process this packet. */
     if (print_packet_info) {
@@ -3234,6 +3282,10 @@ process_packet(capture_file *cf, gint64 offset, struct wtap_pkthdr *whdr,
         exit(2);
       }
     }
+
+    /* this must be set after print_packet() [bug #8160] */
+    prev_dis_frame = fdata;
+    prev_dis = &prev_dis_frame;
   }
 
   prev_cap_frame = fdata;
@@ -3241,7 +3293,7 @@ process_packet(capture_file *cf, gint64 offset, struct wtap_pkthdr *whdr,
 
   if (do_dissection) {
     epan_dissect_cleanup(&edt);
-    frame_data_cleanup(&fdata);
+    frame_data_destroy(&fdata);
   }
   return passed;
 }
@@ -3283,11 +3335,11 @@ get_line_buf(size_t len)
     ;
   if (line_bufp == NULL) {
     line_buf_len = new_line_buf_len;
-    line_bufp = g_malloc(line_buf_len + 1);
+    line_bufp = (char *)g_malloc(line_buf_len + 1);
   } else {
     if (new_line_buf_len > line_buf_len) {
       line_buf_len = new_line_buf_len;
-      line_bufp = g_realloc(line_bufp, line_buf_len + 1);
+      line_bufp = (char *)g_realloc(line_bufp, line_buf_len + 1);
     }
   }
   return line_bufp;
@@ -3923,26 +3975,6 @@ write_failure_message(const char *filename, int err)
           filename, g_strerror(err));
 }
 
-/*
- * Print to the standard error.  This is a command-line tool, so there's
- * no need to pop up a console.
- */
-void
-vfprintf_stderr(const char *fmt, va_list ap)
-{
-  vfprintf(stderr, fmt, ap);
-}
-
-void
-fprintf_stderr(const char *fmt, ...)
-{
-  va_list ap;
-
-  va_start(ap, fmt);
-  vfprintf_stderr(fmt, ap);
-  va_end(ap);
-}
-
 /*
  * Report an error in command-line arguments.
  */