Fix a few minor memory leaks...
[obnox/wireshark/wip.git] / tshark.c
index 1e1e077bca8ab294272503a12d1bee08e339c8dc..a2bc6bb1ccf813092a8ca21d3d3feaf4ebe2d1cd 100644 (file)
--- a/tshark.c
+++ b/tshark.c
@@ -62,8 +62,7 @@
 #include <glib.h>
 #include <epan/epan.h>
 #include <epan/filesystem.h>
-#include <epan/privileges.h>
-#include <wiretap/file_util.h>
+#include <wsutil/privileges.h>
 
 #include "globals.h"
 #include <epan/timestamp.h>
@@ -97,7 +96,6 @@
 #endif /* _WIN32 */
 #include "capture_sync.h"
 #endif /* HAVE_LIBPCAP */
-#include "epan/emem.h"
 #include "log.h"
 #include <epan/funnel.h>
 
@@ -147,7 +145,7 @@ static const char please_report[] =
 static gboolean print_packet_counts;
 
 
-static capture_options capture_opts;
+static capture_options global_capture_opts;
 
 #ifdef SIGINFO
 static gboolean infodelay;     /* if TRUE, don't print capture info in SIGINFO handler */
@@ -185,6 +183,34 @@ static void read_failure_message(const char *filename, int err);
 
 capture_file cfile;
 
+/*
+ * Mark a particular frame.
+ * Copied from file.c
+ */
+void
+cf_mark_frame(capture_file *cf, frame_data *frame)
+{
+  if (! frame->flags.marked) {
+    frame->flags.marked = TRUE;
+    if (cf->count > cf->marked_count)
+      cf->marked_count++;
+  }
+}
+
+/*
+ * Unmark a particular frame.
+ * Copied from file.c
+ */
+void
+cf_unmark_frame(capture_file *cf, frame_data *frame)
+{
+  if (frame->flags.marked) {
+    frame->flags.marked = FALSE;
+    if (cf->marked_count > 0)
+      cf->marked_count--;
+  }
+}
+
 
 static void list_capture_types(void) {
     int i;
@@ -284,6 +310,7 @@ print_usage(gboolean print_ver)
   fprintf(output, "  -h                       display this help and exit\n");
   fprintf(output, "  -v                       display version info and exit\n");
   fprintf(output, "  -o <name>:<value> ...    override preference setting\n");
+  fprintf(output, "  -K <keytab>              keytab file to use for kerberos decryption\n");
 }
 
 /*
@@ -421,12 +448,11 @@ add_decode_as(const gchar *cl_param)
   ftenum_t                      dissector_table_selector_type;
   struct protocol_name_search   user_protocol_name;
 
-/* The following code will allocate and copy the command-line options in a string pointed by decoded_param */
+  /* The following code will allocate and copy the command-line options in a string pointed by decoded_param */
 
   g_assert(cl_param);
-  decoded_param = g_malloc( sizeof(gchar) * (strlen(cl_param) + 1) ); /* Allocate enough space to have a working copy of the command-line parameter */
+  decoded_param = g_strdup(cl_param);
   g_assert(decoded_param);
-  strcpy(decoded_param, cl_param);
 
 
   /* The lines below will parse this string (modifying it) to extract all
@@ -726,7 +752,7 @@ main(int argc, char *argv[])
   GLogLevelFlags       log_flags;
   int                  optind_initial;
 
-#define OPTSTRING_INIT "a:b:c:C:d:De:E:f:F:G:hi:lLnN:o:pqr:R:s:St:T:vVw:xX:y:z:"
+#define OPTSTRING_INIT "a:b:c:C:d:De:E:f:F:G:hi:K:lLnN:o:pqr:R:s:St:T:vVw:xX:y:z:"
 #ifdef HAVE_LIBPCAP
 #ifdef _WIN32
 #define OPTSTRING_WIN32 "B:"
@@ -798,7 +824,7 @@ main(int argc, char *argv[])
   initialize_funnel_ops();
 
 #ifdef HAVE_LIBPCAP
-  capture_opts_init(&capture_opts, NULL /* cfile */);
+  capture_opts_init(&global_capture_opts, NULL /* cfile */);
 #endif
 
   timestamp_set_type(TS_RELATIVE);
@@ -835,6 +861,8 @@ main(int argc, char *argv[])
      If none of our build or other processes uses "-G" with no arguments,
      we can just process it with the other arguments. */
   if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
+         proto_initialize_all_prefixes();
+
     if (argc == 2)
       proto_registrar_dump_fields(1);
     else {
@@ -956,7 +984,7 @@ main(int argc, char *argv[])
       case 'B':        /* Buffer size */
 #endif /* _WIN32 */
 #ifdef HAVE_LIBPCAP
-        status = capture_opts_add_opt(&capture_opts, opt, optarg, &start_capture);
+        status = capture_opts_add_opt(&global_capture_opts, opt, optarg, &start_capture);
         if(status != 0) {
             exit(status);
         }
@@ -972,6 +1000,11 @@ main(int argc, char *argv[])
         if (!add_decode_as(optarg))
           exit(1);
         break;
+#if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
+      case 'K':        /* Kerberos keytab file */
+        read_keytab_file(optarg);
+        break;
+#endif
       case 'D':        /* Print a list of capture devices and exit */
 #ifdef HAVE_LIBPCAP
         status = capture_opts_list_interfaces(FALSE);
@@ -1188,13 +1221,13 @@ main(int argc, char *argv[])
       rfilter = get_args_as_string(argc, argv, optind);
     } else {
 #ifdef HAVE_LIBPCAP
-      if (capture_opts.has_cfilter) {
+      if (global_capture_opts.has_cfilter) {
         cmdarg_err("Capture filters were specified both with \"-f\""
             " and with additional command-line arguments");
         exit(1);
       }
-      capture_opts.has_cfilter = TRUE;
-      capture_opts.cfilter = get_args_as_string(argc, argv, optind);
+      global_capture_opts.has_cfilter = TRUE;
+      global_capture_opts.cfilter = get_args_as_string(argc, argv, optind);
 #else
       capture_option_specified = TRUE;
 #endif
@@ -1202,7 +1235,7 @@ main(int argc, char *argv[])
   }
 
 #ifdef HAVE_LIBPCAP
-  if (!capture_opts.saving_to_file) {
+  if (!global_capture_opts.saving_to_file) {
     /* We're not saving the capture to a file; if "-q" wasn't specified,
        we should print packet information */
     if (!quiet)
@@ -1213,7 +1246,7 @@ main(int argc, char *argv[])
        output, reject the request.  At best, we could redirect that
        to the standard error; we *can't* write both to the standard
        output and have either of them be useful. */
-    if (strcmp(capture_opts.save_file, "-") == 0 && print_packet_info) {
+    if (strcmp(global_capture_opts.save_file, "-") == 0 && print_packet_info) {
       cmdarg_err("You can't write both raw packet data and dissected packets"
           " to the standard output.");
       exit(1);
@@ -1240,7 +1273,7 @@ main(int argc, char *argv[])
      support in capture files we read). */
 #ifdef HAVE_LIBPCAP
   if (cf_name != NULL) {
-    if (capture_opts.has_cfilter) {
+    if (global_capture_opts.has_cfilter) {
       cmdarg_err("Only read filters, not capture filters, "
           "can be specified when reading a capture file.");
       exit(1);
@@ -1265,7 +1298,7 @@ main(int argc, char *argv[])
       exit(1);
     }
     /* No - did they specify a ring buffer option? */
-    if (capture_opts.multi_files_on) {
+    if (global_capture_opts.multi_files_on) {
       cmdarg_err("Ring buffer requested, but a capture isn't being done.");
       exit(1);
     }
@@ -1275,22 +1308,22 @@ main(int argc, char *argv[])
        * "-r" was specified, so we're reading a capture file.
        * Capture options don't apply here.
        */
-      if (capture_opts.multi_files_on) {
+      if (global_capture_opts.multi_files_on) {
         cmdarg_err("Multiple capture files requested, but "
                    "a capture isn't being done.");
         exit(1);
       }
-      if (capture_opts.has_file_duration) {
+      if (global_capture_opts.has_file_duration) {
         cmdarg_err("Switching capture files after a time interval was specified, but "
                    "a capture isn't being done.");
         exit(1);
       }
-      if (capture_opts.has_ring_num_files) {
+      if (global_capture_opts.has_ring_num_files) {
         cmdarg_err("A ring buffer of capture files was specified, but "
           "a capture isn't being done.");
         exit(1);
       }
-      if (capture_opts.has_autostop_files) {
+      if (global_capture_opts.has_autostop_files) {
         cmdarg_err("A maximum number of capture files was specified, but "
           "a capture isn't being done.");
         exit(1);
@@ -1300,7 +1333,7 @@ main(int argc, char *argv[])
        * and byte count as well as a write file. Other autostop options remain valid
        * only for a write file.
        */
-      if (capture_opts.has_autostop_duration) {
+      if (global_capture_opts.has_autostop_duration) {
         cmdarg_err("A maximum capture time was specified, but "
           "a capture isn't being done.");
         exit(1);
@@ -1309,7 +1342,7 @@ main(int argc, char *argv[])
       /*
        * "-r" wasn't specified, so we're doing a live capture.
        */
-      if (capture_opts.saving_to_file) {
+      if (global_capture_opts.saving_to_file) {
         /* They specified a "-w" flag, so we'll be saving to a capture file. */
 
         /* When capturing, we only support writing libpcap format. */
@@ -1317,23 +1350,23 @@ main(int argc, char *argv[])
           cmdarg_err("Live captures can only be saved in libpcap format.");
           exit(1);
         }
-        if (capture_opts.multi_files_on) {
+        if (global_capture_opts.multi_files_on) {
           /* Multiple-file mode doesn't work under certain conditions:
              a) it doesn't work if you're writing to the standard output;
              b) it doesn't work if you're writing to a pipe;
          */
-          if (strcmp(capture_opts.save_file, "-") == 0) {
+          if (strcmp(global_capture_opts.save_file, "-") == 0) {
             cmdarg_err("Multiple capture files requested, but "
               "the capture is being written to the standard output.");
             exit(1);
           }
-          if (capture_opts.output_to_pipe) {
+          if (global_capture_opts.output_to_pipe) {
             cmdarg_err("Multiple capture files requested, but "
               "the capture file is a pipe.");
             exit(1);
           }
-          if (!capture_opts.has_autostop_filesize &&
-             !capture_opts.has_file_duration) {
+          if (!global_capture_opts.has_autostop_filesize &&
+             !global_capture_opts.has_file_duration) {
             cmdarg_err("Multiple capture files requested, but "
               "no maximum capture file size or duration was specified.");
             exit(1);
@@ -1343,12 +1376,12 @@ main(int argc, char *argv[])
         /* 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
            we're saving to a file. */
-        if (capture_opts.has_autostop_filesize) {
+        if (global_capture_opts.has_autostop_filesize) {
           cmdarg_err("Maximum capture file size specified, but "
            "capture isn't being saved to a file.");
           exit(1);
         }
-        if (capture_opts.multi_files_on) {
+        if (global_capture_opts.multi_files_on) {
           cmdarg_err("Multiple capture files requested, but "
             "the capture isn't being saved to a file.");
           exit(1);
@@ -1383,6 +1416,11 @@ main(int argc, char *argv[])
   for (i = 0; i < cfile.cinfo.num_cols; i++) {
     cfile.cinfo.col_fmt[i] = get_column_format(i);
     cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
+    if (cfile.cinfo.col_fmt[i] == COL_CUSTOM) {
+      cfile.cinfo.col_custom_field[i] = g_strdup(get_column_custom_field(i));
+    } else {
+      cfile.cinfo.col_custom_field[i] = NULL;
+    }
     cfile.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
       NUM_COL_FMTS);
     get_column_format_matches(cfile.cinfo.fmt_matx[i], cfile.cinfo.col_fmt[i]);
@@ -1392,8 +1430,8 @@ main(int argc, char *argv[])
     else
       cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
     cfile.cinfo.col_fence[i] = 0;
-    cfile.cinfo.col_expr[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
-    cfile.cinfo.col_expr_val[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
+    cfile.cinfo.col_expr.col_expr[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
+    cfile.cinfo.col_expr.col_expr_val[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
   }
 
   for (i = 0; i < cfile.cinfo.num_cols; i++) {
@@ -1410,8 +1448,8 @@ main(int argc, char *argv[])
   }
 
 #ifdef HAVE_LIBPCAP
-  capture_opts_trim_snaplen(&capture_opts, MIN_PACKET_SIZE);
-  capture_opts_trim_ring_num_files(&capture_opts);
+  capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
+  capture_opts_trim_ring_num_files(&global_capture_opts);
 #endif
 
   if (rfilter != NULL) {
@@ -1513,9 +1551,9 @@ main(int argc, char *argv[])
 
     /* Process the packets in the file */
 #ifdef HAVE_LIBPCAP
-    err = load_cap_file(&cfile, capture_opts.save_file, out_file_type,
-        capture_opts.has_autostop_packets ? capture_opts.autostop_packets : 0,
-        capture_opts.has_autostop_filesize ? capture_opts.autostop_filesize : 0);
+    err = load_cap_file(&cfile, global_capture_opts.save_file, out_file_type,
+        global_capture_opts.has_autostop_packets ? global_capture_opts.autostop_packets : 0,
+        global_capture_opts.has_autostop_filesize ? global_capture_opts.autostop_filesize : 0);
 #else
     err = load_cap_file(&cfile, NULL, out_file_type, 0, 0);
 #endif
@@ -1543,14 +1581,14 @@ main(int argc, char *argv[])
 #endif
 
     /* trim the interface name and exit if that failed */
-    if (!capture_opts_trim_iface(&capture_opts,
+    if (!capture_opts_trim_iface(&global_capture_opts,
         (prefs->capture_device) ? get_if_name(prefs->capture_device) : NULL)) {
         exit(2);
     }
 
     /* if requested, list the link layer types and exit */
     if (list_link_layer_types) {
-        status = capture_opts_list_link_layer_types(&capture_opts, FALSE);
+        status = capture_opts_list_link_layer_types(&global_capture_opts, FALSE);
         exit(status);
     }
 
@@ -1778,13 +1816,13 @@ capture(void)
 #endif /* SIGINFO */
 #endif /* _WIN32 */
 
-  capture_opts.state = CAPTURE_PREPARING;
+  global_capture_opts.state = CAPTURE_PREPARING;
 
   /* Let the user know what interface was chosen. */
-  capture_opts.iface_descr = get_interface_descriptive_name(capture_opts.iface);
-  fprintf(stderr, "Capturing on %s\n", capture_opts.iface_descr);
+  global_capture_opts.iface_descr = get_interface_descriptive_name(global_capture_opts.iface);
+  fprintf(stderr, "Capturing on %s\n", global_capture_opts.iface_descr);
 
-  ret = sync_pipe_start(&capture_opts);
+  ret = sync_pipe_start(&global_capture_opts);
 
   if (!ret)
     return FALSE;
@@ -1845,26 +1883,6 @@ void main_window_update(void)
 {
 }
 
-/* XXX - move the call to simple_dialog() out of capture_sync.c */
-#include "simple_dialog.h"
-
-/* capture_sync.c want's to tell us an error */
-gpointer simple_dialog(ESD_TYPE_E type _U_, gint btn_mask _U_,
-                                          const gchar *msg_format, ...)
-{
-       va_list ap;
-
-       /* XXX - do we need to display buttons and alike? */
-       va_start(ap, msg_format);
-       fprintf(stderr, "tshark: ");
-       vfprintf(stderr, msg_format, ap);
-       fprintf(stderr, "\n");
-       va_end(ap);
-
-       return NULL;
-}
-
-
 /* capture child detected an error */
 void
 capture_input_error_message(capture_options *capture_opts _U_, char *error_msg, char *secondary_error_msg)
@@ -1952,7 +1970,6 @@ capture_input_new_file(capture_options *capture_opts, gchar *new_file)
       g_free(capture_opts->save_file);
       capture_opts->save_file = NULL;
       return FALSE;
-      break;
     }
   }
 
@@ -2063,19 +2080,19 @@ report_counts_siginfo(int signum _U_)
 
 /* capture child detected any packet drops? */
 void
-capture_input_drops(capture_options *capture_opts _U_, int dropped)
+capture_input_drops(capture_options *capture_opts _U_, guint32 dropped)
 {
-       if (print_packet_counts) {
-       /* We're printing packet counts to stderr.
-          Send a newline so that we move to the line after the packet count. */
-         fprintf(stderr, "\n");
-       }
-
-       if(dropped != 0) {
-               /* We're printing packet counts to stderr.
-                  Send a newline so that we move to the line after the packet count. */
-                 fprintf(stderr, "%u packet%s dropped\n", dropped, plurality(dropped, "", "s"));
-       }
+  if (print_packet_counts) {
+    /* We're printing packet counts to stderr.
+       Send a newline so that we move to the line after the packet count. */
+    fprintf(stderr, "\n");
+  }
+
+  if (dropped != 0) {
+    /* We're printing packet counts to stderr.
+       Send a newline so that we move to the line after the packet count. */
+    fprintf(stderr, "%u packet%s dropped\n", dropped, plurality(dropped, "", "s"));
+  }
 }
 
 
@@ -2127,7 +2144,7 @@ capture_cleanup(DWORD ctrltype _U_)
      building it with Cygwin may make the problem go away). */
 
   /* tell the capture child to stop */
-  sync_pipe_stop(&capture_opts);
+  sync_pipe_stop(&global_capture_opts);
 
   /* don't stop our own loop already here, otherwise status messages and
    * cleanup wouldn't be done properly. The child will indicate the stop of
@@ -2140,7 +2157,7 @@ static void
 capture_cleanup(int signum _U_)
 {
   /* tell the capture child to stop */
-  sync_pipe_stop(&capture_opts);
+  sync_pipe_stop(&global_capture_opts);
 }
 #endif /* _WIN32 */
 #endif /* HAVE_LIBPCAP */
@@ -2229,10 +2246,11 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
         }
       }
       /* Stop reading if we have the maximum number of packets;
-       * note that a zero max_packet_count will never be matched
-       * (unless we roll over the packet number?)
+       * When the -c option has not been used, max_packet_count
+       * starts at 0, which practically means, never stop reading.
+       * (unless we roll over max_packet_count ?)
        */
-      if(max_packet_count == cf->count || (max_byte_count != 0 && data_offset >= max_byte_count)) {
+      if( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) {
         err = 0; /* This is not an error */
         break;
       }
@@ -2245,6 +2263,7 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
     case WTAP_ERR_UNSUPPORTED_ENCAP:
       cmdarg_err("\"%s\" has a packet with a network type that TShark doesn't support.\n(%s)",
                  cf->filename, err_info);
+      g_free(err_info);
       break;
 
     case WTAP_ERR_CANT_READ:
@@ -2260,6 +2279,7 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
     case WTAP_ERR_BAD_RECORD:
       cmdarg_err("\"%s\" appears to be damaged or corrupt.\n(%s)",
                  cf->filename, err_info);
+      g_free(err_info);
       break;
 
     default:
@@ -2346,12 +2366,16 @@ fill_in_fdata(frame_data *fdata, capture_file *cf,
     cf->elapsed_time = fdata->rel_ts;
   }
 
+  /* If we don't have the time stamp of the previous displayed packet,
+     it's because this is the first packet that's being displayed.  Save the time
+     stamp of this packet as the time stamp of the previous displayed
+     packet. */
+  if (nstime_is_unset(&prev_dis_ts))
+    prev_dis_ts = fdata->abs_ts;
+
   /* Get the time elapsed between the previous displayed packet and
      this packet. */
-  if (nstime_is_unset(&prev_dis_ts))
-    nstime_set_zero(&fdata->del_dis_ts);
-  else
-    nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
+  nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
 
   /* Get the time elapsed between the previous captured packet and
      this packet. */
@@ -2394,7 +2418,7 @@ process_packet(capture_file *cf, gint64 offset, const struct wtap_pkthdr *whdr,
     }
 
     passed = TRUE;
-    if (cf->rfcode || verbose || num_tap_filters!=0)
+    if (cf->rfcode || verbose || num_tap_filters!=0 || have_custom_cols(&cf->cinfo))
       create_proto_tree = TRUE;
     else
       create_proto_tree = FALSE;
@@ -2409,6 +2433,8 @@ process_packet(capture_file *cf, gint64 offset, const struct wtap_pkthdr *whdr,
     if (cf->rfcode)
       epan_dissect_prime_dfilter(edt, cf->rfcode);
 
+    col_custom_prime_edt(edt, &cf->cinfo);
+
     tap_queue_init(edt);
 
     /* We only need the columns if we're printing packet info but we're
@@ -2600,7 +2626,7 @@ print_columns(capture_file *cf)
        * the same time, sort of like an "Update list of packets
        * in real time" capture in Wireshark.)
        */
-      if (capture_opts.iface != NULL)
+      if (global_capture_opts.iface != NULL)
         continue;
 #endif
       column_len = strlen(cf->cinfo.col_data[i]);
@@ -3116,9 +3142,7 @@ cmdarg_err(const char *fmt, ...)
   va_list ap;
 
   va_start(ap, fmt);
-  fprintf(stderr, "tshark: ");
-  vfprintf(stderr, fmt, ap);
-  fprintf(stderr, "\n");
+  failure_message(fmt, ap);
   va_end(ap);
 }
 
@@ -3135,5 +3159,3 @@ cmdarg_err_cont(const char *fmt, ...)
   fprintf(stderr, "\n");
   va_end(ap);
 }
-
-