Ethereal-dev: [ethereal-dev] more real-time capture and full display
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Laurent Deniel <deniel@xxxxxxxxxxx>
Date: Sat, 08 May 1999 18:36:08 +0200
Hi all,
Here is a diff to current CVS tree that enhances the -S option of
John patch :
- now, capture and full display of decoded packet are possible at the
same time !
- open/reload is no more needed
- the child uses a pipe to sync the father
- the father is able to read the cap file at reception of something
in the pipe (make use of gtk_input_add_full)
- sync is performed every DUMP_FREQ packets (should be configurable)
- the father is able to detect that the child has ended or crashed
- the child ends if the father exits (SIGPIPE)
- the father automatically opens the cap file when the child starts
and captures at least one packet
- SIGUSR1 and sleep are no more needed
- the problem of execlp is fixed (use execl with correct PATH).
Sorry Gilbert, I have not yet tested this patch with wiretap.
Laurent.
--
Laurent DENIEL | E-mail: deniel@xxxxxxxxxxx
Paris, FRANCE | deniel@xxxxxxxxxxxxxxxxxxxxxxxxxxxx
| WWW : http://www.worldnet.fr/~deniel
All above opinions are personal, unless stated otherwise.diff -u --recursive --new-file ethereal/capture.c ethereal-new/capture.c
--- ethereal/capture.c Fri Apr 30 21:52:21 1999
+++ ethereal-new/capture.c Sat May 8 18:00:47 1999
@@ -43,6 +43,8 @@
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
+#include <signal.h>
+#include <errno.h>
#ifdef NEED_SNPRINTF_H
# ifdef HAVE_STDARG_H
@@ -70,6 +72,13 @@
extern GtkWidget *info_bar;
extern guint file_ctx;
+extern gchar *ethereal_path;
+extern int fork_mode;
+extern int sync_pipe[];
+extern int sync_mode;
+extern int sigusr2_received;
+extern int quit_after_cap;
+
/* File selection data keys */
#define E_CAP_PREP_FS_KEY "cap_prep_fs"
#define E_CAP_PREP_TE_KEY "cap_prep_te"
@@ -84,6 +93,9 @@
/* Capture filter key */
#define E_CAP_FILT_TE_KEY "cap_filt_te"
+/* how often to force an fflush */
+#define DUMP_FREQ 4
+
GList *
get_interface_list() {
GList *il = NULL;
@@ -337,7 +349,7 @@
cf.cfilter = g_strdup(gtk_entry_get_text(GTK_ENTRY(filter_te)));
}
cf.count =
- atoi(g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(count_cb)->entry))));
+ atoi( g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(count_cb)->entry))));
cf.snap = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(snap_sb));
if (cf.snap < 1)
cf.snap = MAX_PACKET_SIZE;
@@ -354,7 +366,53 @@
cf.save_file = tempnam(NULL, "ether");
cf.user_saved = 0;
- capture();
+ if( fork_mode ){ /* use fork() for capture */
+ int fork_child;
+ char ssnap[24];
+ char scount[24]; /* need a constant for len of numbers */
+
+ sprintf(ssnap,"%d",cf.snap); /* in liu of itoa */
+ sprintf(scount,"%d",cf.count);
+ signal(SIGCHLD, SIG_IGN);
+ if (sync_mode) pipe(sync_pipe);
+ if((fork_child = fork()) == 0){
+ /* args: -k -- capture
+ * -i interface specification
+ * -w file to write
+ * -c count to capture
+ * -Q quit after capture (forces -k)
+ * -s snaplen
+ * should add -b -m -t from this invocation: TODO
+ */
+ if (sync_mode) {
+ close(1);
+ dup(sync_pipe[1]);
+ close(sync_pipe[0]);
+ execl(ethereal_path,"ethereal","-k","-Q","-i",cf.iface,"-w",cf.save_file,
+ "-c",scount,"-s", ssnap, "-S", 0);
+ }
+ else
+ execl(ethereal_path,"ethereal","-k","-Q","-i",cf.iface,"-w",cf.save_file,
+ "-c",scount,"-s", ssnap,0);
+ }
+ else {
+ cf.filename = cf.save_file;
+ close(sync_pipe[1]);
+ if (sync_mode) {
+ while (!sigusr2_received) {
+ struct timeval timeout = {1,0};
+ select(0, NULL, NULL, NULL, &timeout);
+ if (kill(fork_child, 0) == -1 && errno == ESRCH)
+ break;
+ }
+ if (sigusr2_received)
+ load_cap_file(cf.save_file, &cf);
+ sigusr2_received = FALSE;
+ }
+ }
+ }
+ else
+ capture();
}
void
@@ -381,6 +439,7 @@
ld.counts.total = 0;
ld.max = cf.count;
ld.linktype = DLT_NULL;
+ ld.signal_sent = 0;
ld.counts.tcp = 0;
ld.counts.udp = 0;
ld.counts.ospf = 0;
@@ -401,6 +460,7 @@
pcap_close(pch);
return;
}
+
ld.linktype = pcap_datalink(pch);
if (cf.cfilter) {
@@ -504,6 +564,11 @@
"that you have the proper interface specified.");
}
+ if( quit_after_cap ){
+ /* DON'T unlink the save file. Presumably someone wants it. */
+ gtk_exit(0);
+ }
+
if (cf.save_file) load_cap_file(cf.save_file, &cf);
#ifdef USE_ITEM
set_menu_sensitivity("/File/Save", TRUE);
@@ -534,6 +599,7 @@
capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
const u_char *pd) {
+ static int dump_count = 0;
loop_data *ld = (loop_data *) user;
if ((++ld->counts.total >= ld->max) && (ld->max > 0))
@@ -543,6 +609,15 @@
/* Currently, pcap_dumper_t is a FILE *. Let's hope that doesn't change. */
if (ld->pdh) pcap_dump((u_char *) ld->pdh, phdr, pd);
+ /* flush every DUMP_FREQ times */
+
+ if ( !dump_count ){
+ fflush((FILE *)ld->pdh);
+ if (sync_mode)
+ write(1, "D", 1);
+ }
+ dump_count = (dump_count + 1) % DUMP_FREQ;
+
switch (ld->linktype) {
case DLT_EN10MB :
capture_eth(pd, phdr->caplen, &ld->counts);
@@ -563,4 +638,13 @@
capture_raw(pd, phdr->caplen, &ld->counts);
break;
}
+
+ if (sync_mode && !ld->signal_sent) {
+ /* will trigger the father to open the cap file which contains
+ at least one complete packet */
+ fflush((FILE *)ld->pdh);
+ kill(getppid(), SIGUSR2);
+ ld->signal_sent = 1;
+ }
+
}
diff -u --recursive --new-file ethereal/capture.h ethereal-new/capture.h
--- ethereal/capture.h Fri Apr 30 21:52:21 1999
+++ ethereal-new/capture.h Sat May 8 17:52:48 1999
@@ -30,6 +30,7 @@
gint go;
gint max;
gint linktype;
+ gint signal_sent;
packet_counts counts;
pcap_dumper_t *pdh;
} loop_data;
diff -u --recursive --new-file ethereal/ethereal.c ethereal-new/ethereal.c
--- ethereal/ethereal.c Fri May 7 19:35:30 1999
+++ ethereal-new/ethereal.c Sat May 8 18:01:51 1999
@@ -55,6 +55,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <netinet/in.h>
+#include <signal.h>
#ifdef NEED_SNPRINTF_H
# ifdef HAVE_STDARG_H
@@ -92,11 +93,18 @@
frame_data *fd;
gint start_capture = 0;
gchar comp_info_str[256];
+gchar *ethereal_path = NULL;
ts_type timestamp_type = RELATIVE;
GtkStyle *item_style;
+int sync_mode; /* allow sync */
+int sync_pipe[2]; /* used to sync father */
+int fork_mode; /* fork a child to do the capture */
+int sigusr2_received = 0;
+int quit_after_cap; /* Makes a "capture only mode". Implies -k */
+
#define E_DFILTER_TE_KEY "display_filter_te"
/* About Ethereal window */
@@ -281,7 +289,10 @@
(file_sel)->cancel_button), "clicked", (GtkSignalFunc)
gtk_widget_destroy, GTK_OBJECT (file_sel));
- gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_sel), "");
+ if( fork_mode && (cf.save_file != NULL) )
+ gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_sel), cf.save_file);
+ else
+ gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_sel), "");
gtk_widget_show(file_sel);
}
@@ -408,17 +419,19 @@
packet_list_select_cb(GtkWidget *w, gint row, gint col, gpointer evt) {
GList *l;
+ if (!sync_mode) {
#ifdef WITH_WIRETAP
if (cf.wth) return;
#else
if (cf.pfh) return;
#endif
+ }
blank_packetinfo();
gtk_text_freeze(GTK_TEXT(byte_view));
gtk_text_set_point(GTK_TEXT(byte_view), 0);
gtk_text_forward_delete(GTK_TEXT(byte_view),
gtk_text_get_length(GTK_TEXT(byte_view)));
- l = g_list_nth(cf.plist, row);
+ l = g_list_nth(cf.plist_first, row);
if (l) {
fd = (frame_data *) l->data;
fseek(cf.fh, fd->file_off, SEEK_SET);
@@ -491,14 +504,16 @@
#endif
}
if (start_capture) {
- if (cf.save_file)
- capture();
- else
- capture();
+ capture();
start_capture = 0;
}
}
+static void
+sigusr2_handler(int sig) {
+ sigusr2_received = 1;
+}
+
static void
ethereal_proto_init(void) {
@@ -545,13 +560,17 @@
gint *col_fmt;
gchar **col_title;
+ ethereal_path = argv[0];
+
/* Let GTK get its args */
gtk_init (&argc, &argv);
+
prefs = read_prefs();
/* Initialize the capture file struct */
cf.plist = NULL;
+ cf.plist_first = NULL;
#ifdef WITH_WIRETAP
cf.wth = NULL;
#else
@@ -584,7 +603,7 @@
#endif
/* Now get our args */
- while ((opt = getopt(argc, argv, "b:B:c:hi:m:nP:r:s:t:T:w:v")) != EOF) {
+ while ((opt = getopt(argc, argv, "b:B:c:Fhi:km:nP:Qr:Ss:t:T:w:v")) != EOF) {
switch (opt) {
case 'b': /* Bold font */
bold_font = g_strdup(optarg);
@@ -595,6 +614,9 @@
case 'c': /* Capture xxx packets */
cf.count = atoi(optarg);
break;
+ case 'F': /* Fork to capture */
+ fork_mode = 1;
+ break;
case 'h': /* Print help and exit */
print_usage();
exit(0);
@@ -614,12 +636,19 @@
case 'P': /* Packet list pane height */
pl_size = atoi(optarg);
break;
+ case 'Q': /* Quit after capture (just capture to file) */
+ quit_after_cap = 1;
+ start_capture = 1; /*** -Q implies -k !! ***/
+ break;
case 'r': /* Read capture file xxx */
cf_name = g_strdup(optarg);
break;
case 's': /* Set the snapshot (capture) length */
cf.snap = atoi(optarg);
break;
+ case 'S': /* "Sync" mode: used for following file ala tail -f */
+ sync_mode = 1;
+ break;
case 't': /* Time stamp type */
if (strcmp(optarg, "r") == 0)
timestamp_type = RELATIVE;
@@ -647,6 +676,9 @@
break;
}
}
+
+ if (sync_mode)
+ signal(SIGUSR2, sigusr2_handler);
/* Build the column format array */
col_fmt = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
diff -u --recursive --new-file ethereal/file.c ethereal-new/file.c
--- ethereal/file.c Fri Apr 30 21:52:29 1999
+++ ethereal-new/file.c Sat May 8 18:12:32 1999
@@ -38,6 +38,7 @@
#include <string.h>
#include <sys/stat.h>
#include <errno.h>
+#include <fcntl.h>
#ifdef NEED_SNPRINTF_H
# ifdef HAVE_STDARG_H
@@ -66,6 +67,10 @@
extern GtkWidget *packet_list, *prog_bar, *info_bar, *byte_view, *tree_view;
extern guint file_ctx;
+extern int sync_mode;
+extern int sync_pipe[];
+
+guint cap_input_id;
static guint32 firstsec, firstusec;
static guint32 lastsec, lastusec;
@@ -128,6 +133,7 @@
cf->snap = 0;
if (cf->plist == NULL) {
cf->plist = g_list_alloc();
+ cf->plist_first = cf->plist;
cf->plist->data = (frame_data *) g_malloc(sizeof(frame_data));
} else {
cf->plist = g_list_first(cf->plist);
@@ -229,6 +235,8 @@
gtk_statusbar_pop(GTK_STATUSBAR(w), context);
}
+static int tail_cap_file(char *, capture_file *);
+
int
load_cap_file(char *fname, capture_file *cf) {
gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
@@ -238,6 +246,9 @@
size_t msg_len;
int err;
+ if (sync_mode)
+ return tail_cap_file(fname, cf);
+
close_cap_file(cf, info_bar, file_ctx);
/* Initialize protocol-speficic variables */
@@ -318,6 +329,92 @@
return err;
}
+void
+cap_file_input_cb (gpointer data, gint source, GdkInputCondition condition) {
+
+ capture_file *cf = (capture_file *)data;
+ char buffer[256];
+
+ if (read(sync_pipe[0], buffer, 256) <= 0) {
+#ifdef WITH_WIRETAP
+ wtap_close(cf->wth);
+ cf->wth = NULL;
+#else
+ pcap_close(cf->pfh);
+ cf->pfh = NULL;
+#endif
+ gtk_input_remove(cap_input_id);
+ return;
+ }
+
+ gtk_clist_freeze(GTK_CLIST(packet_list));
+#ifdef WITH_WIRETAP
+ wtap_loop(cf->wth, 0 /* or DUMP_FREQ */, wtap_dispatch_cb, (u_char *) cf);
+#else
+ pcap_loop(cf->pfh, 0 /* or DUMP_FREQ */, pcap_dispatch_cb, (u_char *) cf);
+#endif
+ gtk_clist_thaw(GTK_CLIST(packet_list));
+}
+
+void
+cap_file_destroy_cb (gpointer data) {
+ capture_file *cf = (capture_file *)data;
+ cf->plist = g_list_first(cf->plist);
+#ifdef USE_ITEM
+ set_menu_sensitivity("/File/Save as", TRUE);
+#else
+ set_menu_sensitivity("<Main>/File/Save as", TRUE);
+#endif
+}
+
+int
+tail_cap_file(char *fname, capture_file *cf) {
+ int err;
+
+ close_cap_file(cf, info_bar, file_ctx);
+
+ /* Initialize protocol-speficic variables */
+ ncp_init_protocol();
+
+ err = open_cap_file(fname, cf);
+#ifdef WITH_WIRETAP
+ if ((err == 0) && (cf->cd_t != WTAP_FILE_UNKNOWN)) {
+#else
+ if ((err == 0) && (cf->cd_t != CD_UNKNOWN)) {
+#endif
+
+#ifdef USE_ITEM
+ set_menu_sensitivity("/File/Close", TRUE);
+ set_menu_sensitivity("/File/Reload", FALSE);
+#else
+ set_menu_sensitivity("<Main>/File/Close", TRUE);
+ set_menu_sensitivity("<Main>/File/Reload", FALSE);
+#endif
+ cf->fh = fopen(fname, "r");
+ cap_input_id = gtk_input_add_full (sync_pipe[0],
+ GDK_INPUT_READ,
+ cap_file_input_cb,
+ NULL,
+ (gpointer) cf,
+ cap_file_destroy_cb);
+ }
+ else {
+#ifdef USE_ITEM
+ set_menu_sensitivity("/File/Close", FALSE);
+ set_menu_sensitivity("/File/Save", FALSE);
+ set_menu_sensitivity("/File/Save as", FALSE);
+ set_menu_sensitivity("/File/Reload", FALSE);
+#else
+ set_menu_sensitivity("<Main>/File/Close", FALSE);
+ set_menu_sensitivity("<Main>/File/Save", FALSE);
+ set_menu_sensitivity("<Main>/File/Save as", FALSE);
+ set_menu_sensitivity("<Main>/File/Reload", FALSE);
+#endif
+ }
+ return err;
+}
+
+
static void
#ifdef WITH_WIRETAP
wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr, int offset,
@@ -342,7 +439,7 @@
fdata->file_off = offset;
fdata->lnk_t = phdr->pkt_encap;
#else
- fdata->file_off = ftell(cf->fh) - phdr->caplen;
+ fdata->file_off = ftell(pcap_file(cf->pfh)) - phdr->caplen;
#endif
fdata->abs_secs = phdr->ts.tv_sec;
fdata->abs_usecs = phdr->ts.tv_usec;
diff -u --recursive --new-file ethereal/file.h ethereal-new/file.h
--- ethereal/file.h Fri Apr 30 21:52:29 1999
+++ ethereal-new/file.h Sat May 8 17:56:44 1999
@@ -92,6 +92,7 @@
*/
/*guint8 pd[MAX_PACKET_SIZE];*/ /* Packet data */
guint8 pd[65536]; /* Packet data */
+ GList *plist_first;/* First packet in list */
GList *plist; /* Packet list */
frame_data *cur; /* Current list item */
column_info cinfo; /* Column formatting information */
- Follow-Ups:
- Re: [ethereal-dev] more real-time capture and full display
- From: Don Lafontaine
- Re: [ethereal-dev] more real-time capture and full display
- References:
- Re: [ethereal-dev] John's almost-real-time capture
- From: Guy Harris
- Re: [ethereal-dev] John's almost-real-time capture
- From: Laurent Deniel
- Re: [ethereal-dev] John's almost-real-time capture
- Prev by Date: [ethereal-dev] Ethereal Team
- Next by Date: Re: [ethereal-dev] more real-time capture and full display
- Previous by thread: Re: [ethereal-dev] John's almost-real-time capture
- Next by thread: Re: [ethereal-dev] more real-time capture and full display
- Index(es):





