In Ethereal, attempt to get the packet statistics from libpcap when

capturing; if we succeed, display the packet drops count as the "Drops"
value in the status line and as the "Dropped packets" statistics in the
summary dialog box, otherwise don't display it at all.

In Tethereal, attempt to get the packet statistics from libpcap when
capturing; if we succeed, and if there were any dropped packets, print
out the count of dropped packets when the capture finishes.

svn path=/trunk/; revision=3016
This commit is contained in:
Guy Harris 2001-02-11 09:28:17 +00:00
parent 8cd8391b9a
commit bf0a3a32d1
10 changed files with 113 additions and 45 deletions

View File

@ -1,7 +1,7 @@
/* capture.c
* Routines for packet capture windows
*
* $Id: capture.c,v 1.138 2001/02/10 09:08:14 guy Exp $
* $Id: capture.c,v 1.139 2001/02/11 09:28:15 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -268,6 +268,8 @@ do_capture(char *capfile_name)
char *msg;
int err;
int capture_succeeded;
gboolean stats_known;
struct pcap_stat stats;
if (capfile_name != NULL) {
/* Try to open/create the specified file for use as a capture buffer. */
@ -556,7 +558,7 @@ do_capture(char *capfile_name)
}
} else {
/* Not sync mode. */
capture_succeeded = capture();
capture_succeeded = capture(&stats_known, &stats);
if (quit_after_cap) {
/* DON'T unlink the save file. Presumably someone wants it. */
gtk_exit(0);
@ -566,6 +568,39 @@ do_capture(char *capfile_name)
if ((err = open_cap_file(cfile.save_file, is_tempfile, &cfile)) == 0) {
/* Set the read filter to NULL. */
cfile.rfcode = NULL;
/* Get the packet-drop statistics.
XXX - there are currently no packet-drop statistics stored
in libpcap captures, and that's what we're reading.
At some point, we will add support in Wiretap to return
packet-drop statistics for capture file formats that store it,
and will make "read_cap_file()" get those statistics from
Wiretap. We clear the statistics (marking them as "not known")
in "open_cap_file()", and "read_cap_file()" will only fetch
them and mark them as known if Wiretap supplies them, so if
we get the statistics now, after calling "open_cap_file()" but
before calling "read_cap_file()", the values we store will
be used by "read_cap_file()".
If a future libpcap capture file format stores the statistics,
we'll put them into the capture file that we write, and will
thus not have to set them here - "read_cap_file()" will get
them from the file and use them. */
if (stats_known) {
cfile.drops_known = TRUE;
/* XXX - on some systems, libpcap doesn't bother filling in
"ps_ifdrop" - it doesn't even set it to zero - so we don't
bother looking at it.
Ideally, libpcap would have an interface that gave us
several statistics - perhaps including various interface
error statistics - and would tell us which of them it
supplies, allowing us to display only the ones it does. */
cfile.drops = stats.ps_drop;
}
switch (read_cap_file(&cfile, &err)) {
case READ_SUCCESS:
@ -1111,7 +1146,7 @@ static loop_data ld;
/* Do the low-level work of a capture.
Returns TRUE if it succeeds, FALSE otherwise. */
int
capture(void)
capture(gboolean *stats_known, struct pcap_stat *stats)
{
GtkWidget *cap_w, *main_vb, *stop_bt, *counts_tb;
pcap_t *pch;
@ -1144,7 +1179,7 @@ capture(void)
const gchar *title;
gint *value_ptr;
GtkWidget *label, *value, *percent;
} stats[] = {
} counts[] = {
{ "Total", &ld.counts.total },
{ "SCTP", &ld.counts.sctp },
{ "TCP", &ld.counts.tcp },
@ -1158,7 +1193,7 @@ capture(void)
{ "Other", &ld.counts.other }
};
#define N_STATS (sizeof stats / sizeof stats[0])
#define N_COUNTS (sizeof counts / sizeof counts[0])
/* Initialize Windows Socket if we are in a WIN32 OS
This needs to be done before querying the interface for network/netmask */
@ -1192,6 +1227,9 @@ capture(void)
ld.counts.other = 0;
ld.pdh = NULL;
/* We haven't yet gotten the capture statistics. */
*stats_known = FALSE;
/* Open the network interface to capture from it. */
pch = pcap_open_live(cfile.iface, cfile.snap, promisc_mode,
CAP_READ_TIMEOUT, err_str);
@ -1375,33 +1413,33 @@ capture(void)
gtk_widget_show(main_vb);
/* Individual statistic elements */
counts_tb = gtk_table_new(N_STATS, 3, TRUE);
counts_tb = gtk_table_new(N_COUNTS, 3, TRUE);
gtk_box_pack_start(GTK_BOX(main_vb), counts_tb, TRUE, TRUE, 3);
gtk_widget_show(counts_tb);
for (i = 0; i < N_STATS; i++) {
stats[i].label = gtk_label_new(stats[i].title);
gtk_misc_set_alignment(GTK_MISC(stats[i].label), 0.0f, 0.0f);
for (i = 0; i < N_COUNTS; i++) {
counts[i].label = gtk_label_new(counts[i].title);
gtk_misc_set_alignment(GTK_MISC(counts[i].label), 0.0f, 0.0f);
stats[i].value = gtk_label_new("0");
gtk_misc_set_alignment(GTK_MISC(stats[i].value), 0.0f, 0.0f);
counts[i].value = gtk_label_new("0");
gtk_misc_set_alignment(GTK_MISC(counts[i].value), 0.0f, 0.0f);
stats[i].percent = gtk_label_new("0.0%");
gtk_misc_set_alignment(GTK_MISC(stats[i].percent), 0.0f, 0.0f);
counts[i].percent = gtk_label_new("0.0%");
gtk_misc_set_alignment(GTK_MISC(counts[i].percent), 0.0f, 0.0f);
gtk_table_attach_defaults(GTK_TABLE(counts_tb),
stats[i].label, 0, 1, i, i + 1);
counts[i].label, 0, 1, i, i + 1);
gtk_table_attach(GTK_TABLE(counts_tb),
stats[i].value,
counts[i].value,
1, 2, i, i + 1, 0, 0, 5, 0);
gtk_table_attach_defaults(GTK_TABLE(counts_tb),
stats[i].percent, 2, 3, i, i + 1);
counts[i].percent, 2, 3, i, i + 1);
gtk_widget_show(stats[i].label);
gtk_widget_show(stats[i].value);
gtk_widget_show(stats[i].percent);
gtk_widget_show(counts[i].label);
gtk_widget_show(counts[i].value);
gtk_widget_show(counts[i].percent);
}
/* allow user to either click a stop button, or the close button on
@ -1506,16 +1544,16 @@ capture(void)
if (cur_time > upd_time) {
upd_time = cur_time;
for (i = 0; i < N_STATS; i++) {
for (i = 0; i < N_COUNTS; i++) {
snprintf(label_str, sizeof(label_str), "%d",
*stats[i].value_ptr);
*counts[i].value_ptr);
gtk_label_set(GTK_LABEL(stats[i].value), label_str);
gtk_label_set(GTK_LABEL(counts[i].value), label_str);
snprintf(label_str, sizeof(label_str), "(%.1f%%)",
pct(*stats[i].value_ptr, ld.counts.total));
pct(*counts[i].value_ptr, ld.counts.total));
gtk_label_set(GTK_LABEL(stats[i].percent), label_str);
gtk_label_set(GTK_LABEL(counts[i].percent), label_str);
}
/* do sync here, too */
@ -1561,7 +1599,13 @@ capture(void)
close(pipe_fd);
else
#endif
{
/* Get the capture statistics, so we know how many packets were
dropped. */
if (pcap_stats(pch, stats) >= 0)
*stats_known = TRUE;
pcap_close(pch);
}
#ifdef WIN32
/* Shut down windows sockets */

View File

@ -1,7 +1,7 @@
/* capture.h
* Definitions for packet capture windows
*
* $Id: capture.h,v 1.24 2000/10/11 06:01:14 guy Exp $
* $Id: capture.h,v 1.25 2001/02/11 09:28:15 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -42,7 +42,7 @@ extern gboolean capture_child; /* if this is the child for "-S" */
void do_capture(char *capfile_name);
/* Do the low-level work of a capture. */
int capture(void);
int capture(gboolean *stats_known, struct pcap_stat *stats);
/* Stop a capture from a menu item. */
void capture_stop(void);

18
file.c
View File

@ -1,7 +1,7 @@
/* file.c
* File I/O routines
*
* $Id: file.c,v 1.231 2001/02/10 09:08:14 guy Exp $
* $Id: file.c,v 1.232 2001/02/11 09:28:15 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -170,6 +170,7 @@ open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
cf->cd_t = wtap_file_type(cf->wth);
cf->count = 0;
cf->drops_known = FALSE;
cf->drops = 0;
cf->esec = 0;
cf->eusec = 0;
@ -265,7 +266,8 @@ set_display_filename(capture_file *cf)
{
gchar *name_ptr;
size_t msg_len;
gchar *done_fmt = " File: %s Drops: %u";
static const gchar done_fmt_nodrops[] = " File: %s";
static const gchar done_fmt_drops[] = " File: %s Drops: %u";
gchar *done_msg;
gchar *win_name_fmt = "%s - Ethereal";
gchar *win_name;
@ -280,9 +282,15 @@ set_display_filename(capture_file *cf)
name_ptr = "<capture>";
}
msg_len = strlen(name_ptr) + strlen(done_fmt) + 64;
done_msg = g_malloc(msg_len);
snprintf(done_msg, msg_len, done_fmt, name_ptr, cf->drops);
if (cf->drops_known) {
msg_len = strlen(name_ptr) + strlen(done_fmt_drops) + 64;
done_msg = g_malloc(msg_len);
snprintf(done_msg, msg_len, done_fmt_drops, name_ptr, cf->drops);
} else {
msg_len = strlen(name_ptr) + strlen(done_fmt_nodrops);
done_msg = g_malloc(msg_len);
snprintf(done_msg, msg_len, done_fmt_nodrops, name_ptr);
}
gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, done_msg);
g_free(done_msg);

3
file.h
View File

@ -1,7 +1,7 @@
/* file.h
* Definitions for file structures and routines
*
* $Id: file.h,v 1.80 2001/02/01 20:21:13 gram Exp $
* $Id: file.h,v 1.81 2001/02/11 09:28:15 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -68,6 +68,7 @@ typedef struct _capture_file {
int lnk_t; /* Link-layer type with which to save capture */
guint32 vers; /* Version. For tcpdump minor is appended to major */
guint32 count; /* Packet count */
gboolean drops_known; /* TRUE if we know how many packets were dropped */
guint32 drops; /* Dropped packets */
guint32 esec; /* Elapsed seconds */
guint32 eusec; /* Elapsed microseconds */

View File

@ -1,6 +1,6 @@
/* main.c
*
* $Id: main.c,v 1.178 2001/02/08 03:55:45 guy Exp $
* $Id: main.c,v 1.179 2001/02/11 09:28:17 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -693,6 +693,8 @@ main(int argc, char *argv[])
gchar *save_file = NULL;
GList *if_list;
gchar err_str[PCAP_ERRBUF_SIZE];
gboolean stats_known;
struct pcap_stat stats;
#else
gboolean capture_option_specified = FALSE;
#endif
@ -1226,7 +1228,8 @@ main(int argc, char *argv[])
a temporary file and fork off *another* child process (so don't
call "do_capture()"). */
capture();
/* XXX - hand these stats to the parent process */
capture(&stats_known, &stats);
/* The capture is done; there's nothing more for us to do. */
gtk_exit(0);

View File

@ -3,7 +3,7 @@
*
* Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com>
*
* $Id: packet_win.c,v 1.17 2001/02/01 20:21:22 gram Exp $
* $Id: packet_win.c,v 1.18 2001/02/11 09:28:17 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -50,7 +50,6 @@
#include "main.h"
#include "timestamp.h"
#include "packet.h"
#include "capture.h"
#include "summary.h"
#include "file.h"
#include "menu.h"

View File

@ -1,7 +1,7 @@
/* summary_dlg.c
* Routines for capture file summary window
*
* $Id: summary_dlg.c,v 1.8 2000/08/21 18:20:19 deniel Exp $
* $Id: summary_dlg.c,v 1.9 2001/02/11 09:28:17 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -142,8 +142,10 @@ summary_open_cb(GtkWidget *w, gpointer d)
}
/* Dropped count */
snprintf(string_buff, SUM_STR_MAX, "Dropped packets: %i", summary.drops);
add_string_to_box(string_buff, data_box);
if (summary.drops_known) {
snprintf(string_buff, SUM_STR_MAX, "Dropped packets: %u", summary.drops);
add_string_to_box(string_buff, data_box);
}
/* Byte count */
snprintf(string_buff, SUM_STR_MAX, "Bytes of traffic: %d", summary.bytes);

View File

@ -1,7 +1,7 @@
/* summary.c
* Routines for capture file summary info
*
* $Id: summary.c,v 1.19 2000/08/21 18:20:11 deniel Exp $
* $Id: summary.c,v 1.20 2001/02/11 09:28:15 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -94,6 +94,7 @@ summary_fill_in(summary_tally *st)
st->snap = cfile.snap;
st->elapsed_time = secs_usecs(cfile.esec, cfile.eusec);
st->packet_count = cfile.count;
st->drops_known = cfile.drops_known;
st->drops = cfile.drops;
st->iface = cfile.iface;
st->dfilter = cfile.dfilter;

View File

@ -1,7 +1,7 @@
/* summary.h
* Definitions for capture file summary data
*
* $Id: summary.h,v 1.5 2000/08/21 18:20:12 deniel Exp $
* $Id: summary.h,v 1.6 2001/02/11 09:28:15 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -40,7 +40,8 @@ typedef struct _summary_tally {
long file_length; /* file length in bytes */
int encap_type; /* wiretap encapsulation type */
int snap; /* snapshot length */
int drops; /* number of packet drops */
gboolean drops_known; /* TRUE if number of packet drops is known */
guint32 drops; /* number of packet drops */
const char *iface; /* interface name */
const char *dfilter; /* display filter */
const char *cfilter; /* capture filter */

View File

@ -1,6 +1,6 @@
/* tethereal.c
*
* $Id: tethereal.c,v 1.65 2001/02/10 09:08:14 guy Exp $
* $Id: tethereal.c,v 1.66 2001/02/11 09:28:15 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -544,6 +544,7 @@ capture(int packet_count, int out_file_type)
static const char ppamsg[] = "can't find PPA for ";
char *libpcap_warn;
#endif
struct pcap_stat stats;
/* Initialize the table of conversations. */
epan_conversation_init();
@ -660,13 +661,20 @@ capture(int packet_count, int out_file_type)
printf("Capturing on %s\n", cfile.iface);
inpkts = pcap_loop(ld.pch, packet_count, capture_pcap_cb, (u_char *) &ld);
pcap_close(ld.pch);
/* Send a newline if we were printing packet counts to stdout */
if (cfile.save_file != NULL) {
/* We're saving to a file, which means we're printing packet counts
to the standard output. Send a newline so that we move to the
line after the packet count. */
printf("\n");
}
/* Get the capture statistics, and, if any packets were dropped, report
that. */
if (pcap_stats(ld.pch, &stats) >= 0)
printf("%u packets dropped\n", stats.ps_drop);
pcap_close(ld.pch);
return TRUE;
error:
@ -1364,6 +1372,7 @@ open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
cf->cd_t = wtap_file_type(cf->wth);
cf->count = 0;
cf->drops_known = FALSE;
cf->drops = 0;
cf->esec = 0;
cf->eusec = 0;