#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;
#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;
/* The open succeeded. Close whatever capture file we had open,
and fill in the information for this file. */
+ cf_callback_invoke(cf_cb_file_closing, cf);
cf_reset_state(cf);
/* Cleanup all data structures used for dissection. */
} else
cf->has_snap = TRUE;
+ /* Allocate a frame_data_sequence for the frames in this file */
+ cf->frames = new_frame_data_sequence();
+
nstime_set_zero(&cf->elapsed_time);
nstime_set_unset(&first_ts);
nstime_set_unset(&prev_dis_ts);
nstime_set_unset(&prev_cap_ts);
cum_bytes = 0;
-#if GLIB_CHECK_VERSION(2,10,0)
-#else
- /* memory chunks have been deprecated in favor of the slice allocator,
- * which has been added in 2.10
- */
- cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
- sizeof(frame_data),
- FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
- G_ALLOC_AND_FREE);
- g_assert(cf->plist_chunk);
-#endif
-
/* Adjust timestamp precision if auto is selected, col width will be adjusted */
cf_timestamp_auto_precision(cf);
/* XXX needed ? */
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:
/* ...which means we have nothing to save. */
cf->user_saved = FALSE;
-#if GLIB_CHECK_VERSION(2,10,0)
- if (cf->plist_start != NULL)
- g_slice_free_chain(frame_data, cf->plist_start, next);
-#else
- /* memory chunks have been deprecated in favor of the slice allocator,
- * which has been added in 2.10
- */
- if (cf->plist_chunk != NULL) {
- g_mem_chunk_destroy(cf->plist_chunk);
- cf->plist_chunk = NULL;
- }
-#endif
dfilter_free(cf->rfcode);
cf->rfcode = NULL;
- cf->plist_start = NULL;
- cf->plist_end = NULL;
+ if (cf->frames != NULL) {
+ free_frame_data_sequence(cf->frames);
+ cf->frames = NULL;
+ }
+#ifdef WANT_PACKET_EDITOR
+ if (cf->edited_frames) {
+ g_tree_destroy(cf->edited_frames);
+ cf->edited_frames = NULL;
+ }
+#endif
cf_unselect_packet(cf); /* nothing to select */
- cf->first_displayed = NULL;
- cf->last_displayed = NULL;
+ cf->first_displayed = 0;
+ cf->last_displayed = 0;
- /* No frame selected, no field in that frame selected. */
- cf->current_frame = NULL;
+ /* No frames, no frame selected, no field in that frame selected. */
+ cf->count = 0;
+ cf->current_frame = 0;
cf->current_row = 0;
cf->finfo_selected = NULL;
new_packet_list_thaw();
cf->f_datalen = 0;
- cf->count = 0;
nstime_set_zero(&cf->elapsed_time);
reset_tap_listeners();
*/
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;
}
g_snprintf(status_str, status_size,
- "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
- file_pos / 1024, size / 1024);
+ "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
+ file_pos / 1024, size / 1024);
return progbar_val;
}
const char *errmsg;
char errmsg_errno[1024+1];
gint64 data_offset;
+ gint64 file_pos;
progdlg_t *volatile progbar = NULL;
gboolean stop_flag;
volatile gint64 size;
/* Progress so far. */
progbar_val = 0.0f;
+ /* The packet list window will be empty untill the file is completly loaded */
new_packet_list_freeze();
stop_flag = FALSE;
while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
if (size >= 0) {
count++;
+ file_pos = wtap_read_so_far(cf->wth);
+
/* Create the progress bar if necessary.
* 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, status_str, sizeof(status_str));
+ progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
if (from_save == FALSE)
progbar = delayed_create_progress_dlg("Loading", name_ptr,
TRUE, &stop_flag, &start_time, progbar_val);
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 (data_offset >= progbar_nextstep) {
+ if (file_pos >= progbar_nextstep) {
if (progbar != NULL) {
- 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) */
+ progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
+ /* update the packet bar content on the first run or frequently on very large files */
#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) {
+ if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
displayed_once = 1;
- new_packet_list_thaw();
- if (auto_scroll_live)
- new_packet_list_moveto_end();
- new_packet_list_freeze();
+ packets_bar_update();
}
}
#endif /* HAVE_LIBPCAP */
WTAP_ENCAP_PER_PACKET). */
cf->lnk_t = wtap_file_encap(cf->wth);
- cf->current_frame = cf->first_displayed;
+ cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
cf->current_row = 0;
new_packet_list_thaw();
/* 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){
+ if (cf->first_displayed != 0){
new_packet_list_select_first_row();
}
errmsg = errmsg_errno;
break;
+ case WTAP_ERR_DECOMPRESS:
+ g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+ "The compressed capture file appears to be damaged or corrupt.\n"
+ "(%s)", err_info);
+ g_free(err_info);
+ errmsg = errmsg_errno;
+ break;
+
default:
g_snprintf(errmsg_errno, sizeof(errmsg_errno),
"An error occurred while reading the"
/* 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)
+ if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
new_packet_list_moveto_end();
if (cf->state == FILE_READ_ABORTED) {
return CF_READ_ABORTED;
}
- if (auto_scroll_live && cf->plist_end != NULL)
+ if (auto_scroll_live && cf->count != 0)
new_packet_list_moveto_end();
/* We're done reading sequentially through the file. */
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;
+ if (cf->first_displayed == 0)
+ cf->first_displayed = fdata->num;
/* This is the last frame we've seen so far. */
- cf->last_displayed = fdata;
+ cf->last_displayed = fdata->num;
}
epan_dissect_cleanup(&edt);
return row;
}
-/*
- * Initialize the col_text and col_text_len arrays.
- */
-static void
-init_col_text(frame_data *fdata, gint num_cols)
-{
- fdata->col_text_len = se_alloc0(sizeof(fdata->col_text_len) * num_cols);
- fdata->col_text = se_alloc0(sizeof(fdata->col_text) * num_cols);
-}
-
/* read in a new packet */
/* returns the row of the new packet in the packet list or -1 if not displayed */
static int
const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
const guchar *buf = wtap_buf_ptr(cf->wth);
+ frame_data fdlocal;
+ guint32 framenum;
frame_data *fdata;
int passed;
int row = -1;
- cf->count++;
+ /* The frame number of this packet is one more than the count of
+ frames in this packet. */
+ framenum = cf->count + 1;
- /* Allocate the next list entry, and add it to the list.
- * memory chunks have been deprecated in favor of the slice allocator,
- * which has been added in 2.10
- */
-#if GLIB_CHECK_VERSION(2,10,0)
- fdata = g_slice_new(frame_data);
-#else
- fdata = g_mem_chunk_alloc(cf->plist_chunk);
-#endif
-
- frame_data_init(fdata, cf->count, phdr, offset, cum_bytes);
- init_col_text(fdata, cf->cinfo.num_cols);
+ frame_data_init(&fdlocal, framenum, phdr, offset, cum_bytes);
passed = TRUE;
if (cf->rfcode) {
epan_dissect_t edt;
epan_dissect_init(&edt, TRUE, FALSE);
epan_dissect_prime_dfilter(&edt, cf->rfcode);
- epan_dissect_run(&edt, pseudo_header, buf, fdata, NULL);
+ epan_dissect_run(&edt, pseudo_header, buf, &fdlocal, NULL);
passed = dfilter_apply_edt(cf->rfcode, &edt);
epan_dissect_cleanup(&edt);
}
if (passed) {
- cap_file_add_fdata(cf, fdata);
+ /* This does a shallow copy of fdlocal, which is good enough. */
+ fdata = frame_data_sequence_add(cf->frames, &fdlocal);
- cf->f_datalen = offset + fdata->cap_len;
+ cf->count++;
+ cf->f_datalen = offset + fdlocal.cap_len;
if (!cf->redissecting) {
row = add_packet_to_packet_list(fdata, cf, dfcode,
filtering_tap_listeners, tap_flags,
pseudo_header, buf, TRUE, TRUE);
}
- } else {
- /* We didn't pass read filter so roll back count */
- cf->count--;
-
- /* XXX - if we didn't have read filters, or if we could avoid
- allocating the "frame_data" structure until we knew whether
- the frame passed the read filter, we could use a G_ALLOC_ONLY
- memory chunk...
-
- ...but, at least in one test I did, where I just made the chunk
- a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
- seem to save a noticeable amount of time or space. */
-#if GLIB_CHECK_VERSION(2,10,0)
- /* memory chunks have been deprecated in favor of the slice allocator,
- * which has been added in 2.10
- */
- g_slice_free(frame_data,fdata);
-#else
- g_mem_chunk_free(cf->plist_chunk, fdata);
-#endif
}
return row;
/* Get the sum of the seek positions in all of the files. */
file_pos = 0;
for (i = 0; i < in_file_count; i++)
- file_pos += wtap_read_so_far(in_files[i].wth, NULL);
+ file_pos += wtap_read_so_far(in_files[i].wth);
progbar_val = (gfloat) file_pos / (gfloat) f_len;
if (progbar_val > 1.0f) {
/* Some file probably grew while we were reading it.
errmsg = errmsg_errno;
break;
+ case WTAP_ERR_DECOMPRESS:
+ g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+ "The compressed capture file %%s appears to be damaged or corrupt.\n"
+ "(%s)", err_info);
+ g_free(err_info);
+ errmsg = errmsg_errno;
+ break;
+
default:
g_snprintf(errmsg_errno, sizeof(errmsg_errno),
"An error occurred while reading the"
gchar *err_info;
char errmsg_errno[1024+1];
+#ifdef WANT_PACKET_EDITOR
+ /* if fdata->file_off == -1 it means packet was edited, and we must find data inside edited_frames tree */
+ if (G_UNLIKELY(fdata->file_off == -1)) {
+ const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
+
+ if (!frame) {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "fdata->file_off == -1, but can't find modified frame!");
+ return FALSE;
+ }
+
+ *pseudo_header = frame->ph;
+ memcpy(pd, frame->pd, fdata->cap_len);
+ return TRUE;
+ }
+#endif
+
if (!wtap_seek_read(cf->wth, fdata->file_off, pseudo_header, pd,
fdata->cap_len, &err, &err_info)) {
switch (err) {
rescan_packets(capture_file *cf, const char *action, const char *action_item,
gboolean refilter, gboolean redissect)
{
- /* Rescan packets new packet list */
+ /* Rescan packets new packet list */
+ guint32 framenum;
frame_data *fdata;
progdlg_t *progbar = NULL;
gboolean stop_flag;
}
/* We don't yet know which will be the first and last frames displayed. */
- cf->first_displayed = NULL;
- cf->last_displayed = NULL;
+ cf->first_displayed = 0;
+ cf->last_displayed = 0;
/* We currently don't display any packets */
cf->displayed_count = 0;
selected_frame_seen = FALSE;
- for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
+ for (framenum = 1; framenum <= cf->count; framenum++) {
+ fdata = frame_data_sequence_find(cf->frames, framenum);
+
/* 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
* "init_dissection()"), and null out the GSList pointer. */
fdata->flags.visited = 0;
frame_data_cleanup(fdata);
-
- /* cleanup_dissection() calls se_free_all();
- * And after that fdata->col_text (which is allocated using se_alloc0())
- * no longer points to valid memory.
- */
- init_col_text(fdata, cf->cinfo.num_cols);
}
if (!cf_read_frame(cf, fdata))
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) {
+ for (; framenum <= cf->count; framenum++) {
+ fdata = frame_data_sequence_find(cf->frames, framenum);
fdata->flags.visited = 0;
frame_data_cleanup(fdata);
}
if (selected_frame_num == 0) {
new_packet_list_select_first_row();
}else{
- new_packet_list_find_row_from_data(selected_frame, TRUE);
+ if (!new_packet_list_select_row_from_data(selected_frame)) {
+ /* We didn't find a row corresponding to this frame.
+ 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 dissected.",
+ simple_dialog_primary_start(), simple_dialog_primary_end());
+ }
}
}
static void
ref_time_packets(capture_file *cf)
{
+ guint32 framenum;
frame_data *fdata;
nstime_set_unset(&first_ts);
nstime_set_unset(&prev_dis_ts);
cum_bytes = 0;
- for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
+ for (framenum = 1; framenum <= cf->count; framenum++) {
+ fdata = frame_data_sequence_find(cf->frames, framenum);
+
/* just add some value here until we know if it is being displayed or not */
fdata->cum_bytes = cum_bytes + fdata->pkt_len;
union wtap_pseudo_header *, const guint8 *, void *),
void *callback_args)
{
+ guint32 framenum;
frame_data *fdata;
union wtap_pseudo_header pseudo_header;
guint8 pd[WTAP_MAX_PACKET_SIZE+1];
packet_range_process_init(range);
- /* Iterate through the list of packets, printing the packets that
+ /* Iterate through all the packets, printing the packets that
were selected by the current display filter. */
- for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
+ for (framenum = 1; framenum <= cf->count; framenum++) {
+ fdata = frame_data_sequence_find(cf->frames, framenum);
+
/* 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
if (fh == NULL)
return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
- write_pdml_preamble(fh);
+ write_pdml_preamble(fh, cf->filename);
if (ferror(fh)) {
fclose(fh);
return CF_PRINT_WRITE_ERROR;
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;
+ return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
}
static match_result
void *criterion, search_direction dir)
{
frame_data *start_fd;
+ guint32 framenum;
frame_data *fdata;
frame_data *new_fd = NULL;
progdlg_t *progbar = NULL;
gboolean stop_flag;
int count;
- int row;
+ gboolean found;
float progbar_val;
GTimeVal start_time;
gchar status_str[100];
picked, calling a routine to run the filter on the packet, see if
it matches, and stop if so. */
count = 0;
- fdata = start_fd;
+ framenum = start_fd->num;
/* Update the progress bar when it gets to this value. */
progbar_nextstep = 0;
/* Go past the current frame. */
if (dir == SD_BACKWARD) {
/* Go on to the previous frame. */
- fdata = fdata->prev;
- if (fdata == NULL) {
+ if (framenum == 1) {
/*
* XXX - other apps have a bit more of a detailed message
* for this, and instead of offering "OK" and "Cancel",
if (prefs.gui_find_wrap)
{
statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
- fdata = cf->plist_end; /* wrap around */
+ framenum = cf->count; /* wrap around */
}
else
{
statusbar_push_temporary_msg("Search reached the beginning.");
- fdata = start_fd; /* stay on previous packet */
+ framenum = start_fd->num; /* stay on previous packet */
}
- }
+ } else
+ framenum--;
} else {
/* Go on to the next frame. */
- fdata = fdata->next;
- if (fdata == NULL) {
+ if (framenum == cf->count) {
if (prefs.gui_find_wrap)
{
statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
- fdata = cf->plist_start; /* wrap around */
+ framenum = 1; /* wrap around */
}
else
{
statusbar_push_temporary_msg("Search reached the end.");
- fdata = start_fd; /* stay on previous packet */
+ framenum = start_fd->num; /* stay on previous packet */
}
- }
+ } else
+ framenum++;
}
+ fdata = frame_data_sequence_find(cf->frames, framenum);
count++;
if (new_fd != NULL) {
/* Find and select */
cf->search_in_progress = TRUE;
- row = new_packet_list_find_row_from_data(fdata, TRUE);
+ found = new_packet_list_select_row_from_data(new_fd);
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. */
+ if (!found) {
+ /* We didn't find a row corresponding to this frame.
+ 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.",
+ "The capture file is probably not fully dissected.",
simple_dialog_primary_start(), simple_dialog_primary_end());
return FALSE;
}
{
frame_data *fdata;
- for (fdata = cf->plist_start; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
- ;
+ fdata = frame_data_sequence_find(cf->frames, fnumber);
if (fdata == NULL) {
/* we didn't find a packet with that packet number */
return FALSE; /* we failed to go to that packet */
}
- new_packet_list_find_row_from_data(fdata, TRUE);
+ if (!new_packet_list_select_row_from_data(fdata)) {
+ /* We didn't find a row corresponding to this frame.
+ 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 dissected.",
+ simple_dialog_primary_start(), simple_dialog_primary_end());
+ return FALSE;
+ }
return TRUE; /* we got to that packet */
}
gboolean
-cf_goto_top_frame()
+cf_goto_top_frame(void)
{
/* Find and select */
new_packet_list_select_first_row();
}
gboolean
-cf_goto_bottom_frame()
+cf_goto_bottom_frame(void)
{
/* Find and select */
new_packet_list_select_last_row();
GtkCList; see the comment in "add_packet_to_packet_list()". */
if (row == 0 && cf->first_displayed == cf->last_displayed)
- fdata = cf->first_displayed;
+ fdata = frame_data_sequence_find(cf->frames, cf->first_displayed);
}
/* If fdata _still_ isn't set simply give up. */
"Gzip compression not supported by this file type.");
break;
+ case WTAP_ERR_DECOMPRESS:
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ "The compressed file \"%s\" appears to be damaged or corrupt.\n"
+ "(%s)", filename, err_info);
+ g_free(err_info);
+ break;
+
default:
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"The file \"%s\" could not be %s: %s.",
* indent-tabs-mode: nil
* End:
*
- * ex: set shiftwidth=2 tabstop=8 expandtab
+ * ex: set shiftwidth=2 tabstop=8 expandtab:
* :indentSize=2:tabSize=8:noTabs=true:
*/