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