Squelch an MSVC++ complaint.
[obnox/wireshark/wip.git] / tethereal.c
index 6a6fc71b7c059ae21b2c56d136c05c8a9cde1b9b..75318067d735d6061306d2cd3e1f7ea25e7d3730 100644 (file)
@@ -1,9 +1,9 @@
 /* tethereal.c
  *
- * $Id: tethereal.c,v 1.83 2001/05/31 08:36:41 guy Exp $
+ * $Id: tethereal.c,v 1.97 2001/11/09 07:44:48 guy Exp $
  *
  * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@zing.org>
+ * By Gerald Combs <gerald@ethereal.com>
  * Copyright 1998 Gerald Combs
  *
  * Text-mode variant, by Gilbert Ramirez <gram@xiexie.org>.
 #include <pcap.h>
 #endif
 
+#ifdef HAVE_LIBZ
+#include <zlib.h>      /* to get the libz version number */
+#endif
+
 #ifdef NEED_SNPRINTF_H
 # include "snprintf.h"
 #endif
 #include "print.h"
 #include "resolv.h"
 #include "util.h"
+#ifdef HAVE_LIBPCAP
+#include "pcap-util.h"
+#endif
 #include "conversation.h"
+#include "reassemble.h"
 #include "plugins.h"
 #include "register.h"
 
@@ -128,16 +136,15 @@ typedef struct {
 } cb_args_t;
 
 static int load_cap_file(capture_file *, int);
-static void wtap_dispatch_cb_write(u_char *, const struct wtap_pkthdr *, int,
+static void wtap_dispatch_cb_write(u_char *, const struct wtap_pkthdr *, long,
     union wtap_pseudo_header *, const u_char *);
 static void show_capture_file_io_error(const char *, int, gboolean);
-static void wtap_dispatch_cb_print(u_char *, const struct wtap_pkthdr *, int,
+static void wtap_dispatch_cb_print(u_char *, const struct wtap_pkthdr *, long,
     union wtap_pseudo_header *, const u_char *);
 
 packet_info  pi;
 capture_file cfile;
 FILE        *data_out_file = NULL;
-guint        main_ctx, file_ctx;
 ts_type timestamp_type = RELATIVE;
 #ifdef HAVE_LIBPCAP
 static int promisc_mode = TRUE;
@@ -201,18 +208,17 @@ main(int argc, char *argv[])
   extern char         *optarg;
   gboolean             arg_error = FALSE;
 #ifdef HAVE_LIBPCAP
-#ifdef WIN32
-  char pcap_version[] = WPCAP_STRING;
-#else
+#ifdef HAVE_PCAP_VERSION
   extern char          pcap_version[];
-#endif
-#endif
+#endif /* HAVE_PCAP_VERSION */
+#endif /* HAVE_LIBPCAP */
 
 #ifdef WIN32
   WSADATA              wsaData;
 #endif
 
-  char                *gpf_path, *pf_path;
+  char                *gpf_path;
+  const char          *pf_path;
   int                  gpf_open_errno, pf_open_errno;
   int                  err;
 #ifdef HAVE_LIBPCAP
@@ -301,10 +307,14 @@ main(int argc, char *argv[])
 
 #ifdef HAVE_LIBPCAP
   g_string_append(comp_info_str, ", with libpcap ");
+#ifdef HAVE_PCAP_VERSION
   g_string_append(comp_info_str, pcap_version);
-#else
+#else /* HAVE_PCAP_VERSION */
+  g_string_append(comp_info_str, "(version unknown)");
+#endif /* HAVE_PCAP_VERSION */
+#else /* HAVE_LIBPCAP */
   g_string_append(comp_info_str, ", without libpcap");
-#endif
+#endif /* HAVE_LIBPCAP */
 
 #ifdef HAVE_LIBZ
   g_string_append(comp_info_str, ", with libz ");
@@ -439,6 +449,7 @@ main(int argc, char *argv[])
           break;
 
         case PREFS_SET_NO_SUCH_PREF:
+        case PREFS_SET_OBSOLETE:
           fprintf(stderr, "tethereal: -o flag \"%s\" specifies unknown preference\n",
                        optarg);
           exit(1);
@@ -634,7 +645,8 @@ main(int argc, char *argv[])
 static int
 capture(int packet_count, int out_file_type)
 {
-  gchar       err_str[PCAP_ERRBUF_SIZE];
+  gchar       open_err_str[PCAP_ERRBUF_SIZE];
+  gchar       lookup_net_err_str[PCAP_ERRBUF_SIZE];
   bpf_u_int32 netnum, netmask;
   struct bpf_program fcode;
   void        (*oldhandler)(int);
@@ -652,11 +664,22 @@ capture(int packet_count, int out_file_type)
   /* Initialize protocol-specific variables */
   init_all_protocols();
 
+  /* Initialize the common data structures for fragment reassembly.
+     Must be done *after* "init_all_protocols()", as "init_all_protocols()"
+     may free up space for fragments, which it finds by using the
+     data structures that "reassemble_init()" frees. */
+  reassemble_init();
+
   ld.linktype       = WTAP_ENCAP_UNKNOWN;
   ld.pdh            = NULL;
 
-  /* Open the network interface to capture from it. */
-  ld.pch = pcap_open_live(cfile.iface, cfile.snap, promisc_mode, 1000, err_str);
+  /* Open the network interface to capture from it.
+     Some versions of libpcap may put warnings into the error buffer
+     if they succeed; to tell if that's happened, we have to clear
+     the error buffer, and check if it's still a null string.  */
+  open_err_str[0] = '\0';
+  ld.pch = pcap_open_live(cfile.iface, cfile.snap, promisc_mode, 1000,
+                         open_err_str);
 
   if (ld.pch == NULL) {
     /* Well, we couldn't start the capture. */
@@ -672,14 +695,14 @@ capture(int packet_count, int out_file_type)
        "Note that the driver Tethereal uses for packet capture on Windows\n"
        "doesn't support capturing on Token Ring interfaces, and doesn't\n"
        "support capturing on PPP/WAN interfaces in Windows NT/2000.\n",
-       err_str);
+       open_err_str);
 #else
       /* If we got a "can't find PPA for XXX" message, warn the user (who
          is running Ethereal on HP-UX) that they don't have a version
         of libpcap that properly handles HP-UX (libpcap 0.6.x and later
         versions, which properly handle HP-UX, say "can't find /dev/dlpi
         PPA for XXX" rather than "can't find PPA for XXX"). */
-      if (strncmp(err_str, ppamsg, sizeof ppamsg - 1) == 0)
+      if (strncmp(open_err_str, ppamsg, sizeof ppamsg - 1) == 0)
        libpcap_warn =
          "\n\n"
          "You are running Tethereal with a version of the libpcap library\n"
@@ -696,21 +719,21 @@ capture(int packet_count, int out_file_type)
     snprintf(errmsg, sizeof errmsg,
       "The capture session could not be initiated (%s).\n"
       "Please check to make sure you have sufficient permissions, and that\n"
-      "you have the proper interface specified.%s", err_str, libpcap_warn);
+      "you have the proper interface specified.%s", open_err_str, libpcap_warn);
 #endif
     goto error;
   }
 
   if (cfile.cfilter) {
     /* A capture filter was specified; set it up. */
-    if (pcap_lookupnet (cfile.iface, &netnum, &netmask, err_str) < 0) {
+    if (pcap_lookupnet(cfile.iface, &netnum, &netmask, lookup_net_err_str) < 0) {
       /*
        * Well, we can't get the netmask for this interface; it's used
        * only for filters that check for broadcast IP addresses, so
        * we just warn the user, and punt and use 0.
        */
       fprintf(stderr, 
-        "Warning:  Couldn't obtain netmask info (%s)\n.", err_str);
+        "Warning:  Couldn't obtain netmask info (%s)\n.", lookup_net_err_str);
       netmask = 0;
     }
     if (pcap_compile(ld.pch, &fcode, cfile.cfilter, 1, netmask) < 0) {
@@ -725,7 +748,8 @@ capture(int packet_count, int out_file_type)
     }
   }
 
-  ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(ld.pch));
+  ld.linktype = wtap_pcap_encap_to_wtap_encap(get_pcap_linktype(ld.pch,
+       cfile.iface));
   if (cfile.save_file != NULL) {
     /* Set up to write to the capture file. */
     if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
@@ -743,6 +767,11 @@ capture(int packet_count, int out_file_type)
     }
   }
 
+  /* Does "open_err_str" contain a non-empty string?  If so, "pcap_open_live()"
+     returned a warning; print it, but keep capturing. */
+  if (open_err_str[0] != '\0')
+    fprintf(stderr, "tethereal: WARNING: %s.\n", open_err_str);
+
   /* Catch SIGINT and SIGTERM and, if we get either of them, clean up
      and exit.
      XXX - deal with signal semantics on various platforms.  Or just
@@ -785,6 +814,12 @@ capture(int packet_count, int out_file_type)
   }
   pcap_close(ld.pch);
 
+  if (cfile.save_file != NULL) {
+    /* We're saving to a file; close the file. */
+    if (!wtap_dump_close(ld.pdh, &err))
+      show_capture_file_io_error(cfile.save_file, err, TRUE);
+  }
+
   return TRUE;
 
 error:
@@ -899,6 +934,10 @@ load_cap_file(capture_file *cf, int out_file_type)
     args.pdh = pdh;
     success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_write, (u_char *) &args,
                        &err);
+
+    /* Now close the capture file. */
+    if (!wtap_dump_close(pdh, &err))
+      show_capture_file_io_error(cfile.save_file, err, TRUE);
   } else {
     args.cf = cf;
     args.pdh = NULL;
@@ -952,7 +991,7 @@ out:
 static void
 fill_in_fdata(frame_data *fdata, capture_file *cf,
        const struct wtap_pkthdr *phdr,
-       const union wtap_pseudo_header *pseudo_header, int offset)
+       const union wtap_pseudo_header *pseudo_header, long offset)
 {
   int i;
 
@@ -997,8 +1036,8 @@ fill_in_fdata(frame_data *fdata, capture_file *cf,
   /* 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 (cf->esec < fdata->rel_secs
-       || (cf->esec == fdata->rel_secs && cf->eusec < fdata->rel_usecs)) {
+  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;
   }
@@ -1028,8 +1067,8 @@ clear_fdata(frame_data *fdata)
 }
 
 static void
-wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr, int offset,
-  union wtap_pseudo_header *pseudo_header, const u_char *buf)
+wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr,
+  long offset, union wtap_pseudo_header *pseudo_header, const u_char *buf)
 {
   cb_args_t    *args = (cb_args_t *) user;
   capture_file *cf = args->cf;
@@ -1125,8 +1164,8 @@ show_capture_file_io_error(const char *fname, int err, gboolean is_close)
 }
 
 static void
-wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset,
-  union wtap_pseudo_header *pseudo_header, const u_char *buf)
+wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr,
+  long offset, union wtap_pseudo_header *pseudo_header, const u_char *buf)
 {
   cb_args_t    *args = (cb_args_t *) user;
   capture_file *cf = args->cf;
@@ -1162,8 +1201,9 @@ wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset,
       print_args.print_summary = FALSE;
       print_args.print_hex = print_hex;
       print_args.expand_all = TRUE;
+      print_args.suppress_unmarked = FALSE;
       proto_tree_print(FALSE, &print_args, (GNode *)protocol_tree,
-                       buf, &fdata, stdout);
+                       &fdata, stdout);
       if (!print_hex) {
         /* "print_hex_data()" will put out a leading blank line, as well
           as a trailing one; print one here, to separate the packets,
@@ -1476,7 +1516,6 @@ open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
 {
   wtap       *wth;
   int         err;
-  FILE_T      fh;
   int         fd;
   struct stat cf_stat;
   char        err_msg[2048+1];
@@ -1486,7 +1525,6 @@ open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
     goto fail;
 
   /* Find the size of the file. */
-  fh = wtap_file(wth);
   fd = wtap_fd(wth);
   if (fstat(fd, &cf_stat) < 0) {
     err = errno;
@@ -1502,6 +1540,12 @@ open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
   /* Initialize protocol-specific variables */
   init_all_protocols();
 
+  /* Initialize the common data structures for fragment reassembly.
+     Must be done *after* "init_all_protocols()", as "init_all_protocols()"
+     may free up space for fragments, which it finds by using the
+     data structures that "reassemble_init()" frees. */
+  reassemble_init();
+
   cf->wth = wth;
   cf->filed = fd;
   cf->f_len = cf_stat.st_size;