#include "merge.h"
#include "alert_box.h"
#include "simple_dialog.h"
+#include "main_statusbar.h"
#include "progress_dlg.h"
#include "ui_util.h"
#include <epan/prefs.h>
#include <epan/dfilter/dfilter-macro.h>
#include <wsutil/file_util.h>
#include <epan/strutil.h>
+#include <epan/addr_resolv.h>
#ifdef HAVE_LIBPCAP
gboolean auto_scroll_live;
static void rescan_packets(capture_file *cf, const char *action, const char *action_item,
gboolean refilter, gboolean redissect);
-static gboolean match_protocol_tree(capture_file *cf, frame_data *fdata,
+typedef enum {
+ MR_NOTMATCHED,
+ MR_MATCHED,
+ MR_ERROR
+} match_result;
+static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
void *criterion);
static void match_subtree_text(proto_node *node, gpointer data);
-static gboolean match_summary_line(capture_file *cf, frame_data *fdata,
+static match_result match_summary_line(capture_file *cf, frame_data *fdata,
void *criterion);
-static gboolean match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
+static match_result match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
void *criterion);
-static gboolean match_ascii(capture_file *cf, frame_data *fdata,
+static match_result match_ascii(capture_file *cf, frame_data *fdata,
void *criterion);
-static gboolean match_unicode(capture_file *cf, frame_data *fdata,
+static match_result match_unicode(capture_file *cf, frame_data *fdata,
void *criterion);
-static gboolean match_binary(capture_file *cf, frame_data *fdata,
+static match_result match_binary(capture_file *cf, frame_data *fdata,
void *criterion);
-static gboolean match_dfilter(capture_file *cf, frame_data *fdata,
+static match_result match_dfilter(capture_file *cf, frame_data *fdata,
void *criterion);
-static gboolean find_packet(capture_file *cf,
- gboolean (*match_function)(capture_file *, frame_data *, void *),
+static match_result match_marked(capture_file *cf, frame_data *fdata,
void *criterion);
+static match_result match_time_reference(capture_file *cf, frame_data *fdata,
+ void *criterion);
+static gboolean find_packet(capture_file *cf,
+ match_result (*match_function)(capture_file *, frame_data *, void *),
+ void *criterion, search_direction dir);
static void cf_open_failure_alert_box(const char *filename, int err,
gchar *err_info, gboolean for_writing,
static const char *file_rename_error_message(int err);
static void cf_write_failure_alert_box(const char *filename, int err);
static void cf_close_failure_alert_box(const char *filename, int err);
-#ifdef NEW_PACKET_LIST
static void ref_time_packets(capture_file *cf);
-#endif
/* Update the progress bar this many times when reading a file. */
#define N_PROGBAR_UPDATES 100
/* We read around 200k/100ms don't update the progress bar more often than that */
#define FRAME_DATA_CHUNK_SIZE 1024
-/* this callback mechanism should possibly be replaced by the g_signal_...() stuff (if I only would know how :-) */
+/*
+ * We could probably use g_signal_...() instead of the callbacks below but that
+ * would require linking our CLI programs to libgobject and creating an object
+ * instance for the signals.
+ */
typedef struct {
cf_callback_t cb_fct;
gpointer user_data;
void
cf_timestamp_auto_precision(capture_file *cf)
{
-#ifdef NEW_PACKET_LIST
int i;
-#endif
int prec = timestamp_get_precision();
g_assert_not_reached();
}
}
-#ifdef NEW_PACKET_LIST
/* Set the column widths of those columns that show the time in
"command-line-specified" format. */
for (i = 0; i < cf->cinfo.num_cols; i++) {
new_packet_list_resize_column(i);
}
}
-#endif
}
gulong
cf->displayed_count = 0;
cf->marked_count = 0;
cf->ignored_count = 0;
+ cf->ref_time_count = 0;
cf->drops_known = FALSE;
cf->drops = 0;
cf->snap = wtap_snapshot_length(cf->wth);
g_assert(cf->plist_chunk);
#endif
-#ifdef NEW_PACKET_LIST
/* Adjust timestamp precision if auto is selected, col width will be adjusted */
cf_timestamp_auto_precision(cf);
/* XXX needed ? */
new_packet_list_queue_draw();
-#else
- /* change the time formats now, as we might have a new precision */
- cf_change_time_formats(cf);
-#endif
fileset_file_opened(fname);
if(cf->cd_t == WTAP_FILE_BER) {
ber_set_filename(cf->filename);
}
+ wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
+ wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
+
return CF_OK;
fail:
cf->finfo_selected = NULL;
/* Clear the packet list. */
-#ifdef NEW_PACKET_LIST
new_packet_list_freeze();
new_packet_list_clear();
new_packet_list_thaw();
-#else
- packet_list_freeze();
- packet_list_clear();
- packet_list_thaw();
-#endif
cf->f_datalen = 0;
cf->count = 0;
main_window_exit();
}
-static float calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos){
-
+static float
+calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
+{
float progbar_val;
progbar_val = (gfloat) file_pos / (gfloat) size;
if (progbar_val > 1.0) {
- /* The file probably grew while we were reading it.
- Update file size, and try again. */
+
+ /* The file probably grew while we were reading it.
+ * Update file size, and try again.
+ */
size = wtap_file_size(cf->wth, NULL);
+
+ /* Another possibility is that we're reading a compressed file and we've
+ * read more (uncompressed) data from the file than exists in the
+ * (compressed) file. So check how much data we've actually read.
+ *
+ * This is inside this "if val > 1.0" check to avoid the lseek() when
+ * reading uncompressed files. Testing has (thus far) shown no progress
+ * bar weirdness resulting from switching from the data offset (when
+ * reading the first part of the file) to the real file position.
+ */
+ file_pos = wtap_read_so_far(cf->wth, NULL);
+
if (size >= 0)
progbar_val = (gfloat) file_pos / (gfloat) size;
- /* If it's still > 1, either "wtap_file_size()" failed (in which
- case there's not much we can do about it), or the file
- *shrank* (in which case there's not much we can do about
- it); just clip the progress value at 1.0. */
+
+ /* If it's still > 1, either "wtap_file_size()" failed (in which
+ * case there's not much we can do about it), or the file
+ * *shrank* (in which case there's not much we can do about
+ * it); just clip the progress value at 1.0.
+ */
if (progbar_val > 1.0f)
progbar_val = 1.0f;
}
+
+ g_snprintf(status_str, status_size,
+ "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
+ file_pos / 1024, size / 1024);
+
return progbar_val;
}
/* Progress so far. */
progbar_val = 0.0f;
-#ifdef NEW_PACKET_LIST
new_packet_list_freeze();
-#else
- packet_list_freeze();
-#endif
stop_flag = FALSE;
g_get_current_time(&start_time);
if (size >= 0) {
count++;
/* Create the progress bar if necessary.
- * Check wether it should be created or not every MIN_NUMBER_OF_PACKET
+ * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
*/
if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)){
- progbar_val = calc_progbar_val( cf, size, data_offset);
+ progbar_val = calc_progbar_val(cf, size, data_offset, status_str, sizeof(status_str));
if (from_save == FALSE)
progbar = delayed_create_progress_dlg("Loading", name_ptr,
TRUE, &stop_flag, &start_time, progbar_val);
that for every packet can be costly, especially on a big file. */
if (data_offset >= progbar_nextstep) {
if (progbar != NULL) {
- progbar_val = calc_progbar_val( cf, size, data_offset);
+ progbar_val = calc_progbar_val(cf, size, data_offset, status_str, sizeof(status_str));
/* update the packet lists content on the first run or frequently on very large files */
/* (on smaller files the display update takes longer than reading the file) */
#ifdef HAVE_LIBPCAP
if (progbar_quantum > 500000 || displayed_once == 0) {
if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->plist_end != NULL) {
displayed_once = 1;
-#ifdef NEW_PACKET_LIST
new_packet_list_thaw();
if (auto_scroll_live)
new_packet_list_moveto_end();
new_packet_list_freeze();
-#else
- packet_list_thaw();
- if (auto_scroll_live)
- packet_list_moveto_end();
- packet_list_freeze();
-#endif /* NEW_PACKET_LIST */
}
}
#endif /* HAVE_LIBPCAP */
- g_snprintf(status_str, sizeof(status_str),
- "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
- data_offset / 1024, size / 1024);
update_progress_dlg(progbar, progbar_val, status_str);
}
progbar_nextstep += progbar_quantum;
cf->current_frame = cf->first_displayed;
cf->current_row = 0;
-#ifdef NEW_PACKET_LIST
new_packet_list_thaw();
-#else
- packet_list_thaw();
-#endif
if (from_save == FALSE)
cf_callback_invoke(cf_cb_file_read_finished, cf);
else
/* If we have any displayed packets to select, select the first of those
packets by making the first row the selected row. */
if (cf->first_displayed != NULL){
-#ifdef NEW_PACKET_LIST
new_packet_list_select_first_row();
-#else
- packet_list_select_row(0);
-#endif /* NEW_PACKET_LIST */
}
if(stop_flag) {
dfilter_t *dfcode;
gboolean filtering_tap_listeners;
guint tap_flags;
- volatile gboolean visible = FALSE;
gboolean compiled;
/* Compile the current display filter.
*err = 0;
-#ifdef NEW_PACKET_LIST
new_packet_list_check_end();
/* Don't freeze/thaw the list when doing live capture */
/*new_packet_list_freeze();*/
-#else
- packet_list_check_end();
- packet_list_freeze();
-#endif
/*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
- wtap_cleareof(cf->wth);
- while (to_read != 0 && (wtap_read(cf->wth, err, &err_info, &data_offset))) {
+ while (to_read != 0) {
+ wtap_cleareof(cf->wth);
+ if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
+ break;
+ }
if (cf->state == FILE_READ_ABORTED) {
/* Well, the user decided to exit Wireshark. Break out of the
loop, and let the code below (which is called even if there
TRY{
if (read_packet(cf, dfcode, filtering_tap_listeners, tap_flags,
data_offset) != -1) {
- visible = TRUE;
newly_displayed_packets++;
- }else{
- visible = FALSE;
}
}
CATCH(OutOfMemoryError) {
/* XXX - how to avoid a busy wait? */
/* Sleep(100); */
};
-#ifdef NEW_PACKET_LIST
/* Don't freeze/thaw the list when doing live capture */
/*new_packet_list_thaw();*/
-#else
- packet_list_thaw();
-#endif
return CF_READ_ABORTED;
}
ENDTRY;
/*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
cf->count, cf->state, *err);*/
-#ifdef NEW_PACKET_LIST
/* Don't freeze/thaw the list when doing live capture */
/*new_packet_list_thaw();*/
/* With the new packet list the first packet
*/
if(!cf->current_frame)
new_packet_list_select_first_row();
-#else
- /* XXX - this causes "flickering" of the list */
- packet_list_thaw();
-#endif
/* moving to the end of the packet list - if the user requested so and
we have some new packets. */
if (newly_displayed_packets && auto_scroll_live && cf->plist_end != NULL)
-#ifdef NEW_PACKET_LIST
- if(visible)
new_packet_list_moveto_end();
-#else
- /* this doesn't seem to work well with a frozen GTK_Clist, so do this after
- packet_list_thaw() is done, see bugzilla 1188 */
- /* XXX - this cheats and looks inside the packet list to find the final
- row number. */
- packet_list_moveto_end();
-#endif /* NEW_PACKET_LIST */
if (cf->state == FILE_READ_ABORTED) {
/* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
return CF_READ_OK;
}
+void
+cf_fake_continue_tail(capture_file *cf) {
+ cf->state = FILE_READ_DONE;
+}
+
cf_read_status_t
cf_finish_tail(capture_file *cf, int *err)
{
return CF_READ_ERROR;
}
-#ifdef NEW_PACKET_LIST
new_packet_list_check_end();
/* Don't freeze/thaw the list when doing live capture */
/*new_packet_list_freeze();*/
-#else
- packet_list_check_end();
- packet_list_freeze();
-#endif
while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
if (cf->state == FILE_READ_ABORTED) {
dfilter_free(dfcode);
}
-#ifdef NEW_PACKET_LIST
/* Don't freeze/thaw the list when doing live capture */
/*new_packet_list_thaw();*/
-#else
- packet_list_thaw();
-#endif
if (cf->state == FILE_READ_ABORTED) {
/* Well, the user decided to abort the read. We're only called
}
if (auto_scroll_live && cf->plist_end != NULL)
-#ifdef NEW_PACKET_LIST
new_packet_list_moveto_end();
-#else
- /* XXX - this cheats and looks inside the packet list to find the final
- row number. */
- packet_list_moveto_end();
-#endif
/* We're done reading sequentially through the file. */
cf->state = FILE_READ_DONE;
cf->rfcode = rfcode;
}
-#ifdef NEW_PACKET_LIST
static int
add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
dfilter_t *dfcode, gboolean filtering_tap_listeners,
} else
fdata->flags.passed_dfilter = 1;
+ if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
+ cf->displayed_count++;
+
if (add_to_packet_list) {
/* We fill the needed columns from new_packet_list */
row = new_packet_list_append(cinfo, fdata, &edt.pi);
/* This is the last frame we've seen so far. */
cf->last_displayed = fdata;
-
- cf->displayed_count++;
}
epan_dissect_cleanup(&edt);
return row;
}
-#else
-
-static int
-add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
- dfilter_t *dfcode, gboolean filtering_tap_listeners,
- guint tap_flags,
- union wtap_pseudo_header *pseudo_header, const guchar *buf,
- gboolean refilter,
- gboolean add_to_packet_list _U_)
+/*
+ * Initialize the col_text and col_text_len arrays.
+ */
+static void
+init_col_text(frame_data *fdata, gint num_cols)
{
- gboolean create_proto_tree = FALSE;
- epan_dissect_t edt;
- column_info *cinfo;
- gint row = -1;
-
- cinfo = &cf->cinfo;
-
- /* just add some value here until we know if it is being displayed or not */
- fdata->cum_bytes = cum_bytes + fdata->pkt_len;
-
- frame_data_set_before_dissect(fdata, &cf->elapsed_time,
- &first_ts, &prev_dis_ts, &prev_cap_ts);
-
- /* If either
-
- we have a display filter and are re-applying it;
-
- we have a list of color filters;
-
- we have tap listeners with filters;
-
- we have tap listeners that require a protocol tree;
-
- we have custom columns;
-
- allocate a protocol tree root node, so that we'll construct
- a protocol tree against which a filter expression can be
- evaluated. */
- if ((dfcode != NULL && refilter) ||
- color_filters_used() ||
- have_custom_cols(cinfo) ||
- filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE))
- create_proto_tree = TRUE;
-
- /* Dissect the frame. */
- epan_dissect_init(&edt, create_proto_tree, FALSE);
-
- if (dfcode != NULL && refilter) {
- epan_dissect_prime_dfilter(&edt, dfcode);
- }
-
- /* prepare color filters */
- color_filters_prime_edt(&edt);
- col_custom_prime_edt(&edt, cinfo);
-
- tap_queue_init(&edt);
- epan_dissect_run(&edt, pseudo_header, buf, fdata, cinfo);
- tap_push_tapped_queue(&edt);
-
- /* If we have a display filter, apply it if we're refiltering, otherwise
- leave the "passed_dfilter" flag alone.
-
- If we don't have a display filter, set "passed_dfilter" to 1. */
- if (dfcode != NULL) {
- if (refilter) {
- fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0;
- }
- } else
- fdata->flags.passed_dfilter = 1;
-
- if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) )
- {
- frame_data_set_after_dissect(fdata, &cum_bytes, &prev_dis_ts);
-
- epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
-
- /* If we haven't yet seen the first frame, this is it.
-
- XXX - we must do this before we add the row to the display,
- as, if the display's GtkCList's selection mode is
- GTK_SELECTION_BROWSE, when the first entry is added to it,
- "cf_select_packet()" will be called, and it will fetch the row
- data for the 0th row, and will get a null pointer rather than
- "fdata", as "gtk_clist_append()" won't yet have returned and
- thus "gtk_clist_set_row_data()" won't yet have been called.
-
- We thus need to leave behind bread crumbs so that
- "cf_select_packet()" can find this frame. See the comment
- in "cf_select_packet()". */
- if (cf->first_displayed == NULL)
- cf->first_displayed = fdata;
-
- /* This is the last frame we've seen so far. */
- cf->last_displayed = fdata;
-
- row = packet_list_append(cinfo->col_data, fdata);
-
- /* colorize packet: first apply color filters
- * then if packet is marked, use preferences to overwrite color
- * we do both to make sure that when a packet gets un-marked, the
- * color will be correctly set (fixes bug 2038)
- */
- fdata->color_filter = color_filters_colorize_packet(row, &edt);
- if (fdata->flags.marked) {
- packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
- }
- if (fdata->flags.ignored) {
- packet_list_set_colors(row, &prefs.gui_ignored_fg, &prefs.gui_ignored_bg);
- }
-
- cf->displayed_count++;
- }
-
- epan_dissect_cleanup(&edt);
- return row;
+ fdata->col_text_len = se_alloc0(sizeof(*fdata->col_text_len) * num_cols);
+ fdata->col_text = se_alloc0(sizeof(*fdata->col_text) * num_cols);
}
-#endif
/* read in a new packet */
/* returns the row of the new packet in the packet list or -1 if not displayed */
#endif
frame_data_init(fdata, cf->count, phdr, offset, cum_bytes);
-
-#ifdef NEW_PACKET_LIST
- fdata->col_text_len = se_alloc0(sizeof(fdata->col_text_len) * (cf->cinfo.num_cols));
- fdata->col_text = se_alloc0(sizeof(fdata->col_text) * (cf->cinfo.num_cols));
-#endif
+ init_col_text(fdata, cf->cinfo.num_cols);
passed = TRUE;
if (cf->rfcode) {
return CF_OK;
}
-void
-cf_colorize_packets(capture_file *cf)
-{
- rescan_packets(cf, "Colorizing", "all packets", FALSE, FALSE);
-}
-
void
cf_reftime_packets(capture_file *cf)
{
-#ifdef NEW_PACKET_LIST
ref_time_packets(cf);
-#else
- rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
-#endif
}
void
rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
}
+gboolean
+cf_read_frame_r(capture_file *cf, frame_data *fdata,
+ union wtap_pseudo_header *pseudo_header, guint8 *pd)
+{
+ int err;
+ gchar *err_info;
+ char errmsg_errno[1024+1];
+
+ if (!wtap_seek_read(cf->wth, fdata->file_off, pseudo_header, pd,
+ fdata->cap_len, &err, &err_info)) {
+ switch (err) {
+
+ case WTAP_ERR_UNSUPPORTED_ENCAP:
+ g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+ "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
+ err_info);
+ g_free(err_info);
+ break;
+
+ case WTAP_ERR_BAD_RECORD:
+ g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+ "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
+ wtap_strerror(err), err_info);
+ g_free(err_info);
+ break;
+
+ default:
+ g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+ "An error occurred while reading from the file \"%%s\": %s.",
+ wtap_strerror(err));
+ break;
+ }
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg_errno, cf->filename);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+gboolean
+cf_read_frame(capture_file *cf, frame_data *fdata)
+{
+ return cf_read_frame_r(cf, fdata, &cf->pseudo_header, cf->pd);
+}
+
/* Rescan the list of packets, reconstructing the CList.
"action" describes why we're doing this; it's used in the progress
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). */
-#ifdef NEW_PACKET_LIST
static void
rescan_packets(capture_file *cf, const char *action, const char *action_item,
gboolean refilter, gboolean redissect)
progdlg_t *progbar = NULL;
gboolean stop_flag;
int count;
- int err;
- gchar *err_info;
frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
gboolean selected_frame_seen;
- int frame_num;
float progbar_val;
GTimeVal start_time;
gchar status_str[100];
start? */
selected_frame = cf->current_frame;
- /* Mark frane num as not found */
+ /* Mark frame num as not found */
selected_frame_num = -1;
/* Freeze the packet list while we redo it, so we don't get any
g_get_current_time(&start_time);
/* no previous row yet */
- frame_num = -1;
prev_frame_num = -1;
prev_frame = NULL;
/* Well, the user decided to abort the filtering. Just stop.
XXX - go back to the previous filter? Users probably just
- want not to wait for a filtering operation to finish;
- unless we cancel by having no filter, reverting to the
- previous filter will probably be even more expensive than
- continuing the filtering, as it involves going back to the
- beginning and filtering, and even with no filter we currently
- have to re-generate the entire clist, which is also expensive.
-
- I'm not sure what Network Monitor does, but it doesn't appear
- to give you an unfiltered display if you cancel. */
+ want not to wait for a filtering operation to finish;
+ unless we cancel by having no filter, reverting to the
+ previous filter will probably be even more expensive than
+ continuing the filtering, as it involves going back to the
+ beginning and filtering, and even with no filter we currently
+ have to re-generate the entire clist, which is also expensive.
+
+ I'm not sure what Network Monitor does, but it doesn't appear
+ to give you an unfiltered display if you cancel. */
break;
}
* And after that fdata->col_text (which is allocated using se_alloc0())
* no longer points to valid memory.
*/
- fdata->col_text_len = se_alloc0(sizeof(fdata->col_text_len) * (cf->cinfo.num_cols));
- fdata->col_text = se_alloc0(sizeof(fdata->col_text) * (cf->cinfo.num_cols));
+ init_col_text(fdata, cf->cinfo.num_cols);
}
- if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
- cf->pd, fdata->cap_len, &err, &err_info)) {
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
- cf_read_error_message(err, err_info), cf->filename);
- break;
- }
+ if (!cf_read_frame(cf, fdata))
+ break; /* error reading the frame */
/* If the previous frame is displayed, and we haven't yet seen the
selected frame, remember that frame - it's the closest one we've
dfilter_free(dfcode);
}
-#else
+/*
+ * Scan trough all frame data and recalculate the ref time
+ * without rereading the file.
+ * XXX - do we need a progres bar or is this fast enough?
+ */
static void
-rescan_packets(capture_file *cf, const char *action, const char *action_item,
- gboolean refilter, gboolean redissect)
+ref_time_packets(capture_file *cf)
{
frame_data *fdata;
- progdlg_t *progbar = NULL;
- gboolean stop_flag;
- int count;
- int err;
- gchar *err_info;
- frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
- int selected_row, prev_row, preceding_row, following_row;
- gboolean selected_frame_seen;
- int row;
- float progbar_val;
- GTimeVal start_time;
- gchar status_str[100];
- int progbar_nextstep;
- int progbar_quantum;
- dfilter_t *dfcode;
- gboolean filtering_tap_listeners;
- guint tap_flags;
- gboolean add_to_packet_list = TRUE;
- gboolean compiled;
-
- /* Compile the current display filter.
- * We assume this will not fail since cf->dfilter is only set in
- * cf_filter IFF the filter was valid.
- */
- compiled = dfilter_compile(cf->dfilter, &dfcode);
- g_assert(!cf->dfilter || (compiled && dfcode));
-
- /* Do we have any tap listeners with filters? */
- filtering_tap_listeners = have_filtering_tap_listeners();
-
- /* Get the union of the flags for all tap listeners. */
- tap_flags = union_of_tap_listener_flags();
- reset_tap_listeners();
- /* Which frame, if any, is the currently selected frame?
- XXX - should the selected frame or the focus frame be the "current"
- frame, that frame being the one from which "Find Frame" searches
- start? */
- selected_frame = cf->current_frame;
+ nstime_set_unset(&first_ts);
+ nstime_set_unset(&prev_dis_ts);
+ cum_bytes = 0;
- /* We don't yet know what row that frame will be on, if any, after we
- rebuild the clist, however. */
- selected_row = -1;
+ for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
+ /* just add some value here until we know if it is being displayed or not */
+ fdata->cum_bytes = cum_bytes + fdata->pkt_len;
- /* Freeze the packet list while we redo it, so we don't get any
- screen updates while it happens. */
- packet_list_freeze();
+ /*
+ *Timestamps
+ */
- /* Clear it out. */
- packet_list_clear();
-
- 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. */
-
- /* We might receive new packets while redissecting, and we don't
- want to dissect those before their time. */
- cf->redissecting = TRUE;
-
- /* Cleanup all data structures used for dissection. */
- cleanup_dissection();
- /* Initialize all data structures used for dissection. */
- init_dissection();
-
- }
-
- /* We don't yet know which will be the first and last frames displayed. */
- cf->first_displayed = NULL;
- cf->last_displayed = NULL;
-
- reset_elapsed();
-
- /* We currently don't display any packets */
- cf->displayed_count = 0;
-
- /* Iterate through the list of frames. Call a routine for each frame
- to check whether it should be displayed and, if so, add it to
- the display list. */
- nstime_set_unset(&first_ts);
- nstime_set_unset(&prev_dis_ts);
- nstime_set_unset(&prev_cap_ts);
- cum_bytes = 0;
-
- /* Update the progress bar when it gets to this value. */
- progbar_nextstep = 0;
- /* When we reach the value that triggers a progress bar update,
- bump that value by this amount. */
- progbar_quantum = cf->count/N_PROGBAR_UPDATES;
- /* Count of packets at which we've looked. */
- count = 0;
- /* Progress so far. */
- progbar_val = 0.0f;
-
- stop_flag = FALSE;
- g_get_current_time(&start_time);
-
- row = -1; /* no previous row yet */
- prev_row = -1;
- prev_frame = NULL;
-
- preceding_row = -1;
- preceding_frame = NULL;
- following_row = -1;
- following_frame = NULL;
-
- selected_frame_seen = FALSE;
-
- for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
- /* Create the progress bar if necessary.
- We check on every iteration of the loop, so that it takes no
- longer than the standard time to create it (otherwise, for a
- large file, we might take considerably longer than that standard
- time in order to get to the next progress bar step). */
- if (progbar == NULL)
- progbar = delayed_create_progress_dlg(action, action_item, TRUE,
- &stop_flag, &start_time,
- progbar_val);
-
- /* 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()"
- to see if there's any pending input from an X server, and doing
- that for every packet can be costly, especially on a big file. */
- if (count >= progbar_nextstep) {
- /* let's not divide by zero. I should never be started
- * with count == 0, so let's assert that
- */
- g_assert(cf->count > 0);
- progbar_val = (gfloat) count / cf->count;
-
- if (progbar != NULL) {
- g_snprintf(status_str, sizeof(status_str),
- "%4u of %u frames", count, cf->count);
- update_progress_dlg(progbar, progbar_val, status_str);
- }
-
- progbar_nextstep += progbar_quantum;
- }
-
- if (stop_flag) {
- /* Well, the user decided to abort the filtering. Just stop.
-
- XXX - go back to the previous filter? Users probably just
- want not to wait for a filtering operation to finish;
- unless we cancel by having no filter, reverting to the
- previous filter will probably be even more expensive than
- continuing the filtering, as it involves going back to the
- beginning and filtering, and even with no filter we currently
- have to re-generate the entire clist, which is also expensive.
-
- I'm not sure what Network Monitor does, but it doesn't appear
- to give you an unfiltered display if you cancel. */
- break;
- }
-
- count++;
-
- 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_dissection()"), and null out the GSList pointer.
- */
- fdata->flags.visited = 0;
- frame_data_cleanup(fdata);
- }
-
- if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
- cf->pd, fdata->cap_len, &err, &err_info)) {
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
- cf_read_error_message(err, err_info), cf->filename);
- break;
- }
-
- /* If the previous frame is displayed, and we haven't yet seen the
- selected frame, remember that frame - it's the closest one we've
- yet seen before the selected frame. */
- if (prev_row != -1 && !selected_frame_seen) {
- preceding_row = prev_row;
- preceding_frame = prev_frame;
- }
- row = add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners,
- tap_flags, &cf->pseudo_header, cf->pd,
- refilter,
- add_to_packet_list);
-
- /* If this frame is displayed, and this is the first frame we've
- seen displayed after the selected frame, remember this frame -
- it's the closest one we've yet seen at or after the selected
- frame. */
- if (row != -1 && selected_frame_seen && following_row == -1) {
- following_row = row;
- following_frame = fdata;
- }
- if (fdata == selected_frame) {
- selected_row = row;
- selected_frame_seen = TRUE;
- }
-
- /* Remember this row/frame - it'll be the previous row/frame
- on the next pass through the loop. */
- prev_row = row;
- prev_frame = fdata;
- }
-
- /* We are done redissecting the packet list. */
- cf->redissecting = FALSE;
-
- 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 Wireshark grinding on
- until it finishes. Should we just stick them with that? */
- for (; fdata != NULL; fdata = fdata->next) {
- fdata->flags.visited = 0;
- frame_data_cleanup(fdata);
- }
- }
-
- /* We're done filtering the packets; destroy the progress bar if it
- was created. */
- if (progbar != NULL)
- destroy_progress_dlg(progbar);
-
- /* Unfreeze the packet list. */
- packet_list_thaw();
-
- if (selected_row == -1) {
- /* The selected frame didn't pass the filter. */
- if (selected_frame == NULL) {
- /* That's because there *was* no selected frame. Make the first
- displayed frame the current frame. */
- selected_row = 0;
- } else {
- /* Find the nearest displayed frame to the selected frame (whether
- it's before or after that frame) and make that the current frame.
- If the next and previous displayed frames are equidistant from the
- selected frame, choose the next one. */
- g_assert(following_frame == NULL ||
- following_frame->num >= selected_frame->num);
- g_assert(preceding_frame == NULL ||
- preceding_frame->num <= selected_frame->num);
- if (following_frame == NULL) {
- /* No frame after the selected frame passed the filter, so we
- have to select the last displayed frame before the selected
- frame. */
- selected_row = preceding_row;
- } else if (preceding_frame == NULL) {
- /* No frame before the selected frame passed the filter, so we
- have to select the first displayed frame after the selected
- frame. */
- selected_row = following_row;
- } else {
- /* Frames before and after the selected frame passed the filter, so
- we'll select the previous frame */
- selected_row = preceding_row;
- }
- }
- }
-
- if (selected_row == -1) {
- /* There are no frames displayed at all. */
- cf_unselect_packet(cf);
- } else {
- /* Either the frame that was selected passed the filter, or we've
- found the nearest displayed frame to that frame. Select it, make
- it the focus row, and make it visible. */
- if (selected_row == 0) {
- /* Set to invalid to force update of packet list and packet details */
- cf->current_row = -1;
- }
- packet_list_set_selected_row(selected_row);
- }
-
- /* Cleanup and release all dfilter resources */
- dfilter_free(dfcode);
-}
-#endif /* NEW_PACKET_LIST */
-
-/*
- * Scan trough all frame data and recalculate the ref time
- * without rereading the file.
- * XXX - do we need a progres bar or is this fast enough?
- */
-#ifdef NEW_PACKET_LIST
-static void
-ref_time_packets(capture_file *cf)
-{
- frame_data *fdata;
-
- nstime_set_unset(&first_ts);
- nstime_set_unset(&prev_dis_ts);
- nstime_set_unset(&prev_cap_ts);
- cum_bytes = 0;
-
- for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
- /* just add some value here until we know if it is being displayed or not */
- fdata->cum_bytes = cum_bytes + fdata->pkt_len;
-
- /* If we don't have the time stamp of the first packet in the
- capture, it's because this is the first packet. Save the time
- stamp of this packet as the time stamp of the first packet. */
- if (nstime_is_unset(&first_ts)) {
- first_ts = fdata->abs_ts;
- }
- /* if this frames is marked as a reference time frame, reset
- firstsec and firstusec to this frame */
- if(fdata->flags.ref_time){
- first_ts = fdata->abs_ts;
- }
+ /* If we don't have the time stamp of the first packet in the
+ capture, it's because this is the first packet. Save the time
+ stamp of this packet as the time stamp of the first packet. */
+ if (nstime_is_unset(&first_ts)) {
+ first_ts = fdata->abs_ts;
+ }
+ /* if this frames is marked as a reference time frame, reset
+ firstsec and firstusec to this frame */
+ if(fdata->flags.ref_time){
+ first_ts = fdata->abs_ts;
+ }
/* If we don't have the time stamp of the previous displayed packet,
it's because this is the first displayed packet. Save the time
this packet. */
nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
+ prev_dis_ts = fdata->abs_ts;
+
+ /*
+ * Byte counts
+ */
if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ){
/* This frame either passed the display filter list or is marked as
a time reference frame. All time reference frames are displayed
even if they dont pass the display filter */
if(fdata->flags.ref_time){
- /* if this was a TIME REF frame we should reset the cul bytes field */
+ /* if this was a TIME REF frame we should reset the cum_bytes field */
cum_bytes = fdata->pkt_len;
fdata->cum_bytes = cum_bytes;
} else {
}
}
}
-#endif
typedef enum {
PSP_FINISHED,
void *callback_args)
{
frame_data *fdata;
- int err;
- gchar *err_info;
union wtap_pseudo_header pseudo_header;
guint8 pd[WTAP_MAX_PACKET_SIZE+1];
psp_return_t ret = PSP_FINISHED;
}
/* Get the packet */
- if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
- pd, fdata->cap_len, &err, &err_info)) {
+ if (!cf_read_frame_r(cf, fdata, &pseudo_header, pd)) {
/* Attempt to get the packet failed. */
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
- cf_read_error_message(err, err_info), cf->filename);
ret = PSP_FAILED;
break;
}
return CF_PRINT_OK;
}
-#ifndef NEW_PACKET_LIST /* This function is not needed with the new packet list */
-
-/* Scan through the packet list and change all columns that use the
- "command-line-specified" time stamp format to use the current
- value of that format. */
-void
-cf_change_time_formats(capture_file *cf)
-{
- int i;
- frame_data *fdata;
- progdlg_t *progbar = NULL;
- gboolean stop_flag;
- int count;
- int row;
- float progbar_val;
- GTimeVal start_time;
- gchar status_str[100];
- int progbar_nextstep;
- int progbar_quantum;
- gboolean sorted_by_frame_column;
-
- /* Adjust timestamp precision if auto is selected */
- cf_timestamp_auto_precision(cf);
-
- /* Are there any columns with time stamps in the "command-line-specified"
- format?
-
- XXX - we have to force the "column is writable" flag on, as it
- might be off from the last frame that was dissected. */
- col_set_writable(&cf->cinfo, TRUE);
- if (!check_col(&cf->cinfo, COL_CLS_TIME) &&
- !check_col(&cf->cinfo, COL_ABS_TIME) &&
- !check_col(&cf->cinfo, COL_ABS_DATE_TIME) &&
- !check_col(&cf->cinfo, COL_REL_TIME) &&
- !check_col(&cf->cinfo, COL_DELTA_TIME) &&
- !check_col(&cf->cinfo, COL_DELTA_TIME_DIS)) {
- /* No, there aren't any columns in that format, so we have no work
- to do. */
- return;
- }
-
- /* Freeze the packet list while we redo it, so we don't get any
- screen updates while it happens. */
- packet_list_freeze();
-
- /* Update the progress bar when it gets to this value. */
- progbar_nextstep = 0;
- /* When we reach the value that triggers a progress bar update,
- bump that value by this amount. */
- progbar_quantum = cf->count/N_PROGBAR_UPDATES;
- /* Count of packets at which we've looked. */
- count = 0;
- /* Progress so far. */
- progbar_val = 0.0f;
-
- /* If the rows are currently sorted by the frame column then we know
- * the row number of each packet: it's the row number of the previously
- * displayed packet + 1.
- *
- * Otherwise, if the display is sorted by a different column then we have
- * to use the O(N) packet_list_find_row_from_data() (thus making the job
- * of changing the time display format O(N**2)).
- *
- * (XXX - In fact it's still O(N**2) because gtk_clist_set_text() takes
- * the row number and walks that many elements down the clist to find
- * the appropriate element.)
- */
- sorted_by_frame_column = FALSE;
- for (i = 0; i < cf->cinfo.num_cols; i++) {
- if (cf->cinfo.col_fmt[i] == COL_NUMBER)
- {
- sorted_by_frame_column = (i == packet_list_get_sort_column());
- break;
- }
- }
-
- stop_flag = FALSE;
- g_get_current_time(&start_time);
-
- /* Iterate through the list of packets, checking whether the packet
- is in a row of the summary list and, if so, whether there are
- any columns that show the time in the "command-line-specified"
- format and, if so, update that row. */
- for (fdata = cf->plist_start, row = -1; fdata != NULL; fdata = fdata->next) {
- /* Create the progress bar if necessary.
- We check on every iteration of the loop, so that it takes no
- longer than the standard time to create it (otherwise, for a
- large file, we might take considerably longer than that standard
- time in order to get to the next progress bar step). */
- if (progbar == NULL)
- progbar = delayed_create_progress_dlg("Changing", "time display",
- TRUE, &stop_flag, &start_time, progbar_val);
-
- /* 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()"
- to see if there's any pending input from an X server, and doing
- that for every packet can be costly, especially on a big file. */
- if (count >= progbar_nextstep) {
- /* let's not divide by zero. I should never be started
- * with count == 0, so let's assert that
- */
- g_assert(cf->count > 0);
-
- progbar_val = (gfloat) count / cf->count;
-
- if (progbar != NULL) {
- g_snprintf(status_str, sizeof(status_str),
- "%4u of %u packets", count, cf->count);
- update_progress_dlg(progbar, progbar_val, status_str);
- }
-
- progbar_nextstep += progbar_quantum;
- }
-
- if (stop_flag) {
- /* Well, the user decided to abort the redisplay. Just stop.
-
- XXX - this leaves the time field in the old format in
- frames we haven't yet processed. So it goes; should we
- simply not offer them the option of stopping? */
- break;
- }
-
- count++;
-
- /* Find what row this packet is in. */
- if (!sorted_by_frame_column) {
- /* This function is O(N), so we try to avoid using it... */
- row = packet_list_find_row_from_data(fdata);
- } else {
- /* ...which we do by maintaining a count of packets that are
- being displayed (i.e., that have passed the display filter),
- and using the current value of that count as the row number
- (which is why we can only do it when the display is sorted
- by the frame number). */
- if (fdata->flags.passed_dfilter)
- row++;
- else
- continue;
- }
-
- if (row != -1) {
- /* This packet is in the summary list, on row "row". */
-
- for (i = 0; i < cf->cinfo.num_cols; i++) {
- if (col_has_time_fmt(&cf->cinfo, i)) {
- /* This is one of the columns that shows the time in
- "command-line-specified" format; update it. */
- cf->cinfo.col_buf[i][0] = '\0';
- col_set_fmt_time(fdata, &cf->cinfo, cf->cinfo.col_fmt[i], i);
- packet_list_set_text(row, i, cf->cinfo.col_data[i]);
- }
- }
- }
- }
-
- /* We're done redisplaying the packets; destroy the progress bar if it
- was created. */
- if (progbar != NULL)
- destroy_progress_dlg(progbar);
-
- /* Set the column widths of those columns that show the time in
- "command-line-specified" format. */
- for (i = 0; i < cf->cinfo.num_cols; i++) {
- if (col_has_time_fmt(&cf->cinfo, i)) {
- packet_list_set_time_width(cf->cinfo.col_fmt[i], i);
- }
- }
-
- /* Unfreeze the packet list. */
- packet_list_thaw();
-}
-#endif /* NEW_PACKET_LIST */
-
-
-typedef struct {
- const char *string;
- size_t string_len;
- capture_file *cf;
- gboolean frame_matched;
-} match_data;
-
gboolean
-cf_find_packet_protocol_tree(capture_file *cf, const char *string)
+cf_find_packet_protocol_tree(capture_file *cf, const char *string,
+ search_direction dir)
{
match_data mdata;
mdata.string = string;
mdata.string_len = strlen(string);
- return find_packet(cf, match_protocol_tree, &mdata);
+ return find_packet(cf, match_protocol_tree, &mdata, dir);
}
-static gboolean
+gboolean
+cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
+{
+ mdata->frame_matched = FALSE;
+ mdata->string = convert_string_case(cf->sfilter, cf->case_type);
+ mdata->string_len = strlen(mdata->string);
+ mdata->cf = cf;
+ /* Iterate through all the nodes looking for matching text */
+ proto_tree_children_foreach(tree, match_subtree_text, mdata);
+ return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
+}
+
+static match_result
match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
{
match_data *mdata = criterion;
epan_dissect_t edt;
+ /* Load the frame's data. */
+ if (!cf_read_frame(cf, fdata)) {
+ /* Attempt to get the packet failed. */
+ return MR_ERROR;
+ }
+
/* Construct the protocol tree, including the displayed text */
epan_dissect_init(&edt, TRUE, TRUE);
/* We don't need the column information */
mdata->frame_matched = FALSE;
proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
epan_dissect_cleanup(&edt);
- return mdata->frame_matched;
+ return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
}
static void
{
match_data *mdata = (match_data*) data;
const gchar *string = mdata->string;
- size_t string_len = mdata->string_len;
+ size_t string_len = mdata->string_len;
capture_file *cf = mdata->cf;
field_info *fi = PNODE_FINFO(node);
- gchar label_str[ITEM_LABEL_LENGTH];
- gchar *label_ptr;
- size_t label_len;
- guint32 i;
- guint8 c_char;
- size_t c_match = 0;
+ gchar label_str[ITEM_LABEL_LENGTH];
+ gchar *label_ptr;
+ size_t label_len;
+ guint32 i;
+ guint8 c_char;
+ size_t c_match = 0;
g_assert(fi && "dissection with an invisible proto tree?");
if (c_char == string[c_match]) {
c_match++;
if (c_match == string_len) {
- /* No need to look further; we have a match */
- mdata->frame_matched = TRUE;
- return;
+ /* No need to look further; we have a match */
+ mdata->frame_matched = TRUE;
+ mdata->finfo = fi;
+ return;
}
} else
c_match = 0;
}
gboolean
-cf_find_packet_summary_line(capture_file *cf, const char *string)
+cf_find_packet_summary_line(capture_file *cf, const char *string,
+ search_direction dir)
{
match_data mdata;
mdata.string = string;
mdata.string_len = strlen(string);
- return find_packet(cf, match_summary_line, &mdata);
+ return find_packet(cf, match_summary_line, &mdata, dir);
}
-static gboolean
+static match_result
match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
{
match_data *mdata = criterion;
const gchar *string = mdata->string;
- size_t string_len = mdata->string_len;
+ size_t string_len = mdata->string_len;
epan_dissect_t edt;
const char *info_column;
- size_t info_column_len;
- gboolean frame_matched = FALSE;
- gint colx;
- guint32 i;
- guint8 c_char;
- size_t c_match = 0;
+ size_t info_column_len;
+ match_result result = MR_NOTMATCHED;
+ gint colx;
+ guint32 i;
+ guint8 c_char;
+ size_t c_match = 0;
+
+ /* Load the frame's data. */
+ if (!cf_read_frame(cf, fdata)) {
+ /* Attempt to get the packet failed. */
+ return MR_ERROR;
+ }
/* Don't bother constructing the protocol tree */
epan_dissect_init(&edt, FALSE, FALSE);
info_column = edt.pi.cinfo->col_data[colx];
info_column_len = strlen(info_column);
for (i = 0; i < info_column_len; i++) {
- c_char = info_column[i];
- if (cf->case_type)
- c_char = toupper(c_char);
- if (c_char == string[c_match]) {
- c_match++;
- if (c_match == string_len) {
- frame_matched = TRUE;
- break;
- }
- } else
- c_match = 0;
+ c_char = info_column[i];
+ if (cf->case_type)
+ c_char = toupper(c_char);
+ if (c_char == string[c_match]) {
+ c_match++;
+ if (c_match == string_len) {
+ result = MR_MATCHED;
+ break;
+ }
+ } else
+ c_match = 0;
}
break;
}
}
epan_dissect_cleanup(&edt);
- return frame_matched;
+ return result;
}
typedef struct {
} cbs_t; /* "Counted byte string" */
gboolean
-cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size)
+cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
+ search_direction dir)
{
cbs_t info;
switch (cf->scs_type) {
case SCS_ASCII_AND_UNICODE:
- return find_packet(cf, match_ascii_and_unicode, &info);
+ return find_packet(cf, match_ascii_and_unicode, &info, dir);
case SCS_ASCII:
- return find_packet(cf, match_ascii, &info);
+ return find_packet(cf, match_ascii, &info, dir);
case SCS_UNICODE:
- return find_packet(cf, match_unicode, &info);
+ return find_packet(cf, match_unicode, &info, dir);
default:
g_assert_not_reached();
return FALSE;
}
} else
- return find_packet(cf, match_binary, &info);
+ return find_packet(cf, match_binary, &info, dir);
}
-static gboolean
+static match_result
match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
{
- cbs_t *info = criterion;
- const guint8 *ascii_text = info->data;
- size_t textlen = info->data_len;
- gboolean frame_matched;
- guint32 buf_len;
- guint32 i;
- guint8 c_char;
- size_t c_match = 0;
-
- frame_matched = FALSE;
+ cbs_t *info = criterion;
+ const guint8 *ascii_text = info->data;
+ size_t textlen = info->data_len;
+ match_result result;
+ guint32 buf_len;
+ guint32 i;
+ guint8 c_char;
+ size_t c_match = 0;
+
+ /* Load the frame's data. */
+ if (!cf_read_frame(cf, fdata)) {
+ /* Attempt to get the packet failed. */
+ return MR_ERROR;
+ }
+
+ result = MR_NOTMATCHED;
buf_len = fdata->pkt_len;
for (i = 0; i < buf_len; i++) {
c_char = cf->pd[i];
c_char = toupper(c_char);
if (c_char != 0) {
if (c_char == ascii_text[c_match]) {
- c_match++;
- if (c_match == textlen) {
- frame_matched = TRUE;
- cf->search_pos = i; /* Save the position of the last character
- for highlighting the field. */
- break;
- }
+ c_match++;
+ if (c_match == textlen) {
+ result = MR_MATCHED;
+ cf->search_pos = i; /* Save the position of the last character
+ for highlighting the field. */
+ break;
+ }
} else
- c_match = 0;
+ c_match = 0;
}
}
- return frame_matched;
+ return result;
}
-static gboolean
+static match_result
match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
{
- cbs_t *info = criterion;
- const guint8 *ascii_text = info->data;
- size_t textlen = info->data_len;
- gboolean frame_matched;
- guint32 buf_len;
- guint32 i;
- guint8 c_char;
- size_t c_match = 0;
-
- frame_matched = FALSE;
+ cbs_t *info = criterion;
+ const guint8 *ascii_text = info->data;
+ size_t textlen = info->data_len;
+ match_result result;
+ guint32 buf_len;
+ guint32 i;
+ guint8 c_char;
+ size_t c_match = 0;
+
+ /* Load the frame's data. */
+ if (!cf_read_frame(cf, fdata)) {
+ /* Attempt to get the packet failed. */
+ return MR_ERROR;
+ }
+
+ result = MR_NOTMATCHED;
buf_len = fdata->pkt_len;
for (i = 0; i < buf_len; i++) {
c_char = cf->pd[i];
if (c_char == ascii_text[c_match]) {
c_match++;
if (c_match == textlen) {
- frame_matched = TRUE;
- cf->search_pos = i; /* Save the position of the last character
- for highlighting the field. */
- break;
+ result = MR_MATCHED;
+ cf->search_pos = i; /* Save the position of the last character
+ for highlighting the field. */
+ break;
}
} else
c_match = 0;
}
- return frame_matched;
+ return result;
}
-static gboolean
+static match_result
match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
{
- cbs_t *info = criterion;
- const guint8 *ascii_text = info->data;
- size_t textlen = info->data_len;
- gboolean frame_matched;
- guint32 buf_len;
- guint32 i;
- guint8 c_char;
- size_t c_match = 0;
-
- frame_matched = FALSE;
+ cbs_t *info = criterion;
+ const guint8 *ascii_text = info->data;
+ size_t textlen = info->data_len;
+ match_result result;
+ guint32 buf_len;
+ guint32 i;
+ guint8 c_char;
+ size_t c_match = 0;
+
+ /* Load the frame's data. */
+ if (!cf_read_frame(cf, fdata)) {
+ /* Attempt to get the packet failed. */
+ return MR_ERROR;
+ }
+
+ result = MR_NOTMATCHED;
buf_len = fdata->pkt_len;
for (i = 0; i < buf_len; i++) {
c_char = cf->pd[i];
c_match++;
i++;
if (c_match == textlen) {
- frame_matched = TRUE;
- cf->search_pos = i; /* Save the position of the last character
- for highlighting the field. */
- break;
+ result = MR_MATCHED;
+ cf->search_pos = i; /* Save the position of the last character
+ for highlighting the field. */
+ break;
}
} else
c_match = 0;
}
- return frame_matched;
+ return result;
}
-static gboolean
+static match_result
match_binary(capture_file *cf, frame_data *fdata, void *criterion)
{
- cbs_t *info = criterion;
- const guint8 *binary_data = info->data;
- size_t datalen = info->data_len;
- gboolean frame_matched;
- guint32 buf_len;
- guint32 i;
- size_t c_match = 0;
-
- frame_matched = FALSE;
+ cbs_t *info = criterion;
+ const guint8 *binary_data = info->data;
+ size_t datalen = info->data_len;
+ match_result result;
+ guint32 buf_len;
+ guint32 i;
+ size_t c_match = 0;
+
+ /* Load the frame's data. */
+ if (!cf_read_frame(cf, fdata)) {
+ /* Attempt to get the packet failed. */
+ return MR_ERROR;
+ }
+
+ result = MR_NOTMATCHED;
buf_len = fdata->pkt_len;
for (i = 0; i < buf_len; i++) {
if (cf->pd[i] == binary_data[c_match]) {
c_match++;
if (c_match == datalen) {
- frame_matched = TRUE;
- cf->search_pos = i; /* Save the position of the last character
- for highlighting the field. */
- break;
+ result = MR_MATCHED;
+ cf->search_pos = i; /* Save the position of the last character
+ for highlighting the field. */
+ break;
}
} else
c_match = 0;
}
- return frame_matched;
+ return result;
}
gboolean
-cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode)
+cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
+ search_direction dir)
{
- return find_packet(cf, match_dfilter, sfcode);
+ return find_packet(cf, match_dfilter, sfcode, dir);
}
-static gboolean
+gboolean
+cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
+ search_direction dir)
+{
+ dfilter_t *sfcode;
+ gboolean result;
+
+ if (!dfilter_compile(filter, &sfcode)) {
+ /*
+ * XXX - this shouldn't happen, as the filter string is machine
+ * generated
+ */
+ return FALSE;
+ }
+ if (sfcode == NULL) {
+ /*
+ * XXX - this shouldn't happen, as the filter string is machine
+ * generated.
+ */
+ return FALSE;
+ }
+ result = find_packet(cf, match_dfilter, sfcode, dir);
+ dfilter_free(sfcode);
+ return result;
+}
+
+static match_result
match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
{
- dfilter_t *sfcode = criterion;
- epan_dissect_t edt;
- gboolean frame_matched;
+ dfilter_t *sfcode = criterion;
+ epan_dissect_t edt;
+ match_result result;
+
+ /* Load the frame's data. */
+ if (!cf_read_frame(cf, fdata)) {
+ /* Attempt to get the packet failed. */
+ return MR_ERROR;
+ }
epan_dissect_init(&edt, TRUE, FALSE);
epan_dissect_prime_dfilter(&edt, sfcode);
epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
- frame_matched = dfilter_apply_edt(sfcode, &edt);
+ result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
epan_dissect_cleanup(&edt);
- return frame_matched;
+ return result;
+}
+
+gboolean
+cf_find_packet_marked(capture_file *cf, search_direction dir)
+{
+ return find_packet(cf, match_marked, NULL, dir);
+}
+
+static match_result
+match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
+{
+ return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
+}
+
+gboolean
+cf_find_packet_time_reference(capture_file *cf, search_direction dir)
+{
+ return find_packet(cf, match_time_reference, NULL, dir);
+}
+
+static match_result
+match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
+{
+ return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
}
static gboolean
find_packet(capture_file *cf,
- gboolean (*match_function)(capture_file *, frame_data *, void *),
- void *criterion)
+ match_result (*match_function)(capture_file *, frame_data *, void *),
+ void *criterion, search_direction dir)
{
- frame_data *start_fd;
- frame_data *fdata;
- frame_data *new_fd = NULL;
- progdlg_t *progbar = NULL;
- gboolean stop_flag;
- int count;
- int err;
- gchar *err_info;
- int row;
- float progbar_val;
- GTimeVal start_time;
- gchar status_str[100];
- int progbar_nextstep;
- int progbar_quantum;
- const char *title;
+ frame_data *start_fd;
+ frame_data *fdata;
+ frame_data *new_fd = NULL;
+ progdlg_t *progbar = NULL;
+ gboolean stop_flag;
+ int count;
+ int row;
+ float progbar_val;
+ GTimeVal start_time;
+ gchar status_str[100];
+ int progbar_nextstep;
+ int progbar_quantum;
+ const char *title;
+ match_result result;
start_fd = cf->current_frame;
if (start_fd != NULL) {
stop_flag = FALSE;
g_get_current_time(&start_time);
- fdata = start_fd;
title = cf->sfilter?cf->sfilter:"";
for (;;) {
/* Create the progress bar if necessary.
}
/* Go past the current frame. */
- if (cf->sbackward) {
+ if (dir == SD_BACKWARD) {
/* Go on to the previous frame. */
fdata = fdata->prev;
if (fdata == NULL) {
if (prefs.gui_find_wrap)
{
- simple_status("Search reached the beginning. Continuing at end.");
+ statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
fdata = cf->plist_end; /* wrap around */
}
else
{
- simple_status("Search reached the beginning.");
+ statusbar_push_temporary_msg("Search reached the beginning.");
fdata = start_fd; /* stay on previous packet */
}
}
if (fdata == NULL) {
if (prefs.gui_find_wrap)
{
- simple_status("Search reached the end. Continuing at beginning.");
+ statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
fdata = cf->plist_start; /* wrap around */
}
else
{
- simple_status("Search reached the end.");
+ statusbar_push_temporary_msg("Search reached the end.");
fdata = start_fd; /* stay on previous packet */
}
}
/* Is this packet in the display? */
if (fdata->flags.passed_dfilter) {
- /* Yes. Load its data. */
- if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
- cf->pd, fdata->cap_len, &err, &err_info)) {
- /* Read error. Report the error, and go back to the frame
+ /* Yes. Does it match the search criterion? */
+ result = (*match_function)(cf, fdata, criterion);
+ if (result == MR_ERROR) {
+ /* Error; our caller has reported the error. Go back to the frame
where we started. */
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
- cf_read_error_message(err, err_info), cf->filename);
new_fd = start_fd;
break;
- }
-
- /* Does it match the search criterion? */
- if ((*match_function)(cf, fdata, criterion)) {
+ } else if (result == MR_MATCHED) {
+ /* Yes. Go to the new frame. */
new_fd = fdata;
- break; /* found it! */
+ break;
}
}
if (fdata == start_fd) {
/* We're back to the frame we were on originally, and that frame
- doesn't match the search filter. The search failed. */
+ doesn't match the search filter. The search failed. */
break;
}
}
}
if (new_fd != NULL) {
-#ifdef NEW_PACKET_LIST
- /* Find and select */
- row = new_packet_list_find_row_from_data(fdata, TRUE);
-#else
- /* We found a frame. Find what row it's in. */
- row = packet_list_find_row_from_data(new_fd);
-#endif /* NEW_PACKET_LIST */
+ /* Find and select */
+ cf->search_in_progress = TRUE;
+ row = new_packet_list_find_row_from_data(fdata, TRUE);
+ cf->search_in_progress = FALSE;
+ cf->search_pos = 0; /* Reset the position */
if (row == -1) {
- /* We didn't find a row even though we know that a frame
- * exists that satifies the search criteria. This means that the
- * frame isn't being displayed currently so we can't select it. */
- simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
- "%sEnd of capture exceeded!%s\n\n"
- "The capture file is probably not fully loaded.",
- simple_dialog_primary_start(), simple_dialog_primary_end());
- return FALSE;
+ /* We didn't find a row even though we know that a frame
+ * exists that satifies the search criteria. This means that the
+ * frame isn't being displayed currently so we can't select it. */
+ simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
+ "%sEnd of capture exceeded!%s\n\n"
+ "The capture file is probably not fully loaded.",
+ simple_dialog_primary_start(), simple_dialog_primary_end());
+ return FALSE;
}
-
-#ifndef NEW_PACKET_LIST
- /* Select that row, make it the focus row, and make it visible. */
- packet_list_set_selected_row(row);
-#endif /* NEW_PACKET_LIST */
return TRUE; /* success */
} else
return FALSE; /* failure */
cf_goto_frame(capture_file *cf, guint fnumber)
{
frame_data *fdata;
- int row;
for (fdata = cf->plist_start; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
;
if (fdata == NULL) {
/* we didn't find a packet with that packet number */
- simple_status("There is no packet number %u.", fnumber);
+ statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
return FALSE; /* we failed to go to that packet */
}
if (!fdata->flags.passed_dfilter) {
/* that packet currently isn't displayed */
/* XXX - add it to the set of displayed packets? */
- simple_status("Packet number %u isn't displayed.", fnumber);
+ statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
return FALSE; /* we failed to go to that packet */
}
-#ifdef NEW_PACKET_LIST
- row = new_packet_list_find_row_from_data(fdata, TRUE);
-#else
- /* We found that packet, and it's currently being displayed.
- Find what row it's in. */
- row = packet_list_find_row_from_data(fdata);
- g_assert(row != -1);
-
- /* Select that row, make it the focus row, and make it visible. */
- packet_list_set_selected_row(row);
-#endif /* NEW_PACKET_LIST */
+ new_packet_list_find_row_from_data(fdata, TRUE);
return TRUE; /* we got to that packet */
}
gboolean
-cf_goto_top_frame(capture_file *cf _U_)
+cf_goto_top_frame()
{
-#ifdef NEW_PACKET_LIST
/* Find and select */
new_packet_list_select_first_row();
-#else
- frame_data *fdata;
- int row;
- frame_data *lowest_fdata = NULL;
-
- for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
- if (fdata->flags.passed_dfilter) {
- lowest_fdata = fdata;
- break;
- }
- }
-
- if (lowest_fdata == NULL) {
- return FALSE;
- }
-
- /* We found that packet, and it's currently being displayed.
- Find what row it's in. */
- row = packet_list_find_row_from_data(lowest_fdata);
- g_assert(row != -1);
-
- /* Select that row, make it the focus row, and make it visible. */
- packet_list_set_selected_row(row);
-#endif /* NEW_PACKET_LIST */
return TRUE; /* we got to that packet */
}
gboolean
-cf_goto_bottom_frame(capture_file *cf _U_) /* cf is unused w/ NEW_PACKET_LIST */
+cf_goto_bottom_frame()
{
-#ifdef NEW_PACKET_LIST
/* Find and select */
new_packet_list_select_last_row();
-#else
- frame_data *fdata;
- int row;
- frame_data *highest_fdata = NULL;
-
- for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
- if (fdata->flags.passed_dfilter) {
- highest_fdata = fdata;
- }
- }
-
- if (highest_fdata == NULL) {
- return FALSE;
- }
-
- /* We found that packet, and it's currently being displayed.
- Find what row it's in. */
- row = packet_list_find_row_from_data(highest_fdata);
- g_assert(row != -1);
-
- /* Select that row, make it the focus row, and make it visible. */
- packet_list_set_selected_row(row);
-#endif /* NEW_PACKET_LIST */
return TRUE; /* we got to that packet */
}
cf_select_packet(capture_file *cf, int row)
{
frame_data *fdata;
- int err;
- gchar *err_info;
/* Get the frame data struct pointer for this frame */
-#ifdef NEW_PACKET_LIST
fdata = new_packet_list_get_row_data(row);
-#else
- fdata = (frame_data *)packet_list_get_row_data(row);
-#endif
if (fdata == NULL) {
/* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
}
/* Get the data in that frame. */
- if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
- cf->pd, fdata->cap_len, &err, &err_info)) {
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
- cf_read_error_message(err, err_info), cf->filename);
+ if (!cf_read_frame (cf, fdata)) {
return;
}
if (cf->is_tempfile) {
/* The file being saved is a temporary file from a live
capture, so it doesn't need to stay around under that name;
- first, try renaming the capture buffer file to the new name. */
+ first, try renaming the capture buffer file to the new name. */
#ifndef _WIN32
if (ws_rename(cf->filename, fname) == 0) {
/* That succeeded - there's no need to copy the source file. */
do_copy = FALSE;
} else {
if (errno == EXDEV) {
- /* They're on different file systems, so we have to copy the
- file. */
- do_copy = TRUE;
+ /* They're on different file systems, so we have to copy the
+ file. */
+ do_copy = TRUE;
from_filename = cf->filename;
- } else {
- /* The rename failed, but not because they're on different
- file systems - put up an error message. (Or should we
- just punt and try to copy? The only reason why I'd
- expect the rename to fail and the copy to succeed would
- be if we didn't have permission to remove the file from
- the temporary directory, and that might be fixable - but
- is it worth requiring the user to go off and fix it?) */
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
- file_rename_error_message(errno), fname);
- goto fail;
- }
+ } else {
+ /* The rename failed, but not because they're on different
+ file systems - put up an error message. (Or should we
+ just punt and try to copy? The only reason why I'd
+ expect the rename to fail and the copy to succeed would
+ be if we didn't have permission to remove the file from
+ the temporary directory, and that might be fixable - but
+ is it worth requiring the user to go off and fix it?) */
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ file_rename_error_message(errno), fname);
+ goto fail;
+ }
}
#else
do_copy = TRUE;
case WTAP_ERR_UNSUPPORTED_ENCAP:
if (for_writing) {
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"Wireshark can't save this capture in that format.");
} else {
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
"(%s)",
filename, err_info);
case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
if (for_writing) {
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"Wireshark can't save this capture in that format.");
} else {
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
filename);
}
case WTAP_ERR_CANT_OPEN:
if (for_writing) {
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"The file \"%s\" could not be created for some unknown reason.",
filename);
} else {
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"The file \"%s\" could not be opened for some unknown reason.",
filename);
}
return errmsg;
}
-char *
-cf_read_error_message(int err, gchar *err_info)
-{
- static char errmsg_errno[1024+1];
-
- switch (err) {
-
- case WTAP_ERR_UNSUPPORTED_ENCAP:
- g_snprintf(errmsg_errno, sizeof(errmsg_errno),
- "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
- err_info);
- g_free(err_info);
- break;
-
- case WTAP_ERR_BAD_RECORD:
- g_snprintf(errmsg_errno, sizeof(errmsg_errno),
- "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
- wtap_strerror(err), err_info);
- g_free(err_info);
- break;
-
- default:
- g_snprintf(errmsg_errno, sizeof(errmsg_errno),
- "An error occurred while reading from the file \"%%s\": %s.",
- wtap_strerror(err));
- break;
- }
- return errmsg_errno;
-}
-
static void
cf_write_failure_alert_box(const char *filename, int err)
{