Make the bytes-written information from Wiretap a long, as we allow
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 4 Dec 2001 08:26:00 +0000 (08:26 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 4 Dec 2001 08:26:00 +0000 (08:26 +0000)
files to get that big.

From Thomas Wittwer and Matthias Nyffenegger:

Support for "ring buffer mode", wherein there's a ring buffer of N
capture files; as each capture file reaches its maximum size (the ring
buffer works only with a maximum capture file size specified), Ethereal
rolls over to the next capture file in the ring buffer, replacing
whatever packets might be in it with new packets.

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

14 files changed:
Makefile.am
Makefile.nmake
capture.c
capture_stop_conditions.c
doc/ethereal.pod.template
doc/tethereal.pod.template
file.h
gtk/capture_dlg.c
gtk/main.c
tethereal.c
wiretap/file.c
wiretap/wtap-int.h
wiretap/wtap.def
wiretap/wtap.h

index 9a87c8aaf59fa31ddcfdc3e1de6d69fe9ca56b1b..fdf1cd09daef69e0954e158152aa0725fa0860ce 100644 (file)
@@ -1,7 +1,7 @@
 # Makefile.am
 # Automake file for Ethereal
 #
-# $Id: Makefile.am,v 1.390 2001/12/04 07:31:59 guy Exp $
+# $Id: Makefile.am,v 1.391 2001/12/04 08:25:55 guy Exp $
 #
 # Ethereal - Network traffic analyzer
 # By Gerald Combs <gerald@ethereal.com>
@@ -471,6 +471,8 @@ ETHEREAL_COMMON_SRC = \
        reassemble.c   \
        reassemble.h   \
        register.h     \
+       ringbuffer.c   \
+       ringbuffer.h   \
        smb.h          \
        util.c         \
        util.h         \
index fcfcdeb3007710307084044b19782c9b3377df26..d3855abf10d91864f96623d1ef8e380ca0b96608 100644 (file)
@@ -1,7 +1,7 @@
 ## Makefile for building ethereal.exe with Microsoft C and nmake
 ## Use: $(MAKE) /$(MAKEFLAGS) -f makefile.nmake
 #
-# $Id: Makefile.nmake,v 1.149 2001/12/04 07:32:00 guy Exp $
+# $Id: Makefile.nmake,v 1.150 2001/12/04 08:25:55 guy Exp $
 
 include config.nmake
 include <win32.mak>
@@ -262,6 +262,7 @@ ETHEREAL_COMMON_OBJECTS = \
        ptvcursor.obj    \
        reassemble.obj   \
        register.obj     \
+       ringbuffer.obj   \
        util.obj         \
        xdlc.obj         \
        xmlstub.obj      \
index 953982c82ddb1788117b00d3734bcb80e623c121..413b1750edcdf9554fe0ea2d8eb7e960a13a5fda 100644 (file)
--- a/capture.c
+++ b/capture.c
@@ -1,7 +1,7 @@
 /* capture.c
  * Routines for packet capture windows
  *
- * $Id: capture.c,v 1.162 2001/12/04 07:32:00 guy Exp $
+ * $Id: capture.c,v 1.163 2001/12/04 08:25:55 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
 #include "globals.h"
 #include "conditions.h"
 #include "capture_stop_conditions.h"
+#include "ringbuffer.h"
 
 #include "wiretap/libpcap.h"
 #include "wiretap/wtap.h"
@@ -287,8 +288,13 @@ do_capture(char *capfile_name)
   struct pcap_stat stats;
 
   if (capfile_name != NULL) {
-    /* Try to open/create the specified file for use as a capture buffer. */
-    cfile.save_file_fd = open(capfile_name, O_RDWR|O_BINARY|O_TRUNC|O_CREAT, 0600);
+    if (cfile.ringbuffer_on) {
+      /* ringbuffer is enabled */
+      cfile.save_file_fd = ringbuf_init(capfile_name, cfile.ringbuffer_num_files);
+    } else {
+      /* Try to open/create the specified file for use as a capture buffer. */
+      cfile.save_file_fd = open(capfile_name, O_RDWR|O_BINARY|O_TRUNC|O_CREAT, 0600);
+    }
     is_tempfile = FALSE;
   } else {
     /* Choose a random name for the capture buffer */
@@ -302,6 +308,9 @@ do_capture(char *capfile_name)
        "The temporary file to which the capture would be saved (\"%s\")"
        "could not be opened: %s.", capfile_name, strerror(errno));
     } else {
+      if (cfile.ringbuffer_on) {
+        ringbuf_error_cleanup();
+      }
       simple_dialog(ESD_TYPE_CRIT, NULL,
        file_open_error_message(errno, TRUE), capfile_name);
     }
@@ -355,7 +364,7 @@ do_capture(char *capfile_name)
     argv = add_arg(argv, &argc, ssnap);
 
     argv = add_arg(argv, &argc, "-a");
-    sprintf(sautostop_filesize,"filesize:%u",cfile.autostop_filesize);
+    sprintf(sautostop_filesize,"filesize:%d",cfile.autostop_filesize);
     argv = add_arg(argv, &argc, sautostop_filesize);
 
     argv = add_arg(argv, &argc, "-a");
@@ -652,7 +661,11 @@ do_capture(char *capfile_name)
     }
     /* We're not doing a capture any more, so we don't have a save
        file. */
-    g_free(cfile.save_file);
+    if (cfile.ringbuffer_on) {
+      ringbuf_free();
+    } else {
+      g_free(cfile.save_file);
+    }
     cfile.save_file = NULL;
   }
 }
@@ -1234,6 +1247,7 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
   unsigned int i;
   static const char capstart_msg = SP_CAPSTART;
   char        errmsg[4096+1];
+  gboolean    dump_ok;
 #ifndef _WIN32
   static const char ppamsg[] = "can't find PPA for ";
   char       *libpcap_warn;
@@ -1425,8 +1439,13 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
        " that Ethereal doesn't support (data link type %d).", pcap_encap);
     goto error;
   }
-  ld.pdh = wtap_dump_fdopen(cfile.save_file_fd, WTAP_FILE_PCAP,
+  if (cfile.ringbuffer_on) {
+    ld.pdh = ringbuf_init_wtap_dump_fdopen(WTAP_FILE_PCAP, ld.linktype, 
+      snaplen, &err);
+  } else {
+    ld.pdh = wtap_dump_fdopen(cfile.save_file_fd, WTAP_FILE_PCAP,
       ld.linktype, snaplen, &err);
+  }
 
   if (ld.pdh == NULL) {
     /* We couldn't set up to write to the capture file. */
@@ -1555,7 +1574,7 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
   init_capture_stop_conditions();
   /* create stop conditions */
   cnd_stop_capturesize = 
-    cnd_new(CND_CLASS_CAPTURESIZE,(guint32)cfile.autostop_filesize * 1000); 
+    cnd_new(CND_CLASS_CAPTURESIZE,(long)cfile.autostop_filesize * 1000); 
   cnd_stop_timeout = 
     cnd_new(CND_CLASS_TIMEOUT,(gint32)cfile.autostop_duration);
 
@@ -1630,10 +1649,25 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
       ld.sync_packets += inpkts;
     /* check capture stop conditons */
     if (cnd_eval(cnd_stop_timeout) == TRUE) {
+      /* The specified capture time has elapsed; stop the capture. */
       ld.go = FALSE;
     } else if ((cnd_eval(cnd_stop_capturesize, 
                   (guint32)wtap_get_bytes_dumped(ld.pdh))) == TRUE){
-      ld.go = FALSE;
+      /* Capture file reached its maximum size. */
+      if (cfile.ringbuffer_on) {
+        /* Switch to the next ringbuffer file */
+        if (ringbuf_switch_file(&cfile, &ld.pdh, &ld.err)) {
+          /* File switch succeeded: reset the condition */
+          cnd_reset(cnd_stop_capturesize);
+        } else {
+          /* File switch failed: stop here */
+          ld.go = FALSE;
+          continue;
+        }
+      } else {
+        /* no ringbuffer - just stop */
+        ld.go = FALSE;
+      }
     }
     /* Only update once a second so as not to overload slow displays */
     cur_time = time(NULL);
@@ -1686,9 +1720,18 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
     /* A write failed, so we've already told the user there's a problem;
        if the close fails, there's no point in telling them about that
        as well. */
-    wtap_dump_close(ld.pdh, &err);
-  } else {
-    if (!wtap_dump_close(ld.pdh, &err)) {
+    if (cfile.ringbuffer_on) {
+      ringbuf_wtap_dump_close(&cfile, &err);
+    } else {
+      wtap_dump_close(ld.pdh, &err);
+    }
+   } else {
+    if (cfile.ringbuffer_on) {
+      dump_ok = ringbuf_wtap_dump_close(&cfile, &err);
+    } else {
+      dump_ok = wtap_dump_close(ld.pdh, &err);
+    }
+    if (!dump_ok) {
       get_capture_file_io_error(errmsg, sizeof(errmsg), cfile.save_file, err,
                                TRUE);
       if (capture_child) {
@@ -1746,14 +1789,19 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
   return TRUE;
 
 error:
-  /* We can't use the save file, and we have no wtap_dump stream
-     to close in order to close it, so close the FD directly. */
-  close(cfile.save_file_fd);
-
-  /* We couldn't even start the capture, so get rid of the capture
-     file. */
-  unlink(cfile.save_file); /* silently ignore error */
-  g_free(cfile.save_file);
+  if (cfile.ringbuffer_on) {
+    /* cleanup ringbuffer */
+    ringbuf_error_cleanup();
+  } else {
+    /* We can't use the save file, and we have no wtap_dump stream
+       to close in order to close it, so close the FD directly. */
+    close(cfile.save_file_fd);
+
+    /* We couldn't even start the capture, so get rid of the capture
+       file. */
+    unlink(cfile.save_file); /* silently ignore error */
+    g_free(cfile.save_file);
+  }
   cfile.save_file = NULL;
   if (capture_child) {
     /* This is the child process for a sync mode capture.
index d86bf73245e1588f20c7afb04d6e6e3527979595..718db37d52cd52aa0a556581b57f0bbe7115c4bb 100644 (file)
@@ -1,7 +1,7 @@
 /* capture_stop_conditions.c
  * Implementation for 'stop condition handler'.
  *
- * $Id: capture_stop_conditions.c,v 1.1 2001/12/04 07:32:00 guy Exp $
+ * $Id: capture_stop_conditions.c,v 1.2 2001/12/04 08:25:55 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -143,7 +143,7 @@ const char* CND_CLASS_CAPTURESIZE = "cnd_class_capturesize";
 
 /* structure that contains user supplied data for this condition */ 
 typedef struct _cnd_capturesize_dat{
-  guint32 max_capture_size;
+  long max_capture_size;
 }cnd_capturesize_dat;
 
 /*
@@ -162,7 +162,7 @@ static condition* _cnd_constr_capturesize(condition* cnd, va_list ap){
   if((data = (cnd_capturesize_dat*)malloc(sizeof(cnd_capturesize_dat))) == NULL)
     return NULL;
   /* initialize user data */
-  data->max_capture_size = va_arg(ap, guint32);
+  data->max_capture_size = va_arg(ap, long);
   cnd_set_user_data(cnd, (void*)data);
   return cnd;
 } /* END _cnd_constr_capturesize() */
@@ -192,7 +192,7 @@ static gboolean _cnd_eval_capturesize(condition* cnd, va_list ap){
   cnd_capturesize_dat* data = (cnd_capturesize_dat*)cnd_get_user_data(cnd);
   /* check capturesize here */
   if(data->max_capture_size == 0) return FALSE; /* 0 == infinite */ 
-  if(va_arg(ap, guint32) >= data->max_capture_size){
+  if(va_arg(ap, long) >= data->max_capture_size){
     return TRUE;
   }
   return FALSE;
index d145bafa3e43f39c9f664de2a2b0dee0fb2e77a5..144d7736cdde152ffeb7a93c47d061d806b93703 100644 (file)
@@ -7,6 +7,7 @@ ethereal - Interactively browse network traffic
 
 B<ethereal>
 S<[ B<-a> capture autostop condition ] ...>
+S<[ B<-b> number of ring buffer files ]>
 S<[ B<-B> byte view height ]>
 S<[ B<-c> count ]>
 S<[ B<-f> capture filter expression ]>
index ea34ca58abafb59efab1d70936c3b05ec5e5c495..98bc95b5271c95f874d6ff4b3a2d8c8280245a0f 100644 (file)
@@ -7,6 +7,7 @@ tethereal - Dump and analyze network traffic
 
 B<tethereal>
 S<[ B<-a> capture autostop condition ] ...>
+S<[ B<-b> number of ring buffer files ]>
 S<[ B<-c> count ]>
 S<[ B<-D> ]>
 S<[ B<-f> capture filter expression ]>
diff --git a/file.h b/file.h
index ed04edc0b4480a8161331f7b71c966e29d5af315..70b471eb9633ca8276c9fe44abc3ee3d58d69a22 100644 (file)
--- a/file.h
+++ b/file.h
@@ -1,7 +1,7 @@
 /* file.h
  * Definitions for file structures and routines
  *
- * $Id: file.h,v 1.85 2001/12/04 07:32:00 guy Exp $
+ * $Id: file.h,v 1.86 2001/12/04 08:25:55 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -87,8 +87,10 @@ typedef struct _capture_file {
   epan_dissect_t *edt; /* Protocol dissection fo rcurrently selected packet */
   FILE        *print_fh;  /* File we're printing to */
 #ifdef HAVE_LIBPCAP
-  guint32      autostop_filesize; /* Maximum capture file size */
+  gint32       autostop_filesize; /* Maximum capture file size */
   gint32       autostop_duration; /* Maximum capture duration */
+  gboolean     ringbuffer_on; /* Ringbuffer option */
+  guint32      ringbuffer_num_files; /* Number of ringbuffer files */
 #endif
 } capture_file;
 
index 182b95c974aaee09f485d0e448271890905b7b24..b798b60fe9baa4e99b6fbb8cda6453b45e7cc2e9 100644 (file)
@@ -1,7 +1,7 @@
 /* capture_dlg.c
  * Routines for packet capture windows
  *
- * $Id: capture_dlg.c,v 1.49 2001/12/04 07:32:04 guy Exp $
+ * $Id: capture_dlg.c,v 1.50 2001/12/04 08:25:58 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -56,6 +56,7 @@
 #include "dlg_utils.h"
 #include "pcap-util.h"
 #include "prefs.h"
+#include "ringbuffer.h"
 
 #ifdef _WIN32
 #include "capture-wpcap.h"
@@ -75,6 +76,8 @@
 #define E_CAP_T_RESOLVE_KEY   "cap_t_resolve"
 #define E_CAP_FILESIZE_KEY    "cap_filesize"
 #define E_CAP_DURATION_KEY    "cap_duration"
+#define E_CAP_RING_TB_KEY     "cap_ringbuffer_tb"
+#define E_CAP_RING_SB_KEY     "cap_ringbuffer_sb"
 
 #define E_FS_CALLER_PTR_KEY       "fs_caller_ptr"
 #define E_FILE_SEL_DIALOG_PTR_KEY "file_sel_dialog_ptr"
@@ -91,6 +94,12 @@ cap_prep_fs_cancel_cb(GtkWidget *w, gpointer data);
 static void
 cap_prep_fs_destroy_cb(GtkWidget *win, gpointer data);
 
+static void
+capture_prep_sync_toggle_cb(GtkWidget *sync_cb, gpointer parent_w);
+
+static void
+capture_prep_ringbuffer_toggle_cb(GtkWidget *ringbuffer_tb, gpointer parent_w);
+
 static void
 capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
 
@@ -126,9 +135,10 @@ capture_prep_cb(GtkWidget *w, gpointer d)
                 *caplen_hb, *table,
                 *bbox, *ok_bt, *cancel_bt, *snap_lb,
                 *snap_sb, *promisc_cb, *sync_cb, *auto_scroll_cb,
-                *m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
+                *m_resolv_cb, *n_resolv_cb, *t_resolv_cb,
+                *ringbuffer_hb, *ringbuffer_on_tb, *ringbuffer_nbf_lb, *ringbuffer_nbf_sb;
   GtkAccelGroup *accel_group;
-  GtkAdjustment *snap_adj;
+  GtkAdjustment *snap_adj, *ringbuffer_nbf_adj;
   GList         *if_list, *count_list = NULL, *filesize_list = NULL, *duration_list = NULL;
   gchar         *count_item1 = "0 (Infinite)", count_item2[16],
                 *filesize_item1 = "0 (Infinite)", filesize_item2[16],
@@ -240,7 +250,7 @@ capture_prep_cb(GtkWidget *w, gpointer d)
   
   filesize_list = g_list_append(filesize_list, filesize_item1);
   if (cfile.autostop_filesize) {
-    snprintf(filesize_item2, 15, "%u", cfile.autostop_filesize);
+    snprintf(filesize_item2, 15, "%d", cfile.autostop_filesize);
     filesize_list = g_list_append(filesize_list, filesize_item2);
   }
 
@@ -323,10 +333,41 @@ capture_prep_cb(GtkWidget *w, gpointer d)
   gtk_container_add(GTK_CONTAINER(main_vb), promisc_cb);
   gtk_widget_show(promisc_cb);
 
+  /* Misc row: Ringbuffer toggle button and Ringbuffer spinbutton */
+  ringbuffer_hb = gtk_hbox_new(FALSE, 3);
+  gtk_container_add(GTK_CONTAINER(main_vb), ringbuffer_hb);
+  gtk_widget_show(ringbuffer_hb);
+
+  ringbuffer_on_tb = dlg_check_button_new_with_label_with_mnemonic(
+    "Use _ringbuffer", accel_group);
+  if (prefs.capture_real_time == TRUE)
+    cfile.ringbuffer_on = FALSE;
+  gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(ringbuffer_on_tb),cfile.ringbuffer_on);
+  gtk_signal_connect(GTK_OBJECT(ringbuffer_on_tb), "toggled",
+    GTK_SIGNAL_FUNC(capture_prep_ringbuffer_toggle_cb), GTK_OBJECT(cap_open_w));
+  gtk_box_pack_start(GTK_BOX(ringbuffer_hb), ringbuffer_on_tb, FALSE, FALSE, 0);
+  gtk_widget_show(ringbuffer_on_tb);
+  
+  ringbuffer_nbf_lb = gtk_label_new("Number of files");
+  gtk_misc_set_alignment(GTK_MISC(ringbuffer_nbf_lb), 1, 0.5);
+  gtk_box_pack_start(GTK_BOX(ringbuffer_hb), ringbuffer_nbf_lb, FALSE, FALSE, 6);
+  gtk_widget_show(ringbuffer_nbf_lb);
+
+  ringbuffer_nbf_adj = (GtkAdjustment *) gtk_adjustment_new((float) cfile.ringbuffer_num_files,
+    RINGBUFFER_MIN_NUM_FILES, RINGBUFFER_MAX_NUM_FILES, 1.0, 10.0, 0.0);
+  ringbuffer_nbf_sb = gtk_spin_button_new (ringbuffer_nbf_adj, 0, 0);
+  gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (ringbuffer_nbf_sb), TRUE);
+  gtk_widget_set_usize (ringbuffer_nbf_sb, 40, 0);
+  gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_sb), cfile.ringbuffer_on);
+  gtk_box_pack_start (GTK_BOX(ringbuffer_hb), ringbuffer_nbf_sb, TRUE, TRUE, 0); 
+  gtk_widget_show(ringbuffer_nbf_sb);
+  
   /* Misc row: Capture file checkboxes */
   sync_cb = dlg_check_button_new_with_label_with_mnemonic(
                "_Update list of packets in real time", accel_group);
   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(sync_cb), prefs.capture_real_time);
+  gtk_signal_connect(GTK_OBJECT(sync_cb), "toggled",
+    GTK_SIGNAL_FUNC(capture_prep_sync_toggle_cb), GTK_OBJECT(cap_open_w));
   gtk_container_add(GTK_CONTAINER(main_vb), sync_cb);
   gtk_widget_show(sync_cb);
 
@@ -393,6 +434,8 @@ capture_prep_cb(GtkWidget *w, gpointer d)
   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_T_RESOLVE_KEY,  t_resolv_cb);
   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_FILESIZE_KEY,  filesize_cb);
   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_DURATION_KEY,  duration_cb);
+  gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_RING_TB_KEY,  ringbuffer_on_tb);
+  gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_RING_SB_KEY,  ringbuffer_nbf_sb);
 
   /* Catch the "activate" signal on the frame number and file name text
      entries, so that if the user types Return there, we act as if the
@@ -544,7 +587,7 @@ static void
 capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w) {
   GtkWidget *if_cb, *filter_te, *file_te, *count_cb, *snap_sb, *promisc_cb,
             *sync_cb, *auto_scroll_cb, *m_resolv_cb, *n_resolv_cb, *t_resolv_cb,
-            *filesize_cb, *duration_cb;
+            *filesize_cb, *duration_cb, *ringbuffer_on_tb, *ringbuffer_nbf_sb;
   gchar *if_text;
   gchar *if_name;
   gchar *filter_text;
@@ -564,6 +607,8 @@ capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w) {
   t_resolv_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_T_RESOLVE_KEY);
   filesize_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_FILESIZE_KEY);
   duration_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_DURATION_KEY);
+  ringbuffer_on_tb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_RING_TB_KEY);
+  ringbuffer_nbf_sb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_RING_SB_KEY);
 
   if_text =
     g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry)));
@@ -633,6 +678,25 @@ capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w) {
   prefs.name_resolve |= (GTK_TOGGLE_BUTTON (n_resolv_cb)->active ? PREFS_RESOLV_NETWORK : PREFS_RESOLV_NONE);
   prefs.name_resolve |= (GTK_TOGGLE_BUTTON (t_resolv_cb)->active ? PREFS_RESOLV_TRANSPORT : PREFS_RESOLV_NONE);
 
+  cfile.ringbuffer_on = GTK_TOGGLE_BUTTON (ringbuffer_on_tb)->active && !(prefs.capture_real_time);
+  if (cfile.ringbuffer_on == TRUE) {
+    if (save_file == NULL) {
+      simple_dialog(ESD_TYPE_CRIT, NULL,
+        "You must specify a save file if you want to use the ringbuffer.");
+      return;
+    } else if (cfile.autostop_filesize == 0) {
+      simple_dialog(ESD_TYPE_CRIT, NULL,
+        "You must specify a maximum save file size other \nthan 0 (infinite) if you want to use the ringbuffer.");
+      return;
+    }
+  }
+
+  cfile.ringbuffer_num_files = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ringbuffer_nbf_sb));
+  if (cfile.ringbuffer_num_files < RINGBUFFER_MIN_NUM_FILES)
+    cfile.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
+  else if (cfile.ringbuffer_num_files > RINGBUFFER_MAX_NUM_FILES)
+    cfile.ringbuffer_num_files = RINGBUFFER_MAX_NUM_FILES;
+
   gtk_widget_destroy(GTK_WIDGET(parent_w));
 
   do_capture(save_file);
@@ -673,4 +737,36 @@ capture_prep_destroy_cb(GtkWidget *win, gpointer user_data)
   cap_open_w = NULL;
 }
 
+static void
+capture_prep_ringbuffer_toggle_cb(GtkWidget *ringbuffer_tb, gpointer parent_w)
+{
+  GtkWidget *ringbuffer_nbf_sb, *sync_cb;
+
+  ringbuffer_nbf_sb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_RING_SB_KEY);
+  sync_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_SYNC_KEY);
+
+  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ringbuffer_tb)) == TRUE) {
+    gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_sb), TRUE);
+    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sync_cb)) == TRUE) {
+      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sync_cb), FALSE);
+    }
+  } else {
+    gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_sb), FALSE);
+  }
+}
+
+static void
+capture_prep_sync_toggle_cb(GtkWidget *sync_cb, gpointer parent_w)
+{
+  GtkWidget *ringbuffer_on_tb;
+
+  ringbuffer_on_tb  = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_RING_TB_KEY);
+
+  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sync_cb)) == TRUE) {
+    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ringbuffer_on_tb)) == TRUE) {
+      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ringbuffer_on_tb), FALSE);
+    }
+  }
+}
+
 #endif /* HAVE_LIBPCAP */
index d6872248d8d2fb61e460472b64abdf7cde549967..13ba0b6854200d15d097a6418f1f871479284b26 100644 (file)
@@ -1,6 +1,6 @@
 /* main.c
  *
- * $Id: main.c,v 1.214 2001/12/04 07:32:04 guy Exp $
+ * $Id: main.c,v 1.215 2001/12/04 08:25:59 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
 #include "strutil.h"
 #include "register.h"
 #include "prefs.h"
+#include "ringbuffer.h"
 #include "image/clist_ascend.xpm"
 #include "image/clist_descend.xpm"
 
@@ -795,8 +796,9 @@ print_usage(void) {
 #ifdef HAVE_LIBPCAP
   fprintf(stderr, "%s [ -vh ] [ -klpQS ] [ -a <capture autostop condition> ] ...\n",
          PACKAGE);
-  fprintf(stderr, "\t[ -B <byte view height> ] [ -c <count> ] [ -f <capture filter> ]\n");
-  fprintf(stderr, "\t[ -i <interface> ] [ -m <medium font> ] [ -n ] [ -N <resolving> ]\n");
+  fprintf(stderr, "\t[ -b <number of ringbuffer files> ] [ -B <byte view height> ]\n");
+  fprintf(stderr, "\t[ -c <count> ] [ -f <capture filter> ] [ -i <interface> ]\n");
+  fprintf(stderr, "\t[ -m <medium font> ] [ -n ] [ -N <resolving> ]\n");
   fprintf(stderr, "\t[ -o <preference setting> ] ... [ -P <packet list height> ]\n");
   fprintf(stderr, "\t[ -r <infile> ] [ -R <read filter> ] [ -s <snaplen> ] \n");
   fprintf(stderr, "\t[ -t <time stamp format> ] [ -T <tree view height> ]\n");
@@ -1045,6 +1047,8 @@ main(int argc, char *argv[])
 #ifdef HAVE_LIBPCAP
   cfile.autostop_duration = 0;
   cfile.autostop_filesize = 0;
+  cfile.ringbuffer_on = FALSE;
+  cfile.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
 #endif
   col_init(&cfile.cinfo, prefs->num_cols);
 
@@ -1111,7 +1115,7 @@ main(int argc, char *argv[])
 #endif
 
   /* Now get our args */
-  while ((opt = getopt(argc, argv, "a:B:c:f:hi:klm:nN:o:pP:Qr:R:Ss:t:T:w:W:vZ:")) !=  EOF) {
+  while ((opt = getopt(argc, argv, "a:b:B:c:f:hi:klm:nN:o:pP:Qr:R:Ss:t:T:w:W:vZ:")) !=  EOF) {
     switch (opt) {
       case 'a':        /* autostop criteria */
 #ifdef HAVE_LIBPCAP
@@ -1122,6 +1126,21 @@ main(int argc, char *argv[])
 #else
         capture_option_specified = TRUE;
         arg_error = TRUE;
+#endif
+        break;
+      case 'b':        /* Ringbuffer option */
+#ifdef HAVE_LIBPCAP
+        cfile.ringbuffer_on = TRUE;
+        /* get optional ringbuffer number of files parameter */
+        if (optarg[0] != '-') {
+          cfile.ringbuffer_num_files = get_positive_int(optarg, "ringbuffer number of files");
+        } else {
+          cfile.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
+          optind--;
+        }
+#else
+        capture_option_specified = TRUE;
+        arg_error = TRUE;
 #endif
         break;
       case 'B':        /* Byte view pane height */
@@ -1420,6 +1439,27 @@ main(int argc, char *argv[])
   else if (cfile.snap < MIN_PACKET_SIZE)
     cfile.snap = MIN_PACKET_SIZE;
   
+  if (cfile.ringbuffer_on == TRUE) {
+    /* Ringbuffer works just under certain conditions: 
+       a) prefs->capture_real_time and cfile.ringbuffer_on are mutially 
+          exclusive. prefs->capture_real_time takes precedence. 
+       b) Ringbuffer does not work with temporary files
+       c) It makes no sense to enable the ringbuffer if the maximum
+           file size is set to infinite */
+    if (prefs->capture_real_time == TRUE ||
+        cfile.save_file == NULL ||
+        cfile.autostop_filesize == 0) {
+      /* turn ringbuffer off */
+      cfile.ringbuffer_on = FALSE;
+    }
+  }
+
+  /* Check the value range of the ringbuffer_num_files parameter */
+  if (cfile.ringbuffer_num_files < RINGBUFFER_MIN_NUM_FILES)
+    cfile.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
+  else if (cfile.ringbuffer_num_files > RINGBUFFER_MAX_NUM_FILES)
+    cfile.ringbuffer_num_files = RINGBUFFER_MAX_NUM_FILES;
+  
   rc_file = get_persconffile_path(RC_FILE, FALSE);
   gtk_rc_parse(rc_file);
 
index 05409cc504f9117822e119c12e562df0531bf1d3..1a505c2394b45431f2465c9ebb5abc7412f895e7 100644 (file)
@@ -1,6 +1,6 @@
 /* tethereal.c
  *
- * $Id: tethereal.c,v 1.100 2001/12/04 07:32:00 guy Exp $
+ * $Id: tethereal.c,v 1.101 2001/12/04 08:25:55 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
 #include "register.h"
 #include "conditions.h"
 #include "capture_stop_conditions.h"
+#include "ringbuffer.h"
 
 #ifdef WIN32
 #include "capture-wpcap.h"
@@ -345,6 +346,8 @@ main(int argc, char *argv[])
 #ifdef HAVE_LIBPCAP
   cfile.autostop_duration = 0;
   cfile.autostop_filesize = 0;
+  cfile.ringbuffer_on = FALSE;
+  cfile.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
 #endif
   col_init(&cfile.cinfo, prefs->num_cols);
 
@@ -402,7 +405,7 @@ main(int argc, char *argv[])
 #endif
     
   /* Now get our args */
-  while ((opt = getopt(argc, argv, "a:c:Df:F:hi:lnN:o:pr:R:s:t:vw:Vx")) != EOF) {
+  while ((opt = getopt(argc, argv, "a:b:c:Df:F:hi:lnN:o:pr:R:s:t:vw:Vx")) != EOF) {
     switch (opt) {
       case 'a':        /* autostop criteria */
 #ifdef HAVE_LIBPCAP
@@ -413,6 +416,21 @@ main(int argc, char *argv[])
 #else
         capture_option_specified = TRUE;
         arg_error = TRUE;
+#endif
+        break;
+      case 'b':        /* Ringbuffer option */
+#ifdef HAVE_LIBPCAP
+        cfile.ringbuffer_on = TRUE;
+        /* get optional ringbuffer number of files parameter */
+        if (optarg[0] != '-') {
+          cfile.ringbuffer_num_files = get_positive_int(optarg, "ring buffer number of files");
+        } else {
+          cfile.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
+          optind--;
+        }
+#else
+        capture_option_specified = TRUE;
+        arg_error = TRUE;
 #endif
         break;
       case 'c':        /* Capture xxx packets */
@@ -639,6 +657,27 @@ main(int argc, char *argv[])
   else if (cfile.snap < MIN_PACKET_SIZE)
     cfile.snap = MIN_PACKET_SIZE;
   
+  if (cfile.ringbuffer_on) {
+    /* Ringbuffer works just under certain conditions:*/ 
+    if (cfile.save_file == NULL) {
+       /* Ringbuffer does not work with temporary files */
+      fprintf(stderr, "tethereal: Turning ring buffer off (no save file specified).\n");
+      cfile.ringbuffer_on = FALSE;
+    }
+    if (cfile.autostop_filesize == 0) {
+       /* It makes no sense to enable the ring buffer if the maximum
+          file size is set to infinite */
+      fprintf(stderr, "tethereal: Turning ring buffer off (file size = 0).\n");
+      cfile.ringbuffer_on = FALSE;
+    }
+  }
+
+  /* Check the value range of the ringbuffer_num_files parameter */
+  if (cfile.ringbuffer_num_files < RINGBUFFER_MIN_NUM_FILES)
+    cfile.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
+  else if (cfile.ringbuffer_num_files > RINGBUFFER_MAX_NUM_FILES)
+    cfile.ringbuffer_num_files = RINGBUFFER_MAX_NUM_FILES;
+  
   if (rfilter != NULL) {
     if (!dfilter_compile(rfilter, &rfcode)) {
       fprintf(stderr, "tethereal: %s\n", dfilter_error_msg);
@@ -693,6 +732,10 @@ main(int argc, char *argv[])
         free_interface_list(if_list);
     }
     capture(packet_count, out_file_type);
+
+    if (cfile.ringbuffer_on) {
+      ringbuf_free();
+    }
 #else
     /* No - complain. */
     fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
@@ -725,6 +768,7 @@ capture(int packet_count, int out_file_type)
   char       *libpcap_warn;
 #endif
   struct pcap_stat stats;
+  gboolean    dump_ok;
 
   /* Initialize the table of conversations. */
   epan_conversation_init();
@@ -825,8 +869,19 @@ capture(int packet_count, int out_file_type)
                " that Tethereal doesn't support.");
       goto error;
     }
-    ld.pdh = wtap_dump_open(cfile.save_file, out_file_type,
-               ld.linktype, pcap_snapshot(ld.pch), &err);
+    if (cfile.ringbuffer_on) {
+      cfile.save_file_fd = ringbuf_init(cfile.save_file,
+        cfile.ringbuffer_num_files);
+      if (cfile.save_file_fd != -1) {
+        ld.pdh = ringbuf_init_wtap_dump_fdopen(out_file_type, ld.linktype,
+          pcap_snapshot(ld.pch), &err);
+      } else {
+        ld.pdh = NULL;
+      }
+    } else {
+      ld.pdh = wtap_dump_open(cfile.save_file, out_file_type,
+                ld.linktype, pcap_snapshot(ld.pch), &err);
+    }
 
     if (ld.pdh == NULL) {
       snprintf(errmsg, sizeof errmsg, file_open_error_message(errno, TRUE),
@@ -859,7 +914,7 @@ capture(int packet_count, int out_file_type)
   init_capture_stop_conditions();
   /* create stop conditions */ 
   cnd_stop_capturesize = cnd_new((char*)CND_CLASS_CAPTURESIZE,
-                                 (guint32)cfile.autostop_filesize * 1000);
+                                 (long)cfile.autostop_filesize * 1000);
   cnd_stop_timeout = cnd_new((char*)CND_CLASS_TIMEOUT,
                              (gint32)cfile.autostop_duration);
 
@@ -877,7 +932,20 @@ capture(int packet_count, int out_file_type)
     } else if ((cnd_eval(cnd_stop_capturesize, 
                   (guint32)wtap_get_bytes_dumped(ld.pdh))) == TRUE){
       /* A capture stop condition has become true. */
-      ld.go = FALSE;
+      if (cfile.ringbuffer_on) {
+        /* Switch to the next ringbuffer file */
+        if (ringbuf_switch_file(&cfile, &ld.pdh, &err) == TRUE) {
+          /* File switch failed: reset the condition */
+          cnd_reset(cnd_stop_capturesize);
+        } else {
+          /* File switch failed: stop here */
+          ld.go = FALSE;
+          continue;
+        }
+      } else {
+        /* No ringbuffer - just stop. */
+        ld.go = FALSE;
+      }
     }
   }
   
@@ -912,14 +980,22 @@ 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))
+    /* We're saving to a file or files; close all files. */
+    if (cfile.ringbuffer_on) {
+      dump_ok = ringbuf_wtap_dump_close(&cfile, &err);
+    } else {
+      dump_ok = wtap_dump_close(ld.pdh, &err);
+    }
+    if (!dump_ok)
       show_capture_file_io_error(cfile.save_file, err, TRUE);
   }
 
   return TRUE;
 
 error:
+  if (cfile.ringbuffer_on) {
+    ringbuf_error_cleanup();
+  }
   g_free(cfile.save_file);
   cfile.save_file = NULL;
   fprintf(stderr, "tethereal: %s\n", errmsg);
index edc3fd076c813569a656141e6db2fed74cff30b0..5376d293c1a5605d46055bac7c5f46f3ad255fa7 100644 (file)
@@ -1,6 +1,6 @@
 /* file.c
  *
- * $Id: file.c,v 1.75 2001/12/04 07:32:05 guy Exp $
+ * $Id: file.c,v 1.76 2001/12/04 08:26:00 guy Exp $
  *
  * Wiretap Library
  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
@@ -606,7 +606,13 @@ gboolean wtap_dump_close(wtap_dumper *wdh, int *err)
        return ret;
 }
 
-int wtap_get_bytes_dumped(wtap_dumper *wdh)
+long wtap_get_bytes_dumped(wtap_dumper *wdh)
 {
        return wdh->bytes_dumped;
 }
+
+void wtap_set_bytes_dumped(wtap_dumper *wdh, long bytes_dumped)
+{
+       wdh->bytes_dumped = bytes_dumped;
+}
+
index 972b1d1988fd9b6669116765bb1bb52abee49608..2a7473600c3a61a682562de8f9dda12d46ffd128 100644 (file)
@@ -1,6 +1,6 @@
 /* wtap-int.h
  *
- * $Id: wtap-int.h,v 1.16 2001/12/04 07:32:05 guy Exp $
+ * $Id: wtap-int.h,v 1.17 2001/12/04 08:26:00 guy Exp $
  *
  * Wiretap Library
  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
@@ -186,7 +186,7 @@ struct wtap_dumper {
        int                     file_type;
        int                     snaplen;
        int                     encap;
-       int                     bytes_dumped;
+       long                    bytes_dumped;
 
        union {
                void                    *opaque;
index 1df14018f76a69b84ef7cf504f14eb2018a24a01..c7314ee7b19ed7323898679d4b5f88c0df7106fd 100644 (file)
@@ -17,6 +17,7 @@ wtap_file_type
 wtap_file_type_short_string\r
 wtap_file_type_string\r
 wtap_get_bytes_dumped\r
+wtap_set_bytes_dumped\r
 wtap_loop\r
 wtap_open_offline\r
 wtap_pcap_encap_to_wtap_encap\r
index 8835636079d60a9f556c226b824bcfe533a712f6..ff2cc6039902f013517919cfc6083638d3b3ca6c 100644 (file)
@@ -1,6 +1,6 @@
 /* wtap.h
  *
- * $Id: wtap.h,v 1.97 2001/12/04 07:32:05 guy Exp $
+ * $Id: wtap.h,v 1.98 2001/12/04 08:26:00 guy Exp $
  *
  * Wiretap Library
  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
@@ -339,7 +339,8 @@ gboolean wtap_dump(wtap_dumper *, const struct wtap_pkthdr *,
        const union wtap_pseudo_header *pseudo_header, const u_char *, int *err);
 FILE* wtap_dump_file(wtap_dumper *);
 gboolean wtap_dump_close(wtap_dumper *, int *);
-int wtap_get_bytes_dumped(wtap_dumper *);
+long wtap_get_bytes_dumped(wtap_dumper *);
+void wtap_set_bytes_dumped(wtap_dumper *wdh, long bytes_dumped);
 
 /* XXX - needed until "wiretap" can do live packet captures */
 int wtap_pcap_encap_to_wtap_encap(int encap);