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):