1999-09-11 12:38:18 +00:00
|
|
|
/* main.c
|
1998-09-16 03:22:19 +00:00
|
|
|
*
|
1999-12-02 04:30:15 +00:00
|
|
|
* $Id: main.c,v 1.58 1999/12/02 04:30:13 gerald Exp $
|
1998-09-16 02:39:15 +00:00
|
|
|
*
|
|
|
|
* Ethereal - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@zing.org>
|
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
1999-02-19 05:28:38 +00:00
|
|
|
* Richard Sharpe, 13-Feb-1999, added support for initializing structures
|
|
|
|
* needed by dissect routines
|
1998-09-16 02:39:15 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* To do:
|
|
|
|
* - Graphs
|
|
|
|
* - Check for end of packet in dissect_* routines.
|
|
|
|
* - Playback window
|
|
|
|
* - Multiple window support
|
|
|
|
* - Add cut/copy/paste
|
|
|
|
* - Create header parsing routines
|
|
|
|
* - Make byte view scrollbars automatic?
|
|
|
|
* - Make byte view selections more fancy?
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
|
1998-12-17 05:42:33 +00:00
|
|
|
#include <stdlib.h>
|
1998-09-16 02:39:15 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
1999-07-13 02:53:26 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_UNISTD_H
|
1998-09-16 02:39:15 +00:00
|
|
|
#include <unistd.h>
|
1999-07-13 02:53:26 +00:00
|
|
|
#endif
|
|
|
|
|
1999-06-12 07:04:35 +00:00
|
|
|
#include <errno.h>
|
1998-09-16 02:39:15 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
1999-07-13 02:53:26 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_DIRECT_H
|
|
|
|
#include <direct.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_NETINET_IN_H
|
1998-09-16 02:39:15 +00:00
|
|
|
#include <netinet/in.h>
|
1999-07-13 02:53:26 +00:00
|
|
|
#endif
|
|
|
|
|
1999-05-11 18:51:10 +00:00
|
|
|
#include <signal.h>
|
1998-09-16 02:39:15 +00:00
|
|
|
|
1999-01-04 07:39:14 +00:00
|
|
|
#ifdef NEED_SNPRINTF_H
|
|
|
|
# ifdef HAVE_STDARG_H
|
|
|
|
# include <stdarg.h>
|
|
|
|
# else
|
|
|
|
# include <varargs.h>
|
|
|
|
# endif
|
|
|
|
# include "snprintf.h"
|
|
|
|
#endif
|
|
|
|
|
1999-11-29 04:31:05 +00:00
|
|
|
#if defined(HAVE_UCD_SNMP_SNMP_H)
|
1999-11-29 03:07:19 +00:00
|
|
|
#ifdef HAVE_UCD_SNMP_VERSION_H
|
|
|
|
#include <ucd-snmp/version.h>
|
1999-11-29 04:31:05 +00:00
|
|
|
#endif /* HAVE_UCD_SNMP_VERSION_H */
|
|
|
|
#elif defined(HAVE_SNMP_SNMP_H)
|
|
|
|
#ifdef HAVE_SNMP_VERSION_H
|
|
|
|
#include <snmp/version.h>
|
|
|
|
#endif /* HAVE_SNMP_VERSION_H */
|
|
|
|
#endif /* SNMP */
|
1999-11-29 03:07:19 +00:00
|
|
|
|
1999-06-14 21:46:36 +00:00
|
|
|
#ifdef NEED_STRERROR_H
|
|
|
|
#include "strerror.h"
|
|
|
|
#endif
|
|
|
|
|
1999-09-09 02:42:40 +00:00
|
|
|
#include "main.h"
|
1999-06-19 01:14:51 +00:00
|
|
|
#include "timestamp.h"
|
1998-09-16 02:39:15 +00:00
|
|
|
#include "packet.h"
|
1999-02-09 00:35:38 +00:00
|
|
|
#include "capture.h"
|
1999-06-22 22:02:39 +00:00
|
|
|
#include "summary.h"
|
1998-09-16 02:39:15 +00:00
|
|
|
#include "file.h"
|
1999-09-09 02:42:40 +00:00
|
|
|
#include "menu.h"
|
1999-09-09 03:32:03 +00:00
|
|
|
#include "prefs_dlg.h"
|
1998-11-17 04:29:13 +00:00
|
|
|
#include "column.h"
|
1998-09-16 02:39:15 +00:00
|
|
|
#include "print.h"
|
|
|
|
#include "resolv.h"
|
1998-09-17 03:12:28 +00:00
|
|
|
#include "follow.h"
|
|
|
|
#include "util.h"
|
1999-09-09 02:42:40 +00:00
|
|
|
#include "proto_draw.h"
|
1999-07-07 22:52:57 +00:00
|
|
|
#include "dfilter.h"
|
1999-09-09 02:42:40 +00:00
|
|
|
#include "keys.h"
|
1999-04-06 16:24:50 +00:00
|
|
|
|
1998-09-17 03:12:28 +00:00
|
|
|
FILE *data_out_file = NULL;
|
|
|
|
packet_info pi;
|
1998-09-16 02:39:15 +00:00
|
|
|
capture_file cf;
|
|
|
|
GtkWidget *file_sel, *packet_list, *tree_view, *byte_view, *prog_bar,
|
1998-10-12 01:40:57 +00:00
|
|
|
*info_bar;
|
1998-09-16 02:39:15 +00:00
|
|
|
GdkFont *m_r_font, *m_b_font;
|
|
|
|
guint main_ctx, file_ctx;
|
1998-12-27 20:47:53 +00:00
|
|
|
gchar comp_info_str[256];
|
1999-05-11 18:51:10 +00:00
|
|
|
gchar *ethereal_path = NULL;
|
|
|
|
gchar *medium_font = MONO_MEDIUM_FONT;
|
|
|
|
gchar *bold_font = MONO_BOLD_FONT;
|
1999-08-14 19:53:31 +00:00
|
|
|
gchar *last_open_dir = NULL;
|
1998-09-16 02:39:15 +00:00
|
|
|
|
1998-09-27 22:12:47 +00:00
|
|
|
ts_type timestamp_type = RELATIVE;
|
|
|
|
|
1998-12-29 04:05:38 +00:00
|
|
|
GtkStyle *item_style;
|
|
|
|
|
1999-11-19 22:32:00 +00:00
|
|
|
/* Specifies the field currently selected in the GUI protocol tree */
|
|
|
|
field_info *finfo_selected = NULL;
|
1999-06-24 16:25:59 +00:00
|
|
|
|
1999-10-19 04:11:23 +00:00
|
|
|
static void follow_destroy_cb(GtkWidget *win, gpointer data);
|
|
|
|
static void follow_charset_toggle_cb(GtkWidget *w, gpointer parent_w);
|
|
|
|
static void follow_load_text(GtkWidget *text, char *filename, gboolean show_ascii);
|
1999-10-30 06:42:10 +00:00
|
|
|
static void follow_print_stream(GtkWidget *w, gpointer parent_w);
|
1999-11-19 22:32:00 +00:00
|
|
|
static char* hfinfo_numeric_format(header_field_info *hfinfo);
|
1998-10-12 01:40:57 +00:00
|
|
|
|
1998-10-16 01:18:35 +00:00
|
|
|
/* About Ethereal window */
|
|
|
|
void
|
|
|
|
about_ethereal( GtkWidget *w, gpointer data ) {
|
|
|
|
simple_dialog(ESD_TYPE_INFO, NULL,
|
|
|
|
"GNU Ethereal - network protocol analyzer\n"
|
1999-11-29 21:33:36 +00:00
|
|
|
"Version %s (C) 1998-1999 Gerald Combs <gerald@zing.org>\n"
|
1998-12-27 20:47:53 +00:00
|
|
|
"Compiled with %s\n\n"
|
1998-10-16 01:18:35 +00:00
|
|
|
"Contributors:\n"
|
1999-04-06 16:24:50 +00:00
|
|
|
|
|
|
|
"Gilbert Ramirez <gramirez@tivoli.com>\n"
|
1999-04-04 02:49:23 +00:00
|
|
|
"Hannes R. Boehm <hannes@boehm.org>\n"
|
|
|
|
"Mike Hall <mlh@io.com>\n"
|
|
|
|
"Bobo Rajec <bobo@bsp-consulting.sk>\n"
|
|
|
|
"Laurent Deniel <deniel@worldnet.fr>\n"
|
|
|
|
"Don Lafontaine <lafont02@cn.ca>\n"
|
1999-11-11 08:45:34 +00:00
|
|
|
"Guy Harris <guy@alum.mit.edu>\n"
|
1999-04-04 02:49:23 +00:00
|
|
|
"Simon Wilkinson <sxw@dcs.ed.ac.uk>\n"
|
|
|
|
"Joerg Mayer <jmayer@telemation.de>\n"
|
|
|
|
"Martin Maciaszek <fastjack@i-s-o.net>\n"
|
|
|
|
"Didier Jorand <Didier.Jorand@alcatel.fr>\n"
|
1999-04-05 21:54:41 +00:00
|
|
|
"Jun-ichiro itojun Hagino <itojun@iijlab.net>\n"
|
1999-04-06 16:24:50 +00:00
|
|
|
"Richard Sharpe <sharpe@ns.aus.com>\n"
|
1999-05-12 06:04:47 +00:00
|
|
|
"John McDermott <jjm@jkintl.com>\n"
|
1999-06-11 15:30:55 +00:00
|
|
|
"Jeff Jahr <jjahr@shastanets.com>\n"
|
|
|
|
"Brad Robel-Forrest <bradr@watchguard.com>\n"
|
1999-06-11 16:45:02 +00:00
|
|
|
"Ashok Narayanan <ashokn@cisco.com>\n"
|
1999-06-22 22:02:39 +00:00
|
|
|
"Aaron Hillegass <aaron@classmax.com>\n"
|
1999-07-07 00:34:58 +00:00
|
|
|
"Jason Lango <jal@netapp.com>\n"
|
1999-07-08 04:23:28 +00:00
|
|
|
"Johan Feyaerts <Johan.Feyaerts@siemens.atea.be>\n"
|
1999-11-29 22:45:34 +00:00
|
|
|
"Olivier Abad <abad@daba.dhis.net>\n"
|
1999-07-28 23:16:42 +00:00
|
|
|
"Thierry Andry <Thierry.Andry@advalvas.be>\n"
|
1999-08-20 21:57:29 +00:00
|
|
|
"Jeff Foster <jfoste@woodward.com>\n"
|
1999-09-14 08:06:47 +00:00
|
|
|
"Peter Torvals <petertv@xoommail.com>\n"
|
1999-10-11 18:04:48 +00:00
|
|
|
"Christophe Tronche <ch.tronche@computer.org>\n"
|
1999-10-14 01:29:07 +00:00
|
|
|
"Nathan Neulinger <nneul@umr.edu>\n"
|
1999-10-22 06:31:39 +00:00
|
|
|
"Tomislav Vujec <tvujec@carnet.hr>\n"
|
1999-10-24 00:56:11 +00:00
|
|
|
"Kojak <kojak@bigwig.net>\n"
|
1999-10-29 01:04:44 +00:00
|
|
|
"Uwe Girlich <Uwe.Girlich@philosys.de>\n"
|
1999-10-30 06:42:10 +00:00
|
|
|
"Warren Young <tangent@mail.com>\n"
|
1999-11-17 02:17:29 +00:00
|
|
|
"Heikki Vatiainen <hessu@cs.tut.fi>\n"
|
1999-11-23 04:43:44 +00:00
|
|
|
"Greg Hankins <gregh@twoguys.org>\n"
|
1999-04-06 16:24:50 +00:00
|
|
|
|
|
|
|
"\nSee http://ethereal.zing.org for more information",
|
1998-12-27 20:47:53 +00:00
|
|
|
VERSION, comp_info_str);
|
1998-10-16 01:18:35 +00:00
|
|
|
}
|
|
|
|
|
1999-08-17 00:10:22 +00:00
|
|
|
/* Follow the TCP stream, if any, to which the last packet that we called
|
|
|
|
a dissection routine on belongs (this might be the most recently
|
|
|
|
selected packet, or it might be the last packet in the file). */
|
1998-09-17 03:12:28 +00:00
|
|
|
void
|
1998-10-12 01:40:57 +00:00
|
|
|
follow_stream_cb( GtkWidget *w, gpointer data ) {
|
1999-08-18 02:59:05 +00:00
|
|
|
char filename1[128+1];
|
1999-11-26 05:23:40 +00:00
|
|
|
GtkWidget *streamwindow, *box, *text, *vscrollbar, *table,
|
|
|
|
*filter_te;
|
1999-10-30 06:42:10 +00:00
|
|
|
GtkWidget *hbox, *close_bt, *print_bt, *button;
|
1999-08-16 23:58:30 +00:00
|
|
|
int tmp_fd;
|
1999-10-11 06:39:26 +00:00
|
|
|
gchar *follow_filter;
|
1998-12-22 05:52:51 +00:00
|
|
|
|
1998-09-17 03:12:28 +00:00
|
|
|
if( pi.ipproto == 6 ) {
|
|
|
|
/* we got tcp so we can follow */
|
1999-08-16 23:58:30 +00:00
|
|
|
/* Create a temporary file into which to dump the reassembled data
|
|
|
|
from the TCP stream, and set "data_out_file" to refer to it, so
|
1999-08-17 00:10:22 +00:00
|
|
|
that the TCP code will write to it.
|
|
|
|
|
|
|
|
XXX - it might be nicer to just have the TCP code directly
|
|
|
|
append stuff to the text widget for the TCP stream window,
|
|
|
|
if we can arrange that said window not pop up until we're
|
|
|
|
done. */
|
1999-08-18 02:59:05 +00:00
|
|
|
tmp_fd = create_tempfile( filename1, sizeof filename1, "follow");
|
1999-08-16 23:58:30 +00:00
|
|
|
if (tmp_fd == -1) {
|
|
|
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
|
|
|
"Could not create temporary file %s: %s", filename1, strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
data_out_file = fdopen( tmp_fd, "w" );
|
|
|
|
if( data_out_file == NULL ) {
|
|
|
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
|
|
|
"Could not create temporary file %s: %s", filename1, strerror(errno));
|
|
|
|
close(tmp_fd);
|
|
|
|
unlink(filename1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create a new filter that matches all packets in the TCP stream,
|
|
|
|
and set the display filter entry accordingly */
|
1999-07-31 13:55:16 +00:00
|
|
|
reset_tcp_reassembly();
|
1999-10-11 06:39:26 +00:00
|
|
|
follow_filter = build_follow_filter( &pi );
|
1999-08-20 19:43:10 +00:00
|
|
|
|
1999-11-26 05:23:40 +00:00
|
|
|
/* set the display filter entry accordingly */
|
|
|
|
filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
|
|
|
|
gtk_entry_set_text(GTK_ENTRY(filter_te), follow_filter);
|
|
|
|
|
1999-08-16 23:58:30 +00:00
|
|
|
/* Run the display filter so it goes in effect. */
|
1999-10-11 06:39:26 +00:00
|
|
|
filter_packets(&cf, follow_filter);
|
1999-08-20 19:43:10 +00:00
|
|
|
|
1998-09-17 03:12:28 +00:00
|
|
|
/* the data_out_file should now be full of the streams information */
|
|
|
|
fclose( data_out_file );
|
1999-08-20 19:43:10 +00:00
|
|
|
|
1998-09-17 03:12:28 +00:00
|
|
|
/* the filename1 file now has all the text that was in the session */
|
|
|
|
streamwindow = gtk_window_new( GTK_WINDOW_TOPLEVEL);
|
|
|
|
gtk_widget_set_name( streamwindow, "TCP stream window" );
|
1999-11-28 14:50:23 +00:00
|
|
|
|
1999-10-19 04:11:23 +00:00
|
|
|
gtk_signal_connect( GTK_OBJECT(streamwindow), "delete_event",
|
|
|
|
GTK_SIGNAL_FUNC(follow_destroy_cb), NULL);
|
|
|
|
gtk_signal_connect( GTK_OBJECT(streamwindow), "destroy",
|
|
|
|
GTK_SIGNAL_FUNC(follow_destroy_cb), NULL);
|
|
|
|
|
1999-03-23 20:25:50 +00:00
|
|
|
if( incomplete_tcp_stream ) {
|
|
|
|
gtk_window_set_title( GTK_WINDOW(streamwindow),
|
|
|
|
"Contents of TCP stream (incomplete)" );
|
|
|
|
} else {
|
|
|
|
gtk_window_set_title( GTK_WINDOW(streamwindow),
|
|
|
|
"Contents of TCP stream" );
|
|
|
|
}
|
1998-09-17 03:12:28 +00:00
|
|
|
gtk_widget_set_usize( GTK_WIDGET(streamwindow), DEF_WIDTH, DEF_HEIGHT );
|
|
|
|
gtk_container_border_width( GTK_CONTAINER(streamwindow), 2 );
|
1999-08-20 19:43:10 +00:00
|
|
|
|
1998-09-17 03:12:28 +00:00
|
|
|
/* setup the container */
|
|
|
|
box = gtk_vbox_new( FALSE, 0 );
|
|
|
|
gtk_container_add( GTK_CONTAINER(streamwindow), box );
|
|
|
|
gtk_widget_show( box );
|
1999-08-20 19:43:10 +00:00
|
|
|
|
1998-09-17 03:12:28 +00:00
|
|
|
/* set up the table we attach to */
|
|
|
|
table = gtk_table_new( 1, 2, FALSE );
|
|
|
|
gtk_table_set_col_spacing( GTK_TABLE(table), 0, 2);
|
|
|
|
gtk_box_pack_start( GTK_BOX(box), table, TRUE, TRUE, 0 );
|
|
|
|
gtk_widget_show( table );
|
1999-08-20 19:43:10 +00:00
|
|
|
|
1998-09-17 03:12:28 +00:00
|
|
|
/* create a text box */
|
|
|
|
text = gtk_text_new( NULL, NULL );
|
|
|
|
gtk_text_set_editable( GTK_TEXT(text), FALSE);
|
|
|
|
gtk_table_attach( GTK_TABLE(table), text, 0, 1, 0, 1,
|
|
|
|
GTK_EXPAND | GTK_SHRINK | GTK_FILL,
|
|
|
|
GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0 );
|
|
|
|
gtk_widget_show(text);
|
1999-08-20 19:43:10 +00:00
|
|
|
|
1999-10-19 04:11:23 +00:00
|
|
|
/* Create hbox */
|
|
|
|
hbox = gtk_hbox_new( FALSE, 1 );
|
|
|
|
gtk_box_pack_end( GTK_BOX(box), hbox, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show(hbox);
|
|
|
|
|
|
|
|
#define E_FOLLOW_ASCII_KEY "follow_ascii_key"
|
|
|
|
|
|
|
|
/* Create Radio Buttons */
|
|
|
|
button = gtk_radio_button_new_with_label(NULL, "ASCII");
|
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
|
|
|
|
gtk_object_set_data(GTK_OBJECT(streamwindow), E_FOLLOW_ASCII_KEY, button);
|
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
|
|
|
|
gtk_signal_connect(GTK_OBJECT(button), "toggled",
|
|
|
|
GTK_SIGNAL_FUNC(follow_charset_toggle_cb),
|
|
|
|
GTK_OBJECT(streamwindow));
|
|
|
|
gtk_widget_show(button);
|
|
|
|
|
|
|
|
button = gtk_radio_button_new_with_label(
|
|
|
|
gtk_radio_button_group(GTK_RADIO_BUTTON(button)),
|
|
|
|
"EBCDIC");
|
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE);
|
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show(button);
|
|
|
|
|
|
|
|
/* Create Close Button */
|
|
|
|
close_bt = gtk_button_new_with_label("Close");
|
|
|
|
gtk_signal_connect_object(GTK_OBJECT(close_bt), "clicked",
|
|
|
|
GTK_SIGNAL_FUNC(gtk_widget_destroy),
|
|
|
|
GTK_OBJECT(streamwindow));
|
|
|
|
gtk_box_pack_end( GTK_BOX(hbox), close_bt, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show( close_bt );
|
|
|
|
|
1999-10-30 06:42:10 +00:00
|
|
|
/* Create Print Button */
|
|
|
|
print_bt = gtk_button_new_with_label("Print");
|
|
|
|
gtk_signal_connect(GTK_OBJECT(print_bt), "clicked",
|
|
|
|
GTK_SIGNAL_FUNC(follow_print_stream),
|
|
|
|
GTK_OBJECT(streamwindow));
|
|
|
|
gtk_box_pack_end( GTK_BOX(hbox), print_bt, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show( print_bt );
|
1999-10-19 04:11:23 +00:00
|
|
|
|
1998-09-17 03:12:28 +00:00
|
|
|
/* create the scrollbar */
|
|
|
|
vscrollbar = gtk_vscrollbar_new( GTK_TEXT(text)->vadj );
|
|
|
|
gtk_table_attach( GTK_TABLE(table), vscrollbar, 1, 2, 0, 1,
|
|
|
|
GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0 );
|
|
|
|
gtk_widget_show( vscrollbar );
|
|
|
|
gtk_widget_realize( text );
|
1999-08-20 19:43:10 +00:00
|
|
|
|
1999-10-19 04:11:23 +00:00
|
|
|
/* Tuck away the filename and textbox into streamwindow */
|
|
|
|
#define E_FOLLOW_FILENAME_KEY "follow_filename_key"
|
|
|
|
#define E_FOLLOW_TEXT_KEY "follow_text_key"
|
|
|
|
|
|
|
|
gtk_object_set_data(GTK_OBJECT(streamwindow), E_FOLLOW_FILENAME_KEY,
|
|
|
|
g_strdup(filename1));
|
|
|
|
gtk_object_set_data(GTK_OBJECT(streamwindow), E_FOLLOW_TEXT_KEY, text);
|
|
|
|
|
|
|
|
follow_load_text(text, filename1, TRUE);
|
|
|
|
|
|
|
|
data_out_file = NULL;
|
|
|
|
gtk_widget_show( streamwindow );
|
|
|
|
} else {
|
|
|
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
|
|
|
"Error following stream. Please make\n"
|
|
|
|
"sure you have a TCP packet selected.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The destroy call back has the responsibility of
|
|
|
|
* unlinking the temporary file */
|
|
|
|
static void
|
|
|
|
follow_destroy_cb(GtkWidget *win, gpointer data)
|
|
|
|
{
|
|
|
|
char *filename;
|
|
|
|
|
|
|
|
filename = (char*) gtk_object_get_data(GTK_OBJECT(win),
|
|
|
|
E_FOLLOW_FILENAME_KEY);
|
|
|
|
g_assert(filename);
|
|
|
|
|
|
|
|
unlink(filename);
|
|
|
|
gtk_widget_destroy(win);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handles the ASCII/EBCDIC toggling */
|
|
|
|
static void
|
|
|
|
follow_charset_toggle_cb(GtkWidget *w, gpointer parent_w)
|
|
|
|
{
|
|
|
|
gboolean show_ascii = FALSE;
|
|
|
|
GtkWidget *button, *text;
|
|
|
|
char *filename;
|
|
|
|
|
|
|
|
|
|
|
|
button = (GtkWidget*) gtk_object_get_data(GTK_OBJECT(parent_w),
|
|
|
|
E_FOLLOW_ASCII_KEY);
|
|
|
|
text = (GtkWidget*) gtk_object_get_data(GTK_OBJECT(parent_w),
|
|
|
|
E_FOLLOW_TEXT_KEY);
|
|
|
|
filename = (char*) gtk_object_get_data(GTK_OBJECT(parent_w),
|
|
|
|
E_FOLLOW_FILENAME_KEY);
|
|
|
|
|
|
|
|
g_assert(button);
|
|
|
|
g_assert(text);
|
|
|
|
g_assert(filename);
|
|
|
|
|
|
|
|
if (GTK_TOGGLE_BUTTON(button)->active)
|
|
|
|
show_ascii = TRUE;
|
|
|
|
|
|
|
|
follow_load_text(text, filename, show_ascii);
|
|
|
|
}
|
|
|
|
|
1999-10-30 06:42:10 +00:00
|
|
|
static void follow_print_stream(GtkWidget *w, gpointer parent_w)
|
|
|
|
{
|
|
|
|
FILE *fh = NULL;
|
|
|
|
int to_file = -1;
|
|
|
|
char* print_dest = NULL;
|
|
|
|
char* filename;
|
|
|
|
|
|
|
|
switch (prefs.pr_dest) {
|
|
|
|
case PR_DEST_CMD:
|
|
|
|
print_dest = prefs.pr_cmd;
|
|
|
|
to_file = FALSE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PR_DEST_FILE:
|
|
|
|
print_dest = prefs.pr_file;
|
|
|
|
to_file = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (print_dest != NULL) {
|
|
|
|
fh = open_print_dest(to_file, print_dest);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fh == NULL) {
|
|
|
|
switch (to_file) {
|
|
|
|
case -1:
|
|
|
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
|
|
|
"Couldn't figure out where to send the print "
|
|
|
|
"job. Check your preferences.");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FALSE:
|
|
|
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
|
|
|
"Couldn't run print command %s.", prefs.pr_cmd);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRUE:
|
|
|
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
|
|
|
file_write_error_message(errno),
|
|
|
|
prefs.pr_file);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
filename = (char*) gtk_object_get_data(GTK_OBJECT(parent_w),
|
|
|
|
E_FOLLOW_FILENAME_KEY);
|
|
|
|
|
|
|
|
if (filename != NULL) {
|
|
|
|
print_preamble(fh);
|
|
|
|
print_file(fh, filename);
|
|
|
|
print_finale(fh);
|
|
|
|
close_print_dest(to_file, fh);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
simple_dialog(ESD_TYPE_WARN, NULL, "Could not find data to print.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-11-28 03:35:20 +00:00
|
|
|
#define FLT_BUF_SIZE 1024
|
1999-10-19 04:11:23 +00:00
|
|
|
static void
|
|
|
|
follow_load_text(GtkWidget *text, char *filename, gboolean show_ascii)
|
|
|
|
{
|
1999-12-02 04:30:15 +00:00
|
|
|
int bytes_already, bcount;
|
|
|
|
tcp_stream_chunk sc;
|
|
|
|
guint32 client_addr = 0;
|
|
|
|
guint16 client_port = 0;
|
|
|
|
|
|
|
|
/* Delete any info already in text box */
|
|
|
|
bytes_already = gtk_text_get_length(GTK_TEXT(text));
|
|
|
|
if (bytes_already > 0) {
|
|
|
|
gtk_text_set_point(GTK_TEXT(text), 0);
|
|
|
|
gtk_text_forward_delete(GTK_TEXT(text), bytes_already);
|
|
|
|
}
|
1999-10-19 04:11:23 +00:00
|
|
|
|
1998-09-17 03:12:28 +00:00
|
|
|
/* stop the updates while we fill the text box */
|
|
|
|
gtk_text_freeze( GTK_TEXT(text) );
|
1999-10-19 04:11:23 +00:00
|
|
|
data_out_file = fopen( filename, "r" );
|
1998-09-17 03:12:28 +00:00
|
|
|
if( data_out_file ) {
|
1999-11-28 03:35:20 +00:00
|
|
|
char buffer[FLT_BUF_SIZE];
|
1998-09-17 03:12:28 +00:00
|
|
|
int nchars;
|
1999-11-28 03:35:20 +00:00
|
|
|
while(fread(&sc.src_addr, 1, sizeof(sc), data_out_file)) {
|
|
|
|
if (client_addr == 0) {
|
|
|
|
client_addr = sc.src_addr;
|
|
|
|
client_port = sc.src_port;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (sc.dlen > 0) {
|
|
|
|
bcount = (sc.dlen < FLT_BUF_SIZE) ? sc.dlen : FLT_BUF_SIZE;
|
|
|
|
nchars = fread( buffer, 1, bcount, data_out_file );
|
|
|
|
if (nchars == 0)
|
|
|
|
break;
|
|
|
|
sc.dlen -= bcount;
|
|
|
|
if (show_ascii) {
|
|
|
|
/* If our native arch is EBCDIC, call:
|
|
|
|
* ASCII_TO_EBCDIC(buffer, nchars);
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* If our native arch is ASCII, call: */
|
|
|
|
EBCDIC_to_ASCII(buffer, nchars);
|
|
|
|
}
|
|
|
|
if (client_addr == sc.src_addr && client_port == sc.src_port)
|
1999-12-02 04:30:15 +00:00
|
|
|
gtk_text_insert( GTK_TEXT(text), m_r_font, &prefs.st_client_fg,
|
|
|
|
&prefs.st_client_bg, buffer, nchars );
|
1999-11-28 03:35:20 +00:00
|
|
|
else
|
1999-12-02 04:30:15 +00:00
|
|
|
gtk_text_insert( GTK_TEXT(text), m_r_font, &prefs.st_server_fg,
|
|
|
|
&prefs.st_server_bg, buffer, nchars );
|
1998-09-17 03:12:28 +00:00
|
|
|
}
|
|
|
|
}
|
1999-08-17 00:10:22 +00:00
|
|
|
if( ferror( data_out_file ) ) {
|
|
|
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
1999-10-19 04:11:23 +00:00
|
|
|
"Error reading temporary file %s: %s", filename, strerror(errno));
|
1999-08-17 00:10:22 +00:00
|
|
|
}
|
1998-09-17 03:12:28 +00:00
|
|
|
fclose( data_out_file );
|
1999-08-16 23:58:30 +00:00
|
|
|
} else {
|
|
|
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
1999-10-19 04:11:23 +00:00
|
|
|
"Could not open temporary file %s: %s", filename, strerror(errno));
|
1998-09-17 03:12:28 +00:00
|
|
|
}
|
|
|
|
gtk_text_thaw( GTK_TEXT(text) );
|
|
|
|
}
|
|
|
|
|
1999-06-24 16:25:59 +00:00
|
|
|
/* Match selected byte pattern */
|
|
|
|
void
|
|
|
|
match_selected_cb(GtkWidget *w, gpointer data)
|
|
|
|
{
|
1999-11-19 22:32:00 +00:00
|
|
|
char *buf;
|
1999-11-26 05:23:40 +00:00
|
|
|
GtkWidget *filter_te;
|
1999-11-19 22:32:00 +00:00
|
|
|
char *ptr, *format, *stringified;
|
|
|
|
int i, dfilter_len, abbrev_len;
|
|
|
|
guint8 *c;
|
|
|
|
header_field_info *hfinfo;
|
1999-06-24 16:25:59 +00:00
|
|
|
|
1999-08-04 03:37:45 +00:00
|
|
|
filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
|
1999-06-24 16:25:59 +00:00
|
|
|
|
1999-11-19 22:32:00 +00:00
|
|
|
if (!finfo_selected) {
|
1999-06-24 16:25:59 +00:00
|
|
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
|
|
|
"Error determining selected bytes. Please make\n"
|
|
|
|
"sure you have selected a field within the tree\n"
|
|
|
|
"view to be matched.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1999-11-19 22:32:00 +00:00
|
|
|
hfinfo = finfo_selected->hfinfo;
|
|
|
|
g_assert(hfinfo);
|
|
|
|
abbrev_len = strlen(hfinfo->abbrev);
|
|
|
|
|
|
|
|
switch(hfinfo->type) {
|
|
|
|
|
|
|
|
case FT_BOOLEAN:
|
|
|
|
dfilter_len = abbrev_len + 2;
|
|
|
|
buf = g_malloc0(dfilter_len);
|
|
|
|
snprintf(buf, dfilter_len, "%s%s", finfo_selected->value.numeric ? "" : "!",
|
|
|
|
hfinfo->abbrev);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_UINT8:
|
|
|
|
case FT_UINT16:
|
|
|
|
case FT_UINT24:
|
|
|
|
case FT_UINT32:
|
|
|
|
case FT_INT8:
|
|
|
|
case FT_INT16:
|
|
|
|
case FT_INT24:
|
|
|
|
case FT_INT32:
|
|
|
|
dfilter_len = abbrev_len + 20;
|
|
|
|
buf = g_malloc0(dfilter_len);
|
|
|
|
format = hfinfo_numeric_format(hfinfo);
|
|
|
|
snprintf(buf, dfilter_len, format, hfinfo->abbrev, finfo_selected->value.numeric);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_IPv4:
|
1999-11-19 23:01:26 +00:00
|
|
|
dfilter_len = abbrev_len + 4 + 15 + 1;
|
1999-11-19 22:32:00 +00:00
|
|
|
buf = g_malloc0(dfilter_len);
|
1999-11-19 23:01:26 +00:00
|
|
|
snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
|
|
|
|
ipv4_addr_str(&(finfo_selected->value.ipv4)));
|
1999-11-19 22:32:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_IPXNET:
|
|
|
|
dfilter_len = abbrev_len + 15;
|
|
|
|
buf = g_malloc0(dfilter_len);
|
|
|
|
snprintf(buf, dfilter_len, "%s == 0x%08x", hfinfo->abbrev,
|
|
|
|
finfo_selected->value.numeric);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_IPv6:
|
|
|
|
stringified = ip6_to_str((struct e_in6_addr*) &(finfo_selected->value.ipv6));
|
|
|
|
dfilter_len = abbrev_len + 4 + strlen(stringified) + 1;
|
|
|
|
buf = g_malloc0(dfilter_len);
|
|
|
|
snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
|
|
|
|
stringified);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_DOUBLE:
|
|
|
|
dfilter_len = abbrev_len + 30;
|
|
|
|
buf = g_malloc0(dfilter_len);
|
|
|
|
snprintf(buf, dfilter_len, "%s == %f", hfinfo->abbrev,
|
|
|
|
finfo_selected->value.floating);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_ETHER:
|
|
|
|
dfilter_len = abbrev_len + 22;
|
|
|
|
buf = g_malloc0(dfilter_len);
|
1999-11-26 05:23:40 +00:00
|
|
|
snprintf(buf, dfilter_len, "%s == %s",
|
1999-11-19 22:32:00 +00:00
|
|
|
hfinfo->abbrev,
|
1999-11-26 05:23:40 +00:00
|
|
|
ether_to_str(finfo_selected->value.ether));
|
1999-11-19 22:32:00 +00:00
|
|
|
break;
|
|
|
|
#if 0
|
|
|
|
|
|
|
|
case FT_ABSOLUTE_TIME:
|
|
|
|
case FT_RELATIVE_TIME:
|
|
|
|
memcpy(&fi->value.time, va_arg(ap, struct timeval*),
|
|
|
|
sizeof(struct timeval));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_STRING:
|
|
|
|
/* This g_strdup'ed memory is freed in proto_tree_free_node() */
|
|
|
|
fi->value.string = g_strdup(va_arg(ap, char*));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FT_TEXT_ONLY:
|
|
|
|
; /* nothing */
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
c = cf.pd + finfo_selected->start;
|
|
|
|
buf = g_malloc0(32 + finfo_selected->length * 3);
|
|
|
|
ptr = buf;
|
|
|
|
|
1999-11-26 05:23:40 +00:00
|
|
|
sprintf(ptr, "frame[%d] == ", finfo_selected->start);
|
1999-11-19 22:32:00 +00:00
|
|
|
ptr = buf+strlen(buf);
|
|
|
|
|
|
|
|
if (finfo_selected->length == 1) {
|
|
|
|
sprintf(ptr, "0x%02x", *c++);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (i=0;i<finfo_selected->length; i++) {
|
|
|
|
if (i == 0 ) {
|
|
|
|
sprintf(ptr, "%02x", *c++);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sprintf(ptr, ":%02x", *c++);
|
|
|
|
}
|
|
|
|
ptr = buf+strlen(buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
1999-06-24 16:25:59 +00:00
|
|
|
|
|
|
|
/* create a new one and set the display filter entry accordingly */
|
1999-11-26 05:23:40 +00:00
|
|
|
gtk_entry_set_text(GTK_ENTRY(filter_te), buf);
|
|
|
|
|
1999-07-31 18:26:07 +00:00
|
|
|
/* Run the display filter so it goes in effect. */
|
1999-10-11 06:39:26 +00:00
|
|
|
filter_packets(&cf, buf);
|
1999-11-19 22:32:00 +00:00
|
|
|
|
|
|
|
/* Don't g_free(buf) here. filter_packets() will do it the next time it's called */
|
|
|
|
}
|
|
|
|
|
|
|
|
static char*
|
|
|
|
hfinfo_numeric_format(header_field_info *hfinfo)
|
|
|
|
{
|
|
|
|
char *format = NULL;
|
|
|
|
|
|
|
|
/* Pick the proper format string */
|
|
|
|
switch(hfinfo->display) {
|
|
|
|
case BASE_DEC:
|
|
|
|
case BASE_NONE:
|
|
|
|
case BASE_OCT: /* I'm lazy */
|
|
|
|
case BASE_BIN: /* I'm lazy */
|
|
|
|
switch(hfinfo->type) {
|
|
|
|
case FT_UINT8:
|
|
|
|
case FT_UINT16:
|
|
|
|
case FT_UINT24:
|
|
|
|
case FT_UINT32:
|
|
|
|
format = "%s == %u";
|
|
|
|
break;
|
|
|
|
case FT_INT8:
|
|
|
|
case FT_INT16:
|
|
|
|
case FT_INT24:
|
|
|
|
case FT_INT32:
|
|
|
|
format = "%s == %d";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case BASE_HEX:
|
|
|
|
switch(hfinfo->type) {
|
|
|
|
case FT_UINT8:
|
|
|
|
format = "%s == 0x%02x";
|
|
|
|
break;
|
|
|
|
case FT_UINT16:
|
|
|
|
format = "%s == 0x%04x";
|
|
|
|
break;
|
|
|
|
case FT_UINT24:
|
|
|
|
format = "%s == 0x%06x";
|
|
|
|
break;
|
|
|
|
case FT_UINT32:
|
|
|
|
format = "%s == 0x%08x";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
;
|
|
|
|
}
|
|
|
|
return format;
|
1999-06-24 16:25:59 +00:00
|
|
|
}
|
|
|
|
|
1999-11-19 22:32:00 +00:00
|
|
|
|
1999-07-11 08:40:52 +00:00
|
|
|
/* Run the current display filter on the current packet set, and
|
|
|
|
redisplay. */
|
|
|
|
static void
|
1999-08-13 23:47:43 +00:00
|
|
|
filter_activate_cb(GtkWidget *w, gpointer data)
|
|
|
|
{
|
1999-11-25 18:02:25 +00:00
|
|
|
GtkCombo *filter_cm = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_CM_KEY);
|
|
|
|
GList *filter_list = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_FL_KEY);
|
|
|
|
GList *li, *nl = NULL;
|
|
|
|
gboolean add_filter = TRUE;
|
|
|
|
|
1999-08-13 23:47:43 +00:00
|
|
|
char *s = gtk_entry_get_text(GTK_ENTRY(w));
|
1999-11-25 18:02:25 +00:00
|
|
|
|
|
|
|
/* GtkCombos don't let us get at their list contents easily, so we maintain
|
|
|
|
our own filter list, and feed it to gtk_combo_set_popdown_strings when
|
|
|
|
a new filter is added. */
|
|
|
|
if (filter_packets(&cf, g_strdup(s))) {
|
|
|
|
li = g_list_first(filter_list);
|
|
|
|
while (li) {
|
|
|
|
if (li->data && strcmp(s, li->data) == 0)
|
|
|
|
add_filter = FALSE;
|
|
|
|
li = li->next;
|
|
|
|
}
|
1999-08-13 23:47:43 +00:00
|
|
|
|
1999-11-25 18:02:25 +00:00
|
|
|
if (add_filter) {
|
|
|
|
filter_list = g_list_append(filter_list, g_strdup(s));
|
|
|
|
li = g_list_first(filter_list);
|
|
|
|
while (li) {
|
|
|
|
nl = g_list_append(nl, strdup(li->data));
|
|
|
|
li = li->next;
|
|
|
|
}
|
|
|
|
gtk_combo_set_popdown_strings(filter_cm, nl);
|
|
|
|
gtk_entry_set_text(GTK_ENTRY(filter_cm->entry), g_list_last(filter_list)->data);
|
|
|
|
}
|
|
|
|
}
|
1999-07-11 08:40:52 +00:00
|
|
|
}
|
|
|
|
|
1999-11-21 15:06:07 +00:00
|
|
|
/* redisplay with no display filter */
|
|
|
|
static void
|
|
|
|
filter_reset_cb(GtkWidget *w, gpointer data)
|
|
|
|
{
|
|
|
|
GtkWidget *filter_te = NULL;
|
|
|
|
|
|
|
|
if ((filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY))) {
|
|
|
|
gtk_entry_set_text(GTK_ENTRY(filter_te), "");
|
|
|
|
}
|
|
|
|
|
|
|
|
filter_packets(&cf, NULL);
|
|
|
|
}
|
|
|
|
|
1998-09-16 02:39:15 +00:00
|
|
|
/* What to do when a list item is selected/unselected */
|
|
|
|
void
|
|
|
|
packet_list_select_cb(GtkWidget *w, gint row, gint col, gpointer evt) {
|
1998-10-16 01:18:35 +00:00
|
|
|
|
1999-07-13 07:14:18 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
1999-05-11 18:51:10 +00:00
|
|
|
if (!sync_mode) {
|
1999-07-13 02:53:26 +00:00
|
|
|
#endif
|
1999-07-11 08:40:52 +00:00
|
|
|
if (cf.wth)
|
|
|
|
return;
|
1999-07-13 07:14:18 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
1999-05-11 18:51:10 +00:00
|
|
|
}
|
1999-07-13 02:53:26 +00:00
|
|
|
#endif
|
1998-09-17 03:12:28 +00:00
|
|
|
blank_packetinfo();
|
1999-07-24 03:22:50 +00:00
|
|
|
select_packet(&cf, row);
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
packet_list_unselect_cb(GtkWidget *w, gint row, gint col, gpointer evt) {
|
Have "close_cap_file()" disable all menu items that make sense only if
you have a capture.
Leave the job of enabling and disabling menu items that make sense only
if you have a capture (except for "File/Save" and "File/Save As...", for
now) up to "load_cap_file()", "close_cap_file()", and the like - don't
scatter that stuff throughout the code.
Disable "File/Print Packet" if no packet is selected; enable it only if
a packet is selected.
If there's a selected packet, and a display filter is run:
if the selected packet passed the filter, re-select it;
if the selected packet didn't pass the filter, un-select it.
If we've opened a live "pcap" capture, but can't do the capture because
we can't get the netmask info, or can't parse the capture filter string,
or can't install the filter, close the live capture and the dump and
delete the dump file.
If we failed to open a live "pcap" capture, don't try to read the
capture file - it doesn't exist.
svn path=/trunk/; revision=384
1999-07-24 02:42:52 +00:00
|
|
|
unselect_packet(&cf);
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-08-15 07:28:23 +00:00
|
|
|
tree_view_cb(GtkWidget *w, gpointer data) {
|
1999-06-24 16:25:59 +00:00
|
|
|
|
1999-11-15 22:52:03 +00:00
|
|
|
field_info *finfo;
|
1999-11-19 22:32:00 +00:00
|
|
|
int tree_selected_start = -1;
|
|
|
|
int tree_selected_len = -1;
|
1998-09-16 02:39:15 +00:00
|
|
|
|
|
|
|
if (GTK_TREE(w)->selection) {
|
1999-11-15 22:52:03 +00:00
|
|
|
finfo =
|
1999-11-16 08:00:20 +00:00
|
|
|
gtk_object_get_data(GTK_OBJECT(GTK_TREE(w)->selection->data),
|
1999-11-15 22:52:03 +00:00
|
|
|
E_TREEINFO_FIELD_INFO_KEY);
|
|
|
|
g_assert(finfo);
|
1999-11-19 22:32:00 +00:00
|
|
|
finfo_selected = finfo;
|
1999-11-15 22:52:03 +00:00
|
|
|
tree_selected_start = finfo->start;
|
|
|
|
tree_selected_len = finfo->length;
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)));
|
1999-11-06 06:28:07 +00:00
|
|
|
packet_hex_print(GTK_TEXT(byte_view), cf.pd, cf.current_frame->cap_len,
|
1999-11-22 06:24:56 +00:00
|
|
|
tree_selected_start, tree_selected_len,
|
|
|
|
cf.current_frame->encoding);
|
1999-06-24 16:25:59 +00:00
|
|
|
|
1998-09-16 02:39:15 +00:00
|
|
|
gtk_text_thaw(GTK_TEXT(byte_view));
|
|
|
|
}
|
|
|
|
|
1999-09-11 12:38:18 +00:00
|
|
|
void collapse_all_cb(GtkWidget *widget, gpointer data) {
|
|
|
|
if (cf.protocol_tree)
|
|
|
|
collapse_all_tree(cf.protocol_tree, tree_view);
|
|
|
|
}
|
|
|
|
|
|
|
|
void expand_all_cb(GtkWidget *widget, gpointer data) {
|
|
|
|
if (cf.protocol_tree)
|
|
|
|
expand_all_tree(cf.protocol_tree, tree_view);
|
|
|
|
}
|
|
|
|
|
1998-09-16 02:39:15 +00:00
|
|
|
void
|
|
|
|
file_quit_cmd_cb (GtkWidget *widget, gpointer data) {
|
Allow the user to save either all of the current capture, or only the
packets that are currently being displayed from that capture.
Centralize the code to control whether "File:Save" and "File:Save As"
are enabled (and *always* have "File:Save As" enabled if you have a
capture; "File:Save" is enabled only if you have a live capture you've
not yet saved, although it does the same thing as "File:Save As").
Have the "save_file" member of a "capture_file" structure represent
*only* the file currently being *written* to by a capture, and, if there
is no capture currently in progress, have it be NULL; the name of the
file currently being *displayed" is in the "filename" member, and an
"is_tempfile" member indicates whether it's a temporary file for a live
capture or not.
Have "close_cap_file()" delete the current capture file if it's a
temporary capture file that hasn't been saved (in its entirety - saving
selected frames doesn't count). Do the same (if there *is* a current
capture file) when exiting.
The "Ready to load or capture" message is the only statusbar message in
the "main" context; "close_cap_file()" should never pop it, it should
only pop whatever message exists in the "file" context, and thus has no
need to take, as an argument, the context for the message it should pop.
Update the man page to reflect the new behavior of "File:Save" and
"File:Save As", and to reflect recent changes to "Display:Match Selected".
svn path=/trunk/; revision=1170
1999-11-30 20:50:15 +00:00
|
|
|
/* If we have a capture file open, and it's a temporary file,
|
|
|
|
unlink it. */
|
|
|
|
if (cf.filename != NULL && cf.is_tempfile)
|
|
|
|
unlink(cf.filename);
|
1998-09-16 02:39:15 +00:00
|
|
|
gtk_exit(0);
|
|
|
|
}
|
|
|
|
|
1999-07-07 22:52:57 +00:00
|
|
|
/* call initialization routines at program startup time */
|
1999-02-19 05:28:38 +00:00
|
|
|
static void
|
|
|
|
ethereal_proto_init(void) {
|
1999-10-29 01:04:44 +00:00
|
|
|
init_dissect_rpc();
|
1999-07-07 22:52:57 +00:00
|
|
|
proto_init();
|
1999-02-19 05:28:38 +00:00
|
|
|
init_dissect_udp();
|
1999-07-07 22:52:57 +00:00
|
|
|
dfilter_init();
|
1999-02-19 05:28:38 +00:00
|
|
|
}
|
|
|
|
|
1999-08-26 06:20:50 +00:00
|
|
|
static void
|
|
|
|
ethereal_proto_cleanup(void) {
|
|
|
|
proto_cleanup();
|
|
|
|
dfilter_cleanup();
|
|
|
|
}
|
|
|
|
|
Improve the alert boxes put up for file open/read/write errors. (Some
influence came from
http://developer.apple.com/techpubs/mac/HIGuidelines/HIGuidelines-232.html
which has a section on dialog box and alert box messages. However,
we're largely dealing with technoids, not with The Rest Of Us, so I
didn't go as far as one perhaps should.)
Unfortunately, it looks like it's a bit more work to arrange that, if
you give a bad file name to the "-r" flag, the dialog box pop up only
*after* the main window pops up - it has the annoying habit of popping
up *before* the main window pops up, and sometimes getting *obscured* by
it, when I do that. The removal of the dialog box stuff from
"load_cap_file()" was intended to facilitate that work. (It might also
be nice if, when an open from the "File/Open" menu item fails, we keep
the file selection box open, and give the user a chance to correct
typos, choose another file name, etc.)
svn path=/trunk/; revision=310
1999-06-12 09:10:20 +00:00
|
|
|
static void
|
1998-09-16 02:39:15 +00:00
|
|
|
print_usage(void) {
|
|
|
|
|
1998-12-27 20:47:53 +00:00
|
|
|
fprintf(stderr, "This is GNU %s %s, compiled with %s\n", PACKAGE,
|
1999-05-11 18:51:10 +00:00
|
|
|
VERSION, comp_info_str);
|
1999-10-02 20:00:46 +00:00
|
|
|
fprintf(stderr, "%s [-vh] [-kQS] [-b <bold font>] [-B <byte view height>] [-c count]\n",
|
1998-09-16 02:39:15 +00:00
|
|
|
PACKAGE);
|
1999-10-02 20:00:46 +00:00
|
|
|
fprintf(stderr, " [-f <filter expression>] [-i interface] [-m <medium font>] [-n]\n");
|
|
|
|
fprintf(stderr, " [-P <packet list height>] [-r infile] [-s snaplen]\n");
|
|
|
|
fprintf(stderr, " [-t <time stamp format>] [-T <tree view height>] [-w savefile] \n");
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
|
|
|
|
1998-11-17 04:29:13 +00:00
|
|
|
/* And now our feature presentation... [ fade to music ] */
|
1998-09-16 02:39:15 +00:00
|
|
|
int
|
|
|
|
main(int argc, char *argv[])
|
|
|
|
{
|
1999-10-21 21:47:08 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
char *command_name;
|
|
|
|
#endif
|
|
|
|
char *s;
|
1999-07-13 02:53:26 +00:00
|
|
|
int i;
|
|
|
|
#ifndef WIN32
|
|
|
|
int opt;
|
1998-09-16 02:39:15 +00:00
|
|
|
extern char *optarg;
|
1999-11-04 21:04:35 +00:00
|
|
|
#endif
|
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
extern char pcap_version[];
|
1999-07-13 02:53:26 +00:00
|
|
|
#endif
|
1999-06-12 07:04:35 +00:00
|
|
|
char *pf_path;
|
|
|
|
int pf_open_errno = 0;
|
1999-06-15 03:46:46 +00:00
|
|
|
int err;
|
Add a new global flag "capture_child", which is TRUE if we're a child
process for a sync mode or fork mode capture.
Have that flag control whether we do things that *only* the parent or
*only* the child should do, rather than basing it solely on the setting
of "sync_mode" or "fork_mode" (or, in the case of stuff done in the
child process either in sync mode or fork mode, rather than basing it on
the setting of those flags at all).
Split "do_capture()" into a "run_capture()" routine that starts a
capture (possibly by forking off and execing a child process, if we're
supposed to do sync mode or fork mode captures), and that assumes the
file to which the capture is to write has already been opened and that
"cf.save_file_fd" is the file descriptor for that file, and a
"do_capture()" routine that creates a temporary file, getting an FD for
it, and calls "run_capture()".
Use "run_capture()", rather than "capture()", for "-k" captures, so that
it'll do the capture in a child process if "-S" or "-F" was specified
("do_capture()" won't do because "-k" captures should write to the file
specified by the "-w" flag, not some random temporary file).
For child process captures, however, just use "capture()" - the child
process shouldn't itself fork off a child if we're in sync or fork mode,
and should just write to the file whose file descriptor was specified by
the "-W" flag on the command line.
All this allows you to do "ethereal -S -w <file> -i <interface> -k" to
start a sync mode capture from the command line.
svn path=/trunk/; revision=740
1999-09-30 06:50:01 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
gboolean start_capture = FALSE;
|
1999-10-02 06:26:53 +00:00
|
|
|
gchar *save_file = NULL;
|
Add a new global flag "capture_child", which is TRUE if we're a child
process for a sync mode or fork mode capture.
Have that flag control whether we do things that *only* the parent or
*only* the child should do, rather than basing it solely on the setting
of "sync_mode" or "fork_mode" (or, in the case of stuff done in the
child process either in sync mode or fork mode, rather than basing it on
the setting of those flags at all).
Split "do_capture()" into a "run_capture()" routine that starts a
capture (possibly by forking off and execing a child process, if we're
supposed to do sync mode or fork mode captures), and that assumes the
file to which the capture is to write has already been opened and that
"cf.save_file_fd" is the file descriptor for that file, and a
"do_capture()" routine that creates a temporary file, getting an FD for
it, and calls "run_capture()".
Use "run_capture()", rather than "capture()", for "-k" captures, so that
it'll do the capture in a child process if "-S" or "-F" was specified
("do_capture()" won't do because "-k" captures should write to the file
specified by the "-w" flag, not some random temporary file).
For child process captures, however, just use "capture()" - the child
process shouldn't itself fork off a child if we're in sync or fork mode,
and should just write to the file whose file descriptor was specified by
the "-W" flag on the command line.
All this allows you to do "ethereal -S -w <file> -i <interface> -k" to
start a sync mode capture from the command line.
svn path=/trunk/; revision=740
1999-09-30 06:50:01 +00:00
|
|
|
#endif
|
1998-09-16 02:39:15 +00:00
|
|
|
GtkWidget *window, *main_vbox, *menubar, *u_pane, *l_pane,
|
|
|
|
*bv_table, *bv_hscroll, *bv_vscroll, *stat_hbox,
|
1999-11-25 18:02:25 +00:00
|
|
|
*tv_scrollw, *filter_bt, *filter_cm, *filter_te,
|
|
|
|
*filter_reset;
|
|
|
|
GList *filter_list = NULL;
|
1999-07-22 21:14:13 +00:00
|
|
|
GtkStyle *pl_style;
|
1999-08-10 07:16:47 +00:00
|
|
|
GtkAccelGroup *accel;
|
|
|
|
GtkWidget *packet_sw;
|
1998-11-18 03:01:44 +00:00
|
|
|
gint pl_size = 280, tv_size = 95, bv_size = 75;
|
1999-08-10 07:16:47 +00:00
|
|
|
gchar *rc_file, *cf_name = NULL, *rfilter = NULL;
|
1999-08-15 19:18:46 +00:00
|
|
|
dfilter *rfcode = NULL;
|
|
|
|
gboolean rfilter_parse_failed = FALSE;
|
1998-11-17 04:29:13 +00:00
|
|
|
e_prefs *prefs;
|
1998-09-16 02:39:15 +00:00
|
|
|
|
1999-05-11 18:51:10 +00:00
|
|
|
ethereal_path = argv[0];
|
|
|
|
|
1999-10-21 21:47:08 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
1999-08-05 18:20:41 +00:00
|
|
|
command_name = strrchr(ethereal_path, '/');
|
Have Ethereal, when invoked as "ethereal-dump-fields", dump out a
glossary of display filter symbols, just as it does with "-G", except
that, as it can discover that it was so invoked before even looking at
the command-line arguments, it needn't even bother calling "gtk_init()"
to process those command-line arguments GTK+ cares about, and thus
needn't do any X stuff at all when so invoked.
That allows Ethereal to be built in an environment where you don't have
an X server, and, if your connection to your X server is slow, allows
you to built it faster.
Get rid of the "-G" flag, as it had only a somewhat specialized use.
svn path=/trunk/; revision=444
1999-08-05 06:34:43 +00:00
|
|
|
if (command_name == NULL)
|
|
|
|
command_name = ethereal_path;
|
|
|
|
else
|
|
|
|
command_name++;
|
1999-10-21 21:47:08 +00:00
|
|
|
/* Set "capture_child" to indicate whether this is going to be a child
|
|
|
|
process for a "-S" capture. */
|
|
|
|
capture_child = (strcmp(command_name, CHILD_NAME) == 0);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* If invoked with the "-G" flag, we dump out a glossary of
|
|
|
|
display filter symbols.
|
|
|
|
|
|
|
|
We must do this before calling "gtk_init()", because "gtk_init()"
|
|
|
|
tries to open an X display, and we don't want to have to do any X
|
|
|
|
stuff just to do a build.
|
|
|
|
|
|
|
|
Given that we call "gtk_init()" before doing the regular argument
|
|
|
|
list processing, so that it can handle X and GTK+ arguments and
|
|
|
|
remove them from the list at which we look, this means we must do
|
|
|
|
this before doing the regular argument list processing, as well.
|
|
|
|
|
|
|
|
This means that:
|
|
|
|
|
|
|
|
you must give the "-G" flag as the first flag on the command line;
|
|
|
|
|
|
|
|
you must give it as "-G", nothing more, nothing less;
|
|
|
|
|
|
|
|
any arguments after the "-G" flag will not be used. */
|
|
|
|
if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
|
Have Ethereal, when invoked as "ethereal-dump-fields", dump out a
glossary of display filter symbols, just as it does with "-G", except
that, as it can discover that it was so invoked before even looking at
the command-line arguments, it needn't even bother calling "gtk_init()"
to process those command-line arguments GTK+ cares about, and thus
needn't do any X stuff at all when so invoked.
That allows Ethereal to be built in an environment where you don't have
an X server, and, if your connection to your X server is slow, allows
you to built it faster.
Get rid of the "-G" flag, as it had only a somewhat specialized use.
svn path=/trunk/; revision=444
1999-08-05 06:34:43 +00:00
|
|
|
ethereal_proto_init();
|
|
|
|
proto_registrar_dump();
|
|
|
|
exit(0);
|
|
|
|
}
|
Add a new global flag "capture_child", which is TRUE if we're a child
process for a sync mode or fork mode capture.
Have that flag control whether we do things that *only* the parent or
*only* the child should do, rather than basing it solely on the setting
of "sync_mode" or "fork_mode" (or, in the case of stuff done in the
child process either in sync mode or fork mode, rather than basing it on
the setting of those flags at all).
Split "do_capture()" into a "run_capture()" routine that starts a
capture (possibly by forking off and execing a child process, if we're
supposed to do sync mode or fork mode captures), and that assumes the
file to which the capture is to write has already been opened and that
"cf.save_file_fd" is the file descriptor for that file, and a
"do_capture()" routine that creates a temporary file, getting an FD for
it, and calls "run_capture()".
Use "run_capture()", rather than "capture()", for "-k" captures, so that
it'll do the capture in a child process if "-S" or "-F" was specified
("do_capture()" won't do because "-k" captures should write to the file
specified by the "-w" flag, not some random temporary file).
For child process captures, however, just use "capture()" - the child
process shouldn't itself fork off a child if we're in sync or fork mode,
and should just write to the file whose file descriptor was specified by
the "-W" flag on the command line.
All this allows you to do "ethereal -S -w <file> -i <interface> -k" to
start a sync mode capture from the command line.
svn path=/trunk/; revision=740
1999-09-30 06:50:01 +00:00
|
|
|
|
1998-11-17 04:29:13 +00:00
|
|
|
/* Let GTK get its args */
|
|
|
|
gtk_init (&argc, &argv);
|
1999-05-11 18:51:10 +00:00
|
|
|
|
1999-06-12 07:04:35 +00:00
|
|
|
prefs = read_prefs(&pf_path);
|
|
|
|
if (pf_path != NULL) {
|
|
|
|
/* The preferences file exists, but couldn't be opened; "pf_path" is
|
|
|
|
its pathname. Remember "errno", as that says why the attempt
|
|
|
|
failed. */
|
|
|
|
pf_open_errno = errno;
|
|
|
|
}
|
1999-08-14 19:53:31 +00:00
|
|
|
|
1998-09-16 02:39:15 +00:00
|
|
|
/* Initialize the capture file struct */
|
1999-04-06 16:24:50 +00:00
|
|
|
cf.plist = NULL;
|
1999-08-10 04:13:37 +00:00
|
|
|
cf.plist_end = NULL;
|
1999-04-06 16:24:50 +00:00
|
|
|
cf.wth = NULL;
|
|
|
|
cf.fh = NULL;
|
Allow the user to save either all of the current capture, or only the
packets that are currently being displayed from that capture.
Centralize the code to control whether "File:Save" and "File:Save As"
are enabled (and *always* have "File:Save As" enabled if you have a
capture; "File:Save" is enabled only if you have a live capture you've
not yet saved, although it does the same thing as "File:Save As").
Have the "save_file" member of a "capture_file" structure represent
*only* the file currently being *written* to by a capture, and, if there
is no capture currently in progress, have it be NULL; the name of the
file currently being *displayed" is in the "filename" member, and an
"is_tempfile" member indicates whether it's a temporary file for a live
capture or not.
Have "close_cap_file()" delete the current capture file if it's a
temporary capture file that hasn't been saved (in its entirety - saving
selected frames doesn't count). Do the same (if there *is* a current
capture file) when exiting.
The "Ready to load or capture" message is the only statusbar message in
the "main" context; "close_cap_file()" should never pop it, it should
only pop whatever message exists in the "file" context, and thus has no
need to take, as an argument, the context for the message it should pop.
Update the man page to reflect the new behavior of "File:Save" and
"File:Save As", and to reflect recent changes to "Display:Match Selected".
svn path=/trunk/; revision=1170
1999-11-30 20:50:15 +00:00
|
|
|
cf.filename = NULL;
|
|
|
|
cf.user_saved = FALSE;
|
|
|
|
cf.is_tempfile = FALSE;
|
1999-08-15 19:18:46 +00:00
|
|
|
cf.rfcode = NULL;
|
1999-04-06 16:24:50 +00:00
|
|
|
cf.dfilter = NULL;
|
1999-10-11 06:39:26 +00:00
|
|
|
cf.dfcode = NULL;
|
1999-07-09 04:18:36 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
cf.cfilter = NULL;
|
|
|
|
#endif
|
1999-04-06 16:24:50 +00:00
|
|
|
cf.iface = NULL;
|
|
|
|
cf.save_file = NULL;
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
cf.save_file_fd = -1;
|
DLT_NULL, from "libpcap", means different things on different platforms
and in different capture files; throw in some heuristics to try to
figure out whether the 4-byte header is:
1) PPP-over-HDLC (some version of ISDN4BSD?);
2) big-endian AF_ value (BSD on big-endian platforms);
3) little-endian AF_ value (BSD on little-endian platforms);
4) two octets of 0 followed by an Ethernet type (Linux, at least
on little-endian platforms, as mutated by "libpcap").
Make a separate Wiretap encapsulation type, WTAP_ENCAP_NULL,
corresponding to DLT_NULL.
Have the PPP code dissect the frame if it's PPP-over-HDLC, and have
"ethertype()" dissect the Ethernet type and the rest of the packet if
it's a Linux-style header; dissect it ourselves only if it's an AF_
value.
Have Wiretap impose a maximum packet size of 65535 bytes, so that it
fails more gracefully when handed a corrupt "libpcap" capture file
(other capture file formats with more than a 16-bit capture length
field, if any, will have that check added later), and put that size in
"wtap.h" and have Ethereal use it as its notion of a maximum packet
size.
Have Ethereal put up a "this file appears to be damaged or corrupt"
message box if Wiretap returns a WTAP_ERR_BAD_RECORD error when opening
or reading a capture file.
Include loopback interfaces in the list of interfaces offered by the
"Capture" dialog box, but put them at the end of the list so that it
doesn't default to a loopback interface unless there are no other
interfaces. Also, don't require that an interface in the list have an
IP address associated with it, and only put one entry in the list for a
given interface (SIOCGIFCONF returns one entry per interface *address*,
not per *interface* - and even if you were to use only IP addresses, an
interface could conceivably have more than one IP address).
Exclusively use Wiretap encapsulation types internally, even when
capturing; don't use DLT_ types.
svn path=/trunk/; revision=540
1999-08-22 00:47:56 +00:00
|
|
|
cf.snap = WTAP_MAX_PACKET_SIZE;
|
1999-04-06 16:24:50 +00:00
|
|
|
cf.count = 0;
|
|
|
|
cf.cinfo.num_cols = prefs->num_cols;
|
1999-07-28 03:29:02 +00:00
|
|
|
cf.cinfo.col_fmt = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
|
1999-04-06 16:24:50 +00:00
|
|
|
cf.cinfo.fmt_matx = (gboolean **) g_malloc(sizeof(gboolean *) * cf.cinfo.num_cols);
|
1999-07-28 03:29:02 +00:00
|
|
|
cf.cinfo.col_width = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
|
1999-09-12 06:11:51 +00:00
|
|
|
cf.cinfo.col_title = (gchar **) g_malloc(sizeof(gchar *) * cf.cinfo.num_cols);
|
|
|
|
cf.cinfo.col_data = (gchar **) g_malloc(sizeof(gchar *) * cf.cinfo.num_cols);
|
1998-11-17 04:29:13 +00:00
|
|
|
|
1998-12-27 20:47:53 +00:00
|
|
|
/* Assemble the compile-time options */
|
|
|
|
snprintf(comp_info_str, 256,
|
|
|
|
#ifdef GTK_MAJOR_VERSION
|
1999-11-29 03:07:19 +00:00
|
|
|
"GTK+ %d.%d.%d, %s%s, %s%s, %s%s", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
|
1999-07-09 04:18:36 +00:00
|
|
|
GTK_MICRO_VERSION,
|
1998-12-27 20:47:53 +00:00
|
|
|
#else
|
1999-11-29 03:07:19 +00:00
|
|
|
"GTK+ (version unknown), %s%s, %s%s, %s%s",
|
1999-07-09 04:18:36 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_LIBPCAP
|
1999-11-29 02:45:23 +00:00
|
|
|
"with libpcap ", pcap_version,
|
1999-07-09 04:18:36 +00:00
|
|
|
#else
|
1999-11-29 02:45:23 +00:00
|
|
|
"without libpcap", "",
|
1998-12-27 20:47:53 +00:00
|
|
|
#endif
|
1999-11-29 02:45:23 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_LIBZ
|
|
|
|
#ifdef ZLIB_VERSION
|
1999-11-29 03:07:19 +00:00
|
|
|
"with libz ", ZLIB_VERSION,
|
1999-11-29 02:45:23 +00:00
|
|
|
#else /* ZLIB_VERSION */
|
1999-11-29 03:07:19 +00:00
|
|
|
"with libz ", "(version unknown)",
|
1999-11-29 02:45:23 +00:00
|
|
|
#endif /* ZLIB_VERSION */
|
|
|
|
#else /* HAVE_LIBZ */
|
1999-11-29 03:07:19 +00:00
|
|
|
"without libz", "",
|
1999-11-29 02:45:23 +00:00
|
|
|
#endif /* HAVE_LIBZ */
|
1999-11-29 03:07:19 +00:00
|
|
|
|
|
|
|
#if defined(HAVE_UCD_SNMP_SNMP_H)
|
|
|
|
#ifdef HAVE_UCD_SNMP_VERSION_H
|
|
|
|
"with UCD SNMP ", VersionInfo
|
1999-11-29 04:31:05 +00:00
|
|
|
#else /* HAVE_UCD_SNMP_VERSION_H */
|
1999-11-29 03:07:19 +00:00
|
|
|
"with UCD SNMP ", "(version unknown)"
|
1999-11-29 04:31:05 +00:00
|
|
|
#endif /* HAVE_UCD_SNMP_VERSION_H */
|
1999-11-29 03:07:19 +00:00
|
|
|
#elif defined(HAVE_SNMP_SNMP_H)
|
1999-11-29 04:31:05 +00:00
|
|
|
#ifdef HAVE_SNMP_VERSION_H
|
|
|
|
"with CMU SNMP ", snmp_Version()
|
|
|
|
#else /* HAVE_SNMP_VERSION_H */
|
1999-11-29 03:07:19 +00:00
|
|
|
"with CMU SNMP ", "(version unknown)"
|
1999-11-29 04:31:05 +00:00
|
|
|
#endif /* HAVE_SNMP_VERSION_H */
|
|
|
|
#else /* no SNMP */
|
1999-11-29 03:07:19 +00:00
|
|
|
"without SNMP", ""
|
|
|
|
#endif
|
1999-07-07 22:52:57 +00:00
|
|
|
);
|
1998-12-27 20:47:53 +00:00
|
|
|
|
1999-07-13 02:53:26 +00:00
|
|
|
#ifndef WIN32
|
1998-09-16 02:39:15 +00:00
|
|
|
/* Now get our args */
|
1999-10-02 20:00:46 +00:00
|
|
|
while ((opt = getopt(argc, argv, "b:B:c:f:hi:km:nP:Qr:R:Ss:t:T:w:W:v")) != EOF) {
|
1998-09-16 02:39:15 +00:00
|
|
|
switch (opt) {
|
|
|
|
case 'b': /* Bold font */
|
|
|
|
bold_font = g_strdup(optarg);
|
|
|
|
break;
|
|
|
|
case 'B': /* Byte view pane height */
|
|
|
|
bv_size = atoi(optarg);
|
|
|
|
break;
|
|
|
|
case 'c': /* Capture xxx packets */
|
|
|
|
cf.count = atoi(optarg);
|
|
|
|
break;
|
1999-07-09 04:18:36 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
1999-07-13 02:53:26 +00:00
|
|
|
case 'f':
|
1999-05-11 18:51:10 +00:00
|
|
|
cf.cfilter = g_strdup(optarg);
|
|
|
|
break;
|
1999-07-13 02:53:26 +00:00
|
|
|
#endif
|
1998-09-16 02:39:15 +00:00
|
|
|
case 'h': /* Print help and exit */
|
|
|
|
print_usage();
|
|
|
|
exit(0);
|
|
|
|
break;
|
|
|
|
case 'i': /* Use interface xxx */
|
|
|
|
cf.iface = g_strdup(optarg);
|
|
|
|
break;
|
|
|
|
case 'm': /* Medium font */
|
|
|
|
medium_font = g_strdup(optarg);
|
|
|
|
break;
|
|
|
|
case 'n': /* No name resolution */
|
|
|
|
g_resolving_actif = 0;
|
|
|
|
break;
|
1999-07-13 02:53:26 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
1998-09-16 02:39:15 +00:00
|
|
|
case 'k': /* Start capture immediately */
|
Add a new global flag "capture_child", which is TRUE if we're a child
process for a sync mode or fork mode capture.
Have that flag control whether we do things that *only* the parent or
*only* the child should do, rather than basing it solely on the setting
of "sync_mode" or "fork_mode" (or, in the case of stuff done in the
child process either in sync mode or fork mode, rather than basing it on
the setting of those flags at all).
Split "do_capture()" into a "run_capture()" routine that starts a
capture (possibly by forking off and execing a child process, if we're
supposed to do sync mode or fork mode captures), and that assumes the
file to which the capture is to write has already been opened and that
"cf.save_file_fd" is the file descriptor for that file, and a
"do_capture()" routine that creates a temporary file, getting an FD for
it, and calls "run_capture()".
Use "run_capture()", rather than "capture()", for "-k" captures, so that
it'll do the capture in a child process if "-S" or "-F" was specified
("do_capture()" won't do because "-k" captures should write to the file
specified by the "-w" flag, not some random temporary file).
For child process captures, however, just use "capture()" - the child
process shouldn't itself fork off a child if we're in sync or fork mode,
and should just write to the file whose file descriptor was specified by
the "-W" flag on the command line.
All this allows you to do "ethereal -S -w <file> -i <interface> -k" to
start a sync mode capture from the command line.
svn path=/trunk/; revision=740
1999-09-30 06:50:01 +00:00
|
|
|
start_capture = TRUE;
|
1998-09-16 02:39:15 +00:00
|
|
|
break;
|
1999-07-13 02:53:26 +00:00
|
|
|
#endif
|
1998-09-16 02:39:15 +00:00
|
|
|
case 'P': /* Packet list pane height */
|
|
|
|
pl_size = atoi(optarg);
|
|
|
|
break;
|
1999-07-13 02:53:26 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
1999-05-11 18:51:10 +00:00
|
|
|
case 'Q': /* Quit after capture (just capture to file) */
|
|
|
|
quit_after_cap = 1;
|
Add a new global flag "capture_child", which is TRUE if we're a child
process for a sync mode or fork mode capture.
Have that flag control whether we do things that *only* the parent or
*only* the child should do, rather than basing it solely on the setting
of "sync_mode" or "fork_mode" (or, in the case of stuff done in the
child process either in sync mode or fork mode, rather than basing it on
the setting of those flags at all).
Split "do_capture()" into a "run_capture()" routine that starts a
capture (possibly by forking off and execing a child process, if we're
supposed to do sync mode or fork mode captures), and that assumes the
file to which the capture is to write has already been opened and that
"cf.save_file_fd" is the file descriptor for that file, and a
"do_capture()" routine that creates a temporary file, getting an FD for
it, and calls "run_capture()".
Use "run_capture()", rather than "capture()", for "-k" captures, so that
it'll do the capture in a child process if "-S" or "-F" was specified
("do_capture()" won't do because "-k" captures should write to the file
specified by the "-w" flag, not some random temporary file).
For child process captures, however, just use "capture()" - the child
process shouldn't itself fork off a child if we're in sync or fork mode,
and should just write to the file whose file descriptor was specified by
the "-W" flag on the command line.
All this allows you to do "ethereal -S -w <file> -i <interface> -k" to
start a sync mode capture from the command line.
svn path=/trunk/; revision=740
1999-09-30 06:50:01 +00:00
|
|
|
start_capture = TRUE; /*** -Q implies -k !! ***/
|
1999-05-11 18:51:10 +00:00
|
|
|
break;
|
1999-07-13 02:53:26 +00:00
|
|
|
#endif
|
1998-09-16 02:39:15 +00:00
|
|
|
case 'r': /* Read capture file xxx */
|
Allow the user to save either all of the current capture, or only the
packets that are currently being displayed from that capture.
Centralize the code to control whether "File:Save" and "File:Save As"
are enabled (and *always* have "File:Save As" enabled if you have a
capture; "File:Save" is enabled only if you have a live capture you've
not yet saved, although it does the same thing as "File:Save As").
Have the "save_file" member of a "capture_file" structure represent
*only* the file currently being *written* to by a capture, and, if there
is no capture currently in progress, have it be NULL; the name of the
file currently being *displayed" is in the "filename" member, and an
"is_tempfile" member indicates whether it's a temporary file for a live
capture or not.
Have "close_cap_file()" delete the current capture file if it's a
temporary capture file that hasn't been saved (in its entirety - saving
selected frames doesn't count). Do the same (if there *is* a current
capture file) when exiting.
The "Ready to load or capture" message is the only statusbar message in
the "main" context; "close_cap_file()" should never pop it, it should
only pop whatever message exists in the "file" context, and thus has no
need to take, as an argument, the context for the message it should pop.
Update the man page to reflect the new behavior of "File:Save" and
"File:Save As", and to reflect recent changes to "Display:Match Selected".
svn path=/trunk/; revision=1170
1999-11-30 20:50:15 +00:00
|
|
|
cf_name = optarg;
|
1998-09-16 02:39:15 +00:00
|
|
|
break;
|
1999-08-08 01:29:24 +00:00
|
|
|
case 'R': /* Read file filter */
|
1999-08-15 19:18:46 +00:00
|
|
|
rfilter = optarg;
|
1999-08-08 01:29:24 +00:00
|
|
|
break;
|
1999-07-13 02:53:26 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
1998-09-16 02:39:15 +00:00
|
|
|
case 's': /* Set the snapshot (capture) length */
|
|
|
|
cf.snap = atoi(optarg);
|
|
|
|
break;
|
1999-05-11 18:51:10 +00:00
|
|
|
case 'S': /* "Sync" mode: used for following file ala tail -f */
|
1999-09-23 07:20:20 +00:00
|
|
|
sync_mode = TRUE;
|
1999-05-11 18:51:10 +00:00
|
|
|
break;
|
1999-07-13 02:53:26 +00:00
|
|
|
#endif
|
1998-09-27 22:12:47 +00:00
|
|
|
case 't': /* Time stamp type */
|
|
|
|
if (strcmp(optarg, "r") == 0)
|
|
|
|
timestamp_type = RELATIVE;
|
|
|
|
else if (strcmp(optarg, "a") == 0)
|
|
|
|
timestamp_type = ABSOLUTE;
|
|
|
|
else if (strcmp(optarg, "d") == 0)
|
|
|
|
timestamp_type = DELTA;
|
|
|
|
else {
|
|
|
|
fprintf(stderr, "ethereal: Invalid time stamp type \"%s\"\n",
|
|
|
|
optarg);
|
|
|
|
fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
|
|
|
|
fprintf(stderr, "or \"d\" for delta.\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
break;
|
1998-09-16 02:39:15 +00:00
|
|
|
case 'T': /* Tree view pane height */
|
|
|
|
tv_size = atoi(optarg);
|
|
|
|
break;
|
|
|
|
case 'v': /* Show version and exit */
|
1998-12-27 20:47:53 +00:00
|
|
|
printf("%s %s, with %s\n", PACKAGE, VERSION, comp_info_str);
|
1998-09-16 02:39:15 +00:00
|
|
|
exit(0);
|
|
|
|
break;
|
1999-07-13 02:53:26 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
case 'w': /* Write to capture file xxx */
|
1999-10-02 06:26:53 +00:00
|
|
|
save_file = g_strdup(optarg);
|
1998-09-16 02:39:15 +00:00
|
|
|
break;
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
case 'W': /* Write to capture file FD xxx */
|
|
|
|
cf.save_file_fd = atoi(optarg);
|
|
|
|
break;
|
1999-07-13 02:53:26 +00:00
|
|
|
#endif
|
1999-10-02 20:00:46 +00:00
|
|
|
case '?': /* Bad flag - print usage message */
|
|
|
|
print_usage();
|
|
|
|
break;
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
|
|
|
}
|
1999-07-13 02:53:26 +00:00
|
|
|
#endif
|
1998-12-29 04:05:38 +00:00
|
|
|
|
1999-10-02 19:33:14 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
1999-06-15 03:46:46 +00:00
|
|
|
if (start_capture) {
|
|
|
|
if (cf.iface == NULL) {
|
|
|
|
fprintf(stderr, "ethereal: \"-k\" flag was specified without \"-i\" flag\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
1999-10-02 06:00:07 +00:00
|
|
|
}
|
|
|
|
if (capture_child) {
|
|
|
|
if (cf.save_file_fd == -1) {
|
|
|
|
/* XXX - send this to the standard output as something our parent
|
|
|
|
should put in an error message box? */
|
|
|
|
fprintf(stderr, "%s: \"-W\" flag not specified\n", CHILD_NAME);
|
|
|
|
exit(1);
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
}
|
1999-06-15 03:46:46 +00:00
|
|
|
}
|
1999-10-02 06:00:07 +00:00
|
|
|
#endif
|
1999-06-15 03:46:46 +00:00
|
|
|
|
1998-12-29 04:05:38 +00:00
|
|
|
/* Build the column format array */
|
|
|
|
for (i = 0; i < cf.cinfo.num_cols; i++) {
|
1999-07-28 03:29:02 +00:00
|
|
|
cf.cinfo.col_fmt[i] = get_column_format(i);
|
1999-09-12 06:11:51 +00:00
|
|
|
cf.cinfo.col_title[i] = g_strdup(get_column_title(i));
|
1998-12-29 04:05:38 +00:00
|
|
|
cf.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
|
|
|
|
NUM_COL_FMTS);
|
1999-07-28 03:29:02 +00:00
|
|
|
get_column_format_matches(cf.cinfo.fmt_matx[i], cf.cinfo.col_fmt[i]);
|
1999-10-15 20:33:06 +00:00
|
|
|
if (cf.cinfo.col_fmt[i] == COL_INFO)
|
|
|
|
cf.cinfo.col_data[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
|
|
|
|
else
|
|
|
|
cf.cinfo.col_data[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
|
1998-12-29 04:05:38 +00:00
|
|
|
}
|
|
|
|
|
1998-09-16 02:39:15 +00:00
|
|
|
if (cf.snap < 1)
|
DLT_NULL, from "libpcap", means different things on different platforms
and in different capture files; throw in some heuristics to try to
figure out whether the 4-byte header is:
1) PPP-over-HDLC (some version of ISDN4BSD?);
2) big-endian AF_ value (BSD on big-endian platforms);
3) little-endian AF_ value (BSD on little-endian platforms);
4) two octets of 0 followed by an Ethernet type (Linux, at least
on little-endian platforms, as mutated by "libpcap").
Make a separate Wiretap encapsulation type, WTAP_ENCAP_NULL,
corresponding to DLT_NULL.
Have the PPP code dissect the frame if it's PPP-over-HDLC, and have
"ethertype()" dissect the Ethernet type and the rest of the packet if
it's a Linux-style header; dissect it ourselves only if it's an AF_
value.
Have Wiretap impose a maximum packet size of 65535 bytes, so that it
fails more gracefully when handed a corrupt "libpcap" capture file
(other capture file formats with more than a 16-bit capture length
field, if any, will have that check added later), and put that size in
"wtap.h" and have Ethereal use it as its notion of a maximum packet
size.
Have Ethereal put up a "this file appears to be damaged or corrupt"
message box if Wiretap returns a WTAP_ERR_BAD_RECORD error when opening
or reading a capture file.
Include loopback interfaces in the list of interfaces offered by the
"Capture" dialog box, but put them at the end of the list so that it
doesn't default to a loopback interface unless there are no other
interfaces. Also, don't require that an interface in the list have an
IP address associated with it, and only put one entry in the list for a
given interface (SIOCGIFCONF returns one entry per interface *address*,
not per *interface* - and even if you were to use only IP addresses, an
interface could conceivably have more than one IP address).
Exclusively use Wiretap encapsulation types internally, even when
capturing; don't use DLT_ types.
svn path=/trunk/; revision=540
1999-08-22 00:47:56 +00:00
|
|
|
cf.snap = WTAP_MAX_PACKET_SIZE;
|
1999-02-11 06:17:30 +00:00
|
|
|
else if (cf.snap < MIN_PACKET_SIZE)
|
|
|
|
cf.snap = MIN_PACKET_SIZE;
|
1998-09-16 02:39:15 +00:00
|
|
|
|
|
|
|
rc_file = (gchar *) g_malloc(strlen(getenv("HOME")) + strlen(RC_FILE) + 4);
|
|
|
|
sprintf(rc_file, "%s/%s", getenv("HOME"), RC_FILE);
|
|
|
|
gtk_rc_parse(rc_file);
|
|
|
|
|
|
|
|
if ((m_r_font = gdk_font_load(medium_font)) == NULL) {
|
1999-06-15 03:46:46 +00:00
|
|
|
fprintf(stderr, "ethereal: Error font %s not found (use -m option)\n", medium_font);
|
1998-09-16 02:39:15 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((m_b_font = gdk_font_load(bold_font)) == NULL) {
|
1999-06-15 03:46:46 +00:00
|
|
|
fprintf(stderr, "ethereal: Error font %s not found (use -b option)\n", bold_font);
|
1998-09-16 02:39:15 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Main window */
|
|
|
|
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
|
|
|
gtk_widget_set_name(window, "main window");
|
|
|
|
gtk_signal_connect(GTK_OBJECT(window), "delete_event",
|
|
|
|
GTK_SIGNAL_FUNC(file_quit_cmd_cb), "WM destroy");
|
|
|
|
gtk_signal_connect(GTK_OBJECT(window), "destroy",
|
|
|
|
GTK_SIGNAL_FUNC(file_quit_cmd_cb), "WM destroy");
|
|
|
|
gtk_window_set_title(GTK_WINDOW(window), "The Ethereal Network Analyzer");
|
|
|
|
gtk_widget_set_usize(GTK_WIDGET(window), DEF_WIDTH, -1);
|
1998-12-27 20:47:53 +00:00
|
|
|
gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, FALSE);
|
1998-09-16 02:39:15 +00:00
|
|
|
|
|
|
|
/* Container for menu bar, paned windows and progress/info box */
|
|
|
|
main_vbox = gtk_vbox_new(FALSE, 1);
|
|
|
|
gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
|
|
|
|
gtk_container_add(GTK_CONTAINER(window), main_vbox);
|
|
|
|
gtk_widget_show(main_vbox);
|
|
|
|
|
|
|
|
/* Menu bar */
|
|
|
|
get_main_menu(&menubar, &accel);
|
1998-12-17 05:42:33 +00:00
|
|
|
gtk_window_add_accel_group(GTK_WINDOW(window), accel);
|
1998-09-16 02:39:15 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
|
|
|
|
gtk_widget_show(menubar);
|
|
|
|
|
|
|
|
/* Panes for the packet list, tree, and byte view */
|
|
|
|
u_pane = gtk_vpaned_new();
|
1998-10-12 01:40:57 +00:00
|
|
|
gtk_paned_gutter_size(GTK_PANED(u_pane), (GTK_PANED(u_pane))->handle_size);
|
1998-09-16 02:39:15 +00:00
|
|
|
l_pane = gtk_vpaned_new();
|
1998-10-12 01:40:57 +00:00
|
|
|
gtk_paned_gutter_size(GTK_PANED(l_pane), (GTK_PANED(l_pane))->handle_size);
|
1998-09-16 02:39:15 +00:00
|
|
|
gtk_container_add(GTK_CONTAINER(main_vbox), u_pane);
|
|
|
|
gtk_widget_show(u_pane);
|
|
|
|
gtk_paned_add2 (GTK_PANED(u_pane), l_pane);
|
|
|
|
gtk_widget_show(l_pane);
|
|
|
|
|
|
|
|
/* Packet list */
|
1999-09-12 06:11:51 +00:00
|
|
|
packet_list = gtk_clist_new_with_titles(cf.cinfo.num_cols, cf.cinfo.col_title);
|
1998-11-17 04:29:13 +00:00
|
|
|
gtk_clist_column_titles_passive(GTK_CLIST(packet_list));
|
1998-12-17 05:42:33 +00:00
|
|
|
packet_sw = gtk_scrolled_window_new(NULL, NULL);
|
|
|
|
gtk_widget_show(packet_sw);
|
|
|
|
gtk_container_add(GTK_CONTAINER(packet_sw), packet_list);
|
1998-09-16 02:39:15 +00:00
|
|
|
pl_style = gtk_style_new();
|
|
|
|
gdk_font_unref(pl_style->font);
|
|
|
|
pl_style->font = m_r_font;
|
|
|
|
gtk_widget_set_style(packet_list, pl_style);
|
|
|
|
gtk_widget_set_name(packet_list, "packet list");
|
|
|
|
gtk_signal_connect(GTK_OBJECT(packet_list), "select_row",
|
|
|
|
GTK_SIGNAL_FUNC(packet_list_select_cb), NULL);
|
|
|
|
gtk_signal_connect(GTK_OBJECT(packet_list), "unselect_row",
|
|
|
|
GTK_SIGNAL_FUNC(packet_list_unselect_cb), NULL);
|
1998-11-17 04:29:13 +00:00
|
|
|
for (i = 0; i < cf.cinfo.num_cols; i++) {
|
1999-07-28 03:29:02 +00:00
|
|
|
if (get_column_resize_type(cf.cinfo.col_fmt[i]) != RESIZE_MANUAL)
|
|
|
|
gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
|
|
|
|
|
|
|
|
/* Right-justify the packet number column. */
|
|
|
|
if (cf.cinfo.col_fmt[i] == COL_NUMBER)
|
1998-11-17 04:29:13 +00:00
|
|
|
gtk_clist_set_column_justification(GTK_CLIST(packet_list), i,
|
|
|
|
GTK_JUSTIFY_RIGHT);
|
1999-07-28 03:29:02 +00:00
|
|
|
|
|
|
|
/* Save static column sizes to use during a "-S" capture, so that
|
|
|
|
the columns don't resize during a live capture. */
|
|
|
|
cf.cinfo.col_width[i] = get_column_width(get_column_format(i),
|
|
|
|
pl_style->font);
|
1998-11-17 04:29:13 +00:00
|
|
|
}
|
1998-09-16 02:39:15 +00:00
|
|
|
gtk_widget_set_usize(packet_list, -1, pl_size);
|
1998-12-17 05:42:33 +00:00
|
|
|
gtk_paned_add1(GTK_PANED(u_pane), packet_sw);
|
1998-09-16 02:39:15 +00:00
|
|
|
gtk_widget_show(packet_list);
|
|
|
|
|
|
|
|
/* Tree view */
|
|
|
|
tv_scrollw = gtk_scrolled_window_new(NULL, NULL);
|
|
|
|
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(tv_scrollw),
|
|
|
|
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
|
|
|
gtk_paned_add1(GTK_PANED(l_pane), tv_scrollw);
|
|
|
|
gtk_widget_set_usize(tv_scrollw, -1, tv_size);
|
|
|
|
gtk_widget_show(tv_scrollw);
|
|
|
|
|
|
|
|
tree_view = gtk_tree_new();
|
1998-12-17 05:42:33 +00:00
|
|
|
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(tv_scrollw),
|
|
|
|
tree_view);
|
1998-09-16 02:39:15 +00:00
|
|
|
gtk_tree_set_selection_mode(GTK_TREE(tree_view), GTK_SELECTION_SINGLE);
|
1999-08-15 07:28:23 +00:00
|
|
|
|
|
|
|
/* XXX - what's the difference between the next two lines? */
|
1998-09-16 02:39:15 +00:00
|
|
|
gtk_tree_set_view_lines(GTK_TREE(tree_view), FALSE);
|
1999-08-15 07:28:23 +00:00
|
|
|
gtk_tree_set_view_mode(GTK_TREE(tree_view), GTK_TREE_VIEW_ITEM);
|
|
|
|
|
1998-09-16 02:39:15 +00:00
|
|
|
gtk_signal_connect(GTK_OBJECT(tree_view), "selection_changed",
|
|
|
|
GTK_SIGNAL_FUNC(tree_view_cb), NULL);
|
|
|
|
gtk_widget_show(tree_view);
|
|
|
|
|
1998-12-29 04:05:38 +00:00
|
|
|
item_style = gtk_style_new();
|
|
|
|
gdk_font_unref(item_style->font);
|
|
|
|
item_style->font = m_r_font;
|
|
|
|
|
1998-09-16 02:39:15 +00:00
|
|
|
/* Byte view */
|
|
|
|
bv_table = gtk_table_new (2, 2, FALSE);
|
|
|
|
gtk_paned_add2(GTK_PANED(l_pane), bv_table);
|
|
|
|
gtk_widget_set_usize(bv_table, -1, bv_size);
|
|
|
|
gtk_widget_show(bv_table);
|
|
|
|
|
|
|
|
byte_view = gtk_text_new(NULL, NULL);
|
|
|
|
gtk_text_set_editable(GTK_TEXT(byte_view), FALSE);
|
|
|
|
gtk_text_set_word_wrap(GTK_TEXT(byte_view), FALSE);
|
|
|
|
gtk_table_attach (GTK_TABLE (bv_table), byte_view, 0, 1, 0, 1,
|
|
|
|
GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
|
|
|
|
gtk_widget_show(byte_view);
|
|
|
|
|
|
|
|
bv_hscroll = gtk_hscrollbar_new(GTK_TEXT(byte_view)->hadj);
|
|
|
|
gtk_table_attach(GTK_TABLE(bv_table), bv_hscroll, 0, 1, 1, 2,
|
|
|
|
GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
|
|
|
|
gtk_widget_show (bv_hscroll);
|
|
|
|
|
|
|
|
bv_vscroll = gtk_vscrollbar_new(GTK_TEXT(byte_view)->vadj);
|
|
|
|
gtk_table_attach(GTK_TABLE(bv_table), bv_vscroll, 1, 2, 0, 1,
|
|
|
|
GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
|
|
|
|
gtk_widget_show(bv_vscroll);
|
|
|
|
|
1998-10-12 01:40:57 +00:00
|
|
|
/* Progress/filter/info box */
|
1998-09-16 02:39:15 +00:00
|
|
|
stat_hbox = gtk_hbox_new(FALSE, 1);
|
|
|
|
gtk_container_border_width(GTK_CONTAINER(stat_hbox), 0);
|
|
|
|
gtk_box_pack_start(GTK_BOX(main_vbox), stat_hbox, FALSE, TRUE, 0);
|
|
|
|
gtk_widget_show(stat_hbox);
|
|
|
|
|
1999-09-22 01:26:50 +00:00
|
|
|
prog_bar = gtk_progress_bar_new();
|
1998-10-12 01:40:57 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(stat_hbox), prog_bar, FALSE, TRUE, 3);
|
1998-09-16 02:39:15 +00:00
|
|
|
gtk_widget_show(prog_bar);
|
|
|
|
|
1998-10-12 01:40:57 +00:00
|
|
|
filter_bt = gtk_button_new_with_label("Filter:");
|
|
|
|
gtk_signal_connect(GTK_OBJECT(filter_bt), "clicked",
|
|
|
|
GTK_SIGNAL_FUNC(prefs_cb), (gpointer) E_PR_PG_FILTER);
|
|
|
|
gtk_box_pack_start(GTK_BOX(stat_hbox), filter_bt, FALSE, TRUE, 0);
|
|
|
|
gtk_widget_show(filter_bt);
|
|
|
|
|
1999-11-25 18:02:25 +00:00
|
|
|
filter_cm = gtk_combo_new();
|
|
|
|
filter_list = g_list_append (filter_list, "");
|
|
|
|
gtk_combo_set_popdown_strings(GTK_COMBO(filter_cm), filter_list);
|
|
|
|
gtk_combo_disable_activate(GTK_COMBO(filter_cm));
|
|
|
|
filter_te = GTK_COMBO(filter_cm)->entry;
|
1998-10-12 01:40:57 +00:00
|
|
|
gtk_object_set_data(GTK_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
|
1999-11-25 18:02:25 +00:00
|
|
|
gtk_object_set_data(GTK_OBJECT(filter_te), E_DFILTER_CM_KEY, filter_cm);
|
|
|
|
gtk_object_set_data(GTK_OBJECT(filter_te), E_DFILTER_FL_KEY, filter_list);
|
|
|
|
gtk_box_pack_start(GTK_BOX(stat_hbox), filter_cm, TRUE, TRUE, 3);
|
1999-07-11 08:40:52 +00:00
|
|
|
gtk_signal_connect(GTK_OBJECT(filter_te), "activate",
|
|
|
|
GTK_SIGNAL_FUNC(filter_activate_cb), (gpointer) NULL);
|
1999-11-25 18:02:25 +00:00
|
|
|
gtk_widget_show(filter_cm);
|
1998-11-18 03:17:18 +00:00
|
|
|
|
1999-11-21 15:06:07 +00:00
|
|
|
filter_reset = gtk_button_new_with_label("Reset");
|
|
|
|
gtk_object_set_data(GTK_OBJECT(filter_reset), E_DFILTER_TE_KEY, filter_te);
|
|
|
|
gtk_signal_connect(GTK_OBJECT(filter_reset), "clicked",
|
|
|
|
GTK_SIGNAL_FUNC(filter_reset_cb), (gpointer) NULL);
|
|
|
|
gtk_box_pack_start(GTK_BOX(stat_hbox), filter_reset, FALSE, TRUE, 1);
|
|
|
|
gtk_widget_show(filter_reset);
|
|
|
|
|
1999-08-20 19:43:10 +00:00
|
|
|
/* Sets the text entry widget pointer as the E_DILTER_TE_KEY data
|
|
|
|
* of any widget that ends up calling a callback which needs
|
|
|
|
* that text entry pointer */
|
1999-06-15 04:48:57 +00:00
|
|
|
set_menu_object_data("/File/Open...", E_DFILTER_TE_KEY, filter_te);
|
1999-07-27 02:04:38 +00:00
|
|
|
set_menu_object_data("/File/Reload", E_DFILTER_TE_KEY, filter_te);
|
1999-11-26 05:23:40 +00:00
|
|
|
set_menu_object_data("/Display/Match Selected", E_DFILTER_TE_KEY, filter_te);
|
|
|
|
set_menu_object_data("/Tools/Follow TCP Stream", E_DFILTER_TE_KEY, filter_te);
|
1999-08-20 19:43:10 +00:00
|
|
|
|
1998-09-16 02:39:15 +00:00
|
|
|
info_bar = gtk_statusbar_new();
|
|
|
|
main_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "main");
|
|
|
|
file_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "file");
|
|
|
|
gtk_statusbar_push(GTK_STATUSBAR(info_bar), main_ctx, DEF_READY_MESSAGE);
|
|
|
|
gtk_box_pack_start(GTK_BOX(stat_hbox), info_bar, TRUE, TRUE, 0);
|
|
|
|
gtk_widget_show(info_bar);
|
|
|
|
|
1999-02-19 05:28:38 +00:00
|
|
|
/*
|
|
|
|
Hmmm should we do it here
|
|
|
|
*/
|
|
|
|
|
|
|
|
ethereal_proto_init(); /* Init anything that needs initializing */
|
|
|
|
|
1999-10-02 19:33:14 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
If we're given the "-k" flag, don't start the capture until after we've:
popped up the top-level window (so that it looks like a capture
started from "Capture/Start");
initialized the colors (so that we don't dump core when reading
in the capture file);
popped up any message box for failure to read the preferences
file.
This means we start the capture in "main()", rather than in the realize
callback for the main window, so get rid of that callback.
If we're a child process that's just capturing to a file for our parent
to read, however, we shouldn't pop up the top-level window, because
that's our parent's job; when running that child, set its "argv[0]" to a
special name, so that
1) it shows up in a "ps" with a special name;
2) we don't have to invent Yet Another Flag to say "you're the
child".
(We may want to use the name to turn on *all* behaviors that the capture
child, and only the capture child, should exhibit.)
If "-w" and "-k" were both specified, attempt to open the file specified
by "-w" and, if that succeeds, set "cf.save_file_fd" to refer to it, so
that "-w" plus "-k" works again, rather than popping up a "The file to
which the capture would be saved ... could not be opened: Bad file
descriptor." message box.
svn path=/trunk/; revision=739
1999-09-30 06:11:51 +00:00
|
|
|
/* Is this a "child" ethereal, which is only supposed to pop up a
|
|
|
|
capture box to let us stop the capture, and run a capture
|
|
|
|
to a file that our parent will read? */
|
Add a new global flag "capture_child", which is TRUE if we're a child
process for a sync mode or fork mode capture.
Have that flag control whether we do things that *only* the parent or
*only* the child should do, rather than basing it solely on the setting
of "sync_mode" or "fork_mode" (or, in the case of stuff done in the
child process either in sync mode or fork mode, rather than basing it on
the setting of those flags at all).
Split "do_capture()" into a "run_capture()" routine that starts a
capture (possibly by forking off and execing a child process, if we're
supposed to do sync mode or fork mode captures), and that assumes the
file to which the capture is to write has already been opened and that
"cf.save_file_fd" is the file descriptor for that file, and a
"do_capture()" routine that creates a temporary file, getting an FD for
it, and calls "run_capture()".
Use "run_capture()", rather than "capture()", for "-k" captures, so that
it'll do the capture in a child process if "-S" or "-F" was specified
("do_capture()" won't do because "-k" captures should write to the file
specified by the "-w" flag, not some random temporary file).
For child process captures, however, just use "capture()" - the child
process shouldn't itself fork off a child if we're in sync or fork mode,
and should just write to the file whose file descriptor was specified by
the "-W" flag on the command line.
All this allows you to do "ethereal -S -w <file> -i <interface> -k" to
start a sync mode capture from the command line.
svn path=/trunk/; revision=740
1999-09-30 06:50:01 +00:00
|
|
|
if (!capture_child) {
|
1999-10-02 19:33:14 +00:00
|
|
|
#endif
|
If we're given the "-k" flag, don't start the capture until after we've:
popped up the top-level window (so that it looks like a capture
started from "Capture/Start");
initialized the colors (so that we don't dump core when reading
in the capture file);
popped up any message box for failure to read the preferences
file.
This means we start the capture in "main()", rather than in the realize
callback for the main window, so get rid of that callback.
If we're a child process that's just capturing to a file for our parent
to read, however, we shouldn't pop up the top-level window, because
that's our parent's job; when running that child, set its "argv[0]" to a
special name, so that
1) it shows up in a "ps" with a special name;
2) we don't have to invent Yet Another Flag to say "you're the
child".
(We may want to use the name to turn on *all* behaviors that the capture
child, and only the capture child, should exhibit.)
If "-w" and "-k" were both specified, attempt to open the file specified
by "-w" and, if that succeeds, set "cf.save_file_fd" to refer to it, so
that "-w" plus "-k" works again, rather than popping up a "The file to
which the capture would be saved ... could not be opened: Bad file
descriptor." message box.
svn path=/trunk/; revision=739
1999-09-30 06:11:51 +00:00
|
|
|
/* No. Pop up the main window, and read in a capture file if
|
|
|
|
we were told to. */
|
|
|
|
|
|
|
|
gtk_widget_show(window);
|
|
|
|
|
1999-11-30 05:33:05 +00:00
|
|
|
cf.colors = colfilter_new();
|
If we're given the "-k" flag, don't start the capture until after we've:
popped up the top-level window (so that it looks like a capture
started from "Capture/Start");
initialized the colors (so that we don't dump core when reading
in the capture file);
popped up any message box for failure to read the preferences
file.
This means we start the capture in "main()", rather than in the realize
callback for the main window, so get rid of that callback.
If we're a child process that's just capturing to a file for our parent
to read, however, we shouldn't pop up the top-level window, because
that's our parent's job; when running that child, set its "argv[0]" to a
special name, so that
1) it shows up in a "ps" with a special name;
2) we don't have to invent Yet Another Flag to say "you're the
child".
(We may want to use the name to turn on *all* behaviors that the capture
child, and only the capture child, should exhibit.)
If "-w" and "-k" were both specified, attempt to open the file specified
by "-w" and, if that succeeds, set "cf.save_file_fd" to refer to it, so
that "-w" plus "-k" works again, rather than popping up a "The file to
which the capture would be saved ... could not be opened: Bad file
descriptor." message box.
svn path=/trunk/; revision=739
1999-09-30 06:11:51 +00:00
|
|
|
|
|
|
|
/* If we were given the name of a capture file, read it in now;
|
|
|
|
we defer it until now, so that, if we can't open it, and pop
|
|
|
|
up an alert box, the alert box is more likely to come up on
|
|
|
|
top of the main window - but before the preference-file-error
|
|
|
|
alert box, so, if we get one of those, it's more likely to come
|
|
|
|
up on top of us. */
|
|
|
|
if (cf_name) {
|
|
|
|
if (rfilter != NULL) {
|
1999-10-12 05:01:07 +00:00
|
|
|
if (dfilter_compile(rfilter, &rfcode) != 0) {
|
If we're given the "-k" flag, don't start the capture until after we've:
popped up the top-level window (so that it looks like a capture
started from "Capture/Start");
initialized the colors (so that we don't dump core when reading
in the capture file);
popped up any message box for failure to read the preferences
file.
This means we start the capture in "main()", rather than in the realize
callback for the main window, so get rid of that callback.
If we're a child process that's just capturing to a file for our parent
to read, however, we shouldn't pop up the top-level window, because
that's our parent's job; when running that child, set its "argv[0]" to a
special name, so that
1) it shows up in a "ps" with a special name;
2) we don't have to invent Yet Another Flag to say "you're the
child".
(We may want to use the name to turn on *all* behaviors that the capture
child, and only the capture child, should exhibit.)
If "-w" and "-k" were both specified, attempt to open the file specified
by "-w" and, if that succeeds, set "cf.save_file_fd" to refer to it, so
that "-w" plus "-k" works again, rather than popping up a "The file to
which the capture would be saved ... could not be opened: Bad file
descriptor." message box.
svn path=/trunk/; revision=739
1999-09-30 06:11:51 +00:00
|
|
|
simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
|
|
|
|
rfilter_parse_failed = TRUE;
|
|
|
|
}
|
1999-08-15 19:18:46 +00:00
|
|
|
}
|
If we're given the "-k" flag, don't start the capture until after we've:
popped up the top-level window (so that it looks like a capture
started from "Capture/Start");
initialized the colors (so that we don't dump core when reading
in the capture file);
popped up any message box for failure to read the preferences
file.
This means we start the capture in "main()", rather than in the realize
callback for the main window, so get rid of that callback.
If we're a child process that's just capturing to a file for our parent
to read, however, we shouldn't pop up the top-level window, because
that's our parent's job; when running that child, set its "argv[0]" to a
special name, so that
1) it shows up in a "ps" with a special name;
2) we don't have to invent Yet Another Flag to say "you're the
child".
(We may want to use the name to turn on *all* behaviors that the capture
child, and only the capture child, should exhibit.)
If "-w" and "-k" were both specified, attempt to open the file specified
by "-w" and, if that succeeds, set "cf.save_file_fd" to refer to it, so
that "-w" plus "-k" works again, rather than popping up a "The file to
which the capture would be saved ... could not be opened: Bad file
descriptor." message box.
svn path=/trunk/; revision=739
1999-09-30 06:11:51 +00:00
|
|
|
if (!rfilter_parse_failed) {
|
Allow the user to save either all of the current capture, or only the
packets that are currently being displayed from that capture.
Centralize the code to control whether "File:Save" and "File:Save As"
are enabled (and *always* have "File:Save As" enabled if you have a
capture; "File:Save" is enabled only if you have a live capture you've
not yet saved, although it does the same thing as "File:Save As").
Have the "save_file" member of a "capture_file" structure represent
*only* the file currently being *written* to by a capture, and, if there
is no capture currently in progress, have it be NULL; the name of the
file currently being *displayed" is in the "filename" member, and an
"is_tempfile" member indicates whether it's a temporary file for a live
capture or not.
Have "close_cap_file()" delete the current capture file if it's a
temporary capture file that hasn't been saved (in its entirety - saving
selected frames doesn't count). Do the same (if there *is* a current
capture file) when exiting.
The "Ready to load or capture" message is the only statusbar message in
the "main" context; "close_cap_file()" should never pop it, it should
only pop whatever message exists in the "file" context, and thus has no
need to take, as an argument, the context for the message it should pop.
Update the man page to reflect the new behavior of "File:Save" and
"File:Save As", and to reflect recent changes to "Display:Match Selected".
svn path=/trunk/; revision=1170
1999-11-30 20:50:15 +00:00
|
|
|
if ((err = open_cap_file(cf_name, FALSE, &cf)) == 0) {
|
1999-10-12 05:01:07 +00:00
|
|
|
/* "open_cap_file()" succeeded, so it closed the previous
|
|
|
|
capture file, and thus destroyed any previous read filter
|
|
|
|
attached to "cf". */
|
If we're given the "-k" flag, don't start the capture until after we've:
popped up the top-level window (so that it looks like a capture
started from "Capture/Start");
initialized the colors (so that we don't dump core when reading
in the capture file);
popped up any message box for failure to read the preferences
file.
This means we start the capture in "main()", rather than in the realize
callback for the main window, so get rid of that callback.
If we're a child process that's just capturing to a file for our parent
to read, however, we shouldn't pop up the top-level window, because
that's our parent's job; when running that child, set its "argv[0]" to a
special name, so that
1) it shows up in a "ps" with a special name;
2) we don't have to invent Yet Another Flag to say "you're the
child".
(We may want to use the name to turn on *all* behaviors that the capture
child, and only the capture child, should exhibit.)
If "-w" and "-k" were both specified, attempt to open the file specified
by "-w" and, if that succeeds, set "cf.save_file_fd" to refer to it, so
that "-w" plus "-k" works again, rather than popping up a "The file to
which the capture would be saved ... could not be opened: Bad file
descriptor." message box.
svn path=/trunk/; revision=739
1999-09-30 06:11:51 +00:00
|
|
|
cf.rfcode = rfcode;
|
|
|
|
err = read_cap_file(&cf);
|
|
|
|
s = strrchr(cf_name, '/');
|
|
|
|
if (s) {
|
|
|
|
last_open_dir = cf_name;
|
|
|
|
*s = '\0';
|
|
|
|
}
|
1999-10-12 05:01:07 +00:00
|
|
|
} else {
|
|
|
|
dfilter_destroy(rfcode);
|
|
|
|
cf.rfcode = NULL;
|
1999-08-15 19:18:46 +00:00
|
|
|
}
|
1999-08-15 06:59:13 +00:00
|
|
|
}
|
|
|
|
}
|
1999-10-02 19:33:14 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
1999-06-15 03:46:46 +00:00
|
|
|
}
|
1999-10-02 19:33:14 +00:00
|
|
|
#endif
|
1999-06-15 03:46:46 +00:00
|
|
|
|
1999-06-12 07:04:35 +00:00
|
|
|
/* If we failed to open the preferences file, pop up an alert box;
|
|
|
|
we defer it until now, so that the alert box is more likely to
|
|
|
|
come up on top of the main window. */
|
|
|
|
if (pf_path != NULL) {
|
|
|
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
1999-08-25 03:22:46 +00:00
|
|
|
"Could not open preferences file\n\"%s\": %s.", pf_path,
|
1999-06-12 07:04:35 +00:00
|
|
|
strerror(pf_open_errno));
|
|
|
|
}
|
|
|
|
|
If we're given the "-k" flag, don't start the capture until after we've:
popped up the top-level window (so that it looks like a capture
started from "Capture/Start");
initialized the colors (so that we don't dump core when reading
in the capture file);
popped up any message box for failure to read the preferences
file.
This means we start the capture in "main()", rather than in the realize
callback for the main window, so get rid of that callback.
If we're a child process that's just capturing to a file for our parent
to read, however, we shouldn't pop up the top-level window, because
that's our parent's job; when running that child, set its "argv[0]" to a
special name, so that
1) it shows up in a "ps" with a special name;
2) we don't have to invent Yet Another Flag to say "you're the
child".
(We may want to use the name to turn on *all* behaviors that the capture
child, and only the capture child, should exhibit.)
If "-w" and "-k" were both specified, attempt to open the file specified
by "-w" and, if that succeeds, set "cf.save_file_fd" to refer to it, so
that "-w" plus "-k" works again, rather than popping up a "The file to
which the capture would be saved ... could not be opened: Bad file
descriptor." message box.
svn path=/trunk/; revision=739
1999-09-30 06:11:51 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
Add a new global flag "capture_child", which is TRUE if we're a child
process for a sync mode or fork mode capture.
Have that flag control whether we do things that *only* the parent or
*only* the child should do, rather than basing it solely on the setting
of "sync_mode" or "fork_mode" (or, in the case of stuff done in the
child process either in sync mode or fork mode, rather than basing it on
the setting of those flags at all).
Split "do_capture()" into a "run_capture()" routine that starts a
capture (possibly by forking off and execing a child process, if we're
supposed to do sync mode or fork mode captures), and that assumes the
file to which the capture is to write has already been opened and that
"cf.save_file_fd" is the file descriptor for that file, and a
"do_capture()" routine that creates a temporary file, getting an FD for
it, and calls "run_capture()".
Use "run_capture()", rather than "capture()", for "-k" captures, so that
it'll do the capture in a child process if "-S" or "-F" was specified
("do_capture()" won't do because "-k" captures should write to the file
specified by the "-w" flag, not some random temporary file).
For child process captures, however, just use "capture()" - the child
process shouldn't itself fork off a child if we're in sync or fork mode,
and should just write to the file whose file descriptor was specified by
the "-W" flag on the command line.
All this allows you to do "ethereal -S -w <file> -i <interface> -k" to
start a sync mode capture from the command line.
svn path=/trunk/; revision=740
1999-09-30 06:50:01 +00:00
|
|
|
if (capture_child) {
|
|
|
|
/* This is the child process for a sync mode or fork mode capture,
|
|
|
|
so just do the low-level work of a capture - don't create
|
1999-10-02 06:26:53 +00:00
|
|
|
a temporary file and fork off *another* child process (so don't
|
|
|
|
call "do_capture()"). */
|
Add a new global flag "capture_child", which is TRUE if we're a child
process for a sync mode or fork mode capture.
Have that flag control whether we do things that *only* the parent or
*only* the child should do, rather than basing it solely on the setting
of "sync_mode" or "fork_mode" (or, in the case of stuff done in the
child process either in sync mode or fork mode, rather than basing it on
the setting of those flags at all).
Split "do_capture()" into a "run_capture()" routine that starts a
capture (possibly by forking off and execing a child process, if we're
supposed to do sync mode or fork mode captures), and that assumes the
file to which the capture is to write has already been opened and that
"cf.save_file_fd" is the file descriptor for that file, and a
"do_capture()" routine that creates a temporary file, getting an FD for
it, and calls "run_capture()".
Use "run_capture()", rather than "capture()", for "-k" captures, so that
it'll do the capture in a child process if "-S" or "-F" was specified
("do_capture()" won't do because "-k" captures should write to the file
specified by the "-w" flag, not some random temporary file).
For child process captures, however, just use "capture()" - the child
process shouldn't itself fork off a child if we're in sync or fork mode,
and should just write to the file whose file descriptor was specified by
the "-W" flag on the command line.
All this allows you to do "ethereal -S -w <file> -i <interface> -k" to
start a sync mode capture from the command line.
svn path=/trunk/; revision=740
1999-09-30 06:50:01 +00:00
|
|
|
|
|
|
|
capture();
|
1999-10-02 06:00:07 +00:00
|
|
|
|
|
|
|
/* The capture is done; there's nothing more for us to do. */
|
|
|
|
gtk_exit(0);
|
Add a new global flag "capture_child", which is TRUE if we're a child
process for a sync mode or fork mode capture.
Have that flag control whether we do things that *only* the parent or
*only* the child should do, rather than basing it solely on the setting
of "sync_mode" or "fork_mode" (or, in the case of stuff done in the
child process either in sync mode or fork mode, rather than basing it on
the setting of those flags at all).
Split "do_capture()" into a "run_capture()" routine that starts a
capture (possibly by forking off and execing a child process, if we're
supposed to do sync mode or fork mode captures), and that assumes the
file to which the capture is to write has already been opened and that
"cf.save_file_fd" is the file descriptor for that file, and a
"do_capture()" routine that creates a temporary file, getting an FD for
it, and calls "run_capture()".
Use "run_capture()", rather than "capture()", for "-k" captures, so that
it'll do the capture in a child process if "-S" or "-F" was specified
("do_capture()" won't do because "-k" captures should write to the file
specified by the "-w" flag, not some random temporary file).
For child process captures, however, just use "capture()" - the child
process shouldn't itself fork off a child if we're in sync or fork mode,
and should just write to the file whose file descriptor was specified by
the "-W" flag on the command line.
All this allows you to do "ethereal -S -w <file> -i <interface> -k" to
start a sync mode capture from the command line.
svn path=/trunk/; revision=740
1999-09-30 06:50:01 +00:00
|
|
|
} else {
|
|
|
|
if (start_capture) {
|
|
|
|
/* "-k" was specified; start a capture. */
|
1999-10-02 06:26:53 +00:00
|
|
|
do_capture(save_file);
|
If we're given the "-k" flag, don't start the capture until after we've:
popped up the top-level window (so that it looks like a capture
started from "Capture/Start");
initialized the colors (so that we don't dump core when reading
in the capture file);
popped up any message box for failure to read the preferences
file.
This means we start the capture in "main()", rather than in the realize
callback for the main window, so get rid of that callback.
If we're a child process that's just capturing to a file for our parent
to read, however, we shouldn't pop up the top-level window, because
that's our parent's job; when running that child, set its "argv[0]" to a
special name, so that
1) it shows up in a "ps" with a special name;
2) we don't have to invent Yet Another Flag to say "you're the
child".
(We may want to use the name to turn on *all* behaviors that the capture
child, and only the capture child, should exhibit.)
If "-w" and "-k" were both specified, attempt to open the file specified
by "-w" and, if that succeeds, set "cf.save_file_fd" to refer to it, so
that "-w" plus "-k" works again, rather than popping up a "The file to
which the capture would be saved ... could not be opened: Bad file
descriptor." message box.
svn path=/trunk/; revision=739
1999-09-30 06:11:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
1998-09-16 02:39:15 +00:00
|
|
|
gtk_main();
|
|
|
|
|
1999-08-26 06:20:50 +00:00
|
|
|
ethereal_proto_cleanup();
|
1999-11-10 19:58:54 +00:00
|
|
|
g_free(rc_file);
|
1999-08-26 06:20:50 +00:00
|
|
|
|
1998-09-16 02:39:15 +00:00
|
|
|
exit(0);
|
|
|
|
}
|