From Graeme Lunt
[obnox/wireshark/wip.git] / tethereal.c
index 13f7ce082030dcc14b5a383a17c642e65192622c..da4c3dff6d59594acc60d0f52ea85344568dc1a3 100644 (file)
@@ -84,7 +84,7 @@
 #include "capture_ui_utils.h"
 #include <epan/epan_dissect.h>
 #include <epan/tap.h>
-#include <epan/stat.h>
+#include <epan/stat_cmd_args.h>
 #include <epan/timestamp.h>
 
 #ifdef HAVE_LIBPCAP
  */
 static const gchar decode_as_arg_template[] = "<layer_type>==<selector>,<decode_as_protocol>";
 
-static guint32 firstsec, firstusec;
-static guint32 prevsec, prevusec;
+static nstime_t first_ts;
+static nstime_t prev_ts;
 static GString *comp_info_str, *runtime_info_str;
 
 static gboolean print_packet_info;     /* TRUE if we're to print packet information */
@@ -170,8 +170,8 @@ static gboolean infoprint;  /* if TRUE, print capture info after clearing infodel
 
 
 static int capture(char *, int);
-static void capture_pcap_cb(guchar *, const struct pcap_pkthdr *,
-  const guchar *);
+static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *,
+  const u_char *);
 static void report_counts(void);
 #ifdef _WIN32
 static BOOL WINAPI capture_cleanup(DWORD);
@@ -219,7 +219,7 @@ print_usage(gboolean print_ver)
 
   if (print_ver) {
     output = stdout;
-    fprintf(output, "This is GNU t" PACKAGE " " VERSION "%s"
+    fprintf(output, "This is t" PACKAGE " " VERSION "%s"
         "\n (C) 1998-2005 Gerald Combs <gerald@ethereal.com>"
        "\n%s\n%s\n",
 
@@ -232,18 +232,19 @@ print_usage(gboolean print_ver)
          PACKAGE);
   fprintf(output, "\t[ -b <capture ring buffer option> ] ... [ -c <capture packet count> ]\n");
   fprintf(output, "\t[ -d %s ] ...\n", decode_as_arg_template);
-  fprintf(output, "\t[ -f <capture filter> ] [ -F <output file type> ] [ -i <capture interface> ]\n");
-  fprintf(output, "\t[ -N <name resolving flags> ] [ -o <preference setting> ] ... [ -r <infile> ]\n");
-  fprintf(output, "\t[ -R <read (display) filter> ] [ -s <capture snaplen> ] [ -t <time stamp format> ]\n");
-  fprintf(output, "\t[ -T pdml|ps|psml|text ] [ -w <savefile> ] [ -y <capture link type> ]\n");
-  fprintf(output, "\t[ -z <statistics ]\n");
+  fprintf(output, "\t[ -f <capture filter> ] [ -F <output file type> ]\n");
+  fprintf(output, "\t[ -i <capture interface> ] [ -N <name resolving flags> ]\n");
+  fprintf(output, "\t[ -o <preference setting> ] ... [ -r <infile> ]\n");
+  fprintf(output, "\t[ -R <read (display) filter> ] [ -s <capture snaplen> ]\n");
+  fprintf(output, "\t[ -t <time stamp format> ] [ -T pdml|ps|psml|text ]\n");
+  fprintf(output, "\t[ -w <savefile> ] [ -y <capture link type> ] [ -z <statistics> ]\n");
 #else
   fprintf(output, "\nt%s [ -vh ] [ -lnVx ]\n", PACKAGE);
   fprintf(output, "\t[ -d %s ] ...\n", decode_as_arg_template);
   fprintf(output, "\t[ -F <output file type> ] [ -N <name resolving flags> ]\n");
-  fprintf(output, "\t[ -o <preference setting> ] ... [ -r <infile> ] [ -R <read (display) filter> ]\n");
-  fprintf(output, "\t[ -t <time stamp format> ] [ -T pdml|ps|psml|text ] [ -w <savefile> ]\n");
-  fprintf(output, "\t[ -z <statistics ]\n");
+  fprintf(output, "\t[ -o <preference setting> ] ... [ -r <infile> ]\n");
+  fprintf(output, "\t[ -R <read (display) filter> ] \t[ -t <time stamp format> ]\n");
+  fprintf(output, "\t[ -T pdml|ps|psml|text ] [ -w <savefile> ] [ -z <statistics ]\n");
 #endif
   fprintf(output, "Valid file type arguments to the \"-F\" flag:\n");
   for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
@@ -656,7 +657,8 @@ main(int argc, char *argv[])
   capture_opts_init(&capture_opts, NULL /* cfile */);
 #endif
 
-  set_timestamp_setting(TS_RELATIVE);
+  timestamp_set_type(TS_RELATIVE);
+  timestamp_set_precision(TS_PREC_AUTO);
 
   /* Register all dissectors; we must do this before checking for the
      "-G" flag, as the "-G" flag dumps information registered by the
@@ -961,13 +963,13 @@ main(int argc, char *argv[])
         break;
       case 't':        /* Time stamp type */
         if (strcmp(optarg, "r") == 0)
-          set_timestamp_setting(TS_RELATIVE);
+          timestamp_set_type(TS_RELATIVE);
         else if (strcmp(optarg, "a") == 0)
-          set_timestamp_setting(TS_ABSOLUTE);
+          timestamp_set_type(TS_ABSOLUTE);
         else if (strcmp(optarg, "ad") == 0)
-          set_timestamp_setting(TS_ABSOLUTE_WITH_DATE);
+          timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
         else if (strcmp(optarg, "d") == 0)
-          set_timestamp_setting(TS_DELTA);
+          timestamp_set_type(TS_DELTA);
         else {
           fprintf(stderr, "tethereal: Invalid time stamp type \"%s\"\n",
             optarg);
@@ -1324,6 +1326,33 @@ main(int argc, char *argv[])
       epan_cleanup();
       exit(2);
     }
+
+    /* Set timestamp precision; there should arguably be a command-line
+       option to let the user set this. */
+    switch(wtap_file_tsprecision(cfile.wth)) {
+    case(WTAP_FILE_TSPREC_SEC):
+      timestamp_set_precision(TS_PREC_AUTO_SEC);
+      break;
+    case(WTAP_FILE_TSPREC_DSEC):
+      timestamp_set_precision(TS_PREC_AUTO_DSEC);
+      break;
+    case(WTAP_FILE_TSPREC_CSEC):
+      timestamp_set_precision(TS_PREC_AUTO_CSEC);
+      break;
+    case(WTAP_FILE_TSPREC_MSEC):
+      timestamp_set_precision(TS_PREC_AUTO_MSEC);
+      break;
+    case(WTAP_FILE_TSPREC_USEC):
+      timestamp_set_precision(TS_PREC_AUTO_USEC);
+      break;
+    case(WTAP_FILE_TSPREC_NSEC):
+      timestamp_set_precision(TS_PREC_AUTO_NSEC);
+      break;
+    default:
+      g_assert_not_reached();
+    }
+
+    /* Process the packets in the file */
     err = load_cap_file(&cfile, save_file, out_file_type);
     if (err != 0) {
       epan_cleanup();
@@ -1338,45 +1367,44 @@ main(int argc, char *argv[])
 
 #ifdef _WIN32
     if (!has_wpcap) {
-       fprintf(stderr, "tethereal: Could not load wpcap.dll.\n");
-       exit(2);
+      fprintf(stderr, "tethereal: Could not load wpcap.dll.\n");
+      exit(2);
     }
 #endif
 
     /* Yes; did the user specify an interface to use? */
     if (capture_opts.iface == NULL) {
-        /* No - is a default specified in the preferences file? */
-        if (prefs->capture_device != NULL) {
-            /* Yes - use it. */
-           if_text = strrchr(prefs->capture_device, ' ');
-           if (if_text == NULL) {
-               capture_opts.iface = g_strdup(prefs->capture_device);
-           } else {
-               capture_opts.iface = g_strdup(if_text + 1); /* Skip over space */
-           }
-        } else {
-            /* No - pick the first one from the list of interfaces. */
-            if_list = get_interface_list(&err, err_str);
-            if (if_list == NULL) {
-                switch (err) {
-
-                case CANT_GET_INTERFACE_LIST:
-                    cant_get_if_list_errstr =
-                        cant_get_if_list_error_message(err_str);
-                    fprintf(stderr, "tethereal: %s\n", cant_get_if_list_errstr);
-                    g_free(cant_get_if_list_errstr);
-                    break;
-
-                case NO_INTERFACES_FOUND:
-                    fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
-                    break;
-                }
-                exit(2);
-            }
-           if_info = if_list->data;    /* first interface */
-           capture_opts.iface = g_strdup(if_info->name);
-            free_interface_list(if_list);
-        }
+      /* No - is a default specified in the preferences file? */
+      if (prefs->capture_device != NULL) {
+        /* Yes - use it. */
+        if_text = strrchr(prefs->capture_device, ' ');
+       if (if_text == NULL) {
+          capture_opts.iface = g_strdup(prefs->capture_device);
+       } else {
+          capture_opts.iface = g_strdup(if_text + 1); /* Skip over space */
+       }
+      } else {
+        /* No - pick the first one from the list of interfaces. */
+        if_list = get_interface_list(&err, err_str);
+        if (if_list == NULL) {
+          switch (err) {
+
+          case CANT_GET_INTERFACE_LIST:
+            cant_get_if_list_errstr = cant_get_if_list_error_message(err_str);
+            fprintf(stderr, "tethereal: %s\n", cant_get_if_list_errstr);
+            g_free(cant_get_if_list_errstr);
+            break;
+
+          case NO_INTERFACES_FOUND:
+            fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
+            break;
+         }
+          exit(2);
+       }
+        if_info = if_list->data;       /* first interface */
+       capture_opts.iface = g_strdup(if_info->name);
+        free_interface_list(if_list);
+      }
     }
 
     if (list_link_layer_types) {
@@ -1415,6 +1443,9 @@ main(int argc, char *argv[])
       print_packet_counts = TRUE;
     }
 
+    /* For now, assume libpcap gives microsecond precision. */
+    timestamp_set_precision(TS_PREC_AUTO_USEC);
+
     capture(save_file, out_file_type);
 
     if (capture_opts.multi_files_on) {
@@ -1507,13 +1538,14 @@ capture(char *save_file, int out_file_type)
 
        Do, however, warn that WAN devices aren't supported. */
     g_snprintf(errmsg, sizeof errmsg,
-       "The capture session could not be initiated (%s).\n"
-       "Please check that you have the proper interface specified.\n"
-       "\n"
-       "Note that the WinPcap 2.x version of the driver Ethereal uses for packet\n"
-       "capture on Windows doesn't support capturing on PPP/WAN interfaces in\n"
-       "Windows NT/2000/XP/2003 Server, and that the WinPcap 3.0 and later versions\n"
-       "don't support capturing on PPP/WAN interfaces at all.\n",
+"The capture session could not be initiated (%s).\n"
+"Please check that you have the proper interface specified.\n"
+"\n"
+"Note that version 3.0 of WinPcap, and earlier versions of WinPcap, don't\n"
+"support capturing on PPP/WAN interfaces on Windows NT 4.0 / 2000 / XP /\n"
+"Server 2003.\n"
+"WinPcap 3.1 has support for it on Windows 2000 / XP / Server 2003, but has no\n"
+"support for it on Windows NT 4.0 or Windows Vista (Beta 1).\n",
        open_err_str);
     goto error;
 #else
@@ -1650,7 +1682,7 @@ capture(char *save_file, int out_file_type)
       }
     } else {
       ld.pdh = wtap_dump_open(save_file, out_file_type,
-                ld.linktype, file_snaplen, &err);
+                ld.linktype, file_snaplen, FALSE /* compress */, &err);
     }
 
     if (ld.pdh == NULL) {
@@ -1775,7 +1807,7 @@ capture(char *save_file, int out_file_type)
         errmsg, sizeof errmsg);
     } else
 #endif
-      inpkts = pcap_dispatch(ld.pch, pcap_cnt, capture_pcap_cb, (guchar *) &ld);
+      inpkts = pcap_dispatch(ld.pch, pcap_cnt, capture_pcap_cb, (u_char *) &ld);
     if (inpkts < 0) {
       /* Error from "pcap_dispatch()", or error or "no more packets" from
          "pipe_dispatch(). */
@@ -1815,10 +1847,7 @@ capture(char *save_file, int out_file_type)
       }
       if (ld.output_to_pipe) {
         if (ld.packet_count > packet_count_prev) {
-          if (fflush(wtap_dump_file(ld.pdh))) {
-            volatile_err = errno;
-            ld.go = FALSE;
-          }
+          wtap_dump_flush(ld.pdh);
           packet_count_prev = ld.packet_count;
         }
       }
@@ -1922,8 +1951,8 @@ error:
 }
 
 static void
-capture_pcap_cb(guchar *user, const struct pcap_pkthdr *phdr,
-  const guchar *pd)
+capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
+  const u_char *pd)
 {
   struct wtap_pkthdr whdr;
   union wtap_pseudo_header pseudo_header;
@@ -2090,7 +2119,7 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type)
       snapshot_length = WTAP_MAX_PACKET_SIZE;
     }
     pdh = wtap_dump_open(save_file, out_file_type,
-               linktype, snapshot_length, &err);
+               linktype, snapshot_length, FALSE /* compressed */, &err);
 
     if (pdh == NULL) {
       /* We couldn't set up to write to the capture file. */
@@ -2225,8 +2254,7 @@ fill_in_fdata(frame_data *fdata, capture_file *cf,
   fdata->cap_len = phdr->caplen;
   fdata->file_off = offset;
   fdata->lnk_t = phdr->pkt_encap;
-  fdata->abs_secs  = phdr->ts.tv_sec;
-  fdata->abs_usecs = phdr->ts.tv_usec;
+  fdata->abs_ts = *((nstime_t *) &phdr->ts);
   fdata->flags.passed_dfilter = 0;
   fdata->flags.encoding = CHAR_ASCII;
   fdata->flags.visited = 0;
@@ -2236,39 +2264,33 @@ fill_in_fdata(frame_data *fdata, capture_file *cf,
   /* If we don't have the time stamp of the first packet in the
      capture, it's because this is the first packet.  Save the time
      stamp of this packet as the time stamp of the first packet. */
-  if (!firstsec && !firstusec) {
-    firstsec  = fdata->abs_secs;
-    firstusec = fdata->abs_usecs;
+  if (nstime_is_zero(&first_ts)) {
+    first_ts = fdata->abs_ts;
   }
 
   /* If we don't have the time stamp of the previous displayed packet,
      it's because this is the first displayed packet.  Save the time
      stamp of this packet as the time stamp of the previous displayed
      packet. */
-  if (!prevsec && !prevusec) {
-    prevsec  = fdata->abs_secs;
-    prevusec = fdata->abs_usecs;
+  if (nstime_is_zero(&prev_ts)) {
+    prev_ts = fdata->abs_ts;
   }
 
   /* Get the time elapsed between the first packet and this packet. */
-  compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
-               fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
+  nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
 
   /* If it's greater than the current elapsed time, set the elapsed time
      to it (we check for "greater than" so as not to be confused by
      time moving backwards). */
-  if ((gint32)cf->esec < fdata->rel_secs
-       || ((gint32)cf->esec == fdata->rel_secs && (gint32)cf->eusec < fdata->rel_usecs)) {
-    cf->esec = fdata->rel_secs;
-    cf->eusec = fdata->rel_usecs;
+  if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
+       || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
+    cf->elapsed_time = fdata->rel_ts;
   }
 
   /* Get the time elapsed between the previous displayed packet and
      this packet. */
-  compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
-               fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
-  prevsec = fdata->abs_secs;
-  prevusec = fdata->abs_usecs;
+  nstime_delta(&fdata->del_ts, &fdata->abs_ts, &prev_ts);
+  prev_ts = fdata->abs_ts;
 }
 
 /* Free up all data attached to a "frame_data" structure. */
@@ -2970,9 +2992,7 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
   init_dissection();
 
   cf->wth = wth;
-  cf->filed = -1;      /* not used, but set it anyway */
   cf->f_datalen = 0;   /* not used, but set it anyway */
-  cf->f_len = 0;       /* not used, but set it anyway */
 
   /* Set the file name because we need it to set the follow stream filter.
      XXX - is that still true?  We need it for other reasons, though,
@@ -2989,8 +3009,6 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
   cf->count     = 0;
   cf->drops_known = FALSE;
   cf->drops     = 0;
-  cf->esec      = 0;
-  cf->eusec     = 0;
   cf->snap      = wtap_snapshot_length(cf->wth);
   if (cf->snap == 0) {
     /* Snapshot length not known. */
@@ -2998,8 +3016,9 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
     cf->snap = WTAP_MAX_PACKET_SIZE;
   } else
     cf->has_snap = TRUE;
-  firstsec = 0, firstusec = 0;
-  prevsec = 0, prevusec = 0;
+  nstime_set_zero(&cf->elapsed_time);
+  nstime_set_zero(&first_ts);
+  nstime_set_zero(&prev_ts);
 
   return CF_OK;
 
@@ -3274,7 +3293,7 @@ pipe_dispatch(int fd, loop_data *ldat, struct pcap_hdr *hdr,
     phdr.caplen = rechdr->hdr.incl_len;
     phdr.len = rechdr->hdr.orig_len;
 
-    capture_pcap_cb((guchar *)ldat, &phdr, data);
+    capture_pcap_cb((u_char *)ldat, &phdr, data);
 
     ldat->pipe_state = STATE_EXPECT_REC_HDR;
     return 1;