# 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>
reassemble.c \
reassemble.h \
register.h \
+ ringbuffer.c \
+ ringbuffer.h \
smb.h \
util.c \
util.h \
## 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>
ptvcursor.obj \
reassemble.obj \
register.obj \
+ ringbuffer.obj \
util.obj \
xdlc.obj \
xmlstub.obj \
/* 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"
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 */
"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);
}
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");
}
/* 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;
}
}
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;
" 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. */
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);
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);
/* 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) {
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.
/* 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>
/* 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;
/*
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() */
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;
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 ]>
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 ]>
/* 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>
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;
/* 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>
#include "dlg_utils.h"
#include "pcap-util.h"
#include "prefs.h"
+#include "ringbuffer.h"
#ifdef _WIN32
#include "capture-wpcap.h"
#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"
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);
*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],
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);
}
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);
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
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;
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)));
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);
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 */
/* 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"
#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");
#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);
#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
#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 */
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);
/* 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"
#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);
#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
#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 */
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);
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");
char *libpcap_warn;
#endif
struct pcap_stat stats;
+ gboolean dump_ok;
/* Initialize the table of conversations. */
epan_conversation_init();
" 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),
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);
} 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;
+ }
}
}
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);
/* 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>
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;
+}
+
/* 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>
int file_type;
int snaplen;
int encap;
- int bytes_dumped;
+ long bytes_dumped;
union {
void *opaque;
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
/* 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>
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);