When capturing, we only support writing to libpcap files. Given that,
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Sat, 4 Mar 2006 22:33:04 +0000 (22:33 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Sat, 4 Mar 2006 22:33:04 +0000 (22:33 +0000)
bypass Wiretap; that means we don't have to run the packet through
wtap_process_pcap_packet() and then undo that conversion in Wiretap if
we're just going to write it out, shortening the code path.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@17461 f5534014-38df-0310-8fa8-9805f1628bb7

Makefile.common
capture_loop.c
capture_loop.h
pcapio.c [new file with mode: 0644]
pcapio.h [new file with mode: 0644]
ringbuffer.c
ringbuffer.h
tethereal.c

index eb21e630059aec39b88530a8fd3385e5a9fa2f7e..f27e41f4e879f8f7c360c75acde0c4aefff63c6d 100644 (file)
@@ -58,6 +58,7 @@ ETHEREAL_COMMON_SRC = \
        packet-range.c  \
        print.c \
        ps.c    \
+       pcapio.c        \
        ringbuffer.c    \
        timestats.c     \
        util.c  \
@@ -81,6 +82,7 @@ ETHEREAL_COMMON_INCLUDES =    \
        fileset.h       \
        isprint.h       \
        packet-range.h  \
+       pcapio.h        \
        print.h \
        ps.h    \
        register.h      \
@@ -221,6 +223,7 @@ dumpcap_SOURCES =   \
        clopts_common.c \
        conditions.c    \
        dumpcap.c       \
+       pcapio.c        \
        ringbuffer.c    \
        tempfile.c      \
        version_info.c
index 986f8974d2c6f20d4042fdc51c463b5c3f85f2cf..dc4eb74c517ee3e20d51969b6d1490dcb9f1bf85 100644 (file)
@@ -68,8 +68,7 @@
 
 #include <pcap.h>
 
-#include "wiretap/wtap.h"
-#include "wiretap/wtap-capture.h"
+#include "pcapio.h"
 
 #include "capture-pcap-util.h"
 
@@ -640,7 +639,7 @@ gboolean capture_loop_open_input(capture_options *capture_opts, loop_data *ld, c
 }
 
 
-/* open the capture input file (pcap or capture pipe) */
+/* close the capture input file (pcap or capture pipe) */
 static void capture_loop_close_input(loop_data *ld) {
 
   g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_close_input");
@@ -746,14 +745,14 @@ gboolean capture_loop_init_filter(pcap_t *pcap_h, gboolean from_cap_pipe, const
 }
 
 
-/* open the wiretap part of the capture output file */
-gboolean capture_loop_init_wiretap_output(capture_options *capture_opts, int save_file_fd, loop_data *ld, char *errmsg, int errmsg_len) {
+/* set up to write to the already-opened capture output file/files */
+gboolean capture_loop_init_output(capture_options *capture_opts, int save_file_fd, loop_data *ld, char *errmsg, int errmsg_len) {
   int         pcap_encap;
   int         file_snaplen;
   int         err;
 
 
-  g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_init_wiretap_output");
+  g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_init_output");
 
   /* get packet encapsulation type and snaplen */
 #ifndef _WIN32
@@ -768,22 +767,15 @@ gboolean capture_loop_init_wiretap_output(capture_options *capture_opts, int sav
   }
 
   /* Set up to write to the capture file. */
-  ld->wtap_linktype = wtap_pcap_encap_to_wtap_encap(pcap_encap);
-  if (ld->wtap_linktype == WTAP_ENCAP_UNKNOWN) {
-    g_snprintf(errmsg, errmsg_len,
-       "The network you're capturing from is of a type"
-       " that (T)Ethereal doesn't support (data link type %d).", pcap_encap);
-    return FALSE;
-  }
+  ld->linktype = pcap_encap;
   if (capture_opts->multi_files_on) {
-    ld->wtap_pdh = ringbuf_init_wtap_dump_fdopen(WTAP_FILE_PCAP, ld->wtap_linktype,
-      file_snaplen, &err);
+    ld->pdh = ringbuf_init_libpcap_fdopen(ld->linktype, file_snaplen, &err);
   } else {
-    ld->wtap_pdh = wtap_dump_fdopen(save_file_fd, WTAP_FILE_PCAP,
-      ld->wtap_linktype, file_snaplen, FALSE /* compressed */, &err);
+    ld->pdh = libpcap_fdopen(save_file_fd, ld->linktype, file_snaplen,
+                             &ld->bytes_written, &err);
   }
 
-  if (ld->wtap_pdh == NULL) {
+  if (ld->pdh == NULL) {
     /* We couldn't set up to write to the capture file. */
     /* XXX - use cf_open_error_message from tethereal instead? */
     switch (err) {
@@ -824,9 +816,9 @@ gboolean capture_loop_close_output(capture_options *capture_opts, loop_data *ld,
   g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_close_output");
 
   if (capture_opts->multi_files_on) {
-    return ringbuf_wtap_dump_close(&capture_opts->save_file, err_close);
+    return ringbuf_libpcap_dump_close(&capture_opts->save_file, err_close);
   } else {
-    return wtap_dump_close(ld->wtap_pdh, err_close);
+    return libpcap_dump_close(ld->pdh, err_close);
   }
 }
 
@@ -1129,7 +1121,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
   ld.wtap_linktype      = WTAP_ENCAP_UNKNOWN;
   ld.pcap_err           = FALSE;
   ld.from_cap_pipe      = FALSE;
-  ld.wtap_pdh           = NULL;
+  ld.pdh                = NULL;
 #ifndef _WIN32
   ld.cap_pipe_fd        = -1;
 #endif
@@ -1168,8 +1160,8 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
     goto error;
   }
 
-  /* open the wiretap part of the output file (the output file is already open) */
-  if (!capture_loop_init_wiretap_output(capture_opts, save_file_fd, &ld, errmsg, sizeof(errmsg))) {
+  /* set up to write to the already-opened capture output file/files */
+  if (!capture_loop_init_output(capture_opts, save_file_fd, &ld, errmsg, sizeof(errmsg))) {
     goto error;
   }
 
@@ -1186,7 +1178,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
      message to our parent so that they'll open the capture file and
      update its windows to indicate that we have a live capture in
      progress. */
-  wtap_dump_flush(ld.wtap_pdh);
+  libpcap_dump_flush(ld.pdh, NULL);
   sync_pipe_filename_to_parent(capture_opts->save_file);
 
   /* initialize capture stop (and alike) conditions */
@@ -1233,7 +1225,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
 
       /* check capture size condition */
       if (cnd_autostop_size != NULL && cnd_eval(cnd_autostop_size,
-                    (guint32)wtap_get_bytes_dumped(ld.wtap_pdh))){
+                    (guint32)ld.bytes_written)){
         /* Capture size limit reached, do we have another file? */
         if (capture_opts->multi_files_on) {
           if (cnd_autostop_files != NULL && cnd_eval(cnd_autostop_files, ++autostop_files)) {
@@ -1243,15 +1235,15 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
           }
 
           /* Switch to the next ringbuffer file */
-          if (ringbuf_switch_file(&ld.wtap_pdh, &capture_opts->save_file, &save_file_fd, &ld.err)) {
+          if (ringbuf_switch_file(&ld.pdh, &capture_opts->save_file, &save_file_fd, &ld.err)) {
             /* File switch succeeded: reset the conditions */
             cnd_reset(cnd_autostop_size);
             if (cnd_file_duration) {
               cnd_reset(cnd_file_duration);
             }
-            wtap_dump_flush(ld.wtap_pdh);
+            libpcap_dump_flush(ld.pdh, NULL);
             sync_pipe_packet_count_to_parent(inpkts_to_sync_pipe);
-                       inpkts_to_sync_pipe = 0;
+            inpkts_to_sync_pipe = 0;
             sync_pipe_filename_to_parent(capture_opts->save_file);
           } else {
             /* File switch failed: stop here */
@@ -1265,7 +1257,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
         }
       } /* cnd_autostop_size */
       if (capture_opts->output_to_pipe) {
-        wtap_dump_flush(ld.wtap_pdh);
+        libpcap_dump_flush(ld.pdh, NULL);
       }
     } /* inpkts */
 
@@ -1285,10 +1277,10 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
       /* Let the parent process know. */
       if (inpkts_to_sync_pipe) {
         /* do sync here */
-        wtap_dump_flush(ld.wtap_pdh);
+        libpcap_dump_flush(ld.pdh, NULL);
 
-         /* Send our parent a message saying we've written out "inpkts_to_sync_pipe"
-            packets to the capture file. */
+        /* Send our parent a message saying we've written out "inpkts_to_sync_pipe"
+           packets to the capture file. */
         sync_pipe_packet_count_to_parent(inpkts_to_sync_pipe);
 
         inpkts_to_sync_pipe = 0;
@@ -1312,14 +1304,14 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
           }
 
           /* Switch to the next ringbuffer file */
-          if (ringbuf_switch_file(&ld.wtap_pdh, &capture_opts->save_file, &save_file_fd, &ld.err)) {
+          if (ringbuf_switch_file(&ld.pdh, &capture_opts->save_file, &save_file_fd, &ld.err)) {
             /* file switch succeeded: reset the conditions */
             cnd_reset(cnd_file_duration);
             if(cnd_autostop_size)
               cnd_reset(cnd_autostop_size);
-            wtap_dump_flush(ld.wtap_pdh);
+            libpcap_dump_flush(ld.pdh, NULL);
             sync_pipe_packet_count_to_parent(inpkts_to_sync_pipe);
-                       inpkts_to_sync_pipe = 0;
+            inpkts_to_sync_pipe = 0;
             sync_pipe_filename_to_parent(capture_opts->save_file);
           } else {
             /* File switch failed: stop here */
@@ -1517,8 +1509,6 @@ static void
 capture_loop_packet_cb(u_char *user, const struct pcap_pkthdr *phdr,
   const u_char *pd)
 {
-  struct wtap_pkthdr whdr;
-  union wtap_pseudo_header pseudo_header;
   loop_data *ld = (loop_data *) user;
   int err;
 
@@ -1529,22 +1519,11 @@ capture_loop_packet_cb(u_char *user, const struct pcap_pkthdr *phdr,
      ld->go = FALSE;
   }
 
-  /* Convert from libpcap to Wiretap format.
-     If that fails, set "ld->go" to FALSE, to stop the capture, and set
-     "ld->err" to the error. */
-  pd = wtap_process_pcap_packet(ld->wtap_linktype, phdr, pd, &pseudo_header,
-                               &whdr, &err);
-  if (pd == NULL) {
-    ld->go = FALSE;
-    ld->err = err;
-    return;
-  }
-
-  if (ld->wtap_pdh) {
+  if (ld->pdh) {
     /* We're supposed to write the packet to a file; do so.
        If this fails, set "ld->go" to FALSE, to stop the capture, and set
        "ld->err" to the error. */
-    if (!wtap_dump(ld->wtap_pdh, &whdr, &pseudo_header, pd, &err)) {
+    if (!libpcap_write_packet(ld->pdh, phdr, pd, &ld->bytes_written, &err)) {
       ld->go = FALSE;
       ld->err = err;
     }
index defb31110bf6aead73e091f9a5c180269fb27a8a..bfdf7343887a36aeb1a11abc9ec33c30c1565c9a 100644 (file)
@@ -118,9 +118,11 @@ typedef struct _loop_data {
   enum { PIPOK, PIPEOF, PIPERR, PIPNEXIST } cap_pipe_err;
 #endif
 
-  /* wiretap (output file) */
-  wtap_dumper   *wtap_pdh;
+  /* output file */
+  FILE          *pdh;
+  int            linktype;
   gint           wtap_linktype;
+  long           bytes_written;
 
 } loop_data;
 
@@ -152,7 +154,7 @@ extern gboolean
 capture_loop_open_output(capture_options *capture_opts, int *save_file_fd, char *errmsg, int errmsg_len);
 
 extern gboolean
-capture_loop_init_wiretap_output(capture_options *capture_opts, int save_file_fd, loop_data *ld, char *errmsg, int errmsg_len);
+capture_loop_init_output(capture_options *capture_opts, int save_file_fd, loop_data *ld, char *errmsg, int errmsg_len);
 
 extern gboolean 
 capture_loop_close_output(capture_options *capture_opts, loop_data *ld, int *err_close);
diff --git a/pcapio.c b/pcapio.c
new file mode 100644 (file)
index 0000000..ad8f057
--- /dev/null
+++ b/pcapio.c
@@ -0,0 +1,186 @@
+/* pcapio.c
+ * Our own private code for writing libpcap files when capturing.
+ *
+ * We have these because we want a way to open a stream for output given
+ * only a file descriptor.  libpcap 0.9[.x] has "pcap_dump_fopen()", which
+ * provides that, but
+ *
+ *     1) earlier versions of libpcap doesn't have it
+ *
+ * and
+ *
+ *     2) WinPcap doesn't have it, because a file descriptor opened
+ *        by code built for one version of the MSVC++ C library
+ *        can't be used by library routines built for another version
+ *        (e.g., threaded vs. unthreaded).
+ *
+ * Libpcap's pcap_dump() also doesn't return any error indications.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Derived from code in the Wiretap Library
+ * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <pcap.h>
+
+#include <glib.h>
+
+#include "pcapio.h"
+
+/* Magic numbers in "libpcap" files.
+
+   "libpcap" file records are written in the byte order of the host that
+   writes them, and the reader is expected to fix this up.
+
+   PCAP_MAGIC is the magic number, in host byte order; PCAP_SWAPPED_MAGIC
+   is a byte-swapped version of that.
+
+   PCAP_NSEC_MAGIC is for Ulf Lamping's modified "libpcap" format,
+   which uses the same common file format as PCAP_MAGIC, but the 
+   timestamps are saved in nanosecond resolution instead of microseconds.
+   PCAP_SWAPPED_NSEC_MAGIC is a byte-swapped version of that. */
+#define        PCAP_MAGIC                      0xa1b2c3d4
+#define        PCAP_SWAPPED_MAGIC              0xd4c3b2a1
+#define        PCAP_NSEC_MAGIC                 0xa1b23c4d
+#define        PCAP_SWAPPED_NSEC_MAGIC         0x4d3cb2a1
+
+/* "libpcap" file header. */
+struct pcap_hdr {
+       guint32 magic;          /* magic number */
+       guint16 version_major;  /* major version number */
+       guint16 version_minor;  /* minor version number */
+       gint32  thiszone;       /* GMT to local correction */
+       guint32 sigfigs;        /* accuracy of timestamps */
+       guint32 snaplen;        /* max length of captured packets, in octets */
+       guint32 network;        /* data link type */
+};
+
+/* "libpcap" record header. */
+struct pcaprec_hdr {
+       guint32 ts_sec;         /* timestamp seconds */
+       guint32 ts_usec;        /* timestamp microseconds (nsecs for PCAP_NSEC_MAGIC) */
+       guint32 incl_len;       /* number of octets of packet saved in file */
+       guint32 orig_len;       /* actual length of packet */
+};
+
+/* Returns a FILE * to write to on success, NULL on failure; sets "*err" to
+   an error code, or 0 for a short write, on failure */
+FILE *
+libpcap_fdopen(int fd, int linktype, int snaplen, long *bytes_written,
+    int *err)
+{
+       FILE *fp;
+       struct pcap_hdr file_hdr;
+       size_t nwritten;
+
+       fp = fdopen(fd, "wb");
+       if (fp == NULL) {
+               *err = errno;
+               return NULL;
+       }
+
+       file_hdr.magic = PCAP_MAGIC;
+       /* current "libpcap" format is 2.4 */
+       file_hdr.version_major = 2;
+       file_hdr.version_minor = 4;
+       file_hdr.thiszone = 0;  /* XXX - current offset? */
+       file_hdr.sigfigs = 0;   /* unknown, but also apparently unused */
+       file_hdr.snaplen = snaplen;
+       file_hdr.network = linktype;
+       nwritten = fwrite(&file_hdr, 1, sizeof file_hdr, fp);
+       if (nwritten != sizeof file_hdr) {
+               if (nwritten == 0 && ferror(fp))
+                       *err = errno;
+               else
+                       *err = 0;       /* short write */
+               fclose(fp);
+               return NULL;
+       }
+       *bytes_written = sizeof file_hdr;
+
+       return fp;
+}
+
+/* Write a record for a packet to a dump file.
+   Returns TRUE on success, FALSE on failure. */
+gboolean
+libpcap_write_packet(FILE *fp, const struct pcap_pkthdr *phdr, const u_char *pd,
+    long *bytes_written, int *err)
+{
+       struct pcaprec_hdr rec_hdr;
+       size_t nwritten;
+
+       rec_hdr.ts_sec = phdr->ts.tv_sec;
+       rec_hdr.ts_usec = phdr->ts.tv_usec;
+       rec_hdr.incl_len = phdr->caplen;
+       rec_hdr.orig_len = phdr->len;
+       nwritten = fwrite(&rec_hdr, 1, sizeof rec_hdr, fp);
+       if (nwritten != sizeof rec_hdr) {
+               if (nwritten == 0 && ferror(fp))
+                       *err = errno;
+               else
+                       *err = 0;       /* short write */
+               return FALSE;
+       }
+       *bytes_written += sizeof rec_hdr;
+
+       nwritten = fwrite(pd, 1, phdr->caplen, fp);
+       if (nwritten != phdr->caplen) {
+               if (nwritten == 0 && ferror(fp))
+                       *err = errno;
+               else
+                       *err = 0;       /* short write */
+               return FALSE;
+       }
+       *bytes_written += phdr->caplen;
+       return TRUE;
+}
+
+gboolean
+libpcap_dump_flush(FILE *pd, int *err)
+{
+       if (fflush(pd) == EOF) {
+               if (err != NULL)
+                       *err = errno;
+               return FALSE;
+       }
+       return TRUE;
+}
+
+gboolean
+libpcap_dump_close(FILE *pd, int *err)
+{
+       if (fclose(pd) == EOF) {
+               if (err != NULL)
+                       *err = errno;
+               return FALSE;
+       }
+       return TRUE;
+}
diff --git a/pcapio.h b/pcapio.h
new file mode 100644 (file)
index 0000000..801a563
--- /dev/null
+++ b/pcapio.h
@@ -0,0 +1,44 @@
+/* pcapio.h
+ * Declarations of our own routins for writing libpcap files.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Derived from code in the Wiretap Library
+ * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+/* Returns a FILE * to write to on success, NULL on failure; sets "*err" to
+   an error code, or 0 for a short write, on failure */
+extern FILE *
+libpcap_fdopen(int fd, int linktype, int snaplen, long *bytes_written,
+    int *err);
+
+/* Write a record for a packet to a dump file.
+   Returns TRUE on success, FALSE on failure. */
+extern gboolean
+libpcap_write_packet(FILE *fp, const struct pcap_pkthdr *phdr, const u_char *pd,
+    long *bytes_written, int *err);
+
+extern gboolean
+libpcap_dump_flush(FILE *pd, int *err);
+
+extern gboolean
+libpcap_dump_close(FILE *pd, int *err);
index 0c1e7f4b759a1def7cf8d621bf084a10cd33f8ed..7d1e00af6660c66813115231568927aff01ab866 100644 (file)
 #include <time.h>
 #include <errno.h>
 
-#include <wiretap/wtap.h>
+#include <pcap.h>
+
+#include <glib.h>
+
+#include "pcapio.h"
 #include "ringbuffer.h"
 #include "file_util.h"
 
@@ -79,12 +83,12 @@ typedef struct _ringbuf_data {
   gchar        *fprefix;             /* Filename prefix */
   gchar        *fsuffix;             /* Filename suffix */
   gboolean      unlimited;           /* TRUE if unlimited number of files */
-  int           filetype;
   int           linktype;
   int           snaplen;
 
   int           fd;                 /* Current ringbuffer file descriptor */
-  wtap_dumper  *pdh;  
+  FILE         *pdh;
+  long          bytes_written;      /* Bytes written to the current file */
 } ringbuf_data;
 
 static ringbuf_data rb_data;
@@ -224,18 +228,17 @@ const gchar *ringbuf_current_filename(void)
 }
 
 /*
- * Calls wtap_dump_fdopen() for the current ringbuffer file
+ * Calls libpcap_fdopen() for the current ringbuffer file
  */
-wtap_dumper*
-ringbuf_init_wtap_dump_fdopen(int filetype, int linktype, int snaplen, int *err)
+FILE *
+ringbuf_init_libpcap_fdopen(int linktype, int snaplen, int *err)
 {
 
-  rb_data.filetype = filetype;
   rb_data.linktype = linktype;
   rb_data.snaplen  = snaplen;
 
-  rb_data.pdh = wtap_dump_fdopen(rb_data.fd, filetype, linktype, snaplen, FALSE /* compressed */, err);
-
+  rb_data.pdh = libpcap_fdopen(rb_data.fd, linktype, snaplen,
+                               &rb_data.bytes_written, err);
   return rb_data.pdh;
 }
 
@@ -243,14 +246,14 @@ ringbuf_init_wtap_dump_fdopen(int filetype, int linktype, int snaplen, int *err)
  * Switches to the next ringbuffer file
  */
 gboolean
-ringbuf_switch_file(wtap_dumper **pdh, gchar **save_file, int *save_file_fd, int *err)
+ringbuf_switch_file(FILE **pdh, gchar **save_file, int *save_file_fd, int *err)
 {
   int     next_file_num;
   rb_file *next_rfile = NULL;
 
   /* close current file */
 
-  if (!wtap_dump_close(rb_data.pdh, err)) {
+  if (!libpcap_dump_close(rb_data.pdh, err)) {
     eth_close(rb_data.fd);     /* XXX - the above should have closed this already */
     rb_data.pdh = NULL;        /* it's still closed, we just got an error while closing */
     rb_data.fd = -1;
@@ -270,8 +273,8 @@ ringbuf_switch_file(wtap_dumper **pdh, gchar **save_file, int *save_file_fd, int
     return FALSE;
   }
 
-  if (ringbuf_init_wtap_dump_fdopen(rb_data.filetype, rb_data.linktype,
-                                   rb_data.snaplen, err) == NULL) {
+  if (ringbuf_init_libpcap_fdopen(rb_data.linktype, rb_data.snaplen,
+                                  err) == NULL) {
     return FALSE;
   }
 
@@ -284,16 +287,16 @@ ringbuf_switch_file(wtap_dumper **pdh, gchar **save_file, int *save_file_fd, int
 }
 
 /*
- * Calls wtap_dump_close() for the current ringbuffer file
+ * Calls libpcap_dump_close() for the current ringbuffer file
  */
 gboolean
-ringbuf_wtap_dump_close(gchar **save_file, int *err)
+ringbuf_libpcap_dump_close(gchar **save_file, int *err)
 {
   gboolean  ret_val = TRUE;
 
   /* close current file, if it's open */
   if (rb_data.pdh != NULL) {
-    if (!wtap_dump_close(rb_data.pdh, err)) {
+    if (!libpcap_dump_close(rb_data.pdh, err)) {
       eth_close(rb_data.fd);
       ret_val = FALSE;
     }
@@ -345,14 +348,14 @@ ringbuf_error_cleanup(void)
 
   /* try to close via wtap */
   if (rb_data.pdh != NULL) {
-    if (wtap_dump_close(rb_data.pdh, NULL)) {
+    if (libpcap_dump_close(rb_data.pdh, NULL)) {
       rb_data.fd = -1;
     }
     rb_data.pdh = NULL;
   }
 
   /* close directly if still open */
-  /* XXX - it shouldn't still be open; "wtap_dump_close()" should leave the
+  /* XXX - it shouldn't still be open; "libpcap_dump_close()" should leave the
      file closed even if it fails */
   if (rb_data.fd != -1) {
     eth_close(rb_data.fd);
index 396963b7bf0592eddb8925e91c65e27c7725a6b2..8989f5c4aa5a9fdd17c7996e76e2d3fc5b83b76f 100644 (file)
 
 int ringbuf_init(const char *capture_name, guint num_files);
 const gchar *ringbuf_current_filename(void);
-wtap_dumper* ringbuf_init_wtap_dump_fdopen(int filetype, int linktype,
-  int snaplen, int *err);
-gboolean ringbuf_switch_file(wtap_dumper **pdh, gchar **save_file, int *save_file_fd, int *err);
-gboolean ringbuf_wtap_dump_close(gchar **save_file, int *err);
+FILE *ringbuf_init_libpcap_fdopen(int linktype, int snaplen, int *err);
+gboolean ringbuf_switch_file(FILE **pdh, gchar **save_file, int *save_file_fd, int *err);
+gboolean ringbuf_libpcap_dump_close(gchar **save_file, int *err);
 void ringbuf_free(void);
 void ringbuf_error_cleanup(void);
 
index aad2172a22f254945947dc3e8dc6537470b52278..b0775b06259d386cd296fc2a3a5c327f4b59fdaf 100644 (file)
@@ -95,6 +95,7 @@
 #include <pcap.h>
 #include <setjmp.h>
 #include "capture-pcap-util.h"
+#include "pcapio.h"
 #include <wiretap/wtap-capture.h>
 #ifdef _WIN32
 #include "capture-wpcap.h"
@@ -170,9 +171,9 @@ static void report_counts_siginfo(int);
 #endif /* HAVE_LIBPCAP */
 
 static int load_cap_file(capture_file *, char *, int);
-static gboolean process_packet(capture_file *cf, wtap_dumper *pdh, long offset,
+static gboolean process_packet(capture_file *cf, long offset,
     const struct wtap_pkthdr *whdr, union wtap_pseudo_header *pseudo_header,
-    const guchar *pd, int *err);
+    const guchar *pd);
 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);
@@ -1449,10 +1450,16 @@ main(int argc, char *argv[])
         exit(status);
     }
 
-    if (!quiet) {
+    if (!print_packet_info && !quiet) {
       /*
-       * The user didn't ask us not to print a count of packets as
-       * they arrive, so do so.
+       * We're not printing information for each packet, and the user
+       * didn't ask us not to print a count of packets as they arrive,
+       * so print that count so the user knows that packets are arriving.
+       *
+       * XXX - what if the user wants to do a live capture, doesn't want
+       * to save it to a file, doesn't want information printed for each
+       * packet, does want some "-z" statistic, and wants packet counts
+       * so they know whether they're seeing any packets?
        */
       print_packet_counts = TRUE;
     }
@@ -1509,7 +1516,7 @@ capture(void)
   init_dissection();
 
   ld.wtap_linktype  = WTAP_ENCAP_UNKNOWN;
-  ld.wtap_pdh       = NULL;
+  ld.pdh            = NULL;
   ld.packet_cb      = capture_pcap_cb;
 
 
@@ -1545,12 +1552,14 @@ capture(void)
       goto error;
   }
 
-  /* open the wiretap part of the output file (the output file is already open) */
-  if(!capture_loop_init_wiretap_output(&capture_opts, save_file_fd, &ld, errmsg, sizeof errmsg))
+  /* set up to write to the already-opened capture output file/files */
+  if(!capture_loop_init_output(&capture_opts, save_file_fd, &ld, errmsg, sizeof errmsg))
   {
       goto error;
   }
 
+  ld.wtap_linktype = wtap_pcap_encap_to_wtap_encap(ld.linktype);
+
   /* Save the capture file name. */
   ld.save_file = capture_opts.save_file;
 
@@ -1679,13 +1688,12 @@ capture(void)
            in effect. */
         ld.go = FALSE;
       } else if (cnd_autostop_size != NULL &&
-                    cnd_eval(cnd_autostop_size,
-                              (guint32)wtap_get_bytes_dumped(ld.wtap_pdh))) {
+                    cnd_eval(cnd_autostop_size, (guint32)ld.bytes_written)) {
         /* We're saving the capture to a file, and the capture file reached
            its maximum size. */
         if (capture_opts.multi_files_on) {
           /* Switch to the next ringbuffer file */
-          if (ringbuf_switch_file(&ld.wtap_pdh, &capture_opts.save_file, &save_file_fd, &loop_err)) {
+          if (ringbuf_switch_file(&ld.pdh, &capture_opts.save_file, &save_file_fd, &loop_err)) {
             /* File switch succeeded: reset the condition */
             cnd_reset(cnd_autostop_size);
             if (cnd_file_duration) {
@@ -1703,7 +1711,7 @@ capture(void)
       }
       if (capture_opts.output_to_pipe) {
         if (ld.packet_count > packet_count_prev) {
-          wtap_dump_flush(ld.wtap_pdh);
+          libpcap_dump_flush(ld.pdh, NULL);
           packet_count_prev = ld.packet_count;
         }
       }
@@ -1806,18 +1814,12 @@ capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
 {
   struct wtap_pkthdr whdr;
   union wtap_pseudo_header pseudo_header;
+  const guchar *wtap_pd;
   loop_data *ld = (loop_data *) user;
   int loop_err;
   int err;
   int save_file_fd;
-
-  /* Convert from libpcap to Wiretap format.
-     If that fails, ignore the packet (wtap_process_pcap_packet has
-     written an error message). */
-  pd = wtap_process_pcap_packet(ld->wtap_linktype, phdr, pd, &pseudo_header,
-                                &whdr, &err);
-  if (pd == NULL)
-    return;
+  gboolean packet_accepted;
 
 #ifdef SIGINFO
   /*
@@ -1835,7 +1837,7 @@ capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
    */
   if (cnd_file_duration != NULL && cnd_eval(cnd_file_duration)) {
     /* time elapsed for this ring file, switch to the next */
-    if (ringbuf_switch_file(&ld->wtap_pdh, &ld->save_file, &save_file_fd, &loop_err)) {
+    if (ringbuf_switch_file(&ld->pdh, &ld->save_file, &save_file_fd, &loop_err)) {
       /* File switch succeeded: reset the condition */
       cnd_reset(cnd_file_duration);
     } else {
@@ -1845,17 +1847,51 @@ capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
     }
   }
 
-  if (!process_packet(&cfile, ld->wtap_pdh, 0, &whdr, &pseudo_header, pd, &err)) {
-    /* Error writing to a capture file */
+  if (do_dissection) {
+    /* We're goint to print packet information, run a read filter, or
+       process taps.  Use process_packet() to handle that; in order
+       to do that, we need to convert from libpcap to Wiretap format.
+       If that fails, ignore the packet (wtap_process_pcap_packet has
+       written an error message). */
+    wtap_pd = wtap_process_pcap_packet(ld->wtap_linktype, phdr, pd,
+                                       &pseudo_header, &whdr, &err);
+    if (wtap_pd == NULL)
+      return;
+
+    packet_accepted = process_packet(&cfile, 0, &whdr, &pseudo_header, wtap_pd);
+  } else {
+    /* We're just writing out packets. */
+    packet_accepted = TRUE;
+  }
+
+  if (packet_accepted) {
+    /* Count this packet. */
+#ifdef HAVE_LIBPCAP
+    ld->packet_count++;
+#endif
+
+    if (ld->pdh != NULL) {
+      if (!libpcap_write_packet(ld->pdh, phdr, pd, &ld->bytes_written, &err)) {
+        /* Error writing to a capture file */
+        if (print_packet_counts) {
+          /* We're printing counts of packets captured; move to the line after
+             the count. */
+          fprintf(stderr, "\n");
+        }
+        show_capture_file_io_error(ld->save_file, err, FALSE);
+        pcap_close(ld->pcap_h);
+        libpcap_dump_close(ld->pdh, &err);
+        exit(2);
+      }
+    }
     if (print_packet_counts) {
-      /* We're printing counts of packets captured; move to the line after
-         the count. */
-      fprintf(stderr, "\n");
+      /* We're printing packet counts. */
+      if (ld->packet_count != 0) {
+        fprintf(stderr, "\r%u ", ld->packet_count);
+        /* stderr could be line buffered */
+        fflush(stderr);
+      }
     }
-    show_capture_file_io_error(ld->save_file, err, FALSE);
-    pcap_close(ld->pcap_h);
-    wtap_dump_close(ld->wtap_pdh, &err);
-    exit(2);
   }
 
 #ifdef SIGINFO
@@ -2017,13 +2053,21 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type)
     pdh = NULL;
   }
   while (wtap_read(cf->wth, &err, &err_info, &data_offset)) {
-    if (!process_packet(cf, pdh, data_offset, wtap_phdr(cf->wth),
-                        wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth),
-                        &err)) {
-      /* Error writing to a capture file */
-      show_capture_file_io_error(save_file, err, FALSE);
-      wtap_dump_close(pdh, &err);
-      exit(2);
+    if (process_packet(cf, data_offset, wtap_phdr(cf->wth),
+                       wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth))) {
+      /* Either there's no read filtering or this packet passed the
+         filter, so, if we're writing to a capture file, write
+         this packet out. */
+      if (pdh != NULL) {
+        if (!wtap_dump(pdh, wtap_phdr(cf->wth),
+                       wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth),
+                       &err)) {
+          /* Error writing to a capture file */
+          show_capture_file_io_error(save_file, err, FALSE);
+          wtap_dump_close(pdh, &err);
+          exit(2);
+        }
+      }
     }
   }
   if (err != 0) {
@@ -2148,10 +2192,8 @@ clear_fdata(frame_data *fdata)
 }
 
 static gboolean
-process_packet(capture_file *cf, wtap_dumper *pdh, long offset,
-               const struct wtap_pkthdr *whdr,
-               union wtap_pseudo_header *pseudo_header, const guchar *pd,
-               int *err)
+process_packet(capture_file *cf, long offset, const struct wtap_pkthdr *whdr,
+               union wtap_pseudo_header *pseudo_header, const guchar *pd)
 {
   frame_data fdata;
   gboolean create_proto_tree;
@@ -2215,27 +2257,7 @@ process_packet(capture_file *cf, wtap_dumper *pdh, long offset,
   }
 
   if (passed) {
-    /* Count this packet. */
-#ifdef HAVE_LIBPCAP
-    ld.packet_count++;
-#endif
-
     /* Process this packet. */
-    if (pdh != NULL) {
-      /* We're writing to a capture file; write this packet. */
-      if (!wtap_dump(pdh, whdr, pseudo_header, pd, err))
-        return FALSE;
-#ifdef HAVE_LIBPCAP
-      if (print_packet_counts) {
-              /* We're printing packet counts. */
-        if (ld.packet_count != 0) {
-          fprintf(stderr, "\r%u ", ld.packet_count);
-          /* stderr could be line buffered */
-          fflush(stderr);
-        }
-      }
-#endif
-    }
     if (print_packet_info) {
       /* We're printing packet information; print the information for
          this packet. */
@@ -2275,7 +2297,7 @@ process_packet(capture_file *cf, wtap_dumper *pdh, long offset,
     epan_dissect_free(edt);
     clear_fdata(&fdata);
   }
-  return TRUE;
+  return passed;
 }
 
 static void