Ethereal-dev: Re: [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: Mon, 10 May 1999 22:03:19 +0200
Gilbert Ramirez wrote:
>
>
> # ./ethereal -F -S
> User Signal 2
>
> As soon as I get the first packet, "User Signal 2" is printed and my
> main ethereal window is not usable. If I stop the capture, no file is
> loaded into the ethereal GUI. "re-load" does nothing.
>
Strange, the signal should be caught and generated only once but in
the attached diff, I set again the signal handler in the handler
to allow multiple capture sessions.
This diff (to current CVS tree) contains also:
- sync every seconds (no more after n packets)
- reentrancy problem and potential stack overflow fixes
- much stable with heavy loaded network capture
- menu handling fixes (load, reload, close, capture etc.)
- pass -m / -b options to child
- miscellaneous non user visible fixes.
It was tested on Linux and Tru64 (but not on Solaris ;-)
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 --new-file ethereal/capture.c ethereal-new/capture.c
--- ethereal/capture.c Fri Apr 30 21:52:21 1999
+++ ethereal-new/capture.c Mon May 10 21:08:16 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,15 @@
extern GtkWidget *info_bar;
extern guint file_ctx;
+extern gchar *ethereal_path;
+extern gchar *medium_font;
+extern gchar *bold_font;
+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"
@@ -337,7 +348,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 +365,56 @@
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
+ * -S sync mode
+ * -m / -b fonts
+ */
+ 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",
+ "-m", medium_font, "-b", bold_font, 0);
+ }
+ else
+ execl(ethereal_path,"ethereal","-k","-Q","-i",cf.iface,"-w",cf.save_file,
+ "-c",scount,"-s", ssnap,
+ "-m", medium_font, "-b", bold_font, 0);
+ }
+ else {
+ cf.filename = cf.save_file;
+ if (sync_mode) {
+ close(sync_pipe[1]);
+ 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)
+ tail_cap_file(cf.save_file, &cf);
+ sigusr2_received = FALSE;
+ }
+ }
+ }
+ else
+ capture();
}
void
@@ -381,6 +441,8 @@
ld.counts.total = 0;
ld.max = cf.count;
ld.linktype = DLT_NULL;
+ ld.signal_sent = 0;
+ ld.sync_time = 0;
ld.counts.tcp = 0;
ld.counts.udp = 0;
ld.counts.ospf = 0;
@@ -401,6 +463,7 @@
pcap_close(pch);
return;
}
+
ld.linktype = pcap_datalink(pch);
if (cf.cfilter) {
@@ -504,6 +567,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);
@@ -535,6 +603,7 @@
const u_char *pd) {
loop_data *ld = (loop_data *) user;
+ time_t *sync_time= &ld->sync_time, cur_time;
if ((++ld->counts.total >= ld->max) && (ld->max > 0))
{
@@ -543,6 +612,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);
+ cur_time = time(NULL);
+ if (cur_time > *sync_time) {
+ /* sync every seconds */
+ *sync_time = cur_time;
+ fflush((FILE *)ld->pdh);
+ if (sync_mode)
+ write(1, "D", 1);
+ }
+
switch (ld->linktype) {
case DLT_EN10MB :
capture_eth(pd, phdr->caplen, &ld->counts);
@@ -563,4 +641,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 --new-file ethereal/capture.h ethereal-new/capture.h
--- ethereal/capture.h Fri Apr 30 21:52:21 1999
+++ ethereal-new/capture.h Mon May 10 20:30:33 1999
@@ -30,6 +30,8 @@
gint go;
gint max;
gint linktype;
+ gint signal_sent;
+ time_t sync_time;
packet_counts counts;
pcap_dumper_t *pdh;
} loop_data;
diff -u --new-file ethereal/ethereal.c ethereal-new/ethereal.c
--- ethereal/ethereal.c Fri May 7 19:35:30 1999
+++ ethereal-new/ethereal.c Mon May 10 21:27:03 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,20 @@
frame_data *fd;
gint start_capture = 0;
gchar comp_info_str[256];
+gchar *ethereal_path = NULL;
+gchar *medium_font = MONO_MEDIUM_FONT;
+gchar *bold_font = MONO_BOLD_FONT;
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 +291,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 +421,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 +506,17 @@
#endif
}
if (start_capture) {
- if (cf.save_file)
- capture();
- else
- capture();
+ capture();
start_capture = 0;
}
}
+static void
+sigusr2_handler(int sig) {
+ sigusr2_received = 1;
+ signal(SIGUSR2, sigusr2_handler);
+}
+
static void
ethereal_proto_init(void) {
@@ -539,19 +557,23 @@
#endif
gint pl_size = 280, tv_size = 95, bv_size = 75;
gchar *rc_file, *cf_name = NULL;
- gchar *medium_font = MONO_MEDIUM_FONT;
- gchar *bold_font = MONO_BOLD_FONT;
e_prefs *prefs;
gint *col_fmt;
gchar **col_title;
+ ethereal_path = argv[0];
+ sync_pipe[0] = -1;
+ sync_pipe[1] = -1;
+
/* 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 +606,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 +617,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 +639,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 +679,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 --new-file ethereal/file.c ethereal-new/file.c
--- ethereal/file.c Fri Apr 30 21:52:29 1999
+++ ethereal-new/file.c Mon May 10 21:26:00 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);
@@ -318,6 +324,102 @@
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);
+ cf->plist = g_list_first(cf->plist);
+#ifdef USE_ITEM
+ set_menu_sensitivity("/File/Open", TRUE);
+ set_menu_sensitivity("/File/Close", TRUE);
+ set_menu_sensitivity("/File/Save as", TRUE);
+ set_menu_sensitivity("/File/Reload", TRUE);
+ set_menu_sensitivity("/Tools/Capture", TRUE);
+#else
+ set_menu_sensitivity("<Main>/File/Open", TRUE);
+ set_menu_sensitivity("<Main>/File/Close", TRUE);
+ set_menu_sensitivity("<Main>/File/Save as", TRUE);
+ set_menu_sensitivity("<Main>/File/Reload", TRUE);
+ set_menu_sensitivity("<Main>/Tools/Capture", TRUE);
+#endif
+ sync_pipe[0] = -1;
+ return;
+ }
+
+ gtk_clist_freeze(GTK_CLIST(packet_list));
+#ifdef WITH_WIRETAP
+ wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf);
+#else
+ pcap_loop(cf->pfh, 0, pcap_dispatch_cb, (u_char *) cf);
+#endif
+ gtk_clist_thaw(GTK_CLIST(packet_list));
+}
+
+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/Open", FALSE);
+ set_menu_sensitivity("/File/Close", FALSE);
+ set_menu_sensitivity("/File/Reload", FALSE);
+ set_menu_sensitivity("/Tools/Capture", FALSE);
+#else
+ set_menu_sensitivity("<Main>/File/Open", FALSE);
+ set_menu_sensitivity("<Main>/File/Close", FALSE);
+ set_menu_sensitivity("<Main>/File/Reload", FALSE);
+ set_menu_sensitivity("<Main>/Tools/Capture", 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,
+ NULL);
+ }
+ 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
+ close(sync_pipe[0]);
+ sync_pipe[0] = -1;
+ }
+ return err;
+}
+
+
static void
#ifdef WITH_WIRETAP
wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr, int offset,
@@ -328,7 +430,12 @@
frame_data *fdata;
gint i, row;
capture_file *cf = (capture_file *) user;
-
+
+ if (sync_mode && sync_pipe[0] != -1) {
+ /* avoid reentrancy problems and stack overflow */
+ gtk_input_remove(cap_input_id);
+ }
+
while (gtk_events_pending())
gtk_main_iteration();
@@ -342,7 +449,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;
@@ -399,4 +506,15 @@
g_list_append(cf->plist, (gpointer) fdata);
}
cf->plist = cf->plist->next;
+
+ if (sync_mode && sync_pipe[0] != -1) {
+ /* restore pipe handler */
+ cap_input_id = gtk_input_add_full (sync_pipe[0],
+ GDK_INPUT_READ,
+ cap_file_input_cb,
+ NULL,
+ (gpointer) cf,
+ NULL);
+ }
+
}
diff -u --new-file ethereal/file.h ethereal-new/file.h
--- ethereal/file.h Fri Apr 30 21:52:29 1999
+++ ethereal-new/file.h Mon May 10 21:08:50 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 */
@@ -120,6 +121,7 @@
int open_cap_file(char *, capture_file *);
void close_cap_file(capture_file *, void *, guint);
int load_cap_file(char *, capture_file *);
+int tail_cap_file(char *, capture_file *);
/* size_t read_frame_header(capture_file *); */
#endif /* file.h */
- References:
- Re: [ethereal-dev] more real-time capture and full display
- From: Gilbert Ramirez
- Re: [ethereal-dev] more real-time capture and full display
- Prev by Date: Re: [ethereal-dev] more real-time capture and full display
- Next by Date: [ethereal-dev] ethereal packet-nbns.c
- Previous by thread: Re: [ethereal-dev] more real-time capture and full display
- Next by thread: Re: [ethereal-dev] more real-time capture and full display
- Index(es):





