aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am4
-rw-r--r--Makefile.nmake3
-rw-r--r--capture.c86
-rw-r--r--capture_stop_conditions.c8
-rw-r--r--doc/ethereal.pod.template1
-rw-r--r--doc/tethereal.pod.template1
-rw-r--r--file.h6
-rw-r--r--gtk/capture_dlg.c106
-rw-r--r--gtk/main.c48
-rw-r--r--tethereal.c92
-rw-r--r--wiretap/file.c10
-rw-r--r--wiretap/wtap-int.h4
-rw-r--r--wiretap/wtap.def1
-rw-r--r--wiretap/wtap.h5
14 files changed, 325 insertions, 50 deletions
diff --git a/Makefile.am b/Makefile.am
index 9a87c8aaf5..fdf1cd09da 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -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 \
diff --git a/Makefile.nmake b/Makefile.nmake
index fcfcdeb300..d3855abf10 100644
--- a/Makefile.nmake
+++ b/Makefile.nmake
@@ -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 \
diff --git a/capture.c b/capture.c
index 953982c82d..413b1750ed 100644
--- 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>
@@ -147,6 +147,7 @@
#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.
diff --git a/capture_stop_conditions.c b/capture_stop_conditions.c
index d86bf73245..718db37d52 100644
--- a/capture_stop_conditions.c
+++ b/capture_stop_conditions.c
@@ -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;
diff --git a/doc/ethereal.pod.template b/doc/ethereal.pod.template
index d145bafa3e..144d7736cd 100644
--- a/doc/ethereal.pod.template
+++ b/doc/ethereal.pod.template
@@ -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 ]>
diff --git a/doc/tethereal.pod.template b/doc/tethereal.pod.template
index ea34ca58ab..98bc95b527 100644
--- a/doc/tethereal.pod.template
+++ b/doc/tethereal.pod.template
@@ -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 ed04edc0b4..70b471eb96 100644
--- 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;
diff --git a/gtk/capture_dlg.c b/gtk/capture_dlg.c
index 182b95c974..b798b60fe9 100644
--- a/gtk/capture_dlg.c
+++ b/gtk/capture_dlg.c
@@ -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"
@@ -92,6 +95,12 @@ 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);
static void
@@ -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 */
diff --git a/gtk/main.c b/gtk/main.c
index d6872248d8..13ba0b6854 100644
--- a/gtk/main.c
+++ b/gtk/main.c
@@ -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>
@@ -145,6 +145,7 @@
#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
@@ -1124,6 +1128,21 @@ main(int argc, char *argv[])
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 */
bv_size = get_positive_int(optarg, "byte view pane height");
break;
@@ -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);
diff --git a/tethereal.c b/tethereal.c
index 05409cc504..1a505c2394 100644
--- a/tethereal.c
+++ b/tethereal.c
@@ -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>
@@ -106,6 +106,7 @@
#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
@@ -415,6 +418,21 @@ main(int argc, char *argv[])
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 */
#ifdef HAVE_LIBPCAP
packet_count = get_positive_int(optarg, "packet count");
@@ -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);
diff --git a/wiretap/file.c b/wiretap/file.c
index edc3fd076c..5376d293c1 100644
--- a/wiretap/file.c
+++ b/wiretap/file.c
@@ -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;
+}
+
diff --git a/wiretap/wtap-int.h b/wiretap/wtap-int.h
index 972b1d1988..2a7473600c 100644
--- a/wiretap/wtap-int.h
+++ b/wiretap/wtap-int.h
@@ -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;
diff --git a/wiretap/wtap.def b/wiretap/wtap.def
index 1df14018f7..c7314ee7b1 100644
--- a/wiretap/wtap.def
+++ b/wiretap/wtap.def
@@ -17,6 +17,7 @@ wtap_file_type
wtap_file_type_short_string
wtap_file_type_string
wtap_get_bytes_dumped
+wtap_set_bytes_dumped
wtap_loop
wtap_open_offline
wtap_pcap_encap_to_wtap_encap
diff --git a/wiretap/wtap.h b/wiretap/wtap.h
index 8835636079..ff2cc60399 100644
--- a/wiretap/wtap.h
+++ b/wiretap/wtap.h
@@ -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);