diff options
author | Guy Harris <guy@alum.mit.edu> | 2001-12-04 08:26:00 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2001-12-04 08:26:00 +0000 |
commit | 8032fa8a1bafcbf76d3cadcedb03480fbfd51ecf (patch) | |
tree | a634ca1961bfec804908e381e96ad6d793a7f2b9 | |
parent | a1660d6d3afbaeccd77d8e34c695bf65a4f4f09e (diff) |
Make the bytes-written information from Wiretap a long, as we allow
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.
svn path=/trunk/; revision=4323
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | Makefile.nmake | 3 | ||||
-rw-r--r-- | capture.c | 86 | ||||
-rw-r--r-- | capture_stop_conditions.c | 8 | ||||
-rw-r--r-- | doc/ethereal.pod.template | 1 | ||||
-rw-r--r-- | doc/tethereal.pod.template | 1 | ||||
-rw-r--r-- | file.h | 6 | ||||
-rw-r--r-- | gtk/capture_dlg.c | 106 | ||||
-rw-r--r-- | gtk/main.c | 48 | ||||
-rw-r--r-- | tethereal.c | 92 | ||||
-rw-r--r-- | wiretap/file.c | 10 | ||||
-rw-r--r-- | wiretap/wtap-int.h | 4 | ||||
-rw-r--r-- | wiretap/wtap.def | 1 | ||||
-rw-r--r-- | wiretap/wtap.h | 5 |
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 \ @@ -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 ]> @@ -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); |