#endif
#include <epan/epan.h>
+#include <epan/expert.h>
#include <epan/filesystem.h>
#include "color.h"
#include <epan/column.h>
#include <epan/packet.h>
#include <epan/column-utils.h>
-#include "packet-range.h"
-#include "print.h"
#include "file.h"
#include "fileset.h"
-#include "tempfile.h"
+#include "frame_tvbuff.h"
+#include "wsutil/tempfile.h"
#include "merge.h"
#include <epan/prefs.h>
#include "ui/progress_dlg.h"
#include "ui/ui_util.h"
+#include "version_info.h"
+
+/* Needed for addrinfo */
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#ifdef HAVE_NETDB_H
+# include <netdb.h>
+#endif
+
+#ifdef HAVE_WINSOCK2_H
+# include <winsock2.h>
+#endif
+
+#if defined(_WIN32) && defined(INET6)
+# include <ws2tcpip.h>
+#endif
+
#ifdef HAVE_LIBPCAP
gboolean auto_scroll_live;
#endif
static void cf_reset_state(capture_file *cf);
static int read_packet(capture_file *cf, dfilter_t *dfcode,
- epan_dissect_t *edt, column_info *cinfo, gint64 offset);
+ gboolean create_proto_tree, column_info *cinfo, gint64 offset);
static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect);
static void match_subtree_text(proto_node *node, gpointer data);
static match_result match_summary_line(capture_file *cf, frame_data *fdata,
void *criterion);
-static match_result match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
+static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata,
void *criterion);
-static match_result match_ascii(capture_file *cf, frame_data *fdata,
+static match_result match_narrow(capture_file *cf, frame_data *fdata,
void *criterion);
-static match_result match_unicode(capture_file *cf, frame_data *fdata,
+static match_result match_wide(capture_file *cf, frame_data *fdata,
void *criterion);
static match_result match_binary(capture_file *cf, frame_data *fdata,
void *criterion);
g_assert(cb_item != NULL);
while (cb_item != NULL) {
- cb = cb_item->data;
+ cb = (cf_callback_data_t *)cb_item->data;
cb->cb_fct(event, data, cb->user_data);
cb_item = g_list_next(cb_item);
}
{
cf_callback_data_t *cb;
- cb = g_malloc(sizeof(cf_callback_data_t));
+ cb = g_new(cf_callback_data_t,1);
cb->cb_fct = func;
cb->user_data = user_data;
GList *cb_item = cf_callbacks;
while (cb_item != NULL) {
- cb = cb_item->data;
+ cb = (cf_callback_data_t *)cb_item->data;
if (cb->cb_fct == func) {
cf_callbacks = g_list_remove(cf_callbacks, cb);
g_free(cb);
and fill in the information for this file. */
cf_close(cf);
+ /* XXX - we really want to initialize this after we've read all
+ the packets, so we know how much we'll ultimately need. */
+ buffer_init(&cf->buf, 1500);
+
/* Cleanup all data structures used for dissection. */
cleanup_dissection();
/* Initialize all data structures used for dissection. */
/*
* Add an encapsulation type to cf->linktypes.
*/
-void
+static void
cf_add_encapsulation_type(capture_file *cf, int encap)
{
guint i;
/* ...which means we have no changes to that file to save. */
cf->unsaved_changes = FALSE;
+ /* Free up the packet buffer. */
+ buffer_free(&cf->buf);
+
dfilter_free(cf->rfcode);
cf->rfcode = NULL;
if (cf->frames != NULL) {
return progbar_val;
}
-static void
-epan_dissect_finish(epan_dissect_t *edt)
-{
- if (edt->tree)
- proto_tree_free(edt->tree);
-}
-
cf_read_status_t
cf_read(capture_file *cf, gboolean reloading)
{
int err;
gchar *err_info;
gchar *name_ptr;
- gint64 data_offset;
- gint64 file_pos;
- progdlg_t *volatile progbar = NULL;
+ progdlg_t *progbar = NULL;
gboolean stop_flag;
- volatile gint64 size;
- volatile float progbar_val;
GTimeVal start_time;
- gchar status_str[100];
- volatile gint64 progbar_nextstep;
- volatile gint64 progbar_quantum;
dfilter_t *dfcode;
- column_info *cinfo;
- epan_dissect_t edt;
- gboolean create_proto_tree;
+ volatile gboolean create_proto_tree;
guint tap_flags;
- volatile int count = 0;
-#ifdef HAVE_LIBPCAP
- volatile int displayed_once = 0;
-#endif
gboolean compiled;
/* Compile the current display filter.
/* Get the union of the flags for all tap listeners. */
tap_flags = union_of_tap_listener_flags();
- cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
create_proto_tree =
(dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
- epan_dissect_init(&edt, create_proto_tree, FALSE);
- if (dfcode != NULL)
- epan_dissect_prime_dfilter(&edt, dfcode);
reset_tap_listeners();
XXX - do we know this at open time? */
cf->iscompressed = wtap_iscompressed(cf->wth);
- /* Find the size of the file. */
- size = wtap_file_size(cf->wth, NULL);
-
- /* 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. */
- if (size >= 0) {
- progbar_quantum = size/N_PROGBAR_UPDATES;
- if (progbar_quantum < MIN_QUANTUM)
- progbar_quantum = MIN_QUANTUM;
- }else
- progbar_quantum = 0;
- /* Progress so far. */
- progbar_val = 0.0f;
-
/* The packet list window will be empty until the file is completly loaded */
packet_list_freeze();
stop_flag = FALSE;
g_get_current_time(&start_time);
- while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
- if (size >= 0) {
- count++;
- file_pos = wtap_read_so_far(cf->wth);
+ TRY {
+#ifdef HAVE_LIBPCAP
+ int displayed_once = 0;
+#endif
+ int count = 0;
- /* 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, file_pos, status_str, sizeof(status_str));
- if (reloading)
- progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
- TRUE, &stop_flag, &start_time, progbar_val);
- else
- progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
- TRUE, &stop_flag, &start_time, progbar_val);
- }
+ gint64 size;
+ gint64 file_pos;
+ gint64 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()"
- 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 (file_pos >= progbar_nextstep) {
- if (progbar != NULL) {
+ gint64 progbar_quantum;
+ gint64 progbar_nextstep;
+ float progbar_val;
+ gchar status_str[100];
+
+ column_info *cinfo;
+
+ cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
+
+ /* Find the size of the file. */
+ size = wtap_file_size(cf->wth, NULL);
+
+ /* 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. */
+ if (size >= 0) {
+ progbar_quantum = size/N_PROGBAR_UPDATES;
+ if (progbar_quantum < MIN_QUANTUM)
+ progbar_quantum = MIN_QUANTUM;
+ }else
+ progbar_quantum = 0;
+
+ 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, file_pos, status_str, sizeof(status_str));
- /* update the packet bar content on the first run or frequently on very large files */
+ if (reloading)
+ progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
+ TRUE, &stop_flag, &start_time, progbar_val);
+ else
+ progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
+ 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 (file_pos >= progbar_nextstep) {
+ if (progbar != NULL) {
+ 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->count != 0) {
- displayed_once = 1;
- packets_bar_update();
+ if (progbar_quantum > 500000 || displayed_once == 0) {
+ if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
+ displayed_once = 1;
+ packets_bar_update();
+ }
}
- }
#endif /* HAVE_LIBPCAP */
- update_progress_dlg(progbar, progbar_val, status_str);
+ update_progress_dlg(progbar, progbar_val, status_str);
+ }
+ progbar_nextstep += progbar_quantum;
}
- progbar_nextstep += progbar_quantum;
}
- }
- if (stop_flag) {
- /* Well, the user decided to abort the read. He/She will be warned and
- it might be enough for him/her to work with the already loaded
- packets.
- This is especially true for very large capture files, where you don't
- want to wait loading the whole file (which may last minutes or even
- hours even on fast machines) just to see that it was the wrong file. */
- break;
- }
- TRY {
- read_packet(cf, dfcode, &edt, cinfo, data_offset);
+ if (stop_flag) {
+ /* Well, the user decided to abort the read. He/She will be warned and
+ it might be enough for him/her to work with the already loaded
+ packets.
+ This is especially true for very large capture files, where you don't
+ want to wait loading the whole file (which may last minutes or even
+ hours even on fast machines) just to see that it was the wrong file. */
+ break;
+ }
+ read_packet(cf, dfcode, create_proto_tree, cinfo, data_offset);
}
- CATCH(OutOfMemoryError) {
- simple_message_box(ESD_TYPE_ERROR, NULL,
- "Some infos / workarounds can be found at:\n"
- "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
- "Sorry, but Wireshark has run out of memory and has to terminate now!");
+ }
+ CATCH(OutOfMemoryError) {
+ simple_message_box(ESD_TYPE_ERROR, NULL,
+ "Some infos / workarounds can be found at:\n"
+ "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
+ "Sorry, but Wireshark has run out of memory and has to terminate now!");
#if 0
- /* Could we close the current capture and free up memory from that? */
- break;
+ /* Could we close the current capture and free up memory from that? */
#else
- /* we have to terminate, as we cannot recover from the memory error */
- exit(1);
+ /* we have to terminate, as we cannot recover from the memory error */
+ exit(1);
#endif
- }
- ENDTRY;
}
- epan_dissect_finish(&edt);
+ ENDTRY;
/* Free the display name */
g_free(name_ptr);
cf_read_status_t
cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
{
- gint64 data_offset = 0;
- gchar *err_info;
- volatile int newly_displayed_packets = 0;
- dfilter_t *dfcode;
- volatile column_info *cinfo;
- epan_dissect_t edt;
- gboolean create_proto_tree;
- guint tap_flags;
- gboolean compiled;
+ gchar *err_info;
+ int newly_displayed_packets = 0;
+ dfilter_t *dfcode;
+ volatile gboolean create_proto_tree;
+ guint tap_flags;
+ gboolean compiled;
/* Compile the current display filter.
* We assume this will not fail since cf->dfilter is only set in
/* Get the union of the flags for all tap listeners. */
tap_flags = union_of_tap_listener_flags();
- cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
create_proto_tree =
(dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
- epan_dissect_init(&edt, create_proto_tree, FALSE);
- if (dfcode != NULL)
- epan_dissect_prime_dfilter(&edt, dfcode);
*err = 0;
/*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
- 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
- aren't any packets left to read) exit. */
- break;
- }
- TRY{
- if (read_packet(cf, dfcode, &edt, (column_info *) cinfo,
- data_offset) != -1) {
+ TRY {
+ gint64 data_offset = 0;
+ column_info *cinfo;
+
+ cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
+
+ 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
+ aren't any packets left to read) exit. */
+ break;
+ }
+ if (read_packet(cf, dfcode, create_proto_tree, (column_info *) cinfo, data_offset) != -1) {
newly_displayed_packets++;
}
+ to_read--;
}
- CATCH(OutOfMemoryError) {
- simple_message_box(ESD_TYPE_ERROR, NULL,
- "Some infos / workarounds can be found at:\n"
- "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
- "Sorry, but Wireshark has run out of memory and has to terminate now!");
+ }
+ CATCH(OutOfMemoryError) {
+ simple_message_box(ESD_TYPE_ERROR, NULL,
+ "Some infos / workarounds can be found at:\n"
+ "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
+ "Sorry, but Wireshark has run out of memory and has to terminate now!");
#if 0
- /* Could we close the current capture and free up memory from that? */
- return CF_READ_ABORTED;
+ /* Could we close the current capture and free up memory from that? */
+ return CF_READ_ABORTED;
#else
- /* we have to terminate, as we cannot recover from the memory error */
- exit(1);
+ /* we have to terminate, as we cannot recover from the memory error */
+ exit(1);
#endif
- }
- ENDTRY;
- to_read--;
}
- epan_dissect_finish(&edt);
+ ENDTRY;
/* Update the file encapsulation; it might have changed based on the
packets we've read. */
dfilter_t *dfcode;
column_info *cinfo;
gboolean create_proto_tree;
- epan_dissect_t edt;
guint tap_flags;
gboolean compiled;
cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
create_proto_tree =
(dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
- epan_dissect_init(&edt, create_proto_tree, FALSE);
- if (dfcode != NULL)
- epan_dissect_prime_dfilter(&edt, dfcode);
if (cf->wth == NULL) {
cf_close(cf);
aren't any packets left to read) exit. */
break;
}
- read_packet(cf, dfcode, &edt, cinfo, data_offset);
+ read_packet(cf, dfcode, create_proto_tree, cinfo, data_offset);
}
- epan_dissect_finish(&edt);
/* Cleanup and release all dfilter resources */
if (dfcode != NULL) {
cf->rfcode = rfcode;
}
-static void
-find_and_mark_frame_depended_upon(gpointer data, gpointer user_data)
-{
- frame_data *dependent_fd;
- guint32 dependent_frame = GPOINTER_TO_UINT(data);
- capture_file *cf = (capture_file *)user_data;
-
- dependent_fd = frame_data_sequence_find(cf->frames, dependent_frame);
- dependent_fd->flags.dependent_of_displayed = 1;
-}
-
static int
add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
- dfilter_t *dfcode, epan_dissect_t *edt, column_info *cinfo,
- struct wtap_pkthdr *phdr, const guchar *buf,
- gboolean add_to_packet_list)
+ dfilter_t *dfcode, gboolean create_proto_tree, column_info *cinfo,
+ struct wtap_pkthdr *phdr, const guint8 *buf, gboolean add_to_packet_list)
{
- gint row = -1;
+ epan_dissect_t edt;
+ gint row = -1;
frame_data_set_before_dissect(fdata, &cf->elapsed_time,
&first_ts, prev_dis, prev_cap);
prev_cap = fdata;
- epan_dissect_run_with_taps(edt, phdr, buf, fdata, cinfo);
+ /* Dissect the frame. */
+ epan_dissect_init(&edt, create_proto_tree, FALSE);
+
+ if (dfcode != NULL) {
+ epan_dissect_prime_dfilter(&edt, dfcode);
+ }
+
+ epan_dissect_run_with_taps(&edt, phdr, frame_tvbuff_new(fdata, buf), fdata, cinfo);
/* If we don't have a display filter, set "passed_dfilter" to 1. */
if (dfcode != NULL) {
- fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
+ fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0;
if (fdata->flags.passed_dfilter) {
/* This frame passed the display filter but it may depend on other
* (potentially not displayed) frames. Find those frames and mark them
* as depended upon.
*/
- g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf);
+ g_slist_foreach(edt.pi.dependent_frames, find_and_mark_frame_depended_upon, cf->frames);
}
} else
fdata->flags.passed_dfilter = 1;
if (add_to_packet_list) {
/* We fill the needed columns from new_packet_list */
- row = packet_list_append(cinfo, fdata, &edt->pi);
+ row = packet_list_append(cinfo, fdata, &edt.pi);
}
if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
cf->last_displayed = fdata->num;
}
- epan_dissect_reset(edt);
+ epan_dissect_cleanup(&edt);
return row;
}
/* returns the row of the new packet in the packet list or -1 if not displayed */
static int
read_packet(capture_file *cf, dfilter_t *dfcode,
- epan_dissect_t *edt, column_info *cinfo, gint64 offset)
+ gboolean create_proto_tree, column_info *cinfo, gint64 offset)
{
struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
- const guchar *buf = wtap_buf_ptr(cf->wth);
+ const guint8 *buf = wtap_buf_ptr(cf->wth);
frame_data fdlocal;
guint32 framenum;
frame_data *fdata;
epan_dissect_t edt;
epan_dissect_init(&edt, TRUE, FALSE);
epan_dissect_prime_dfilter(&edt, cf->rfcode);
- epan_dissect_run(&edt, phdr, buf, &fdlocal, NULL);
+ epan_dissect_run(&edt, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL);
passed = dfilter_apply_edt(cf->rfcode, &edt);
epan_dissect_cleanup(&edt);
}
if (!cf->redissecting) {
row = add_packet_to_packet_list(fdata, cf, dfcode,
- edt, cinfo,
+ create_proto_tree, cinfo,
phdr, buf, TRUE);
}
}
wtapng_iface_descriptions_t *idb_inf, *idb_inf_merge_file;
wtapng_if_descr_t int_data, *file_int_data;
GString *comment_gstr;
- int i;
fake_interface_ids = TRUE;
/* Create SHB info */
- shb_hdr = wtap_file_get_shb_info(in_files[0].wth);
+ shb_hdr = wtap_file_get_shb_info(in_files[0].wth);
comment_gstr = g_string_new("");
g_string_append_printf(comment_gstr, "%s \n",shb_hdr->opt_comment);
g_string_append_printf(comment_gstr, "File created by merging: \n");
gboolean
cf_read_frame_r(capture_file *cf, frame_data *fdata,
- struct wtap_pkthdr *phdr, guint8 *pd)
+ struct wtap_pkthdr *phdr, Buffer *buf)
{
int err;
gchar *err_info;
}
*phdr = frame->phdr;
- memcpy(pd, frame->pd, fdata->cap_len);
+ buffer_assure_space(buf, frame->phdr.caplen);
+ memcpy(buffer_start_ptr(buf), frame->pd, frame->phdr.caplen);
return TRUE;
}
#endif
- if (!wtap_seek_read(cf->wth, fdata->file_off, phdr, pd,
+ if (!wtap_seek_read(cf->wth, fdata->file_off, phdr, buf,
fdata->cap_len, &err, &err_info)) {
display_basename = g_filename_display_basename(cf->filename);
switch (err) {
gboolean
cf_read_frame(capture_file *cf, frame_data *fdata)
{
- return cf_read_frame_r(cf, fdata, &cf->phdr, cf->pd);
+ return cf_read_frame_r(cf, fdata, &cf->phdr, &cf->buf);
}
/* Rescan the list of packets, reconstructing the CList.
int progbar_quantum;
dfilter_t *dfcode;
column_info *cinfo;
- epan_dissect_t edt;
gboolean create_proto_tree;
guint tap_flags;
gboolean add_to_packet_list = FALSE;
cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
create_proto_tree =
(dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
- epan_dissect_init(&edt, create_proto_tree, FALSE);
- if (dfcode != NULL)
- epan_dissect_prime_dfilter(&edt, dfcode);
reset_tap_listeners();
/* Which frame, if any, is the currently selected 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);
+ frame_data_reset(fdata);
frames_count = cf->count;
}
preceding_frame_num = prev_frame_num;
preceding_frame = prev_frame;
}
- add_packet_to_packet_list(fdata, cf, dfcode, &edt,
- cinfo, &cf->phdr, cf->pd,
+ add_packet_to_packet_list(fdata, cf, dfcode, create_proto_tree,
+ cinfo, &cf->phdr,
+ buffer_start_ptr(&cf->buf),
add_to_packet_list);
/* If this frame is displayed, and this is the first frame we've
prev_frame_num = fdata->num;
prev_frame = fdata;
}
- epan_dissect_finish(&edt);
/* We are done redissecting the packet list. */
cf->redissecting = FALSE;
until it finishes. Should we just stick them with that? */
for (; framenum <= frames_count; framenum++) {
fdata = frame_data_sequence_find(cf->frames, framenum);
- fdata->flags.visited = 0;
- frame_data_cleanup(fdata);
+ frame_data_reset(fdata);
}
}
{
guint32 framenum;
frame_data *fdata;
- guint8 pd[WTAP_MAX_PACKET_SIZE+1];
+ Buffer buf;
psp_return_t ret = PSP_FINISHED;
progdlg_t *progbar = NULL;
range_process_e process_this;
struct wtap_pkthdr phdr;
+ buffer_init(&buf, 1500);
+
/* Update the progress bar when it gets to this value. */
progbar_nextstep = 0;
/* When we reach the value that triggers a progress bar update,
}
/* Get the packet */
- if (!cf_read_frame_r(cf, fdata, &phdr, pd)) {
+ if (!cf_read_frame_r(cf, fdata, &phdr, &buf)) {
/* Attempt to get the packet failed. */
ret = PSP_FAILED;
break;
}
/* Process the packet */
- if (!callback(cf, fdata, &phdr, pd, callback_args)) {
+ if (!callback(cf, fdata, &phdr, buffer_start_ptr(&buf), callback_args)) {
/* Callback failed. We assume it reported the error appropriately. */
ret = PSP_FAILED;
break;
if (progbar != NULL)
destroy_progress_dlg(progbar);
+ buffer_free(&buf);
+
return ret;
}
struct wtap_pkthdr *phdr, const guint8 *pd,
void *argsp)
{
- retap_callback_args_t *args = argsp;
+ retap_callback_args_t *args = (retap_callback_args_t *)argsp;
epan_dissect_t edt;
epan_dissect_init(&edt, args->construct_protocol_tree, FALSE);
- epan_dissect_run_with_taps(&edt, phdr, pd, fdata, args->cinfo);
+ epan_dissect_run_with_taps(&edt, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo);
epan_dissect_cleanup(&edt);
return TRUE;
struct wtap_pkthdr *phdr, const guint8 *pd,
void *argsp)
{
- print_callback_args_t *args = argsp;
+ print_callback_args_t *args = (print_callback_args_t *)argsp;
epan_dissect_t edt;
int i;
char *cp;
information. */
if (args->print_args->print_summary) {
col_custom_prime_edt(&edt, &cf->cinfo);
- epan_dissect_run(&edt, phdr, pd, fdata, &cf->cinfo);
+ epan_dissect_run(&edt, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
} else
- epan_dissect_run(&edt, phdr, pd, fdata, NULL);
+ epan_dissect_run(&edt, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
if (args->print_formfeed) {
if (!new_page(args->print_args->stream))
g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
if (args->print_args->print_summary) {
+ if (!args->print_args->print_col_headings)
+ args->print_header_line = FALSE;
if (args->print_header_line) {
if (!print_line(args->print_args->stream, 0, args->header_line_buf))
goto fail;
if (line_len > args->line_buf_len) {
cp_off = (int) (cp - args->line_buf);
args->line_buf_len = 2 * line_len;
- args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
+ args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
cp = args->line_buf + cp_off;
}
args->print_separator = TRUE;
/* Print a header line if we print any more packet summaries */
- args->print_header_line = TRUE;
+ if (args->print_args->print_col_headings)
+ args->print_header_line = TRUE;
}
if (args->print_args->print_hex) {
+ if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
+ if (!print_line(args->print_args->stream, 0, ""))
+ goto fail;
+ }
/* Print the full packet data as hex. */
if (!print_hex_data(args->print_args->stream, &edt))
goto fail;
args->print_separator = TRUE;
/* Print a header line if we print any more packet summaries */
- args->print_header_line = TRUE;
+ if (args->print_args->print_col_headings)
+ args->print_header_line = TRUE;
} /* if (args->print_args->print_dissections != print_dissections_none) */
epan_dissect_cleanup(&edt);
fmt_data *cfmt;
callback_args.print_args = print_args;
- callback_args.print_header_line = TRUE;
+ callback_args.print_header_line = print_args->print_col_headings;
callback_args.header_line_buf = NULL;
callback_args.header_line_buf_len = 256;
callback_args.print_formfeed = FALSE;
callback_args.num_visible_cols = 0;
callback_args.visible_cols = NULL;
- if (!print_preamble(print_args->stream, cf->filename)) {
+ if (!print_preamble(print_args->stream, cf->filename, wireshark_svnversion)) {
destroy_print_stream(print_args->stream);
return CF_PRINT_WRITE_ERROR;
}
if (print_args->print_summary) {
/* We're printing packet summaries. Allocate the header line buffer
and get the column widths. */
- callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
+ callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
/* Find the number of visible columns and the last visible column */
for (i = 0; i < prefs.num_cols; i++) {
if (line_len > callback_args.header_line_buf_len) {
cp_off = (int) (cp - callback_args.header_line_buf);
callback_args.header_line_buf_len = 2 * line_len;
- callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
+ callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
callback_args.header_line_buf_len + 1);
cp = callback_args.header_line_buf + cp_off;
}
/* Now start out the main line buffer with the same length as the
header line buffer. */
callback_args.line_buf_len = callback_args.header_line_buf_len;
- callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
+ callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
} /* if (print_summary) */
/* Iterate through the list of packets, printing the packets we were
struct wtap_pkthdr *phdr, const guint8 *pd,
void *argsp)
{
- FILE *fh = argsp;
+ FILE *fh = (FILE *)argsp;
epan_dissect_t edt;
/* Create the protocol tree, but don't fill in the column information. */
epan_dissect_init(&edt, TRUE, TRUE);
- epan_dissect_run(&edt, phdr, pd, fdata, NULL);
+ epan_dissect_run(&edt, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
/* Write out the information in that tree. */
proto_tree_write_pdml(&edt, fh);
struct wtap_pkthdr *phdr, const guint8 *pd,
void *argsp)
{
- FILE *fh = argsp;
+ FILE *fh = (FILE *)argsp;
epan_dissect_t edt;
gboolean proto_tree_needed;
proto_tree_needed = have_custom_cols(&cf->cinfo);
epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
col_custom_prime_edt(&edt, &cf->cinfo);
- epan_dissect_run(&edt, phdr, pd, fdata, &cf->cinfo);
+ epan_dissect_run(&edt, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
/* Write out the information in that tree. */
struct wtap_pkthdr *phdr, const guint8 *pd,
void *argsp)
{
- FILE *fh = argsp;
+ FILE *fh = (FILE *)argsp;
epan_dissect_t edt;
gboolean proto_tree_needed;
proto_tree_needed = have_custom_cols(&cf->cinfo);
epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
col_custom_prime_edt(&edt, &cf->cinfo);
- epan_dissect_run(&edt, phdr, pd, fdata, &cf->cinfo);
+ epan_dissect_run(&edt, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
/* Write out the information in that tree. */
struct wtap_pkthdr *phdr,
const guint8 *pd, void *argsp)
{
- FILE *fh = argsp;
+ FILE *fh = (FILE *)argsp;
epan_dissect_t edt;
epan_dissect_init(&edt, TRUE, TRUE);
- epan_dissect_run(&edt, phdr, pd, fdata, NULL);
+ epan_dissect_run(&edt, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
proto_tree_write_carrays(fdata->num, fh, &edt);
epan_dissect_cleanup(&edt);
static match_result
match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
{
- match_data *mdata = criterion;
+ match_data *mdata = (match_data *)criterion;
epan_dissect_t edt;
/* Load the frame's data. */
/* Construct the protocol tree, including the displayed text */
epan_dissect_init(&edt, TRUE, TRUE);
/* We don't need the column information */
- epan_dissect_run(&edt, &cf->phdr, cf->pd, fdata, NULL);
+ epan_dissect_run(&edt, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
/* Iterate through all the nodes, seeing if they have text that matches. */
mdata->cf = cf;
static match_result
match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
{
- match_data *mdata = criterion;
+ match_data *mdata = (match_data *)criterion;
const gchar *string = mdata->string;
size_t string_len = mdata->string_len;
epan_dissect_t edt;
/* Don't bother constructing the protocol tree */
epan_dissect_init(&edt, FALSE, FALSE);
/* Get the column information */
- epan_dissect_run(&edt, &cf->phdr, cf->pd, fdata, &cf->cinfo);
+ epan_dissect_run(&edt, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata,
+ &cf->cinfo);
/* Find the Info column */
for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
size_t data_len;
} cbs_t; /* "Counted byte string" */
+
+/*
+ * The current match_* routines only support ASCII case insensitivity and don't
+ * convert UTF-8 inputs to UTF-16 for matching.
+ *
+ * We could modify them to use the GLib Unicode routines or the International
+ * Components for Unicode library but it's not apparent that we could do so
+ * without consuming a lot more CPU and memory or that searching would be
+ * significantly better.
+ */
+
gboolean
cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
search_direction dir)
/* String search - what type of string? */
switch (cf->scs_type) {
- case SCS_ASCII_AND_UNICODE:
- return find_packet(cf, match_ascii_and_unicode, &info, dir);
+ case SCS_NARROW_AND_WIDE:
+ return find_packet(cf, match_narrow_and_wide, &info, dir);
- case SCS_ASCII:
- return find_packet(cf, match_ascii, &info, dir);
+ case SCS_NARROW:
+ return find_packet(cf, match_narrow, &info, dir);
- case SCS_UNICODE:
- return find_packet(cf, match_unicode, &info, dir);
+ case SCS_WIDE:
+ return find_packet(cf, match_wide, &info, dir);
default:
g_assert_not_reached();
}
static match_result
-match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
+match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
{
- cbs_t *info = criterion;
+ cbs_t *info = (cbs_t *)criterion;
const guint8 *ascii_text = info->data;
size_t textlen = info->data_len;
match_result result;
guint32 buf_len;
+ guint8 *pd;
guint32 i;
guint8 c_char;
size_t c_match = 0;
result = MR_NOTMATCHED;
buf_len = fdata->cap_len;
+ pd = buffer_start_ptr(&cf->buf);
i = 0;
while (i < buf_len) {
- c_char = cf->pd[i];
+ c_char = pd[i];
if (cf->case_type)
c_char = toupper(c_char);
if (c_char != '\0') {
}
static match_result
-match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
+match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
{
- cbs_t *info = criterion;
+ guint8 *pd;
+ cbs_t *info = (cbs_t *)criterion;
const guint8 *ascii_text = info->data;
size_t textlen = info->data_len;
match_result result;
result = MR_NOTMATCHED;
buf_len = fdata->cap_len;
+ pd = buffer_start_ptr(&cf->buf);
i = 0;
while (i < buf_len) {
- c_char = cf->pd[i];
+ c_char = pd[i];
if (cf->case_type)
c_char = toupper(c_char);
if (c_char == ascii_text[c_match]) {
}
static match_result
-match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
+match_wide(capture_file *cf, frame_data *fdata, void *criterion)
{
- cbs_t *info = criterion;
+ cbs_t *info = (cbs_t *)criterion;
const guint8 *ascii_text = info->data;
size_t textlen = info->data_len;
match_result result;
guint32 buf_len;
+ guint8 *pd;
guint32 i;
guint8 c_char;
size_t c_match = 0;
result = MR_NOTMATCHED;
buf_len = fdata->cap_len;
+ pd = buffer_start_ptr(&cf->buf);
i = 0;
while (i < buf_len) {
- c_char = cf->pd[i];
+ c_char = pd[i];
if (cf->case_type)
c_char = toupper(c_char);
if (c_char == ascii_text[c_match]) {
static match_result
match_binary(capture_file *cf, frame_data *fdata, void *criterion)
{
- cbs_t *info = criterion;
+ cbs_t *info = (cbs_t *)criterion;
const guint8 *binary_data = info->data;
size_t datalen = info->data_len;
match_result result;
guint32 buf_len;
+ guint8 *pd;
guint32 i;
size_t c_match = 0;
result = MR_NOTMATCHED;
buf_len = fdata->cap_len;
+ pd = buffer_start_ptr(&cf->buf);
i = 0;
while (i < buf_len) {
- if (cf->pd[i] == binary_data[c_match]) {
+ if (pd[i] == binary_data[c_match]) {
c_match += 1;
if (c_match == datalen) {
result = MR_MATCHED;
static match_result
match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
{
- dfilter_t *sfcode = criterion;
+ dfilter_t *sfcode = (dfilter_t *)criterion;
epan_dissect_t edt;
match_result result;
epan_dissect_init(&edt, TRUE, FALSE);
epan_dissect_prime_dfilter(&edt, sfcode);
- epan_dissect_run(&edt, &cf->phdr, cf->pd, fdata, NULL);
+ epan_dissect_run(&edt, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
epan_dissect_cleanup(&edt);
return result;
cf->edt = epan_dissect_new(TRUE, TRUE);
tap_build_interesting(cf->edt);
- epan_dissect_run(cf->edt, &cf->phdr, cf->pd, cf->current_frame,
- NULL);
+ epan_dissect_run(cf->edt, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf),
+ cf->current_frame, NULL);
dfilter_macro_build_ftv_cache(cf->edt->tree);
cf->packet_comment_count++;
}
+ expert_update_comment_count(cf->packet_comment_count);
+
/* OK, we have unsaved changes. */
cf->unsaved_changes = TRUE;
}
/*
- * Does this capture file have any comments?
+ * What types of comments does this capture file have?
*/
-gboolean
-cf_has_comments(capture_file *cf)
+guint32
+cf_comment_types(capture_file *cf)
{
- return (cf_read_shb_comment(cf) != NULL || cf->packet_comment_count != 0);
+ guint32 comment_types = 0;
+
+ if (cf_read_shb_comment(cf) != NULL)
+ comment_types |= WTAP_COMMENT_PER_SECTION;
+ if (cf->packet_comment_count != 0)
+ comment_types |= WTAP_COMMENT_PER_PACKET;
+ return comment_types;
}
typedef struct {
struct wtap_pkthdr *phdr, const guint8 *pd,
void *argsp)
{
- save_callback_args_t *args = argsp;
+ save_callback_args_t *args = (save_callback_args_t *)argsp;
struct wtap_pkthdr hdr;
int err;
gchar *display_basename;
hdr.presence_flags |= WTAP_HAS_TS;
if (fdata->flags.has_if_id)
hdr.presence_flags |= WTAP_HAS_INTERFACE_ID;
+ if (fdata->flags.has_pack_flags)
+ hdr.presence_flags |= WTAP_HAS_PACK_FLAGS;
hdr.ts.secs = fdata->abs_ts.secs;
hdr.ts.nsecs = fdata->abs_ts.nsecs;
hdr.caplen = fdata->cap_len;
/* pcapng */
hdr.interface_id = fdata->interface_id; /* identifier of the interface. */
/* options */
+ hdr.pack_flags = fdata->pack_flags;
hdr.opt_comment = fdata->opt_comment; /* NULL if not available */
/* pseudo */
hdr.pseudo_header = phdr->pseudo_header;
gboolean
cf_can_write_with_wiretap(capture_file *cf)
{
- int ft;
-
- for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
- /* To save a file with Wiretap, Wiretap has to handle that format,
- and its code to handle that format must be able to write a file
- with this file's encapsulation types. */
- if (wtap_dump_can_write_encaps(ft, cf->linktypes)) {
- /* OK, we can write it out in this type. */
- return TRUE;
- }
+ /* We don't care whether we support the comments in this file or not;
+ if we can't, we'll offer the user the option of discarding the
+ comments. */
+ return wtap_dump_can_write(cf->linktypes, 0);
+}
+
+/*
+ * Should we let the user do a save?
+ *
+ * We should if:
+ *
+ * the file has unsaved changes, and we can save it in some
+ * format through Wiretap
+ *
+ * or
+ *
+ * the file is a temporary file and has no unsaved changes (so
+ * that "saving" it just means copying it).
+ *
+ * XXX - we shouldn't allow files to be edited if they can't be saved,
+ * so cf->unsaved_changes should be true only if the file can be saved.
+ *
+ * We don't care whether we support the comments in this file or not;
+ * if we can't, we'll offer the user the option of discarding the
+ * comments.
+ */
+gboolean
+cf_can_save(capture_file *cf)
+{
+ if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
+ /* Saved changes, and we can write it out with Wiretap. */
+ return TRUE;
}
- /* No, we couldn't save it in any format. */
+ if (cf->is_tempfile && !cf->unsaved_changes) {
+ /*
+ * Temporary file with no unsaved changes, so we can just do a
+ * raw binary copy.
+ */
+ return TRUE;
+ }
+
+ /* Nothing to save. */
return FALSE;
}
+/*
+ * Should we let the user do a "save as"?
+ *
+ * That's true if:
+ *
+ * we can save it in some format through Wiretap
+ *
+ * or
+ *
+ * the file is a temporary file and has no unsaved changes (so
+ * that "saving" it just means copying it).
+ *
+ * XXX - we shouldn't allow files to be edited if they can't be saved,
+ * so cf->unsaved_changes should be true only if the file can be saved.
+ *
+ * We don't care whether we support the comments in this file or not;
+ * if we can't, we'll offer the user the option of discarding the
+ * comments.
+ */
+gboolean
+cf_can_save_as(capture_file *cf)
+{
+ if (wtap_dump_can_write(cf->linktypes, 0)) {
+ /* We can write it out with Wiretap. */
+ return TRUE;
+ }
+
+ if (cf->is_tempfile && !cf->unsaved_changes) {
+ /*
+ * Temporary file with no unsaved changes, so we can just do a
+ * raw binary copy.
+ */
+ return TRUE;
+ }
+
+ /* Nothing to save. */
+ return FALSE;
+}
+
+/*
+ * Does this file have unsaved data?
+ */
+gboolean
+cf_has_unsaved_data(capture_file *cf)
+{
+ /*
+ * If this is a temporary file, or a file with unsaved changes, it
+ * has unsaved data.
+ */
+ return cf->is_tempfile || cf->unsaved_changes;
+}
+
/*
* Quick scan to find packet offsets.
*/
gchar *name_ptr;
gint64 data_offset;
gint64 file_pos;
- progdlg_t *volatile progbar = NULL;
+ progdlg_t *progbar = NULL;
gboolean stop_flag;
- volatile gint64 size;
- volatile float progbar_val;
+ gint64 size;
+ float progbar_val;
GTimeVal start_time;
gchar status_str[100];
- volatile gint64 progbar_nextstep;
- volatile gint64 progbar_quantum;
+ gint64 progbar_nextstep;
+ gint64 progbar_quantum;
guint32 framenum;
frame_data *fdata;
- volatile int count = 0;
+ int count = 0;
#ifdef HAVE_LIBPCAP
- volatile int displayed_once = 0;
+ int displayed_once = 0;
#endif
/* Close the old handle. */
progbar_quantum = MIN_QUANTUM;
}else
progbar_quantum = 0;
- /* Progress so far. */
- progbar_val = 0.0f;
stop_flag = FALSE;
g_get_current_time(&start_time);
gboolean compressed, gboolean discard_comments,
gboolean dont_reopen)
{
- gchar *fname_new = NULL;
- int err;
- gchar *err_info;
+ gchar *err_info;
+ gchar *fname_new = NULL;
+ wtap_dumper *pdh;
+ frame_data *fdata;
+ struct addrinfo *addrs;
+ guint framenum;
+ int err;
+#ifdef _WIN32
+ gchar *display_basename;
+#endif
enum {
SAVE_WITH_MOVE,
SAVE_WITH_COPY,
SAVE_WITH_WTAP
- } how_to_save;
- wtap_dumper *pdh;
+ } how_to_save;
save_callback_args_t callback_args;
-#ifdef _WIN32
- gchar *display_basename;
-#endif
- guint framenum;
- frame_data *fdata;
cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
+ addrs = get_addrinfo_list();
+
if (save_format == cf->cd_t && compressed == cf->iscompressed
- && !discard_comments && !cf->unsaved_changes) {
+ && !discard_comments && !cf->unsaved_changes
+ && !(addrs && addrs->ai_next &&
+ wtap_dump_has_name_resolution(save_format))) {
/* We're saving in the format it's already in, and we're
not discarding comments, and there are no changes we have
- in memory that aren't saved to the file, so we can just move
- or copy the raw data. */
+ in memory that aren't saved to the file, and we have no name
+ resolution blocks to write, so we can just move or copy the raw data. */
if (cf->is_tempfile) {
/* The file being saved is a temporary file from a live
}
/* Add address resolution */
- wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
+ wtap_dump_set_addrinfo_list(pdh, addrs);
/* Iterate through the list of packets, processing all the packets. */
callback_args.pdh = pdh;