/* file.c
* File I/O routines
*
- * $Id$
- *
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "config.h"
+#include <config.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
-#include <signal.h>
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#include <wsutil/tempfile.h>
#include <wsutil/file_util.h>
+#include <wsutil/filesystem.h>
+#include <wsutil/ws_version_info.h>
#include <wiretap/merge.h>
+#include <epan/exceptions.h>
#include <epan/epan-int.h>
#include <epan/epan.h>
#include <epan/column.h>
#include <epan/packet.h>
#include <epan/column-utils.h>
#include <epan/expert.h>
-#include <epan/filesystem.h>
#include <epan/prefs.h>
#include <epan/dfilter/dfilter.h>
#include <epan/epan_dissect.h>
#include <epan/tap.h>
-#include <epan/dissectors/packet-data.h>
#include <epan/dissectors/packet-ber.h>
#include <epan/timestamp.h>
#include <epan/dfilter/dfilter-macro.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_LIBPCAP
-gboolean auto_scroll_live;
+gboolean auto_scroll_live; /* GTK+ only? */
#endif
-static guint32 cum_bytes;
-const static frame_data *ref;
-static frame_data *prev_dis;
-static frame_data *prev_cap;
-
-static gulong computed_elapsed;
-
-static void cf_reset_state(capture_file *cf);
-
-static int read_packet(capture_file *cf, dfilter_t *dfcode,
- gboolean create_proto_tree, column_info *cinfo, gint64 offset);
+static int read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
+ column_info *cinfo, gint64 offset);
static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect);
match_result (*match_function)(capture_file *, frame_data *, void *),
void *criterion, search_direction dir);
+static const char *cf_get_user_packet_comment(capture_file *cf, const frame_data *fd);
+
static void cf_open_failure_alert_box(const char *filename, int err,
gchar *err_info, gboolean for_writing,
int file_type);
cb->cb_fct = func;
cb->user_data = user_data;
- cf_callbacks = g_list_append(cf_callbacks, cb);
+ cf_callbacks = g_list_prepend(cf_callbacks, cb);
}
void
-cf_callback_remove(cf_callback_t func)
+cf_callback_remove(cf_callback_t func, gpointer user_data)
{
cf_callback_data_t *cb;
GList *cb_item = cf_callbacks;
while (cb_item != NULL) {
cb = (cf_callback_data_t *)cb_item->data;
- if (cb->cb_fct == func) {
+ if (cb->cb_fct == func && cb->user_data == user_data) {
cf_callbacks = g_list_remove(cf_callbacks, cb);
g_free(cb);
return;
cf_timestamp_auto_precision(capture_file *cf)
{
int i;
- int prec = timestamp_get_precision();
-
/* don't try to get the file's precision if none is opened */
if (cf->state == FILE_CLOSED) {
return;
}
- /* if we are in auto mode, set precision of current file */
- if (prec == TS_PREC_AUTO ||
- prec == TS_PREC_AUTO_SEC ||
- prec == TS_PREC_AUTO_DSEC ||
- prec == TS_PREC_AUTO_CSEC ||
- prec == TS_PREC_AUTO_MSEC ||
- prec == TS_PREC_AUTO_USEC ||
- prec == TS_PREC_AUTO_NSEC)
- {
- switch(wtap_file_tsprecision(cf->wth)) {
- case(WTAP_FILE_TSPREC_SEC):
- timestamp_set_precision(TS_PREC_AUTO_SEC);
- break;
- case(WTAP_FILE_TSPREC_DSEC):
- timestamp_set_precision(TS_PREC_AUTO_DSEC);
- break;
- case(WTAP_FILE_TSPREC_CSEC):
- timestamp_set_precision(TS_PREC_AUTO_CSEC);
- break;
- case(WTAP_FILE_TSPREC_MSEC):
- timestamp_set_precision(TS_PREC_AUTO_MSEC);
- break;
- case(WTAP_FILE_TSPREC_USEC):
- timestamp_set_precision(TS_PREC_AUTO_USEC);
- break;
- case(WTAP_FILE_TSPREC_NSEC):
- timestamp_set_precision(TS_PREC_AUTO_NSEC);
- break;
- default:
- g_assert_not_reached();
- }
- }
/* 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++) {
}
gulong
-cf_get_computed_elapsed(void)
+cf_get_computed_elapsed(capture_file *cf)
{
- return computed_elapsed;
-}
-
-static void reset_elapsed(void)
-{
- computed_elapsed = 0;
+ return cf->computed_elapsed;
}
/*
* GLIB_CHECK_VERSION(2,28,0) adds g_get_real_time which could minimize or
* replace this
*/
-static void compute_elapsed(GTimeVal *start_time)
+static void compute_elapsed(capture_file *cf, GTimeVal *start_time)
{
gdouble delta_time;
GTimeVal time_now;
delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
time_now.tv_usec - start_time->tv_usec;
- computed_elapsed = (gulong) (delta_time / 1000); /* ms */
+ cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */
}
-const nstime_t *
+static const nstime_t *
ws_get_frame_ts(void *data, guint32 frame_num)
{
capture_file *cf = (capture_file *) data;
- if (prev_dis && prev_dis->num == frame_num)
- return &prev_dis->abs_ts;
+ if (cf->prev_dis && cf->prev_dis->num == frame_num)
+ return &cf->prev_dis->abs_ts;
- if (prev_cap && prev_cap->num == frame_num)
- return &prev_cap->abs_ts;
+ if (cf->prev_cap && cf->prev_cap->num == frame_num)
+ return &cf->prev_cap->abs_ts;
if (cf->frames) {
frame_data *fd = frame_data_sequence_find(cf->frames, frame_num);
return NULL;
}
-epan_t *
+static const char *
+ws_get_user_comment(void *data, const frame_data *fd)
+{
+ capture_file *cf = (capture_file *) data;
+
+ return cf_get_user_packet_comment(cf, fd);
+}
+
+static epan_t *
ws_epan_new(capture_file *cf)
{
epan_t *epan = epan_new();
epan->data = cf;
epan->get_frame_ts = ws_get_frame_ts;
+ epan->get_interface_name = cap_file_get_interface_name;
+ epan->get_user_comment = ws_get_user_comment;
return epan;
}
cf_status_t
-cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
+cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
{
wtap *wth;
gchar *err_info;
- wth = wtap_open_offline(fname, err, &err_info, TRUE);
+ wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
if (wth == NULL)
goto fail;
and fill in the information for this file. */
cf_close(cf);
+ /* Initialize the packet header. */
+ wtap_phdr_init(&cf->phdr);
+
/* 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);
+ ws_buffer_init(&cf->buf, 1500);
- /* Create new epan session for dissection. */
- epan_free(cf->epan);
+ /* Create new epan session for dissection.
+ * (The old one was freed in cf_close().)
+ */
cf->epan = ws_epan_new(cf);
/* We're about to start reading the file. */
/* No user changes yet. */
cf->unsaved_changes = FALSE;
- reset_elapsed();
+ cf->computed_elapsed = 0;
- cf->cd_t = wtap_file_type(cf->wth);
+ cf->cd_t = wtap_file_type_subtype(cf->wth);
+ cf->open_type = type;
cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
cf->count = 0;
cf->packet_comment_count = 0;
cf->frames = new_frame_data_sequence();
nstime_set_zero(&cf->elapsed_time);
- ref = NULL;
- prev_dis = NULL;
- prev_cap = NULL;
- cum_bytes = 0;
+ cf->ref = NULL;
+ cf->prev_dis = NULL;
+ cf->prev_cap = NULL;
+ cf->cum_bytes = 0;
/* Adjust timestamp precision if auto is selected, col width will be adjusted */
cf_timestamp_auto_precision(cf);
packet_list_queue_draw();
cf_callback_invoke(cf_cb_file_opened, cf);
- if (cf->cd_t == WTAP_FILE_BER) {
+ if (cf->cd_t == WTAP_FILE_TYPE_SUBTYPE_BER) {
/* tell the BER dissector the file name */
ber_set_filename(cf->filename);
}
g_array_append_val(cf->linktypes, encap);
}
-/*
- * Reset the state for the currently closed file, but don't do the
- * UI callbacks; this is for use in "cf_open()", where we don't
- * want the UI to go from "file open" to "file closed" back to
- * "file open", we want it to go from "old file open" to "new file
- * open and being read".
- *
- * XXX - currently, cf_open() calls cf_close(), rather than
- * cf_reset_state().
- */
-static void
-cf_reset_state(capture_file *cf)
+/* Reset everything to a pristine state */
+void
+cf_close(capture_file *cf)
{
+ cf->stop_flag = FALSE;
+ if (cf->state == FILE_CLOSED)
+ return; /* Nothing to do */
+
/* Die if we're in the middle of reading a file. */
g_assert(cf->state != FILE_READ_IN_PROGRESS);
+ cf_callback_invoke(cf_cb_file_closing, cf);
+
+ /* close things, if not already closed before */
+ color_filters_cleanup();
+
if (cf->wth) {
wtap_close(cf->wth);
cf->wth = NULL;
/* ...which means we have no changes to that file to save. */
cf->unsaved_changes = FALSE;
+ /* no open_routine type */
+ cf->open_type = WTAP_TYPE_AUTO;
+
+ /* Clean up the packet header. */
+ wtap_phdr_cleanup(&cf->phdr);
+
/* Free up the packet buffer. */
- buffer_free(&cf->buf);
+ ws_buffer_free(&cf->buf);
dfilter_free(cf->rfcode);
cf->rfcode = NULL;
cf->edited_frames = NULL;
}
#endif
+ if (cf->frames_user_comments) {
+ g_tree_destroy(cf->frames_user_comments);
+ cf->frames_user_comments = NULL;
+ }
cf_unselect_packet(cf); /* nothing to select */
cf->first_displayed = 0;
cf->last_displayed = 0;
cf->finfo_selected = NULL;
/* No frame link-layer types, either. */
- g_array_free(cf->linktypes, TRUE);
- cf->linktypes = NULL;
+ if (cf->linktypes != NULL) {
+ g_array_free(cf->linktypes, TRUE);
+ cf->linktypes = NULL;
+ }
/* Clear the packet list. */
packet_list_freeze();
reset_tap_listeners();
+ epan_free(cf->epan);
+ cf->epan = NULL;
+
/* We have no file open. */
cf->state = FILE_CLOSED;
-}
-
-/* Reset everything to a pristine state */
-void
-cf_close(capture_file *cf)
-{
- if (cf->state != FILE_CLOSED) {
- cf_callback_invoke(cf_cb_file_closing, cf);
- /* close things, if not already closed before */
- color_filters_cleanup();
- cf_reset_state(cf);
- epan_free(cf->epan);
- cf->epan = NULL;
-
- cf_callback_invoke(cf_cb_file_closed, cf);
- }
+ cf_callback_invoke(cf_cb_file_closed, cf);
}
static float
gchar *err_info;
gchar *name_ptr;
progdlg_t *progbar = NULL;
- gboolean stop_flag;
GTimeVal start_time;
+ epan_dissect_t edt;
dfilter_t *dfcode;
volatile gboolean create_proto_tree;
guint tap_flags;
* 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);
+ compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
g_assert(!cf->dfilter || (compiled && dfcode));
/* Get the union of the flags for all tap listeners. */
/* The packet list window will be empty until the file is completly loaded */
packet_list_freeze();
- stop_flag = FALSE;
+ cf->stop_flag = FALSE;
g_get_current_time(&start_time);
+ epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
+
TRY {
#ifdef HAVE_LIBPCAP
int displayed_once = 0;
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);
+ TRUE, &cf->stop_flag, &start_time, progbar_val);
else
progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
- TRUE, &stop_flag, &start_time, progbar_val);
+ TRUE, &cf->stop_flag, &start_time, progbar_val);
}
/* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
}
}
- if (stop_flag) {
+ if (cf->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.
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);
+ read_packet(cf, dfcode, &edt, 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!");
+ "More information and workarounds can be found at\n"
+ "https://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? */
#else
dfilter_free(dfcode);
}
+ epan_dissect_cleanup(&edt);
+
/* We're done reading the file; destroy the progress bar if it was created. */
if (progbar != NULL)
destroy_progress_dlg(progbar);
postseq_cleanup_all_protocols();
/* compute the time it took to load the file */
- compute_elapsed(&start_time);
+ compute_elapsed(cf, &start_time);
/* Set the file encapsulation type now; we don't know what it is until
we've looked at all the packets, as we don't know until then whether
packet_list_select_first_row();
}
- if (stop_flag) {
+ if (cf->stop_flag) {
simple_message_box(ESD_TYPE_WARN, NULL,
"The remaining packets in the file were discarded.\n"
"\n"
"As a lot of packets from the original file will be missing,\n"
"remember to be careful when saving the current content to a file.\n",
- "File loading was cancelled!");
+ "File loading was cancelled.");
return CF_READ_ERROR;
}
case WTAP_ERR_UNSUPPORTED:
simple_error_message_box(
"The capture file contains record data that Wireshark doesn't support.\n(%s)",
- err_info);
- g_free(err_info);
- break;
-
- case WTAP_ERR_UNSUPPORTED_ENCAP:
- simple_error_message_box(
- "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
- err_info);
+ err_info != NULL ? err_info : "no information supplied");
g_free(err_info);
break;
- case WTAP_ERR_CANT_READ:
- simple_error_message_box(
- "An attempt to read from the capture file failed for"
- " some unknown reason.");
- break;
-
case WTAP_ERR_SHORT_READ:
simple_error_message_box(
"The capture file appears to have been cut short"
case WTAP_ERR_BAD_FILE:
simple_error_message_box(
"The capture file appears to be damaged or corrupt.\n(%s)",
- err_info);
+ err_info != NULL ? err_info : "no information supplied");
g_free(err_info);
break;
case WTAP_ERR_DECOMPRESS:
simple_error_message_box(
- "The compressed capture file appears to be damaged or corrupt.\n"
- "(%s)", err_info);
+ "The compressed capture file appears to be damaged or corrupt.\n(%s)",
+ err_info != NULL ? err_info : "no information supplied");
g_free(err_info);
break;
}
#ifdef HAVE_LIBPCAP
-cf_status_t
-cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
-{
- cf_status_t cf_status;
-
- cf_status = cf_open(cf, fname, is_tempfile, err);
- return cf_status;
-}
-
cf_read_status_t
cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
{
gchar *err_info;
- int newly_displayed_packets = 0;
+ volatile int newly_displayed_packets = 0;
dfilter_t *dfcode;
- volatile gboolean create_proto_tree;
+ epan_dissect_t edt;
+ gboolean create_proto_tree;
guint tap_flags;
gboolean compiled;
* 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);
+ compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
g_assert(!cf->dfilter || (compiled && dfcode));
/* Get the union of the flags for all tap listeners. */
/*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
+ epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
+
TRY {
gint64 data_offset = 0;
column_info *cinfo;
aren't any packets left to read) exit. */
break;
}
- if (read_packet(cf, dfcode, create_proto_tree, (column_info *) cinfo, data_offset) != -1) {
+ if (read_packet(cf, dfcode, &edt, (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!");
+ "More information and workarounds can be found at\n"
+ "https://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;
dfilter_free(dfcode);
}
+ epan_dissect_cleanup(&edt);
+
/*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
cf->count, cf->state, *err);*/
} else if (*err != 0) {
/* We got an error reading the capture file.
XXX - pop up a dialog box instead? */
- g_warning("Error \"%s\" while reading: \"%s\" (\"%s\")",
- wtap_strerror(*err), err_info, cf->filename);
- g_free(err_info);
-
+ if (err_info != NULL) {
+ g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
+ wtap_strerror(*err), cf->filename, err_info);
+ g_free(err_info);
+ } else {
+ g_warning("Error \"%s\" while reading \"%s\"",
+ wtap_strerror(*err), cf->filename);
+ }
return CF_READ_ERROR;
} else
return CF_READ_OK;
gint64 data_offset;
dfilter_t *dfcode;
column_info *cinfo;
+ epan_dissect_t edt;
gboolean create_proto_tree;
guint tap_flags;
gboolean compiled;
* 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);
+ compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
g_assert(!cf->dfilter || (compiled && dfcode));
/* Get the union of the flags for all tap listeners. */
/* Don't freeze/thaw the list when doing live capture */
/*packet_list_freeze();*/
+ epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
+
while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
if (cf->state == FILE_READ_ABORTED) {
/* Well, the user decided to abort the read. Break out of the
aren't any packets left to read) exit. */
break;
}
- read_packet(cf, dfcode, create_proto_tree, cinfo, data_offset);
+ read_packet(cf, dfcode, &edt, cinfo, data_offset);
}
/* Cleanup and release all dfilter resources */
dfilter_free(dfcode);
}
+ epan_dissect_cleanup(&edt);
+
/* Don't freeze/thaw the list when doing live capture */
/*packet_list_thaw();*/
if (*err != 0) {
/* We got an error reading the capture file.
XXX - pop up a dialog box? */
-
- g_warning("Error \"%s\" while reading: \"%s\" (\"%s\")",
- wtap_strerror(*err), err_info, cf->filename);
- g_free(err_info);
+ if (err_info != NULL) {
+ g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
+ wtap_strerror(*err), cf->filename, err_info);
+ g_free(err_info);
+ } else {
+ g_warning("Error \"%s\" while reading \"%s\"",
+ wtap_strerror(*err), cf->filename);
+ }
return CF_READ_ERROR;
} else {
return CF_READ_OK;
return cf->count;
}
-/* XXX - use a macro instead? */
-void
-cf_set_packet_count(capture_file *cf, int packet_count)
-{
- cf->count = packet_count;
-}
-
/* XXX - use a macro instead? */
gboolean
cf_is_tempfile(capture_file *cf)
static int
add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
- dfilter_t *dfcode, gboolean create_proto_tree, column_info *cinfo,
+ epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
struct wtap_pkthdr *phdr, const guint8 *buf, gboolean add_to_packet_list)
{
- epan_dissect_t edt;
gint row = -1;
frame_data_set_before_dissect(fdata, &cf->elapsed_time,
- &ref, prev_dis);
- prev_cap = fdata;
-
- /* Dissect the frame. */
- epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
+ &cf->ref, cf->prev_dis);
+ cf->prev_cap = fdata;
if (dfcode != NULL) {
- epan_dissect_prime_dfilter(&edt, dfcode);
+ epan_dissect_prime_dfilter(edt, dfcode);
}
- epan_dissect_run_with_taps(&edt, phdr, frame_tvbuff_new(fdata, buf), fdata, cinfo);
+ /* Dissect the frame. */
+ epan_dissect_run_with_taps(edt, cf->cd_t, 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->frames);
+ 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);
}
if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
{
- frame_data_set_after_dissect(fdata, &cum_bytes);
- prev_dis = fdata;
+ frame_data_set_after_dissect(fdata, &cf->cum_bytes);
+ cf->prev_dis = fdata;
/* If we haven't yet seen the first frame, this is it.
cf->last_displayed = fdata->num;
}
- epan_dissect_cleanup(&edt);
+ epan_dissect_reset(edt);
return row;
}
/* read in a new packet */
/* 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,
- gboolean create_proto_tree, column_info *cinfo, gint64 offset)
+read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
+ column_info *cinfo, gint64 offset)
{
struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
const guint8 *buf = wtap_buf_ptr(cf->wth);
frame_data fdlocal;
guint32 framenum;
frame_data *fdata;
- int passed;
+ gboolean passed;
int row = -1;
/* Add this packet's link-layer encapsulation type to cf->linktypes, if
frames in the file so far. */
framenum = cf->count + 1;
- frame_data_init(&fdlocal, framenum, phdr, offset, cum_bytes);
+ frame_data_init(&fdlocal, framenum, phdr, offset, cf->cum_bytes);
passed = TRUE;
if (cf->rfcode) {
- epan_dissect_t edt;
- epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
- epan_dissect_prime_dfilter(&edt, cf->rfcode);
- epan_dissect_run(&edt, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL);
- passed = dfilter_apply_edt(cf->rfcode, &edt);
- epan_dissect_cleanup(&edt);
+ epan_dissect_t rf_edt;
+
+ epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
+ epan_dissect_prime_dfilter(&rf_edt, cf->rfcode);
+ epan_dissect_run(&rf_edt, cf->cd_t, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL);
+ passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
+ epan_dissect_cleanup(&rf_edt);
}
if (passed) {
fdata = frame_data_sequence_add(cf->frames, &fdlocal);
cf->count++;
- if (fdlocal.opt_comment != NULL)
+ if (phdr->opt_comment != NULL)
cf->packet_comment_count++;
cf->f_datalen = offset + fdlocal.cap_len;
if (!cf->redissecting) {
- row = add_packet_to_packet_list(fdata, cf, dfcode,
- create_proto_tree, cinfo,
- phdr, buf, TRUE);
+ row = add_packet_to_packet_list(fdata, cf, edt, dfcode,
+ cinfo, phdr, buf, TRUE);
}
}
return row;
}
-cf_status_t
-cf_merge_files(char **out_filenamep, int in_file_count,
- char *const *in_filenames, int file_type, gboolean do_append)
-{
- merge_in_file_t *in_files, *in_file;
- char *out_filename;
- char *tmpname;
- int out_fd;
- wtap_dumper *pdh;
- int open_err, read_err, write_err, close_err;
- gchar *err_info;
- int err_fileno;
- int i;
- gboolean got_read_error = FALSE, got_write_error = FALSE;
- gint64 data_offset;
- progdlg_t *progbar = NULL;
- gboolean stop_flag;
- gint64 f_len, file_pos;
- float progbar_val;
- GTimeVal start_time;
- gchar status_str[100];
+
+typedef struct _callback_data_t {
+ gint64 f_len;
gint64 progbar_nextstep;
gint64 progbar_quantum;
- gchar *display_basename;
- int selected_frame_type;
- gboolean fake_interface_ids = FALSE;
-
- /* open the input files */
- if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
- &open_err, &err_info, &err_fileno)) {
- g_free(in_files);
- cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
- FALSE, 0);
- return CF_ERROR;
- }
-
- if (*out_filenamep != NULL) {
- out_filename = *out_filenamep;
- out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
- if (out_fd == -1)
- open_err = errno;
- } else {
- out_fd = create_tempfile(&tmpname, "wireshark");
- if (out_fd == -1)
- open_err = errno;
- out_filename = g_strdup(tmpname);
- *out_filenamep = out_filename;
- }
- if (out_fd == -1) {
- err_info = NULL;
- merge_close_in_files(in_file_count, in_files);
- g_free(in_files);
- cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
- return CF_ERROR;
- }
-
- selected_frame_type = merge_select_frame_type(in_file_count, in_files);
-
- /* If we are trying to merge a number of libpcap files with different encapsulation types
- * change the output file type to pcapng and create SHB and IDB:s for the new file use the
- * interface index stored in in_files per file to change the phdr before writing the datablock.
- * XXX should it be an option to convert to pcapng?
- *
- * We need something similar when merging pcapng files possibly with an option to say
- * the same interface(s) used in all in files. SHBs comments should be merged together.
- */
- if ((selected_frame_type == WTAP_ENCAP_PER_PACKET)&&(file_type == WTAP_FILE_PCAP)) {
- /* Write output in pcapng format */
- wtapng_section_t *shb_hdr;
- wtapng_iface_descriptions_t *idb_inf, *idb_inf_merge_file;
- wtapng_if_descr_t int_data, *file_int_data;
- GString *comment_gstr;
-
- fake_interface_ids = TRUE;
- /* Create SHB info */
- 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");
- file_type = WTAP_FILE_PCAPNG;
-
- for (i = 0; i < in_file_count; i++) {
- g_string_append_printf(comment_gstr, "File%d: %s \n",i+1,in_files[i].filename);
- }
- shb_hdr->section_length = -1;
- /* options */
- shb_hdr->opt_comment = g_string_free(comment_gstr, FALSE); /* NULL if not available */
- shb_hdr->shb_hardware = NULL; /* NULL if not available, UTF-8 string containing the */
- /* description of the hardware used to create this section. */
- shb_hdr->shb_os = NULL; /* NULL if not available, UTF-8 string containing the name */
- /* of the operating system used to create this section. */
- shb_hdr->shb_user_appl = "Wireshark"; /* NULL if not available, UTF-8 string containing the name */
- /* of the application used to create this section. */
-
- /* create fake IDB info */
- idb_inf = g_new(wtapng_iface_descriptions_t,1);
- idb_inf->number_of_interfaces = in_file_count; /* TODO make this the number of DIFFERENT encapsulation types
- * check that snaplength is the same too?
- */
- idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
-
- for (i = 0; i < in_file_count; i++) {
- idb_inf_merge_file = wtap_file_get_idb_info(in_files[i].wth);
- /* read the interface data from the in file to our combined interfca data */
- file_int_data = &g_array_index (idb_inf_merge_file->interface_data, wtapng_if_descr_t, 0);
- int_data.wtap_encap = file_int_data->wtap_encap;
- int_data.time_units_per_second = file_int_data->time_units_per_second;
- int_data.link_type = file_int_data->link_type;
- int_data.snap_len = file_int_data->snap_len;
- int_data.if_name = g_strdup(file_int_data->if_name);
- int_data.opt_comment = NULL;
- int_data.if_description = NULL;
- int_data.if_speed = 0;
- int_data.if_tsresol = 6;
- int_data.if_filter_str = NULL;
- int_data.bpf_filter_len = 0;
- int_data.if_filter_bpf_bytes = NULL;
- int_data.if_os = NULL;
- int_data.if_fcslen = -1;
- int_data.num_stat_entries = 0; /* Number of ISB:s */
- int_data.interface_statistics = NULL;
-
- g_array_append_val(idb_inf->interface_data, int_data);
- g_free(idb_inf_merge_file);
-
- /* Set fake interface Id in per file data */
- in_files[i].interface_id = i;
- }
+ GTimeVal start_time;
+ progdlg_t *progbar;
+ gboolean stop_flag;
+} callback_data_t;
- pdh = wtap_dump_fdopen_ng(out_fd, file_type,
- selected_frame_type,
- merge_max_snapshot_length(in_file_count, in_files),
- FALSE /* compressed */, shb_hdr, idb_inf /* wtapng_iface_descriptions_t *idb_inf */, &open_err);
- if (pdh == NULL) {
- ws_close(out_fd);
- merge_close_in_files(in_file_count, in_files);
- g_free(in_files);
- cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
- file_type);
- return CF_ERROR;
- }
+static gboolean
+merge_callback(merge_event event, int num _U_,
+ const merge_in_file_t in_files[], const guint in_file_count,
+ void *data)
+{
+ guint i;
+ callback_data_t *cb_data = (callback_data_t*) data;
- } else {
+ g_assert(cb_data != NULL);
- pdh = wtap_dump_fdopen(out_fd, file_type,
- selected_frame_type,
- merge_max_snapshot_length(in_file_count, in_files),
- FALSE /* compressed */, &open_err);
- if (pdh == NULL) {
- ws_close(out_fd);
- merge_close_in_files(in_file_count, in_files);
- g_free(in_files);
- cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
- file_type);
- return CF_ERROR;
- }
- }
+ switch (event) {
- /* Get the sum of the sizes of all the files. */
- f_len = 0;
- for (i = 0; i < in_file_count; i++)
- f_len += in_files[i].size;
+ case MERGE_EVENT_INPUT_FILES_OPENED:
+ /* do nothing */
+ break;
- /* 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 = f_len/N_PROGBAR_UPDATES;
- /* Progress so far. */
- progbar_val = 0.0f;
+ case MERGE_EVENT_FRAME_TYPE_SELECTED:
+ /* do nothing */
+ break;
- stop_flag = FALSE;
- g_get_current_time(&start_time);
+ case MERGE_EVENT_READY_TO_MERGE:
+ /* Get the sum of the sizes of all the files. */
+ for (i = 0; i < in_file_count; i++)
+ cb_data->f_len += in_files[i].size;
- /* do the merge (or append) */
- for (;;) {
- if (do_append)
- in_file = merge_append_read_packet(in_file_count, in_files, &read_err,
- &err_info);
- else
- in_file = merge_read_packet(in_file_count, in_files, &read_err,
- &err_info);
- if (in_file == NULL) {
- /* EOF */
- break;
- }
+ /* When we reach the value that triggers a progress bar update,
+ bump that value by this amount. */
+ cb_data->progbar_quantum = cb_data->f_len / N_PROGBAR_UPDATES;
- if (read_err != 0) {
- /* I/O error reading from in_file */
- got_read_error = TRUE;
+ g_get_current_time(&cb_data->start_time);
break;
- }
-
- /* Get the sum of the data offsets in all of the files. */
- data_offset = 0;
- for (i = 0; i < in_file_count; i++)
- data_offset += in_files[i].data_offset;
- /* 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(NULL, "Merging", "files",
- FALSE, &stop_flag, &start_time, progbar_val);
- }
+ case MERGE_EVENT_PACKET_WAS_READ:
+ {
+ gint64 data_offset = 0;
- /* 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 (data_offset >= progbar_nextstep) {
- /* Get the sum of the seek positions in all of the files. */
- file_pos = 0;
+ /* Get the sum of the data offsets in all of the files. */
+ data_offset = 0;
for (i = 0; i < in_file_count; i++)
- 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.
- That "shouldn't happen", so we'll just clip the progress
- value at 1.0. */
- progbar_val = 1.0f;
- }
- if (progbar != NULL) {
- g_snprintf(status_str, sizeof(status_str),
- "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
- file_pos / 1024, f_len / 1024);
- update_progress_dlg(progbar, progbar_val, status_str);
+ data_offset += in_files[i].data_offset;
+
+ /* 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 (cb_data->progbar == NULL) {
+ cb_data->progbar = delayed_create_progress_dlg(NULL, "Merging", "files",
+ FALSE, &cb_data->stop_flag, &cb_data->start_time, 0.0f);
}
- progbar_nextstep += progbar_quantum;
- }
- if (stop_flag) {
- /* Well, the user decided to abort the merge. */
- break;
- }
+ /* 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 (data_offset >= cb_data->progbar_nextstep) {
+ float progbar_val;
+ gint64 file_pos = 0;
+ /* Get the sum of the seek positions in all of the files. */
+ for (i = 0; i < in_file_count; i++)
+ file_pos += wtap_read_so_far(in_files[i].wth);
+
+ progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len;
+ if (progbar_val > 1.0f) {
+ /* Some file probably grew while we were reading it.
+ That "shouldn't happen", so we'll just clip the progress
+ value at 1.0. */
+ progbar_val = 1.0f;
+ }
- /* If we have WTAP_ENCAP_PER_PACKETend the infiles are of type WTAP_FILE_PCAP
- * we need to set the interface id in the paket header = the interface index we used
- * in the IDBs interface description for this file(encapsulation type).
- */
- if (fake_interface_ids) {
- struct wtap_pkthdr *phdr;
+ if (cb_data->progbar != NULL) {
+ gchar status_str[100];
+ g_snprintf(status_str, sizeof(status_str),
+ "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
+ file_pos / 1024, cb_data->f_len / 1024);
+ update_progress_dlg(cb_data->progbar, progbar_val, status_str);
+ }
+ cb_data->progbar_nextstep += cb_data->progbar_quantum;
+ }
+ }
+ break;
- phdr = wtap_phdr(in_file->wth);
- phdr->interface_id = in_file->interface_id;
- phdr->presence_flags = phdr->presence_flags | WTAP_HAS_INTERFACE_ID;
- }
- if (!wtap_dump(pdh, wtap_phdr(in_file->wth),
- wtap_buf_ptr(in_file->wth), &write_err)) {
- got_write_error = TRUE;
+ case MERGE_EVENT_DONE:
+ /* We're done merging the files; destroy the progress bar if it was created. */
+ if (cb_data->progbar != NULL)
+ destroy_progress_dlg(cb_data->progbar);
break;
- }
}
- /* We're done merging the files; destroy the progress bar if it was created. */
- if (progbar != NULL)
- destroy_progress_dlg(progbar);
+ return cb_data->stop_flag;
+}
- merge_close_in_files(in_file_count, in_files);
- if (!got_read_error && !got_write_error) {
- if (!wtap_dump_close(pdh, &write_err))
- got_write_error = TRUE;
- } else
- wtap_dump_close(pdh, &close_err);
- if (got_read_error) {
- /*
- * Find the file on which we got the error, and report the error.
- */
- for (i = 0; i < in_file_count; i++) {
- if (in_files[i].state == GOT_ERROR) {
- /* Put up a message box noting that a read failed somewhere along
- the line. */
- display_basename = g_filename_display_basename(in_files[i].filename);
- switch (read_err) {
-
- case WTAP_ERR_UNSUPPORTED_ENCAP:
- simple_error_message_box(
- "The capture file %s has a packet with a network type that Wireshark doesn't support.\n(%s)",
- display_basename, err_info);
- g_free(err_info);
- break;
- case WTAP_ERR_CANT_READ:
- simple_error_message_box(
- "An attempt to read from the capture file %s failed for"
- " some unknown reason.", display_basename);
- break;
+cf_status_t
+cf_merge_files(char **out_filenamep, int in_file_count,
+ char *const *in_filenames, int file_type, gboolean do_append)
+{
+ char *out_filename;
+ char *tmpname;
+ int out_fd;
+ int err = 0;
+ gchar *err_info = NULL;
+ int err_fileno;
+ merge_result status;
+ merge_progress_callback_t cb;
- case WTAP_ERR_SHORT_READ:
- simple_error_message_box(
- "The capture file %s appears to have been cut short"
- " in the middle of a packet.", display_basename);
- break;
- case WTAP_ERR_BAD_FILE:
- simple_error_message_box(
- "The capture file %s appears to be damaged or corrupt.\n(%s)",
- display_basename, err_info);
- g_free(err_info);
- break;
+ if (*out_filenamep != NULL) {
+ out_filename = *out_filenamep;
+ out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
+ if (out_fd == -1)
+ err = errno;
+ } else {
+ out_fd = create_tempfile(&tmpname, "wireshark");
+ if (out_fd == -1)
+ err = errno;
+ out_filename = g_strdup(tmpname);
+ *out_filenamep = out_filename;
+ }
+ if (out_fd == -1) {
+ cf_open_failure_alert_box(out_filename, err, NULL, TRUE, file_type);
+ return CF_ERROR;
+ }
- case WTAP_ERR_DECOMPRESS:
- simple_error_message_box(
- "The compressed capture file %s appears to be damaged or corrupt.\n"
- "(%s)", display_basename, err_info);
- g_free(err_info);
- break;
+ /* prepare our callback routine */
+ cb.callback_func = merge_callback;
+ cb.data = g_malloc0(sizeof(callback_data_t));
- default:
- simple_error_message_box(
- "An error occurred while reading the"
- " capture file %s: %s.",
- display_basename, wtap_strerror(read_err));
- break;
- }
- g_free(display_basename);
- }
- }
- }
+ /* merge the files */
+ status = merge_files(out_fd, out_filename, file_type,
+ (const char *const *) in_filenames, in_file_count,
+ do_append, IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */,
+ "Wireshark", &cb, &err, &err_info, &err_fileno);
- if (got_write_error) {
- /* Put up an alert box for the write error. */
- if (write_err < 0) {
- /* Wiretap error. */
- switch (write_err) {
+ g_free(cb.data);
- case WTAP_ERR_UNSUPPORTED_ENCAP:
- /*
- * This is a problem with the particular frame we're writing;
- * note that, and give the frame number.
- */
- display_basename = g_filename_display_basename(in_file->filename);
- simple_error_message_box(
- "Frame %u of \"%s\" has a network type that can't be saved in a \"%s\" file.",
- in_file->packet_num, display_basename,
- wtap_file_type_string(file_type));
- g_free(display_basename);
- break;
+ switch (status) {
+ case MERGE_OK:
+ break;
- default:
- display_basename = g_filename_display_basename(out_filename);
- simple_error_message_box(
- "An error occurred while writing to the file \"%s\": %s.",
- out_filename, wtap_strerror(write_err));
- g_free(display_basename);
- break;
- }
- } else {
- /* OS error. */
- write_failure_alert_box(out_filename, write_err);
- }
+ case MERGE_USER_ABORTED:
+ /* this isn't really an error, though we will return CF_ERROR later */
+ break;
+
+ case MERGE_ERR_CANT_OPEN_INFILE:
+ cf_open_failure_alert_box(in_filenames[err_fileno], err, err_info,
+ FALSE, 0);
+ break;
+
+ case MERGE_ERR_CANT_OPEN_OUTFILE:
+ cf_open_failure_alert_box(out_filename, err, err_info, TRUE,
+ file_type);
+ ws_close(out_fd);
+ break;
+
+ case MERGE_ERR_CANT_READ_INFILE: /* fall through */
+ case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
+ case MERGE_ERR_CANT_WRITE_OUTFILE:
+ case MERGE_ERR_CANT_CLOSE_OUTFILE:
+ default:
+ simple_error_message_box("%s", err_info ? err_info : "unknown error");
+ break;
}
- if (got_read_error || got_write_error || stop_flag) {
+ g_free(err_info);
+
+ if (status != MERGE_OK) {
/* Callers aren't expected to treat an error or an explicit abort
differently - we put up error dialogs ourselves, so they don't
have to. */
const char *filter_new = dftext ? dftext : "";
const char *filter_old = cf->dfilter ? cf->dfilter : "";
dfilter_t *dfcode;
+ gchar *err_msg;
GTimeVal start_time;
/* if new filter equals old one, do nothing unless told to do so */
* and try to compile it.
*/
dftext = g_strdup(dftext);
- if (!dfilter_compile(dftext, &dfcode)) {
+ if (!dfilter_compile(dftext, &dfcode, &err_msg)) {
/* The attempt failed; report an error. */
simple_message_box(ESD_TYPE_ERROR, NULL,
"See the help for a description of the display filter syntax.",
"\"%s\" isn't a valid display filter: %s",
- dftext, dfilter_error_msg);
+ dftext, err_msg);
+ g_free(err_msg);
g_free(dftext);
return CF_ERROR;
}
void
cf_redissect_packets(capture_file *cf)
{
- rescan_packets(cf, "Reprocessing", "all packets", TRUE);
+ if (cf->state != FILE_CLOSED) {
+ rescan_packets(cf, "Reprocessing", "all packets", TRUE);
+ }
}
gboolean
-cf_read_frame_r(capture_file *cf, frame_data *fdata,
- struct wtap_pkthdr *phdr, Buffer *buf)
+cf_read_record_r(capture_file *cf, const frame_data *fdata,
+ struct wtap_pkthdr *phdr, Buffer *buf)
{
int err;
gchar *err_info;
const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
if (!frame) {
- simple_error_message_box("fdata->file_off == -1, but can't find modified frame!");
+ simple_error_message_box("fdata->file_off == -1, but can't find modified frame.");
return FALSE;
}
*phdr = frame->phdr;
- buffer_assure_space(buf, frame->phdr.caplen);
- memcpy(buffer_start_ptr(buf), frame->pd, frame->phdr.caplen);
+ ws_buffer_assure_space(buf, frame->phdr.caplen);
+ memcpy(ws_buffer_start_ptr(buf), frame->pd, frame->phdr.caplen);
return TRUE;
}
#endif
- if (!wtap_seek_read(cf->wth, fdata->file_off, phdr, buf,
- fdata->cap_len, &err, &err_info)) {
+ if (!wtap_seek_read(cf->wth, fdata->file_off, phdr, buf, &err, &err_info)) {
display_basename = g_filename_display_basename(cf->filename);
switch (err) {
- case WTAP_ERR_UNSUPPORTED_ENCAP:
- simple_error_message_box("The file \"%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
- display_basename, err_info);
- g_free(err_info);
- break;
-
case WTAP_ERR_BAD_FILE:
simple_error_message_box("An error occurred while reading from the file \"%s\": %s.\n(%s)",
- display_basename, wtap_strerror(err), err_info);
+ display_basename, wtap_strerror(err),
+ err_info != NULL ? err_info : "no information supplied");
g_free(err_info);
break;
}
gboolean
-cf_read_frame(capture_file *cf, frame_data *fdata)
+cf_read_record(capture_file *cf, frame_data *fdata)
{
- return cf_read_frame_r(cf, fdata, &cf->phdr, &cf->buf);
+ return cf_read_record_r(cf, fdata, &cf->phdr, &cf->buf);
}
/* Rescan the list of packets, reconstructing the CList.
guint32 framenum;
frame_data *fdata;
progdlg_t *progbar = NULL;
- gboolean stop_flag;
int count;
frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
gchar status_str[100];
int progbar_nextstep;
int progbar_quantum;
+ epan_dissect_t edt;
dfilter_t *dfcode;
column_info *cinfo;
gboolean create_proto_tree;
* 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);
+ compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
g_assert(!cf->dfilter || (compiled && dfcode));
/* Get the union of the flags for all tap listeners. */
/* 'reset' dissection session */
epan_free(cf->epan);
cf->epan = ws_epan_new(cf);
+ cf->cinfo.epan = cf->epan;
/* We need to redissect the packets so we have to discard our old
* packet list store. */
/* 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. */
- ref = NULL;
- prev_dis = NULL;
- prev_cap = NULL;
- cum_bytes = 0;
+ cf->ref = NULL;
+ cf->prev_dis = NULL;
+ cf->prev_cap = NULL;
+ cf->cum_bytes = 0;
/* Update the progress bar when it gets to this value. */
progbar_nextstep = 0;
/* Progress so far. */
progbar_val = 0.0f;
- stop_flag = FALSE;
+ cf->stop_flag = FALSE;
g_get_current_time(&start_time);
/* no previous row yet */
selected_frame_seen = FALSE;
frames_count = cf->count;
+
+ epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
+
for (framenum = 1; framenum <= frames_count; framenum++) {
fdata = frame_data_sequence_find(cf->frames, framenum);
time in order to get to the next progress bar step). */
if (progbar == NULL)
progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
- &stop_flag, &start_time,
+ &cf->stop_flag,
+ &start_time,
progbar_val);
/* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
progbar_nextstep += progbar_quantum;
}
- if (stop_flag) {
+ if (cf->stop_flag) {
/* Well, the user decided to abort the filtering. Just stop.
XXX - go back to the previous filter? Users probably just
/* Frame dependencies from the previous dissection/filtering are no longer valid. */
fdata->flags.dependent_of_displayed = 0;
- if (!cf_read_frame(cf, fdata))
+ if (!cf_read_record(cf, fdata))
break; /* error reading the frame */
/* If the previous frame is displayed, and we haven't yet seen the
preceding_frame_num = prev_frame_num;
preceding_frame = prev_frame;
}
- add_packet_to_packet_list(fdata, cf, dfcode, create_proto_tree,
+
+ add_packet_to_packet_list(fdata, cf, &edt, dfcode,
cinfo, &cf->phdr,
- buffer_start_ptr(&cf->buf),
+ ws_buffer_start_ptr(&cf->buf),
add_to_packet_list);
/* If this frame is displayed, and this is the first frame we've
prev_frame = fdata;
}
+ epan_dissect_cleanup(&edt);
+
/* We are done redissecting the packet list. */
cf->redissecting = FALSE;
packet_list_recreate_visible_rows();
/* Compute the time it took to filter the file */
- compute_elapsed(&start_time);
+ compute_elapsed(cf, &start_time);
packet_list_thaw();
so we can't select it. */
simple_message_box(ESD_TYPE_INFO, NULL,
"The capture file is probably not fully dissected.",
- "End of capture exceeded!");
+ "End of capture exceeded.");
}
}
}
frame_data *fdata;
nstime_t rel_ts;
- ref = NULL;
- prev_dis = NULL;
- cum_bytes = 0;
+ cf->ref = NULL;
+ cf->prev_dis = NULL;
+ cf->cum_bytes = 0;
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;
+ fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
/*
*Timestamps
/* 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 (ref == NULL)
- ref = fdata;
+ if (cf->ref == NULL)
+ cf->ref = fdata;
/* if this frames is marked as a reference time frame, reset
firstsec and firstusec to this frame */
if (fdata->flags.ref_time)
- ref = fdata;
+ cf->ref = fdata;
/* 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
stamp of this packet as the time stamp of the previous displayed
packet. */
- if (prev_dis == NULL) {
- prev_dis = fdata;
+ if (cf->prev_dis == NULL) {
+ cf->prev_dis = fdata;
}
/* Get the time elapsed between the first packet and this packet. */
- fdata->frame_ref_num = (fdata != ref) ? ref->num : 0;
- nstime_delta(&rel_ts, &fdata->abs_ts, &ref->abs_ts);
+ fdata->frame_ref_num = (fdata != cf->ref) ? cf->ref->num : 0;
+ nstime_delta(&rel_ts, &fdata->abs_ts, &cf->ref->abs_ts);
/* If it's greater than the current elapsed time, set the elapsed time
to it (we check for "greater than" so as not to be confused by
/* If this frame is displayed, get the time elapsed between the
previous displayed packet and this packet. */
if ( fdata->flags.passed_dfilter ) {
- fdata->prev_dis_num = prev_dis->num;
- prev_dis = fdata;
+ fdata->prev_dis_num = cf->prev_dis->num;
+ cf->prev_dis = fdata;
}
/*
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 */
+ even if they don't pass the display filter */
if (fdata->flags.ref_time) {
/* if this was a TIME REF frame we should reset the cum_bytes field */
- cum_bytes = fdata->pkt_len;
- fdata->cum_bytes = cum_bytes;
+ cf->cum_bytes = fdata->pkt_len;
+ fdata->cum_bytes = cf->cum_bytes;
} else {
/* increase cum_bytes with this packets length */
- cum_bytes += fdata->pkt_len;
+ cf->cum_bytes += fdata->pkt_len;
}
}
}
} psp_return_t;
static psp_return_t
-process_specified_packets(capture_file *cf, packet_range_t *range,
+process_specified_records(capture_file *cf, packet_range_t *range,
const char *string1, const char *string2, gboolean terminate_is_stop,
gboolean (*callback)(capture_file *, frame_data *,
struct wtap_pkthdr *, const guint8 *, void *),
progdlg_t *progbar = NULL;
int progbar_count;
float progbar_val;
- gboolean progbar_stop_flag;
GTimeVal progbar_start_time;
gchar progbar_status_str[100];
int progbar_nextstep;
range_process_e process_this;
struct wtap_pkthdr phdr;
- buffer_init(&buf, 1500);
+ wtap_phdr_init(&phdr);
+ ws_buffer_init(&buf, 1500);
/* Update the progress bar when it gets to this value. */
progbar_nextstep = 0;
/* Progress so far. */
progbar_val = 0.0f;
- progbar_stop_flag = FALSE;
+ cf->stop_flag = FALSE;
g_get_current_time(&progbar_start_time);
if (range != NULL)
if (progbar == NULL)
progbar = delayed_create_progress_dlg(cf->window, string1, string2,
terminate_is_stop,
- &progbar_stop_flag,
+ &cf->stop_flag,
&progbar_start_time,
progbar_val);
progbar_nextstep += progbar_quantum;
}
- if (progbar_stop_flag) {
+ if (cf->stop_flag) {
/* Well, the user decided to abort the operation. Just stop,
and arrange to return PSP_STOPPED to our caller, so they know
it was stopped explicitly. */
}
/* Get the packet */
- if (!cf_read_frame_r(cf, fdata, &phdr, &buf)) {
+ if (!cf_read_record_r(cf, fdata, &phdr, &buf)) {
/* Attempt to get the packet failed. */
ret = PSP_FAILED;
break;
}
/* Process the packet */
- if (!callback(cf, fdata, &phdr, buffer_start_ptr(&buf), callback_args)) {
+ if (!callback(cf, fdata, &phdr, ws_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);
+ wtap_phdr_cleanup(&phdr);
+ ws_buffer_free(&buf);
return ret;
}
typedef struct {
- gboolean construct_protocol_tree;
+ epan_dissect_t edt;
column_info *cinfo;
} retap_callback_args_t;
static gboolean
-retap_packet(capture_file *cf _U_, frame_data *fdata,
+retap_packet(capture_file *cf, frame_data *fdata,
struct wtap_pkthdr *phdr, const guint8 *pd,
void *argsp)
{
retap_callback_args_t *args = (retap_callback_args_t *)argsp;
- epan_dissect_t edt;
- epan_dissect_init(&edt, cf->epan, args->construct_protocol_tree, FALSE);
- epan_dissect_run_with_taps(&edt, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo);
- epan_dissect_cleanup(&edt);
+ epan_dissect_run_with_taps(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo);
+ epan_dissect_reset(&args->edt);
return TRUE;
}
{
packet_range_t range;
retap_callback_args_t callback_args;
+ gboolean construct_protocol_tree;
gboolean filtering_tap_listeners;
guint tap_flags;
+ psp_return_t ret;
+
+ /* Presumably the user closed the capture file. */
+ if (cf == NULL) {
+ return CF_READ_ABORTED;
+ }
+
+ cf_callback_invoke(cf_cb_file_retap_started, cf);
/* Do we have any tap listeners with filters? */
filtering_tap_listeners = have_filtering_tap_listeners();
/* If any tap listeners have filters, or require the protocol tree,
construct the protocol tree. */
- callback_args.construct_protocol_tree = filtering_tap_listeners ||
- (tap_flags & TL_REQUIRES_PROTO_TREE);
+ construct_protocol_tree = filtering_tap_listeners ||
+ (tap_flags & TL_REQUIRES_PROTO_TREE);
/* If any tap listeners require the columns, construct them. */
callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
/* Reset the tap listeners. */
reset_tap_listeners();
+ epan_dissect_init(&callback_args.edt, cf->epan, construct_protocol_tree, FALSE);
+
/* Iterate through the list of packets, dissecting all packets and
re-running the taps. */
packet_range_init(&range, cf);
packet_range_process_init(&range);
- switch (process_specified_packets(cf, &range, "Recalculating statistics on",
- "all packets", TRUE, retap_packet,
- &callback_args)) {
+
+ ret = process_specified_records(cf, &range, "Recalculating statistics on",
+ "all packets", TRUE, retap_packet,
+ &callback_args);
+
+ epan_dissect_cleanup(&callback_args.edt);
+
+ cf_callback_invoke(cf_cb_file_retap_finished, cf);
+
+ switch (ret) {
case PSP_FINISHED:
/* Completed successfully. */
return CF_READ_OK;
gint *col_widths;
int num_visible_cols;
gint *visible_cols;
+ epan_dissect_t edt;
} print_callback_args_t;
static gboolean
void *argsp)
{
print_callback_args_t *args = (print_callback_args_t *)argsp;
- epan_dissect_t edt;
int i;
char *cp;
int line_len;
int column_len;
int cp_off;
- gboolean proto_tree_needed;
char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
-
- /* Create the protocol tree, and make it visible, if we're printing
- the dissection or the hex data.
- XXX - do we need it if we're just printing the hex data? */
- proto_tree_needed =
- args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex || have_custom_cols(&cf->cinfo);
- epan_dissect_init(&edt, cf->epan, proto_tree_needed, proto_tree_needed);
+ col_item_t* col_item;
/* Fill in the column information if we're printing the summary
information. */
if (args->print_args->print_summary) {
- col_custom_prime_edt(&edt, &cf->cinfo);
- epan_dissect_run(&edt, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
- epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
+ col_custom_prime_edt(&args->edt, &cf->cinfo);
+ epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
+ epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
} else
- epan_dissect_run(&edt, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
+ epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
if (args->print_formfeed) {
if (!new_page(args->print_args->stream))
cp = &args->line_buf[0];
line_len = 0;
for (i = 0; i < args->num_visible_cols; i++) {
+ col_item = &cf->cinfo.columns[args->visible_cols[i]];
/* Find the length of the string for this column. */
- column_len = (int) strlen(cf->cinfo.col_data[args->visible_cols[i]]);
+ column_len = (int) strlen(col_item->col_data);
if (args->col_widths[i] > column_len)
column_len = args->col_widths[i];
}
/* Right-justify the packet number column. */
- if (cf->cinfo.col_fmt[args->visible_cols[i]] == COL_NUMBER)
- g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[args->visible_cols[i]]);
+ if (col_item->col_fmt == COL_NUMBER)
+ g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data);
else
- g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[args->visible_cols[i]]);
+ g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data);
cp += column_len;
if (i != args->num_visible_cols - 1)
*cp++ = ' ';
}
/* Print the information in that tree. */
- if (!proto_tree_print(args->print_args, &edt, args->print_args->stream))
+ if (!proto_tree_print(args->print_args, &args->edt, NULL, args->print_args->stream))
goto fail;
/* Print a blank line if we print anything after this (aka more than one packet). */
goto fail;
}
/* Print the full packet data as hex. */
- if (!print_hex_data(args->print_args->stream, &edt))
+ if (!print_hex_data(args->print_args->stream, &args->edt))
goto fail;
/* Print a blank line if we print anything after this (aka more than one packet). */
args->print_header_line = TRUE;
} /* if (args->print_args->print_dissections != print_dissections_none) */
- epan_dissect_cleanup(&edt);
+ epan_dissect_reset(&args->edt);
/* do we want to have a formfeed between each packet from now on? */
if (args->print_args->print_formfeed) {
return TRUE;
fail:
- epan_dissect_cleanup(&edt);
+ epan_dissect_reset(&args->edt);
return FALSE;
}
psp_return_t ret;
GList *clp;
fmt_data *cfmt;
+ gboolean proto_tree_needed;
callback_args.print_args = print_args;
callback_args.print_header_line = print_args->print_col_headings;
callback_args.num_visible_cols = 0;
callback_args.visible_cols = NULL;
- if (!print_preamble(print_args->stream, cf->filename, wireshark_svnversion)) {
+ if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
destroy_print_stream(print_args->stream);
return CF_PRINT_WRITE_ERROR;
}
if (i == last_visible_col)
callback_args.col_widths[visible_col_count] = 0;
else {
- callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.col_title[i]);
+ callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title);
data_width = get_column_char_width(get_column_format(i));
if (data_width > callback_args.col_widths[visible_col_count])
callback_args.col_widths[visible_col_count] = data_width;
}
/* Find the length of the string for this column. */
- column_len = (int) strlen(cf->cinfo.col_title[i]);
+ column_len = (int) strlen(cf->cinfo.columns[i].col_title);
if (callback_args.col_widths[i] > column_len)
column_len = callback_args.col_widths[visible_col_count];
/* Right-justify the packet number column. */
/* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
- g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.col_title[i]);
+ g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
else*/
- g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.col_title[i]);
+ g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
cp += column_len;
if (i != cf->cinfo.num_cols - 1)
*cp++ = ' ';
callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
} /* if (print_summary) */
+ /* Create the protocol tree, and make it visible, if we're printing
+ the dissection or the hex data.
+ XXX - do we need it if we're just printing the hex data? */
+ proto_tree_needed =
+ callback_args.print_args->print_dissections != print_dissections_none ||
+ callback_args.print_args->print_hex ||
+ have_custom_cols(&cf->cinfo);
+ epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
+
/* Iterate through the list of packets, printing the packets we were
told to print. */
- ret = process_specified_packets(cf, &print_args->range, "Printing",
+ ret = process_specified_records(cf, &print_args->range, "Printing",
"selected packets", TRUE, print_packet,
&callback_args);
-
+ epan_dissect_cleanup(&callback_args.edt);
g_free(callback_args.header_line_buf);
g_free(callback_args.line_buf);
g_free(callback_args.col_widths);
return CF_PRINT_OK;
}
+typedef struct {
+ FILE *fh;
+ epan_dissect_t edt;
+} write_packet_callback_args_t;
+
static gboolean
-write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
+write_pdml_packet(capture_file *cf, frame_data *fdata,
struct wtap_pkthdr *phdr, const guint8 *pd,
void *argsp)
{
- FILE *fh = (FILE *)argsp;
- epan_dissect_t edt;
+ write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
/* Create the protocol tree, but don't fill in the column information. */
- epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
- epan_dissect_run(&edt, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
+ epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
/* Write out the information in that tree. */
- proto_tree_write_pdml(&edt, fh);
+ write_pdml_proto_tree(&args->edt, args->fh);
- epan_dissect_cleanup(&edt);
+ epan_dissect_reset(&args->edt);
- return !ferror(fh);
+ return !ferror(args->fh);
}
cf_print_status_t
cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
{
+ write_packet_callback_args_t callback_args;
FILE *fh;
psp_return_t ret;
return CF_PRINT_WRITE_ERROR;
}
+ callback_args.fh = fh;
+ epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
+
/* Iterate through the list of packets, printing the packets we were
told to print. */
- ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
+ ret = process_specified_records(cf, &print_args->range, "Writing PDML",
"selected packets", TRUE,
- write_pdml_packet, fh);
+ write_pdml_packet, &callback_args);
+
+ epan_dissect_cleanup(&callback_args.edt);
switch (ret) {
struct wtap_pkthdr *phdr, const guint8 *pd,
void *argsp)
{
- FILE *fh = (FILE *)argsp;
- epan_dissect_t edt;
- gboolean proto_tree_needed;
+ write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
- /* Fill in the column information, only create the protocol tree
- if having custom columns. */
- proto_tree_needed = have_custom_cols(&cf->cinfo);
- epan_dissect_init(&edt, cf->epan, proto_tree_needed, proto_tree_needed);
- col_custom_prime_edt(&edt, &cf->cinfo);
- epan_dissect_run(&edt, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
- epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
+ /* Fill in the column information */
+ col_custom_prime_edt(&args->edt, &cf->cinfo);
+ epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
+ epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
- /* Write out the information in that tree. */
- proto_tree_write_psml(&edt, fh);
+ /* Write out the column information. */
+ write_psml_columns(&args->edt, args->fh);
- epan_dissect_cleanup(&edt);
+ epan_dissect_reset(&args->edt);
- return !ferror(fh);
+ return !ferror(args->fh);
}
cf_print_status_t
cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
{
+ write_packet_callback_args_t callback_args;
FILE *fh;
psp_return_t ret;
+ gboolean proto_tree_needed;
+
fh = ws_fopen(print_args->file, "w");
if (fh == NULL)
return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
- write_psml_preamble(fh);
+ write_psml_preamble(&cf->cinfo, fh);
if (ferror(fh)) {
fclose(fh);
return CF_PRINT_WRITE_ERROR;
}
+ callback_args.fh = fh;
+
+ /* Fill in the column information, only create the protocol tree
+ if having custom columns. */
+ proto_tree_needed = have_custom_cols(&cf->cinfo);
+ epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
+
/* Iterate through the list of packets, printing the packets we were
told to print. */
- ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
+ ret = process_specified_records(cf, &print_args->range, "Writing PSML",
"selected packets", TRUE,
- write_psml_packet, fh);
+ write_psml_packet, &callback_args);
+
+ epan_dissect_cleanup(&callback_args.edt);
switch (ret) {
struct wtap_pkthdr *phdr, const guint8 *pd,
void *argsp)
{
- FILE *fh = (FILE *)argsp;
- epan_dissect_t edt;
- gboolean proto_tree_needed;
+ write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
- /* Fill in the column information, only create the protocol tree
- if having custom columns. */
- proto_tree_needed = have_custom_cols(&cf->cinfo);
- epan_dissect_init(&edt, cf->epan, proto_tree_needed, proto_tree_needed);
- col_custom_prime_edt(&edt, &cf->cinfo);
- epan_dissect_run(&edt, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
- epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
+ /* Fill in the column information */
+ col_custom_prime_edt(&args->edt, &cf->cinfo);
+ epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
+ epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
- /* Write out the information in that tree. */
- proto_tree_write_csv(&edt, fh);
+ /* Write out the column information. */
+ write_csv_columns(&args->edt, args->fh);
- epan_dissect_cleanup(&edt);
+ epan_dissect_reset(&args->edt);
- return !ferror(fh);
+ return !ferror(args->fh);
}
cf_print_status_t
cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
{
+ write_packet_callback_args_t callback_args;
+ gboolean proto_tree_needed;
FILE *fh;
psp_return_t ret;
if (fh == NULL)
return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
- write_csv_preamble(fh);
+ write_csv_column_titles(&cf->cinfo, fh);
if (ferror(fh)) {
fclose(fh);
return CF_PRINT_WRITE_ERROR;
}
+ callback_args.fh = fh;
+
+ /* only create the protocol tree if having custom columns. */
+ proto_tree_needed = have_custom_cols(&cf->cinfo);
+ epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
+
/* Iterate through the list of packets, printing the packets we were
told to print. */
- ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
+ ret = process_specified_records(cf, &print_args->range, "Writing CSV",
"selected packets", TRUE,
- write_csv_packet, fh);
+ write_csv_packet, &callback_args);
+
+ epan_dissect_cleanup(&callback_args.edt);
switch (ret) {
return CF_PRINT_WRITE_ERROR;
}
- write_csv_finale(fh);
- if (ferror(fh)) {
- fclose(fh);
- return CF_PRINT_WRITE_ERROR;
- }
-
/* XXX - check for an error */
fclose(fh);
}
static gboolean
-write_carrays_packet(capture_file *cf, frame_data *fdata,
+carrays_write_packet(capture_file *cf, frame_data *fdata,
struct wtap_pkthdr *phdr,
const guint8 *pd, void *argsp)
{
- FILE *fh = (FILE *)argsp;
- epan_dissect_t edt;
+ write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
- epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
- epan_dissect_run(&edt, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
- proto_tree_write_carrays(fdata->num, fh, &edt);
- epan_dissect_cleanup(&edt);
+ epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
+ write_carrays_hex_data(fdata->num, args->fh, &args->edt);
+ epan_dissect_reset(&args->edt);
- return !ferror(fh);
+ return !ferror(args->fh);
}
cf_print_status_t
cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
{
+ write_packet_callback_args_t callback_args;
FILE *fh;
psp_return_t ret;
if (fh == NULL)
return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
- write_carrays_preamble(fh);
-
if (ferror(fh)) {
fclose(fh);
return CF_PRINT_WRITE_ERROR;
}
+ callback_args.fh = fh;
+ epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
+
/* Iterate through the list of packets, printing the packets we were
told to print. */
- ret = process_specified_packets(cf, &print_args->range,
+ ret = process_specified_records(cf, &print_args->range,
"Writing C Arrays",
"selected packets", TRUE,
- write_carrays_packet, fh);
+ carrays_write_packet, &callback_args);
+
+ epan_dissect_cleanup(&callback_args.edt);
+
switch (ret) {
case PSP_FINISHED:
/* Completed successfully. */
return CF_PRINT_WRITE_ERROR;
}
- write_carrays_finale(fh);
-
- if (ferror(fh)) {
- fclose(fh);
- return CF_PRINT_WRITE_ERROR;
- }
-
fclose(fh);
return CF_PRINT_OK;
}
epan_dissect_t edt;
/* Load the frame's data. */
- if (!cf_read_frame(cf, fdata)) {
+ if (!cf_read_record(cf, fdata)) {
/* Attempt to get the packet failed. */
return MR_ERROR;
}
/* Construct the protocol tree, including the displayed text */
epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
/* We don't need the column information */
- epan_dissect_run(&edt, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
+ epan_dissect_run(&edt, cf->cd_t, &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;
for (i = 0; i < label_len; i++) {
c_char = label_ptr[i];
if (cf->case_type)
- c_char = toupper(c_char);
+ c_char = g_ascii_toupper(c_char);
if (c_char == string[c_match]) {
c_match++;
if (c_match == string_len) {
size_t c_match = 0;
/* Load the frame's data. */
- if (!cf_read_frame(cf, fdata)) {
+ if (!cf_read_record(cf, fdata)) {
/* Attempt to get the packet failed. */
return MR_ERROR;
}
/* Don't bother constructing the protocol tree */
epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
/* Get the column information */
- epan_dissect_run(&edt, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata,
+ epan_dissect_run(&edt, cf->cd_t, &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++) {
- if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
+ if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) {
/* Found it. See if we match. */
- info_column = edt.pi.cinfo->col_data[colx];
+ info_column = edt.pi.cinfo->columns[colx].col_data;
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);
+ c_char = g_ascii_toupper(c_char);
if (c_char == string[c_match]) {
c_match++;
if (c_match == string_len) {
size_t c_match = 0;
/* Load the frame's data. */
- if (!cf_read_frame(cf, fdata)) {
+ if (!cf_read_record(cf, fdata)) {
/* Attempt to get the packet failed. */
return MR_ERROR;
}
result = MR_NOTMATCHED;
buf_len = fdata->cap_len;
- pd = buffer_start_ptr(&cf->buf);
+ pd = ws_buffer_start_ptr(&cf->buf);
i = 0;
while (i < buf_len) {
c_char = pd[i];
if (cf->case_type)
- c_char = toupper(c_char);
+ c_char = g_ascii_toupper(c_char);
if (c_char != '\0') {
if (c_char == ascii_text[c_match]) {
c_match += 1;
size_t c_match = 0;
/* Load the frame's data. */
- if (!cf_read_frame(cf, fdata)) {
+ if (!cf_read_record(cf, fdata)) {
/* Attempt to get the packet failed. */
return MR_ERROR;
}
result = MR_NOTMATCHED;
buf_len = fdata->cap_len;
- pd = buffer_start_ptr(&cf->buf);
+ pd = ws_buffer_start_ptr(&cf->buf);
i = 0;
while (i < buf_len) {
c_char = pd[i];
if (cf->case_type)
- c_char = toupper(c_char);
+ c_char = g_ascii_toupper(c_char);
if (c_char == ascii_text[c_match]) {
c_match += 1;
if (c_match == textlen) {
size_t c_match = 0;
/* Load the frame's data. */
- if (!cf_read_frame(cf, fdata)) {
+ if (!cf_read_record(cf, fdata)) {
/* Attempt to get the packet failed. */
return MR_ERROR;
}
result = MR_NOTMATCHED;
buf_len = fdata->cap_len;
- pd = buffer_start_ptr(&cf->buf);
+ pd = ws_buffer_start_ptr(&cf->buf);
i = 0;
while (i < buf_len) {
c_char = pd[i];
if (cf->case_type)
- c_char = toupper(c_char);
+ c_char = g_ascii_toupper(c_char);
if (c_char == ascii_text[c_match]) {
c_match += 1;
if (c_match == textlen) {
size_t c_match = 0;
/* Load the frame's data. */
- if (!cf_read_frame(cf, fdata)) {
+ if (!cf_read_record(cf, fdata)) {
/* Attempt to get the packet failed. */
return MR_ERROR;
}
result = MR_NOTMATCHED;
buf_len = fdata->cap_len;
- pd = buffer_start_ptr(&cf->buf);
+ pd = ws_buffer_start_ptr(&cf->buf);
i = 0;
while (i < buf_len) {
if (pd[i] == binary_data[c_match]) {
dfilter_t *sfcode;
gboolean result;
- if (!dfilter_compile(filter, &sfcode)) {
+ if (!dfilter_compile(filter, &sfcode, NULL)) {
/*
* XXX - this shouldn't happen, as the filter string is machine
* generated
match_result result;
/* Load the frame's data. */
- if (!cf_read_frame(cf, fdata)) {
+ if (!cf_read_record(cf, fdata)) {
/* Attempt to get the packet failed. */
return MR_ERROR;
}
epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
epan_dissect_prime_dfilter(&edt, sfcode);
- epan_dissect_run(&edt, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
+ epan_dissect_run(&edt, cf->cd_t, &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;
frame_data *fdata;
frame_data *new_fd = NULL;
progdlg_t *progbar = NULL;
- gboolean stop_flag;
int count;
gboolean found;
float progbar_val;
/* Progress so far. */
progbar_val = 0.0f;
- stop_flag = FALSE;
+ cf->stop_flag = FALSE;
g_get_current_time(&start_time);
title = cf->sfilter?cf->sfilter:"";
time in order to get to the next progress bar step). */
if (progbar == NULL)
progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
- FALSE, &stop_flag, &start_time, progbar_val);
+ FALSE, &cf->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
progbar_nextstep += progbar_quantum;
}
- if (stop_flag) {
+ if (cf->stop_flag) {
/* Well, the user decided to abort the search. Go back to the
frame where we started. */
new_fd = start_fd;
so we can't select it. */
simple_message_box(ESD_TYPE_INFO, NULL,
"The capture file is probably not fully dissected.",
- "End of capture exceeded!");
+ "End of capture exceeded.");
return FALSE;
}
return TRUE; /* success */
so we can't select it. */
simple_message_box(ESD_TYPE_INFO, NULL,
"The capture file is probably not fully dissected.",
- "End of capture exceeded!");
+ "End of capture exceeded.");
return FALSE;
}
return TRUE; /* we got to that packet */
}
/* Get the data in that frame. */
- if (!cf_read_frame (cf, fdata)) {
+ if (!cf_read_record (cf, fdata)) {
return;
}
cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
tap_build_interesting(cf->edt);
- epan_dissect_run(cf->edt, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf),
+ epan_dissect_run(cf->edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf),
cf->current_frame, NULL);
dfilter_macro_build_ftv_cache(cf->edt->tree);
const gchar *
cf_read_shb_comment(capture_file *cf)
{
- wtapng_section_t *shb_inf;
- const gchar *temp_str;
-
/* Get info from SHB */
- shb_inf = wtap_file_get_shb_info(cf->wth);
- if (shb_inf == NULL)
- return NULL;
- temp_str = shb_inf->opt_comment;
- g_free(shb_inf);
-
- return temp_str;
-
+ return wtap_file_get_shb_comment(cf->wth);
}
void
cf_update_capture_comment(capture_file *cf, gchar *comment)
{
- wtapng_section_t *shb_inf;
+ const gchar *shb_comment;
/* Get info from SHB */
- shb_inf = wtap_file_get_shb_info(cf->wth);
+ shb_comment = wtap_file_get_shb_comment(cf->wth);
/* See if the comment has changed or not */
- if (shb_inf && shb_inf->opt_comment) {
- if (strcmp(shb_inf->opt_comment, comment) == 0) {
+ if (shb_comment) {
+ if (strcmp(shb_comment, comment) == 0) {
g_free(comment);
- g_free(shb_inf);
return;
}
}
- g_free(shb_inf);
-
/* The comment has changed, let's update it */
wtap_write_shb_comment(cf->wth, comment);
/* Mark the file as having unsaved changes */
cf->unsaved_changes = TRUE;
}
-void
-cf_update_packet_comment(capture_file *cf, frame_data *fdata, gchar *comment)
+static const char *
+cf_get_user_packet_comment(capture_file *cf, const frame_data *fd)
{
- if (fdata->opt_comment != NULL) {
- /* OK, remove the old comment. */
- g_free(fdata->opt_comment);
- fdata->opt_comment = NULL;
- cf->packet_comment_count--;
+ if (cf->frames_user_comments)
+ return (const char *)g_tree_lookup(cf->frames_user_comments, fd);
+
+ /* g_warning? */
+ return NULL;
+}
+
+char *
+cf_get_comment(capture_file *cf, const frame_data *fd)
+{
+ char *comment;
+
+ /* fetch user comment */
+ if (fd->flags.has_user_comment)
+ return g_strdup(cf_get_user_packet_comment(cf, fd));
+
+ /* fetch phdr comment */
+ if (fd->flags.has_phdr_comment) {
+ struct wtap_pkthdr phdr; /* Packet header */
+ Buffer buf; /* Packet data */
+
+ wtap_phdr_init(&phdr);
+ ws_buffer_init(&buf, 1500);
+
+ if (!cf_read_record_r(cf, fd, &phdr, &buf))
+ { /* XXX, what we can do here? */ }
+
+ comment = phdr.opt_comment;
+ wtap_phdr_cleanup(&phdr);
+ ws_buffer_free(&buf);
+ return comment;
}
- if (comment != NULL) {
- /* Add the new comment. */
- fdata->opt_comment = comment;
- cf->packet_comment_count++;
+ return NULL;
+}
+
+static int
+frame_cmp(gconstpointer a, gconstpointer b, gpointer user_data _U_)
+{
+ const frame_data *fdata1 = (const frame_data *) a;
+ const frame_data *fdata2 = (const frame_data *) b;
+
+ return (fdata1->num < fdata2->num) ? -1 :
+ (fdata1->num > fdata2->num) ? 1 :
+ 0;
+}
+
+gboolean
+cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
+{
+ char *pkt_comment = cf_get_comment(cf, fd);
+
+ /* Check if the comment has changed */
+ if (!g_strcmp0(pkt_comment, new_comment)) {
+ g_free(pkt_comment);
+ return FALSE;
}
+ g_free(pkt_comment);
+
+ if (pkt_comment)
+ cf->packet_comment_count--;
+
+ if (new_comment)
+ cf->packet_comment_count++;
+
+ fd->flags.has_user_comment = TRUE;
+
+ if (!cf->frames_user_comments)
+ cf->frames_user_comments = g_tree_new_full(frame_cmp, NULL, NULL, g_free);
+
+ /* insert new packet comment */
+ g_tree_replace(cf->frames_user_comments, fd, g_strdup(new_comment));
expert_update_comment_count(cf->packet_comment_count);
/* OK, we have unsaved changes. */
cf->unsaved_changes = TRUE;
+ return TRUE;
}
/*
return comment_types;
}
+#ifdef WANT_PACKET_EDITOR
+static gint
+g_direct_compare_func(gconstpointer a, gconstpointer b, gpointer user_data _U_)
+{
+ if (a > b)
+ return 1;
+ else if (a < b)
+ return -1;
+ else
+ return 0;
+}
+
+static void
+modified_frame_data_free(gpointer data)
+{
+ modified_frame_data *mfd = (modified_frame_data *)data;
+
+ g_free(mfd->pd);
+ g_free(mfd);
+}
+
+/*
+ * Give a frame new, edited data.
+ */
+void
+cf_set_frame_edited(capture_file *cf, frame_data *fd,
+ struct wtap_pkthdr *phdr, guint8 *pd)
+{
+ modified_frame_data *mfd = (modified_frame_data *)g_malloc(sizeof(modified_frame_data));
+
+ mfd->phdr = *phdr;
+ mfd->pd = pd;
+
+ if (cf->edited_frames == NULL)
+ cf->edited_frames = g_tree_new_full(g_direct_compare_func, NULL, NULL,
+ modified_frame_data_free);
+ g_tree_insert(cf->edited_frames, GINT_TO_POINTER(fd->num), mfd);
+ fd->file_off = -1;
+
+ /* Mark the file as having unsaved changes */
+ cf->unsaved_changes = TRUE;
+}
+#endif
+
typedef struct {
wtap_dumper *pdh;
const char *fname;
* up a message box for the failure.
*/
static gboolean
-save_packet(capture_file *cf _U_, frame_data *fdata,
+save_record(capture_file *cf, frame_data *fdata,
struct wtap_pkthdr *phdr, const guint8 *pd,
void *argsp)
{
save_callback_args_t *args = (save_callback_args_t *)argsp;
struct wtap_pkthdr hdr;
int err;
+ gchar *err_info;
gchar *display_basename;
+ const char *pkt_comment;
+
+ if (fdata->flags.has_user_comment)
+ pkt_comment = cf_get_user_packet_comment(cf, fdata);
+ else
+ pkt_comment = phdr->opt_comment;
/* init the wtap header for saving */
/* TODO: reuse phdr */
For WTAP_HAS_PACK_FLAGS, we currently don't save the FCS length
from the packet flags. */
+ hdr.rec_type = phdr->rec_type;
hdr.presence_flags = 0;
if (fdata->flags.has_ts)
hdr.presence_flags |= WTAP_HAS_TS;
- if (fdata->flags.has_if_id)
+ if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
hdr.presence_flags |= WTAP_HAS_INTERFACE_ID;
- if (fdata->flags.has_pack_flags)
+ if (phdr->presence_flags & WTAP_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;
- hdr.len = fdata->pkt_len;
+ hdr.caplen = phdr->caplen;
+ hdr.len = phdr->len;
hdr.pkt_encap = fdata->lnk_t;
/* pcapng */
- hdr.interface_id = fdata->interface_id; /* identifier of the interface. */
+ hdr.interface_id = phdr->interface_id; /* identifier of the interface. */
/* options */
- hdr.pack_flags = fdata->pack_flags;
- hdr.opt_comment = fdata->opt_comment; /* NULL if not available */
+ hdr.pack_flags = phdr->pack_flags;
+ hdr.opt_comment = g_strdup(pkt_comment);
+
/* pseudo */
hdr.pseudo_header = phdr->pseudo_header;
#if 0
hdr.pack_flags = /* XXX - 0 for now (any value for "we don't have it"?) */
#endif
/* and save the packet */
- if (!wtap_dump(args->pdh, &hdr, pd, &err)) {
+ if (!wtap_dump(args->pdh, &hdr, pd, &err, &err_info)) {
if (err < 0) {
/* Wiretap error. */
switch (err) {
- case WTAP_ERR_UNSUPPORTED_ENCAP:
+ case WTAP_ERR_UNWRITABLE_ENCAP:
/*
- * This is a problem with the particular frame we're writing;
- * note that, and give the frame number.
+ * This is a problem with the particular frame we're writing and
+ * the file type and subtype we're writing; note that, and report
+ * the frame number and file type/subtype.
*/
simple_error_message_box(
"Frame %u has a network type that can't be saved in a \"%s\" file.",
- fdata->num, wtap_file_type_string(args->file_type));
+ fdata->num, wtap_file_type_subtype_string(args->file_type));
+ break;
+
+ case WTAP_ERR_PACKET_TOO_LARGE:
+ /*
+ * This is a problem with the particular frame we're writing and
+ * the file type and subtype we're writing; note that, and report
+ * the frame number and file type/subtype.
+ */
+ simple_error_message_box(
+ "Frame %u is larger than Wireshark supports in a \"%s\" file.",
+ fdata->num, wtap_file_type_subtype_string(args->file_type));
+ break;
+
+ case WTAP_ERR_UNWRITABLE_REC_TYPE:
+ /*
+ * This is a problem with the particular record we're writing and
+ * the file type and subtype we're writing; note that, and report
+ * the record number and file type/subtype.
+ */
+ simple_error_message_box(
+ "Record %u has a record type that can't be saved in a \"%s\" file.",
+ fdata->num, wtap_file_type_subtype_string(args->file_type));
+ break;
+
+ case WTAP_ERR_UNWRITABLE_REC_DATA:
+ /*
+ * This is a problem with the particular frame we're writing and
+ * the file type and subtype we're writing; note that, and report
+ * the frame number and file type/subtype.
+ */
+ simple_error_message_box(
+ "Record %u has data that can't be saved in a \"%s\" file.\n(%s)",
+ fdata->num, wtap_file_type_subtype_string(args->file_type),
+ err_info != NULL ? err_info : "no information supplied");
+ g_free(err_info);
break;
default:
}
return FALSE;
}
+
+ g_free(hdr.opt_comment);
return TRUE;
}
* If this is a temporary file, or a file with unsaved changes, it
* has unsaved data.
*/
- return cf->is_tempfile || cf->unsaved_changes;
+ return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes;
}
/*
gchar *err_info;
gchar *name_ptr;
gint64 data_offset;
- gint64 file_pos;
progdlg_t *progbar = NULL;
- gboolean stop_flag;
gint64 size;
float progbar_val;
GTimeVal start_time;
wtap_close(cf->wth);
/* Open the new file. */
- cf->wth = wtap_open_offline(fname, err, &err_info, TRUE);
+ /* XXX: this will go through all open_routines for a matching one. But right
+ now rescan_file() is only used when a file is being saved to a different
+ format than the original, and the user is not given a choice of which
+ reader to use (only which format to save it in), so doing this makes
+ sense for now. */
+ cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, err, &err_info, TRUE);
if (cf->wth == NULL) {
cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
return CF_READ_ERROR;
/* No user changes yet. */
cf->unsaved_changes = FALSE;
- cf->cd_t = wtap_file_type(cf->wth);
+ cf->cd_t = wtap_file_type_subtype(cf->wth);
cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
cf->snap = wtap_snapshot_length(cf->wth);
}else
progbar_quantum = 0;
- stop_flag = FALSE;
+ cf->stop_flag = FALSE;
g_get_current_time(&start_time);
framenum = 0;
fdata->file_off = data_offset;
if (size >= 0) {
count++;
- file_pos = wtap_read_so_far(cf->wth);
+ cf->f_datalen = 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));
+ progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
- TRUE, &stop_flag, &start_time, progbar_val);
+ TRUE, &cf->stop_flag, &start_time, progbar_val);
}
/* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
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 (cf->f_datalen >= progbar_nextstep) {
if (progbar != NULL) {
- progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
+ progbar_val = calc_progbar_val(cf, size, cf->f_datalen, 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 (stop_flag) {
+ if (cf->stop_flag) {
/* Well, the user decided to abort the rescan. Sadly, as this
isn't a reread, recovering is difficult, so we'll just
close the current capture. */
wtap_sequential_close(cf->wth);
/* compute the time it took to load the file */
- compute_elapsed(&start_time);
+ compute_elapsed(cf, &start_time);
/* Set the file encapsulation type now; we don't know what it is until
we've looked at all the packets, as we don't know until then whether
cf_callback_invoke(cf_cb_file_rescan_finished, cf);
- if (stop_flag) {
+ if (cf->stop_flag) {
/* Our caller will give up at this point. */
return CF_READ_ABORTED;
}
case WTAP_ERR_UNSUPPORTED:
simple_error_message_box(
"The capture file contains record data that Wireshark doesn't support.\n(%s)",
- err_info);
+ err_info != NULL ? err_info : "no information supplied");
g_free(err_info);
break;
- case WTAP_ERR_UNSUPPORTED_ENCAP:
- simple_error_message_box(
- "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
- err_info);
- g_free(err_info);
- break;
-
- case WTAP_ERR_CANT_READ:
- simple_error_message_box(
- "An attempt to read from the capture file failed for"
- " some unknown reason.");
- break;
-
case WTAP_ERR_SHORT_READ:
simple_error_message_box(
"The capture file appears to have been cut short"
case WTAP_ERR_BAD_FILE:
simple_error_message_box(
"The capture file appears to be damaged or corrupt.\n(%s)",
- err_info);
+ err_info != NULL ? err_info : "no information supplied");
g_free(err_info);
break;
case WTAP_ERR_DECOMPRESS:
simple_error_message_box(
"The compressed capture file appears to be damaged or corrupt.\n"
- "(%s)", err_info);
+ "(%s)",
+ err_info != NULL ? err_info : "no information supplied");
g_free(err_info);
break;
}
cf_write_status_t
-cf_save_packets(capture_file *cf, const char *fname, guint save_format,
+cf_save_records(capture_file *cf, const char *fname, guint save_format,
gboolean compressed, gboolean discard_comments,
gboolean dont_reopen)
{
gchar *fname_new = NULL;
wtap_dumper *pdh;
frame_data *fdata;
- struct addrinfo *addrs;
+ addrinfo_lists_t *addr_lists;
guint framenum;
int err;
#ifdef _WIN32
cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
- addrs = get_addrinfo_list();
+ addr_lists = get_addrinfo_list();
if (save_format == cf->cd_t && compressed == cf->iscompressed
&& !discard_comments && !cf->unsaved_changes
- && !(addrs && addrs->ai_next &&
- wtap_dump_has_name_resolution(save_format))) {
+ && !(addr_lists && 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, and we have no name
or moving the capture file, we have to do it by writing the packets
out in Wiretap. */
- wtapng_section_t *shb_hdr = NULL;
+ wtapng_section_t *shb_hdr = NULL;
wtapng_iface_descriptions_t *idb_inf = NULL;
+ wtapng_name_res_t *nrb_hdr = NULL;
int encap;
- shb_hdr = wtap_file_get_shb_info(cf->wth);
+ /* XXX: what free's this shb_hdr? */
+ shb_hdr = wtap_file_get_shb_for_new_file(cf->wth);
idb_inf = wtap_file_get_idb_info(cf->wth);
+ nrb_hdr = wtap_file_get_nrb_for_new_file(cf->wth);
/* Determine what file encapsulation type we should use. */
encap = wtap_dump_file_encap_type(cf->linktypes);
from which we're reading the packets that we're writing!) */
fname_new = g_strdup_printf("%s~", fname);
pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
- compressed, shb_hdr, idb_inf, &err);
+ compressed, shb_hdr, idb_inf, nrb_hdr, &err);
} else {
pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
- compressed, shb_hdr, idb_inf, &err);
+ compressed, shb_hdr, idb_inf, nrb_hdr, &err);
}
g_free(idb_inf);
idb_inf = NULL;
}
/* Add address resolution */
- wtap_dump_set_addrinfo_list(pdh, addrs);
+ wtap_dump_set_addrinfo_list(pdh, addr_lists);
/* Iterate through the list of packets, processing all the packets. */
callback_args.pdh = pdh;
callback_args.fname = fname;
callback_args.file_type = save_format;
- switch (process_specified_packets(cf, NULL, "Saving", "packets",
- TRUE, save_packet, &callback_args)) {
+ switch (process_specified_records(cf, NULL, "Saving", "packets",
+ TRUE, save_record, &callback_args)) {
case PSP_FINISHED:
/* Completed successfully. */
the wtap structure, the filename, and the "is temporary"
status applies to the new file; just update that. */
wtap_close(cf->wth);
- cf->wth = wtap_open_offline(fname, &err, &err_info, TRUE);
+ /* Although we're just "copying" and then opening the copy, it will
+ try all open_routine readers to open the copy, so we need to
+ reset the cfile's open_type. */
+ cf->open_type = WTAP_TYPE_AUTO;
+ cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
if (cf->wth == NULL) {
cf_open_failure_alert_box(fname, err, err_info, FALSE, 0);
cf_close(cf);
...as long as, for gzipped files, the process of writing
out the file *also* generates the information needed to
support fast random access to the compressed file. */
+ /* rescan_file will cause us to try all open_routines, so
+ reset cfile's open_type */
+ cf->open_type = WTAP_TYPE_AUTO;
if (rescan_file(cf, fname, FALSE, &err) != CF_READ_OK) {
/* The rescan failed; just close the file. Either
a dialog was popped up for the failure, so the
/* Remove SHB comment, if any. */
wtap_write_shb_comment(cf->wth, NULL);
- /* Remove packet comments. */
+ /* remove all user comments */
for (framenum = 1; framenum <= cf->count; framenum++) {
fdata = frame_data_sequence_find(cf->frames, framenum);
- if (fdata->opt_comment) {
- g_free(fdata->opt_comment);
- fdata->opt_comment = NULL;
- cf->packet_comment_count--;
- }
+
+ fdata->flags.has_phdr_comment = FALSE;
+ fdata->flags.has_user_comment = FALSE;
}
+
+ if (cf->frames_user_comments) {
+ g_tree_destroy(cf->frames_user_comments);
+ cf->frames_user_comments = NULL;
+ }
+
+ cf->packet_comment_count = 0;
}
}
return CF_WRITE_OK;
int err;
wtap_dumper *pdh;
save_callback_args_t callback_args;
- wtapng_section_t *shb_hdr;
- wtapng_iface_descriptions_t *idb_inf;
+ wtapng_section_t *shb_hdr = NULL;
+ wtapng_iface_descriptions_t *idb_inf = NULL;
+ wtapng_name_res_t *nrb_hdr = NULL;
int encap;
cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname);
written, don't special-case the operation - read each packet
and then write it out if it's one of the specified ones. */
- shb_hdr = wtap_file_get_shb_info(cf->wth);
+ /* XXX: what free's this shb_hdr? */
+ shb_hdr = wtap_file_get_shb_for_new_file(cf->wth);
idb_inf = wtap_file_get_idb_info(cf->wth);
+ nrb_hdr = wtap_file_get_nrb_for_new_file(cf->wth);
/* Determine what file encapsulation type we should use. */
encap = wtap_dump_file_encap_type(cf->linktypes);
from which we're reading the packets that we're writing!) */
fname_new = g_strdup_printf("%s~", fname);
pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
- compressed, shb_hdr, idb_inf, &err);
+ compressed, shb_hdr, idb_inf, nrb_hdr, &err);
} else {
pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
- compressed, shb_hdr, idb_inf, &err);
+ compressed, shb_hdr, idb_inf, nrb_hdr, &err);
}
g_free(idb_inf);
idb_inf = NULL;
told to process.
XXX - we've already called "packet_range_process_init(range)", but
- "process_specified_packets()" will do it again. Fortunately,
+ "process_specified_records()" will do it again. Fortunately,
that's harmless in this case, as we haven't done anything to
"range" since we initialized it. */
callback_args.pdh = pdh;
callback_args.fname = fname;
callback_args.file_type = save_format;
- switch (process_specified_packets(cf, range, "Writing", "specified packets",
- TRUE, save_packet, &callback_args)) {
+ switch (process_specified_records(cf, range, "Writing", "specified records",
+ TRUE, save_record, &callback_args)) {
case PSP_FINISHED:
/* Completed successfully. */
case WTAP_ERR_UNSUPPORTED:
/* Seen only when opening a capture file for reading. */
simple_error_message_box(
- "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
+ "The file \"%s\" contains record data that Wireshark doesn't support.\n"
"(%s)",
- display_basename, err_info);
+ display_basename,
+ err_info != NULL ? err_info : "no information supplied");
g_free(err_info);
break;
simple_error_message_box(
"The file \"%s\" is a pipe, and %s capture files can't be "
"written to a pipe.",
- display_basename, wtap_file_type_string(file_type));
+ display_basename, wtap_file_type_subtype_string(file_type));
break;
- case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
+ case WTAP_ERR_UNWRITABLE_FILE_TYPE:
/* Seen only when opening a capture file for writing. */
simple_error_message_box(
"Wireshark doesn't support writing capture files in that format.");
break;
- case WTAP_ERR_UNSUPPORTED_ENCAP:
- if (for_writing) {
- simple_error_message_box("Wireshark can't save this capture in that format.");
- } else {
- simple_error_message_box(
- "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
- "(%s)",
- display_basename, err_info);
- g_free(err_info);
- }
+ case WTAP_ERR_UNWRITABLE_ENCAP:
+ /* Seen only when opening a capture file for writing. */
+ simple_error_message_box("Wireshark can't save this capture in that format.");
break;
case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
simple_error_message_box(
"The file \"%s\" appears to be damaged or corrupt.\n"
"(%s)",
- display_basename, err_info);
+ display_basename,
+ err_info != NULL ? err_info : "no information supplied");
g_free(err_info);
break;
case WTAP_ERR_DECOMPRESS:
simple_error_message_box(
"The compressed file \"%s\" appears to be damaged or corrupt.\n"
- "(%s)", display_basename, err_info);
+ "(%s)", display_basename,
+ err_info != NULL ? err_info : "no information supplied");
g_free(err_info);
break;
filename = g_strdup(cf->filename);
is_tempfile = cf->is_tempfile;
cf->is_tempfile = FALSE;
- if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
+ if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
switch (cf_read(cf, TRUE)) {
case CF_READ_OK: