/* file.c
* File I/O routines
*
- * $Id: file.c,v 1.209 2000/08/21 21:24:01 deniel Exp $
+ * $Id: file.c,v 1.234 2001/03/24 02:07:20 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
# include <netinet/in.h>
#endif
+#include <epan.h>
+
#include "gtk/main.h"
+#include "color.h"
+#include "gtk/color_utils.h"
#include "column.h"
#include "packet.h"
#include "print.h"
#include "menu.h"
#include "util.h"
#include "simple_dialog.h"
+#include "progress_dlg.h"
#include "ui_util.h"
#include "prefs.h"
#include "gtk/proto_draw.h"
-#include "dfilter.h"
+#include "dfilter/dfilter.h"
#include "conversation.h"
#include "globals.h"
+#include "gtk/colors.h"
-#include "plugins.h"
-
-extern GtkWidget *packet_list, *info_bar, *byte_view, *tree_view;
+extern GtkWidget *packet_list, *info_bar, *byte_nb_ptr, *tree_view;
extern guint file_ctx;
gboolean auto_scroll_live = FALSE;
static void read_packet(capture_file *cf, int offset);
static void rescan_packets(capture_file *cf, const char *action,
- gboolean refilter);
+ gboolean refilter, gboolean redissect);
static void set_selected_row(int row);
close_cap_file(cf, info_bar);
/* Initialize the table of conversations. */
- conversation_init();
+ epan_conversation_init();
/* Initialize protocol-specific variables */
init_all_protocols();
cf->cd_t = wtap_file_type(cf->wth);
cf->count = 0;
+ cf->drops_known = FALSE;
cf->drops = 0;
cf->esec = 0;
cf->eusec = 0;
cf->plist_chunk = NULL;
}
if (cf->rfcode != NULL) {
- dfilter_destroy(cf->rfcode);
+ dfilter_free(cf->rfcode);
cf->rfcode = NULL;
}
cf->plist = NULL;
{
gchar *name_ptr;
size_t msg_len;
- gchar *done_fmt = " File: %s Drops: %u";
+ static const gchar done_fmt_nodrops[] = " File: %s";
+ static const gchar done_fmt_drops[] = " File: %s Drops: %u";
gchar *done_msg;
gchar *win_name_fmt = "%s - Ethereal";
gchar *win_name;
name_ptr = "<capture>";
}
- msg_len = strlen(name_ptr) + strlen(done_fmt) + 64;
- done_msg = g_malloc(msg_len);
- snprintf(done_msg, msg_len, done_fmt, name_ptr, cf->drops);
+ if (cf->drops_known) {
+ msg_len = strlen(name_ptr) + strlen(done_fmt_drops) + 64;
+ done_msg = g_malloc(msg_len);
+ snprintf(done_msg, msg_len, done_fmt_drops, name_ptr, cf->drops);
+ } else {
+ msg_len = strlen(name_ptr) + strlen(done_fmt_nodrops);
+ done_msg = g_malloc(msg_len);
+ snprintf(done_msg, msg_len, done_fmt_nodrops, name_ptr);
+ }
gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, done_msg);
g_free(done_msg);
progbar = create_progress_dlg(load_msg, "Stop", &stop_flag);
g_free(load_msg);
- while ((data_offset = wtap_read(cf->wth, err)) > 0) {
+ while ((wtap_read(cf->wth, err, &data_offset))) {
/* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
when we update it, we have to run the GTK+ main loop to get it
to repaint what's pending, and doing so may involve an "ioctl()"
if (cf->first_displayed != NULL)
gtk_signal_emit_by_name(GTK_OBJECT(packet_list), "select_row", 0);
- if (data_offset < 0) {
+ if (*err != 0) {
/* Put up a message box noting that the read failed somewhere along
the line. Don't throw out the stuff we managed to read, though,
if any. */
gtk_clist_freeze(GTK_CLIST(packet_list));
- while (to_read != 0 && (data_offset = wtap_read(cf->wth, err)) > 0) {
+ while (to_read != 0 && (wtap_read(cf->wth, err, &data_offset))) {
if (cf->state == FILE_READ_ABORTED) {
/* Well, the user decided to exit Ethereal. Break out of the
loop, and let the code below (which is called even if there
"finish_tail_cap_file()" will be called, and it will clean up
and exit. */
return READ_ABORTED;
- } else if (data_offset < 0) {
+ } else if (*err != 0) {
/* We got an error reading the capture file.
XXX - pop up a dialog box? */
return (READ_ERROR);
gtk_clist_freeze(GTK_CLIST(packet_list));
- while ((data_offset = wtap_read(cf->wth, err)) > 0) {
+ while ((wtap_read(cf->wth, err, &data_offset))) {
if (cf->state == FILE_READ_ABORTED) {
/* Well, the user decided to abort the read. Break out of the
loop, and let the code below (which is called even if there
set_menus_for_capture_file(TRUE);
set_menus_for_unsaved_capture_file(!cf->user_saved);
- if (data_offset < 0) {
+ if (*err != 0) {
/* We got an error reading the capture file.
XXX - pop up a dialog box? */
return (READ_ERROR);
typedef struct {
color_filter_t *colorf;
- proto_tree *protocol_tree;
- const guint8 *pd;
- frame_data *fdata;
+ epan_dissect_t *edt;
} apply_color_filter_args;
/*
apply_color_filter_args *args = argp;
if (colorf->c_colorfilter != NULL && args->colorf == NULL) {
- if (dfilter_apply(colorf->c_colorfilter, args->protocol_tree, args->pd, args->fdata->cap_len))
+ if (dfilter_apply_edt(colorf->c_colorfilter, args->edt))
args->colorf = colorf;
}
}
apply_color_filter_args args;
gint i, row;
proto_tree *protocol_tree = NULL;
+ epan_dissect_t *edt;
+ GdkColor fg, bg;
/* We don't yet have a color filter to apply. */
args.colorf = NULL;
firstusec = fdata->abs_usecs;
}
- /* Get the time elapsed between the first packet and this packet. */
- cf->esec = fdata->abs_secs - firstsec;
- if (firstusec <= fdata->abs_usecs) {
- cf->eusec = fdata->abs_usecs - firstusec;
- } else {
- cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
- cf->esec--;
- }
-
fdata->cinfo = &cf->cinfo;
for (i = 0; i < fdata->cinfo->num_cols; i++) {
- fdata->cinfo->col_data[i][0] = '\0';
+ fdata->cinfo->col_buf[i][0] = '\0';
+ fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
}
/* If either
we have a list of color filters;
- we have plugins to apply;
-
allocate a protocol tree root node, so that we'll construct
a protocol tree against which a filter expression can be
evaluated. */
- if ((cf->dfcode != NULL && refilter) || filter_list != NULL
-#ifdef HAVE_PLUGINS
- || enabled_plugins_number > 0
-#endif
- )
+ if ((cf->dfcode != NULL && refilter) || filter_list != NULL)
protocol_tree = proto_tree_create_root();
/* Dissect the frame. */
- dissect_packet(pseudo_header, buf, fdata, protocol_tree);
+ edt = epan_dissect_new(pseudo_header, buf, fdata, protocol_tree);
/* If we have a display filter, apply it if we're refiltering, otherwise
leave the "passed_dfilter" flag alone.
if (cf->dfcode != NULL) {
if (refilter) {
if (cf->dfcode != NULL)
- fdata->flags.passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, buf, fdata->cap_len) ? 1 : 0;
+ fdata->flags.passed_dfilter = dfilter_apply_edt(cf->dfcode, edt) ? 1 : 0;
else
fdata->flags.passed_dfilter = 1;
}
the color filters. */
if (fdata->flags.passed_dfilter) {
if (filter_list != NULL) {
- args.protocol_tree = protocol_tree;
- args.pd = buf;
- args.fdata = fdata;
+ args.edt = edt;
g_slist_foreach(filter_list, apply_color_filter, &args);
}
}
if (protocol_tree != NULL)
proto_tree_free(protocol_tree);
+ epan_dissect_free(edt);
+
if (fdata->flags.passed_dfilter) {
/* This frame passed the display filter, so add it to the clist. */
}
/* Get the time elapsed between the first packet and this packet. */
- fdata->rel_secs = cf->esec;
- fdata->rel_usecs = cf->eusec;
+ compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
+ fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
+
+ /* If it's greater than the current elapsed time, set the elapsed time
+ to it (we check for "greater than" so as not to be confused by
+ time moving backwards). */
+ if (cf->esec < fdata->rel_secs
+ || (cf->esec == fdata->rel_secs && cf->eusec < fdata->rel_usecs)) {
+ cf->esec = fdata->rel_secs;
+ cf->eusec = fdata->rel_usecs;
+ }
/* Get the time elapsed between the previous displayed packet and
this packet. */
- fdata->del_secs = fdata->abs_secs - prevsec;
- if (prevusec <= fdata->abs_usecs) {
- fdata->del_usecs = fdata->abs_usecs - prevusec;
- } else {
- fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
- fdata->del_secs--;
- }
+ compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
+ fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
prevsec = fdata->abs_secs;
prevusec = fdata->abs_usecs;
gtk_clist_set_row_data(GTK_CLIST(packet_list), row, fdata);
if (fdata->flags.marked) {
- gtk_clist_set_background(GTK_CLIST(packet_list), row, &prefs.gui_marked_bg);
- gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &prefs.gui_marked_fg);
+ color_t_to_gdkcolor(&bg, &prefs.gui_marked_bg);
+ color_t_to_gdkcolor(&fg, &prefs.gui_marked_fg);
} else if (filter_list != NULL && (args.colorf != NULL)) {
- gtk_clist_set_background(GTK_CLIST(packet_list), row,
- &args.colorf->bg_color);
- gtk_clist_set_foreground(GTK_CLIST(packet_list), row,
- &args.colorf->fg_color);
+ bg = args.colorf->bg_color;
+ fg = args.colorf->fg_color;
} else {
- gtk_clist_set_background(GTK_CLIST(packet_list), row, &WHITE);
- gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &BLACK);
+ bg = WHITE;
+ fg = BLACK;
}
+ gtk_clist_set_background(GTK_CLIST(packet_list), row, &bg);
+ gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &fg);
} else {
/* This frame didn't pass the display filter, so it's not being added
to the clist, and thus has no row. */
int passed;
proto_tree *protocol_tree;
frame_data *plist_end;
+ epan_dissect_t *edt;
/* Allocate the next list entry, and add it to the list. */
fdata = g_mem_chunk_alloc(cf->plist_chunk);
fdata->next = NULL;
fdata->prev = NULL;
fdata->pfd = NULL;
+ fdata->data_src = NULL;
fdata->pkt_len = phdr->len;
fdata->cap_len = phdr->caplen;
fdata->file_off = offset;
passed = TRUE;
if (cf->rfcode) {
protocol_tree = proto_tree_create_root();
- dissect_packet(pseudo_header, buf, fdata, protocol_tree);
- passed = dfilter_apply(cf->rfcode, protocol_tree, buf, fdata->cap_len);
+ edt = epan_dissect_new(pseudo_header, buf, fdata, protocol_tree);
+ passed = dfilter_apply_edt(cf->rfcode, edt);
proto_tree_free(protocol_tree);
+ epan_dissect_free(edt);
}
if (passed) {
plist_end = cf->plist_end;
int
filter_packets(capture_file *cf, gchar *dftext)
{
- dfilter *dfcode;
+ dfilter_t *dfcode;
if (dftext == NULL) {
/* The new filter is an empty filter (i.e., display all packets). */
/*
* We have a filter; try to compile it.
*/
- if (dfilter_compile(dftext, &dfcode) != 0) {
+ if (!dfilter_compile(dftext, &dfcode)) {
/* The attempt failed; report an error. */
simple_dialog(ESD_TYPE_CRIT, NULL, dfilter_error_msg);
return 0;
g_free(cf->dfilter);
cf->dfilter = dftext;
if (cf->dfcode != NULL)
- dfilter_destroy(cf->dfcode);
+ dfilter_free(cf->dfcode);
cf->dfcode = dfcode;
- /* Now rescan the packet list, applying the new filter. */
- rescan_packets(cf, "Filtering", TRUE);
+ /* Now rescan the packet list, applying the new filter, but not
+ throwing away information constructed on a previous pass. */
+ rescan_packets(cf, "Filtering", TRUE, FALSE);
return 1;
}
void
colorize_packets(capture_file *cf)
{
- rescan_packets(cf, "Colorizing", FALSE);
+ rescan_packets(cf, "Colorizing", FALSE, FALSE);
}
void
redissect_packets(capture_file *cf)
{
- rescan_packets(cf, "Reprocessing", TRUE);
+ rescan_packets(cf, "Reprocessing", TRUE, TRUE);
}
/* Rescan the list of packets, reconstructing the CList.
"action" describes why we're doing this; it's used in the progress
dialog box.
- "refilter" is TRUE if we need to re-evaluate the filter expression. */
+ "refilter" is TRUE if we need to re-evaluate the filter expression.
+
+ "redissect" is TRUE if we need to make the dissectors reconstruct
+ any state information they have (because a preference that affects
+ some dissector has changed, meaning some dissector might construct
+ its state differently from the way it was constructed the last time). */
static void
-rescan_packets(capture_file *cf, const char *action, gboolean refilter)
+rescan_packets(capture_file *cf, const char *action, gboolean refilter,
+ gboolean redissect)
{
frame_data *fdata;
progdlg_t *progbar;
rebuild the clist, however. */
selected_row = -1;
- /* We need to re-initialize all the state information that protocols
- keep, because we're making a fresh pass through all the packets. */
+ if (redissect) {
+ /* We need to re-initialize all the state information that protocols
+ keep, because some preference that controls a dissector has changed,
+ which might cause the state information to be constructed differently
+ by that dissector. */
- /* Initialize the table of conversations. */
- conversation_init();
+ /* Initialize the table of conversations. */
+ epan_conversation_init();
- /* Initialize protocol-specific variables */
- init_all_protocols();
+ /* Initialize protocol-specific variables */
+ init_all_protocols();
+ }
/* Freeze the packet list while we redo it, so we don't get any
screen updates while it happens. */
count++;
- /* Since all state for the frame was destroyed, mark the frame
- * as not visited. */
- fdata->flags.visited = 0;
+ if (redissect) {
+ /* Since all state for the frame was destroyed, mark the frame
+ * as not visited, free the GSList referring to the state
+ * data (the per-frame data itself was freed by
+ * "init_all_protocols()"), and null out the GSList pointer. */
+ fdata->flags.visited = 0;
+ if (fdata->pfd) {
+ g_slist_free(fdata->pfd);
+ }
+ fdata->pfd = NULL;
+ if (fdata->data_src) { /* release data source list */
+ g_slist_free(fdata->data_src);
+ }
+ fdata->data_src = NULL;
+ }
wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
cf->pd, fdata->cap_len);
selected_row = row;
}
+ if (redissect) {
+ /* Clear out what remains of the visited flags and per-frame data
+ pointers.
+
+ XXX - that may cause various forms of bogosity when dissecting
+ these frames, as they won't have been seen by this sequential
+ pass, but the only alternative I see is to keep scanning them
+ even though the user requested that the scan stop, and that
+ would leave the user stuck with an Ethereal grinding on
+ until it finishes. Should we just stick them with that? */
+ for (; fdata != NULL; fdata = fdata->next) {
+ fdata->flags.visited = 0;
+ if (fdata->pfd) {
+ g_slist_free(fdata->pfd);
+ }
+ fdata->pfd = NULL;
+ if (fdata->data_src) {
+ g_slist_free(fdata->data_src);
+ }
+ fdata->data_src = NULL;
+ }
+ }
+
/* We're done filtering the packets; destroy the progress bar. */
destroy_progress_dlg(progbar);
char *cp;
int column_len;
int line_len;
+ epan_dissect_t *edt = NULL;
cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
if (cf->print_fh == NULL)
the logical protocol tree. */
fdata->cinfo = &cf->cinfo;
for (i = 0; i < fdata->cinfo->num_cols; i++) {
- fdata->cinfo->col_data[i][0] = '\0';
+ fdata->cinfo->col_buf[i][0] = '\0';
+ fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
}
- dissect_packet(&cf->pseudo_header, cf->pd, fdata, NULL);
+ edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, NULL);
fill_in_columns(fdata);
cp = &line_buf[0];
line_len = 0;
/* Create the logical protocol tree. */
protocol_tree = proto_tree_create_root();
- dissect_packet(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
+ edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
/* Print the information in that tree. */
proto_tree_print(FALSE, print_args, (GNode *)protocol_tree,
if (print_args->print_hex) {
/* Print the full packet data as hex. */
- print_hex_data(cf->print_fh, print_args->format, cf->pd,
- fdata->cap_len, fdata->flags.encoding);
+ print_hex_data(cf->print_fh, print_args->format, fdata);
}
/* Print a blank line if we print anything after this. */
print_separator = TRUE;
}
+ epan_dissect_free(edt);
}
}
if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
/* This is one of the columns that shows the time in
"command-line-specified" format; update it. */
- cf->cinfo.col_data[i][0] = '\0';
+ cf->cinfo.col_buf[i][0] = '\0';
col_set_cls_time(fdata, i);
gtk_clist_set_text(GTK_CLIST(packet_list), row, i,
cf->cinfo.col_data[i]);
clear_tree_and_hex_views(void)
{
/* Clear the hex dump. */
- 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)));
- gtk_text_thaw(GTK_TEXT(byte_view));
+ GtkWidget *byte_view;
+ int i;
+
+/* Get the current tab scroll window, then get the text widget */
+/* from the E_BYTE_VIEW_TEXT_INFO_KEY data field */
+
+ i = gtk_notebook_get_current_page( GTK_NOTEBOOK(byte_nb_ptr));
+
+ if ( i >= 0){
+ byte_view = gtk_notebook_get_nth_page( GTK_NOTEBOOK(byte_nb_ptr), i);
+ byte_view = gtk_object_get_data(GTK_OBJECT(byte_view), E_BYTE_VIEW_TEXT_INFO_KEY);
+
+ 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)));
+ gtk_text_thaw(GTK_TEXT(byte_view));
+ }
/* Remove all nodes in ctree. This is how it's done in testgtk.c in GTK+ */
gtk_clist_clear ( GTK_CLIST(tree_view) );
}
gboolean
-find_packet(capture_file *cf, dfilter *sfcode)
+find_packet(capture_file *cf, dfilter_t *sfcode)
{
frame_data *start_fd;
frame_data *fdata;
proto_tree *protocol_tree;
gboolean frame_matched;
int row;
+ epan_dissect_t *edt;
start_fd = cf->current_frame;
if (start_fd != NULL) {
protocol_tree = proto_tree_create_root();
wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
cf->pd, fdata->cap_len);
- dissect_packet(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
- frame_matched = dfilter_apply(sfcode, protocol_tree, cf->pd, fdata->cap_len);
+ edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
+ frame_matched = dfilter_apply_edt(sfcode, edt);
proto_tree_free(protocol_tree);
+ epan_dissect_free(edt);
if (frame_matched) {
new_fd = fdata;
break; /* found it! */
select_packet(capture_file *cf, int row)
{
frame_data *fdata;
+ tvbuff_t *bv_tvb;
+ int i;
/* Get the frame data struct pointer for this frame */
fdata = (frame_data *) gtk_clist_get_row_data(GTK_CLIST(packet_list), row);
proto_tree_free(cf->protocol_tree);
cf->protocol_tree = proto_tree_create_root();
proto_tree_is_visible = TRUE;
- dissect_packet(&cf->pseudo_header, cf->pd, cf->current_frame,
+ cf->edt = epan_dissect_new(&cf->pseudo_header, cf->pd, cf->current_frame,
cf->protocol_tree);
proto_tree_is_visible = FALSE;
/* Display the GUI protocol tree and hex dump. */
clear_tree_and_hex_views();
+
+ i = 0;
+ while((bv_tvb = g_slist_nth_data ( cf->current_frame->data_src, i++))){
+ add_byte_view( tvb_get_name( bv_tvb), tvb_get_ptr(bv_tvb, 0, -1), tvb_length(bv_tvb));
+ }
+
proto_tree_draw(cf->protocol_tree, tree_view);
- packet_hex_print(GTK_TEXT(byte_view), cf->pd, cf->current_frame->cap_len,
- -1, -1, cf->current_frame->flags.encoding);
+
+ set_notebook_page( byte_nb_ptr, 0);
/* A packet is selected. */
set_menus_for_selected_packet(TRUE);
if (cf->protocol_tree != NULL) {
proto_tree_free(cf->protocol_tree);
cf->protocol_tree = NULL;
+ epan_dissect_free(cf->edt);
}
finfo_selected = NULL;
break;
case WTAP_ERR_SHORT_WRITE:
- errmsg = "Not all the data could be written to the file \"%s\".";
+ errmsg = "Not all the packets could be written to the file \"%s\".";
break;
case ENOSPC: