aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--capture.c22
-rw-r--r--capture.h4
-rw-r--r--doc/ethereal.pod.template15
-rw-r--r--doc/tethereal.pod.template6
-rw-r--r--gtk/capture_dlg.c61
-rw-r--r--gtk/main.c62
-rw-r--r--tethereal.c84
7 files changed, 236 insertions, 18 deletions
diff --git a/capture.c b/capture.c
index fffc3c2949..74ee00f8e0 100644
--- a/capture.c
+++ b/capture.c
@@ -1,7 +1,7 @@
/* capture.c
* Routines for packet capture windows
*
- * $Id: capture.c,v 1.206 2003/04/24 09:07:36 guy Exp $
+ * $Id: capture.c,v 1.207 2003/05/15 13:33:53 deniel Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@@ -1368,6 +1368,7 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
int err, inpkts;
condition *cnd_stop_capturesize = NULL;
condition *cnd_stop_timeout = NULL;
+ condition *cnd_ring_timeout = NULL;
unsigned int i;
static const char capstart_msg = SP_CAPSTART;
char errmsg[4096+1];
@@ -1757,6 +1758,10 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
cnd_stop_timeout =
cnd_new(CND_CLASS_TIMEOUT,(gint32)capture_opts.autostop_duration);
+ if (capture_opts.ringbuffer_on && capture_opts.has_ring_duration)
+ cnd_ring_timeout =
+ cnd_new(CND_CLASS_TIMEOUT, capture_opts.ringbuffer_duration);
+
while (ld.go) {
while (gtk_events_pending()) gtk_main_iteration();
@@ -1861,6 +1866,9 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
if (ringbuf_switch_file(&cfile, &ld.pdh, &ld.err)) {
/* File switch succeeded: reset the condition */
cnd_reset(cnd_stop_capturesize);
+ if (cnd_ring_timeout) {
+ cnd_reset(cnd_ring_timeout);
+ }
} else {
/* File switch failed: stop here */
ld.go = FALSE;
@@ -1918,8 +1926,18 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
if (cnd_stop_timeout != NULL && cnd_eval(cnd_stop_timeout)) {
/* The specified capture time has elapsed; stop the capture. */
ld.go = FALSE;
+ } else if (cnd_ring_timeout != NULL && cnd_eval(cnd_ring_timeout)) {
+ /* time elasped for this ring file, swith to the next */
+ if (ringbuf_switch_file(&cfile, &ld.pdh, &ld.err)) {
+ /* File switch succeeded: reset the condition */
+ cnd_reset(cnd_ring_timeout);
+ } else {
+ /* File switch failed: stop here */
+ ld.go = FALSE;
+ }
}
}
+
} /* while (ld.go) */
/* delete stop conditions */
@@ -1927,6 +1945,8 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
cnd_delete(cnd_stop_capturesize);
if (cnd_stop_timeout != NULL)
cnd_delete(cnd_stop_timeout);
+ if (cnd_ring_timeout != NULL)
+ cnd_delete(cnd_ring_timeout);
if (ld.pcap_err) {
snprintf(errmsg, sizeof(errmsg), "Error while capturing packets: %s",
diff --git a/capture.h b/capture.h
index 961068595f..33287a30a8 100644
--- a/capture.h
+++ b/capture.h
@@ -1,7 +1,7 @@
/* capture.h
* Definitions for packet capture windows
*
- * $Id: capture.h,v 1.34 2003/01/09 19:37:14 guy Exp $
+ * $Id: capture.h,v 1.35 2003/05/15 13:33:53 deniel Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -49,6 +49,8 @@ typedef struct {
gint32 autostop_filesize; /* Maximum capture file size */
gboolean ringbuffer_on; /* TRUE if ring buffer in use */
guint32 ringbuffer_num_files; /* Number of ring buffer files */
+ gboolean has_ring_duration; /* TRUE if ring duration specified */
+ gint32 ringbuffer_duration; /* Switch file after n seconds */
} capture_options;
extern capture_options capture_opts;
diff --git a/doc/ethereal.pod.template b/doc/ethereal.pod.template
index 8b7381abc2..e916f25dcc 100644
--- a/doc/ethereal.pod.template
+++ b/doc/ethereal.pod.template
@@ -7,7 +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> number of ring buffer files [:duration] ]>
S<[ B<-B> byte view height ]>
S<[ B<-c> count ]>
S<[ B<-f> capture filter expression ]>
@@ -128,6 +128,10 @@ discard the data in the first file and start writing to that file. When
that file fills up, B<Ethereal> will discard the data in the next file
and start writing to it, and so on.
+If the optional duration is specified, B<Ethereal> will switch also
+to the next file when the specified number of seconds has elapsed even
+if the current file is not completely fills up.
+
When the capture completes, the files will be renamed to have names
based on the number of the file and on the date and time at which
packets most recently started being written to the file.
@@ -1084,7 +1088,12 @@ can save those packets to a file with the I<File:Save As> menu item.
The I<Use ring buffer> check box lets you specify that the capture
should be done in "ring buffer" mode; the I<Number of files> field
-lets you specify the number of files in the ring buffer.
+lets you specify the number of files in the ring buffer.
+
+The I<Rotate capture file every ... second(s)> check box and field lets
+you to specify that the swith to a next ring buffer file should be done
+if the specified duration has elapsed even if the specified capture size
+is not reached.
The I<Update list of packets in real time> check box lets you specify
whether the display should be updated as packets are captured and, if
@@ -1108,7 +1117,7 @@ running, or the available disk space, may still limit the maximum size
of a capture file).
If "ring buffer" mode is specified, that field becomes the I<Rotate
-capture file very ... kilobyte(s)> field, and specifies the number
+capture file every ... kilobyte(s)> field, and specifies the number
of kilobytes at which to start writing to a new ring buffer file; the
check box is forced to be checked, as "ring buffer" mode requires a file
size to be specified.
diff --git a/doc/tethereal.pod.template b/doc/tethereal.pod.template
index 71736beeb1..ce7fde353f 100644
--- a/doc/tethereal.pod.template
+++ b/doc/tethereal.pod.template
@@ -7,7 +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<-b> number of ring buffer files [:duration] ]>
S<[ B<-c> count ]>
S<[ B<-D> ]>
S<[ B<-f> capture filter expression ]>
@@ -155,6 +155,10 @@ point it'll discard the data in the first file and start writing to that
file. When that file fills up, B<Tethereal> will discard the data in
the next file and start writing to it, and so on.
+If the optional duration is specified, B<Tethereal> will switch also
+to the next file when the specified number of seconds has elapsed even
+if the current file is not completely fills up.
+
When the capture completes, the files will be renamed to have names
based on the number of the file and on the date and time at which
packets most recently started being written to the file.
diff --git a/gtk/capture_dlg.c b/gtk/capture_dlg.c
index 893c1b3b35..2bf3b95147 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.77 2003/01/15 05:20:18 guy Exp $
+ * $Id: capture_dlg.c,v 1.78 2003/05/15 13:38:05 deniel Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@@ -62,6 +62,8 @@
#define E_CAP_RING_ON_TB_KEY "cap_ringbuffer_on_tb"
#define E_CAP_RING_NBF_LB_KEY "cap_ringbuffer_nbf_lb"
#define E_CAP_RING_NBF_SB_KEY "cap_ringbuffer_nbf_sb"
+#define E_CAP_RING_DURATION_CB_KEY "cap_ringbuffer_duration_cb"
+#define E_CAP_RING_DURATION_SB_KEY "cap_ringbuffer_duration_sb"
#define E_CAP_SYNC_KEY "cap_sync"
#define E_CAP_AUTO_SCROLL_KEY "cap_auto_scroll"
#define E_CAP_COUNT_CB_KEY "cap_count_cb"
@@ -134,6 +136,8 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_)
*count_hb, *count_cb, *count_sb, *count_lb,
*filesize_hb, *filesize_cb, *filesize_sb, *filesize_lb,
*duration_hb, *duration_cb, *duration_sb, *duration_lb,
+ *ring_duration_hb, *ring_duration_cb, *ring_duration_sb,
+ *ring_duration_lb,
*resolv_fr, *resolv_vb,
*m_resolv_cb, *n_resolv_cb, *t_resolv_cb,
*bbox, *ok_bt, *cancel_bt;
@@ -141,7 +145,7 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_)
GtkAccelGroup *accel_group;
#endif
GtkAdjustment *snap_adj, *ringbuffer_nbf_adj,
- *count_adj, *filesize_adj, *duration_adj;
+ *count_adj, *filesize_adj, *duration_adj, *ring_duration_adj;
GList *if_list;
int err;
char err_str[PCAP_ERRBUF_SIZE];
@@ -354,6 +358,35 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_)
gtk_box_pack_start (GTK_BOX(ringbuffer_hb), ringbuffer_nbf_sb, TRUE, TRUE, 0);
gtk_widget_show(ringbuffer_nbf_sb);
+ /* Ring buffer duration row */
+ ring_duration_hb = gtk_hbox_new(FALSE, 3);
+ gtk_container_add(GTK_CONTAINER(file_vb), ring_duration_hb);
+ gtk_widget_show(ring_duration_hb);
+
+ ring_duration_cb = gtk_check_button_new_with_label("Rotate capture file every");
+ gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(ring_duration_cb),
+ capture_opts.has_ring_duration);
+ SIGNAL_CONNECT(ring_duration_cb, "toggled",
+ capture_prep_adjust_sensitivity, cap_open_w);
+ gtk_box_pack_start(GTK_BOX(ring_duration_hb), ring_duration_cb,
+ FALSE, FALSE, 0);
+ gtk_widget_show(ring_duration_cb);
+
+ ring_duration_adj = (GtkAdjustment *)gtk_adjustment_new(capture_opts.ringbuffer_duration,
+ 1, INT_MAX, 1.0, 10.0, 0.0);
+ ring_duration_sb = gtk_spin_button_new (ring_duration_adj, 0, 0);
+ gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (ring_duration_sb), TRUE);
+ WIDGET_SET_SIZE(ring_duration_sb, 80, -1);
+ gtk_box_pack_start (GTK_BOX(ring_duration_hb), ring_duration_sb,
+ FALSE, FALSE, 0);
+ gtk_widget_show(ring_duration_sb);
+
+ ring_duration_lb = gtk_label_new("second(s)");
+ gtk_misc_set_alignment(GTK_MISC(ring_duration_lb), 0, 0.5);
+ gtk_box_pack_start(GTK_BOX(ring_duration_hb), ring_duration_lb,
+ FALSE, FALSE, 0);
+ gtk_widget_show(ring_duration_lb);
+
/* Display-related options frame */
display_fr = gtk_frame_new("Display options");
gtk_container_add(GTK_CONTAINER(main_vb), display_fr);
@@ -556,6 +589,8 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_)
OBJECT_SET_DATA(cap_open_w, E_CAP_RING_ON_TB_KEY, ringbuffer_on_tb);
OBJECT_SET_DATA(cap_open_w, E_CAP_RING_NBF_LB_KEY, ringbuffer_nbf_lb);
OBJECT_SET_DATA(cap_open_w, E_CAP_RING_NBF_SB_KEY, ringbuffer_nbf_sb);
+ OBJECT_SET_DATA(cap_open_w, E_CAP_RING_DURATION_CB_KEY, ring_duration_cb);
+ OBJECT_SET_DATA(cap_open_w, E_CAP_RING_DURATION_SB_KEY, ring_duration_sb);
OBJECT_SET_DATA(cap_open_w, E_CAP_SYNC_KEY, sync_cb);
OBJECT_SET_DATA(cap_open_w, E_CAP_AUTO_SCROLL_KEY, auto_scroll_cb);
OBJECT_SET_DATA(cap_open_w, E_CAP_COUNT_CB_KEY, count_cb);
@@ -721,6 +756,7 @@ capture_prep_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w) {
*count_cb, *count_sb,
*filesize_cb, *filesize_sb,
*duration_cb, *duration_sb,
+ *ring_duration_cb, *ring_duration_sb,
*m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
gchar *if_text;
gchar *if_name;
@@ -737,6 +773,8 @@ capture_prep_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w) {
file_te = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_FILE_TE_KEY);
ringbuffer_on_tb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_ON_TB_KEY);
ringbuffer_nbf_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_NBF_SB_KEY);
+ ring_duration_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_DURATION_CB_KEY);
+ ring_duration_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_DURATION_SB_KEY);
sync_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SYNC_KEY);
auto_scroll_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_AUTO_SCROLL_KEY);
count_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_COUNT_CB_KEY);
@@ -867,6 +905,12 @@ capture_prep_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w) {
else if (capture_opts.ringbuffer_num_files > RINGBUFFER_MAX_NUM_FILES)
capture_opts.ringbuffer_num_files = RINGBUFFER_MAX_NUM_FILES;
+ capture_opts.has_ring_duration =
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ring_duration_cb));
+ if (capture_opts.has_ring_duration)
+ capture_opts.ringbuffer_duration =
+ gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ring_duration_sb));
+
gtk_widget_destroy(GTK_WIDGET(parent_w));
do_capture(save_file);
@@ -911,13 +955,16 @@ capture_prep_adjust_sensitivity(GtkWidget *tb _U_, gpointer parent_w)
*sync_cb, *auto_scroll_cb,
*count_cb, *count_sb,
*filesize_cb, *filesize_sb, *filesize_lb,
- *duration_cb, *duration_sb;
+ *duration_cb, *duration_sb,
+ *ring_duration_cb, *ring_duration_sb;
snap_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SNAP_CB_KEY);
snap_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SNAP_SB_KEY);
ringbuffer_on_tb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_ON_TB_KEY);
ringbuffer_nbf_lb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_NBF_LB_KEY);
ringbuffer_nbf_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_NBF_SB_KEY);
+ ring_duration_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_DURATION_CB_KEY);
+ ring_duration_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_DURATION_SB_KEY);
sync_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SYNC_KEY);
auto_scroll_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_AUTO_SCROLL_KEY);
count_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_COUNT_CB_KEY);
@@ -963,6 +1010,7 @@ capture_prep_adjust_sensitivity(GtkWidget *tb _U_, gpointer parent_w)
of ring buffer files, and its label, sensitive. */
gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_lb), TRUE);
gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_sb), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ring_duration_cb), TRUE);
/* Also, indicate that the file size is a size at which to switch
ring buffer files, not a size at which to stop the capture,
@@ -976,6 +1024,7 @@ capture_prep_adjust_sensitivity(GtkWidget *tb _U_, gpointer parent_w)
of ring buffer files, and its label insensitive. */
gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_lb), FALSE);
gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_sb), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(ring_duration_cb), FALSE);
/* Also, indicate that the file size is a size at which to stop the
capture, not a size at which to switch ring buffer files. */
@@ -998,6 +1047,12 @@ capture_prep_adjust_sensitivity(GtkWidget *tb _U_, gpointer parent_w)
after N seconds" checkbox is on. */
gtk_widget_set_sensitive(GTK_WIDGET(duration_sb),
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(duration_cb)));
+
+ /* The ring duration spinbox is sensitive if the "Rotate capture file
+ after N seconds" checkbox is on. */
+ gtk_widget_set_sensitive(GTK_WIDGET(ring_duration_sb),
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ring_duration_cb)));
+
}
#endif /* HAVE_LIBPCAP */
diff --git a/gtk/main.c b/gtk/main.c
index 28dfaa9fc0..a2cbd7ec9c 100644
--- a/gtk/main.c
+++ b/gtk/main.c
@@ -1,6 +1,6 @@
/* main.c
*
- * $Id: main.c,v 1.293 2003/05/04 18:50:56 gerald Exp $
+ * $Id: main.c,v 1.294 2003/05/15 13:38:05 deniel Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@@ -1180,7 +1180,8 @@ print_usage(gboolean print_ver) {
#ifdef HAVE_LIBPCAP
fprintf(stderr, "\n%s [ -vh ] [ -klpQS ] [ -a <capture autostop condition> ] ...\n",
PACKAGE);
- fprintf(stderr, "\t[ -b <number of ringbuffer files> ] [ -B <byte view height> ]\n");
+ fprintf(stderr, "\t[ -b <number of ringbuffer files>[:<duration>] ]\n");
+ fprintf(stderr, "\t[ -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");
@@ -1285,6 +1286,55 @@ set_autostop_criterion(const char *autostoparg)
*colonp = ':'; /* put the colon back */
return TRUE;
}
+
+/*
+ * Given a string of the form "<ring buffer file>:<duration>", as might appear
+ * as an argument to a "-b" option, parse it and set the arguments in
+ * question. Return an indication of whether it succeeded or failed
+ * in some fashion.
+ */
+static gboolean
+get_ring_arguments(const char *arg)
+{
+ guchar *p, *colonp;
+
+ colonp = strchr(arg, ':');
+
+ if (colonp != NULL) {
+ p = colonp;
+ *p++ = '\0';
+ }
+
+ capture_opts.ringbuffer_num_files =
+ get_positive_int(arg, "number of ring buffer files");
+
+ if (colonp == NULL)
+ return TRUE;
+
+ /*
+ * Skip over any white space (there probably won't be any, but
+ * as we allow it in the preferences file, we might as well
+ * allow it here).
+ */
+ while (isspace(*p))
+ p++;
+ if (*p == '\0') {
+ /*
+ * Put the colon back, so if our caller uses, in an
+ * error message, the string they passed us, the message
+ * looks correct.
+ */
+ *colonp = ':';
+ return FALSE;
+ }
+
+ capture_opts.has_ring_duration = TRUE;
+ capture_opts.ringbuffer_duration = get_positive_int(p,
+ "ring buffer duration");
+
+ *colonp = ':'; /* put the colon back */
+ return TRUE;
+}
#endif
#if defined WIN32 || GTK_MAJOR_VERSION < 2
@@ -1554,6 +1604,8 @@ main(int argc, char *argv[])
capture_opts.autostop_filesize = 1;
capture_opts.ringbuffer_on = FALSE;
capture_opts.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
+ capture_opts.has_ring_duration = FALSE;
+ capture_opts.ringbuffer_duration = 1;
/* If this is a capture child process, it should pay no attention
to the "prefs.capture_prom_mode" setting in the preferences file;
@@ -1621,8 +1673,10 @@ main(int argc, char *argv[])
case 'b': /* Ringbuffer option */
#ifdef HAVE_LIBPCAP
capture_opts.ringbuffer_on = TRUE;
- capture_opts.ringbuffer_num_files =
- get_positive_int(optarg, "number of ring buffer files");
+ if (get_ring_arguments(optarg) == FALSE) {
+ fprintf(stderr, "ethereal: Invalid or unknown -b arg \"%s\"\n", optarg);
+ exit(1);
+ }
#else
capture_option_specified = TRUE;
arg_error = TRUE;
diff --git a/tethereal.c b/tethereal.c
index f38d02a80f..01d90cfd84 100644
--- a/tethereal.c
+++ b/tethereal.c
@@ -1,6 +1,6 @@
/* tethereal.c
*
- * $Id: tethereal.c,v 1.183 2003/05/14 10:31:15 deniel Exp $
+ * $Id: tethereal.c,v 1.184 2003/05/15 13:33:53 deniel Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@@ -183,6 +183,8 @@ typedef struct {
gint32 autostop_filesize; /* Maximum capture file size */
gboolean ringbuffer_on; /* TRUE if ring buffer in use */
guint32 ringbuffer_num_files; /* Number of ring buffer files */
+ gboolean has_ring_duration; /* TRUE if ring duration specified */
+ gint32 ringbuffer_duration; /* Switch file after n seconds */
} capture_options;
static capture_options capture_opts = {
@@ -198,8 +200,10 @@ static capture_options capture_opts = {
specified by default */
0, /* maximum capture file size */
FALSE, /* ring buffer off by default */
- RINGBUFFER_MIN_NUM_FILES /* default number of ring buffer
+ RINGBUFFER_MIN_NUM_FILES, /* default number of ring buffer
files */
+ FALSE, /* Switch ring file after some */
+ 0 /* specified time is off by default */
};
#ifdef SIGINFO
@@ -220,7 +224,7 @@ print_usage(gboolean print_ver)
#ifdef HAVE_LIBPCAP
fprintf(stderr, "\nt%s [ -DvVhqSlp ] [ -a <capture autostop condition> ] ...\n",
PACKAGE);
- fprintf(stderr, "\t[ -b <number of ring buffer files> ] [ -c <count> ]\n");
+ fprintf(stderr, "\t[ -b <number of ring buffer files>[:<duration>] ] [ -c <count> ]\n");
fprintf(stderr, "\t[ -f <capture filter> ] [ -F <output file type> ]\n");
fprintf(stderr, "\t[ -i <interface> ] [ -n ] [ -N <resolving> ]\n");
fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r <infile> ] [ -R <read filter> ]\n");
@@ -317,6 +321,55 @@ set_autostop_criterion(const char *autostoparg)
*colonp = ':'; /* put the colon back */
return TRUE;
}
+
+/*
+ * Given a string of the form "<ring buffer file>:<duration>", as might appear
+ * as an argument to a "-b" option, parse it and set the arguments in
+ * question. Return an indication of whether it succeeded or failed
+ * in some fashion.
+ */
+static gboolean
+get_ring_arguments(const char *arg)
+{
+ guchar *p, *colonp;
+
+ colonp = strchr(arg, ':');
+
+ if (colonp != NULL) {
+ p = colonp;
+ *p++ = '\0';
+ }
+
+ capture_opts.ringbuffer_num_files =
+ get_positive_int(arg, "number of ring buffer files");
+
+ if (colonp == NULL)
+ return TRUE;
+
+ /*
+ * Skip over any white space (there probably won't be any, but
+ * as we allow it in the preferences file, we might as well
+ * allow it here).
+ */
+ while (isspace(*p))
+ p++;
+ if (*p == '\0') {
+ /*
+ * Put the colon back, so if our caller uses, in an
+ * error message, the string they passed us, the message
+ * looks correct.
+ */
+ *colonp = ':';
+ return FALSE;
+ }
+
+ capture_opts.has_ring_duration = TRUE;
+ capture_opts.ringbuffer_duration = get_positive_int(p,
+ "ring buffer duration");
+
+ *colonp = ':'; /* put the colon back */
+ return TRUE;
+}
#endif
/* structure to keep track of what tap listeners have been registered.
@@ -461,8 +514,10 @@ main(int argc, char *argv[])
case 'b': /* Ringbuffer option */
#ifdef HAVE_LIBPCAP
capture_opts.ringbuffer_on = TRUE;
- capture_opts.ringbuffer_num_files =
- get_positive_int(optarg, "number of ring buffer files");
+ if (get_ring_arguments(optarg) == FALSE) {
+ fprintf(stderr, "ethereal: Invalid or unknown -b arg \"%s\"\n", optarg);
+ exit(1);
+ }
#else
capture_option_specified = TRUE;
arg_error = TRUE;
@@ -920,6 +975,7 @@ capture(int out_file_type)
char errmsg[1024+1];
condition *volatile cnd_stop_capturesize = NULL;
condition *volatile cnd_stop_timeout = NULL;
+ condition *volatile cnd_ring_timeout = NULL;
#ifndef _WIN32
static const char ppamsg[] = "can't find PPA for ";
char *libpcap_warn;
@@ -1113,6 +1169,10 @@ capture(int out_file_type)
cnd_stop_timeout = cnd_new((const char*)CND_CLASS_TIMEOUT,
(gint32)capture_opts.autostop_duration);
+ if (capture_opts.ringbuffer_on && capture_opts.has_ring_duration)
+ cnd_ring_timeout = cnd_new(CND_CLASS_TIMEOUT,
+ capture_opts.ringbuffer_duration);
+
if (!setjmp(ld.stopenv)) {
ld.go = TRUE;
ld.packet_count = 0;
@@ -1191,6 +1251,15 @@ capture(int out_file_type)
} else if (cnd_stop_timeout != NULL && cnd_eval(cnd_stop_timeout)) {
/* The specified capture time has elapsed; stop the capture. */
ld.go = FALSE;
+ } else if (cnd_ring_timeout != NULL && cnd_eval(cnd_ring_timeout)) {
+ /* time elasped for this ring file, swith to the next */
+ if (ringbuf_switch_file(&cfile, &ld.pdh, &loop_err)) {
+ /* File switch succeeded: reset the condition */
+ cnd_reset(cnd_ring_timeout);
+ } else {
+ /* File switch failed: stop here */
+ ld.go = FALSE;
+ }
} else if (inpkts > 0) {
if (capture_opts.autostop_count != 0 &&
ld.packet_count >= capture_opts.autostop_count) {
@@ -1208,6 +1277,9 @@ capture(int out_file_type)
if (ringbuf_switch_file(&cfile, &ld.pdh, &loop_err)) {
/* File switch succeeded: reset the condition */
cnd_reset(cnd_stop_capturesize);
+ if (cnd_ring_timeout) {
+ cnd_reset(cnd_ring_timeout);
+ }
} else {
/* File switch failed: stop here */
volatile_err = loop_err;
@@ -1235,6 +1307,8 @@ capture(int out_file_type)
cnd_delete(cnd_stop_capturesize);
if (cnd_stop_timeout != NULL)
cnd_delete(cnd_stop_timeout);
+ if (cnd_ring_timeout != NULL)
+ cnd_delete(cnd_ring_timeout);
if ((cfile.save_file != NULL) && !quiet) {
/* We're saving to a file, which means we're printing packet counts