summaryrefslogtreecommitdiffstats
path: root/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'file.c')
-rw-r--r--file.c1903
1 files changed, 1304 insertions, 599 deletions
diff --git a/file.c b/file.c
index d8178ff7..f42c36a4 100644
--- a/file.c
+++ b/file.c
@@ -25,6 +25,7 @@
#include <wsutil/wslog.h>
#include <wsutil/ws_assert.h>
#include <wsutil/version_info.h>
+#include <wsutil/report_message.h>
#include <wiretap/merge.h>
@@ -73,11 +74,11 @@
# include <ws2tcpip.h>
#endif
-static gboolean read_record(capture_file *cf, wtap_rec *rec, Buffer *buf,
- dfilter_t *dfcode, epan_dissect_t *edt, column_info *cinfo, gint64 offset,
+static bool read_record(capture_file *cf, wtap_rec *rec, Buffer *buf,
+ dfilter_t *dfcode, epan_dissect_t *edt, column_info *cinfo, int64_t offset,
fifo_string_cache_t *frame_dup_cache, GChecksum *frame_cksum);
-static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect);
+static void rescan_packets(capture_file *cf, const char *action, const char *action_item, bool redissect);
typedef enum {
MR_NOTMATCHED,
@@ -88,32 +89,45 @@ typedef match_result (*ws_match_function)(capture_file *, frame_data *,
wtap_rec *, Buffer *, void *);
static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
wtap_rec *, Buffer *, void *criterion);
-static void match_subtree_text(proto_node *node, gpointer data);
+static void match_subtree_text(proto_node *node, void *data);
+static void match_subtree_text_reverse(proto_node *node, void *data);
static match_result match_summary_line(capture_file *cf, frame_data *fdata,
wtap_rec *, Buffer *, void *criterion);
static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata,
wtap_rec *, Buffer *, void *criterion);
+static match_result match_narrow_and_wide_reverse(capture_file *cf, frame_data *fdata,
+ wtap_rec *, Buffer *, void *criterion);
static match_result match_narrow_and_wide_case(capture_file *cf, frame_data *fdata,
wtap_rec *, Buffer *, void *criterion);
-static match_result match_narrow(capture_file *cf, frame_data *fdata,
+static match_result match_narrow_and_wide_case_reverse(capture_file *cf, frame_data *fdata,
wtap_rec *, Buffer *, void *criterion);
static match_result match_narrow_case(capture_file *cf, frame_data *fdata,
wtap_rec *, Buffer *, void *criterion);
+static match_result match_narrow_case_reverse(capture_file *cf, frame_data *fdata,
+ wtap_rec *, Buffer *, void *criterion);
static match_result match_wide(capture_file *cf, frame_data *fdata,
wtap_rec *, Buffer *, void *criterion);
+static match_result match_wide_reverse(capture_file *cf, frame_data *fdata,
+ wtap_rec *, Buffer *, void *criterion);
static match_result match_wide_case(capture_file *cf, frame_data *fdata,
wtap_rec *, Buffer *, void *criterion);
+static match_result match_wide_case_reverse(capture_file *cf, frame_data *fdata,
+ wtap_rec *, Buffer *, void *criterion);
static match_result match_binary(capture_file *cf, frame_data *fdata,
wtap_rec *, Buffer *, void *criterion);
+static match_result match_binary_reverse(capture_file *cf, frame_data *fdata,
+ wtap_rec *, Buffer *, void *criterion);
static match_result match_regex(capture_file *cf, frame_data *fdata,
wtap_rec *, Buffer *, void *criterion);
+static match_result match_regex_reverse(capture_file *cf, frame_data *fdata,
+ wtap_rec *, Buffer *, void *criterion);
static match_result match_dfilter(capture_file *cf, frame_data *fdata,
wtap_rec *, Buffer *, void *criterion);
static match_result match_marked(capture_file *cf, frame_data *fdata,
wtap_rec *, Buffer *, void *criterion);
static match_result match_time_reference(capture_file *cf, frame_data *fdata,
wtap_rec *, Buffer *, void *criterion);
-static gboolean find_packet(capture_file *cf, ws_match_function match_function,
+static bool find_packet(capture_file *cf, ws_match_function match_function,
void *criterion, search_direction dir);
static void cf_rename_failure_alert_box(const char *filename, int err);
@@ -127,16 +141,16 @@ static void cf_rename_failure_alert_box(const char *filename, int err);
/*
* Maximum number of records we support in a file.
*
- * It is, at most, the maximum value of a guint32, as we use a guint32
+ * It is, at most, the maximum value of a uint32_t, as we use a uint32_t
* for the frame number.
*
* We allow it to be set to a lower value; see issue #16908 for why
* we're doing this. Thanks, Qt!
*/
-static guint32 max_records = G_MAXUINT32;
+static uint32_t max_records = UINT32_MAX;
void
-cf_set_max_records(guint max_records_arg)
+cf_set_max_records(unsigned max_records_arg)
{
max_records = max_records_arg;
}
@@ -148,13 +162,13 @@ cf_set_max_records(guint max_records_arg)
*/
typedef struct {
cf_callback_t cb_fct;
- gpointer user_data;
+ void * user_data;
} cf_callback_data_t;
-static GList *cf_callbacks = NULL;
+static GList *cf_callbacks;
static void
-cf_callback_invoke(int event, gpointer data)
+cf_callback_invoke(int event, void *data)
{
cf_callback_data_t *cb;
GList *cb_item = cf_callbacks;
@@ -170,7 +184,7 @@ cf_callback_invoke(int event, gpointer data)
}
void
-cf_callback_add(cf_callback_t func, gpointer user_data)
+cf_callback_add(cf_callback_t func, void *user_data)
{
cf_callback_data_t *cb;
@@ -182,7 +196,7 @@ cf_callback_add(cf_callback_t func, gpointer user_data)
}
void
-cf_callback_remove(cf_callback_t func, gpointer user_data)
+cf_callback_remove(cf_callback_t func, void *user_data)
{
cf_callback_data_t *cb;
GList *cb_item = cf_callbacks;
@@ -200,40 +214,25 @@ cf_callback_remove(cf_callback_t func, gpointer user_data)
ws_assert_not_reached();
}
-gulong
+unsigned long
cf_get_computed_elapsed(capture_file *cf)
{
return cf->computed_elapsed;
}
static void
-compute_elapsed(capture_file *cf, gint64 start_time)
+compute_elapsed(capture_file *cf, int64_t start_time)
{
- gint64 delta_time = g_get_monotonic_time() - start_time;
+ int64_t delta_time = g_get_monotonic_time() - start_time;
- cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */
-}
-
-static const nstime_t *
-ws_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num)
-{
- const frame_data *fd = NULL;
- if (prov->prev_dis && prov->prev_dis->num == frame_num) {
- fd = prov->prev_dis;
- } else if (prov->prev_cap && prov->prev_cap->num == frame_num) {
- fd = prov->prev_cap;
- } else if (prov->frames) {
- fd = frame_data_sequence_find(prov->frames, frame_num);
- }
-
- return (fd && fd->has_ts) ? &fd->abs_ts : NULL;
+ cf->computed_elapsed = (unsigned long) (delta_time / 1000); /* ms */
}
static epan_t *
ws_epan_new(capture_file *cf)
{
static const struct packet_provider_funcs funcs = {
- ws_get_frame_ts,
+ cap_file_provider_get_frame_ts,
cap_file_provider_get_interface_name,
cap_file_provider_get_interface_description,
cap_file_provider_get_modified_block
@@ -243,12 +242,12 @@ ws_epan_new(capture_file *cf)
}
cf_status_t
-cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
+cf_open(capture_file *cf, const char *fname, unsigned int type, bool is_tempfile, int *err)
{
wtap *wth;
- gchar *err_info;
+ char *err_info;
- wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
+ wth = wtap_open_offline(fname, type, err, &err_info, true);
if (wth == NULL)
goto fail;
@@ -266,6 +265,12 @@ cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_temp
/* We're about to start reading the file. */
cf->state = FILE_READ_IN_PROGRESS;
+ /* If there was a pending redissection for the old file (there
+ * shouldn't be), clear it. cf_close() should have failed if the
+ * old file's read lock was held, but it doesn't hurt to clear it. */
+ cf->read_lock = false;
+ cf->redissection_queued = RESCAN_NONE;
+
cf->provider.wth = wth;
cf->f_datalen = 0;
@@ -278,20 +283,20 @@ cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_temp
cf->is_tempfile = is_tempfile;
/* No user changes yet. */
- cf->unsaved_changes = FALSE;
+ cf->unsaved_changes = false;
cf->computed_elapsed = 0;
cf->cd_t = wtap_file_type_subtype(cf->provider.wth);
cf->open_type = type;
- cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
+ cf->linktypes = g_array_sized_new(FALSE, FALSE, (unsigned) sizeof(int), 1);
cf->count = 0;
cf->packet_comment_count = 0;
cf->displayed_count = 0;
cf->marked_count = 0;
cf->ignored_count = 0;
cf->ref_time_count = 0;
- cf->drops_known = FALSE;
+ cf->drops_known = false;
cf->drops = 0;
cf->snap = wtap_snapshot_length(cf->provider.wth);
@@ -329,10 +334,10 @@ fail:
static void
cf_add_encapsulation_type(capture_file *cf, int encap)
{
- guint i;
+ unsigned i;
for (i = 0; i < cf->linktypes->len; i++) {
- if (g_array_index(cf->linktypes, gint, i) == encap)
+ if (g_array_index(cf->linktypes, int, i) == encap)
return; /* it's already there */
}
/* It's not already there - add it. */
@@ -343,7 +348,7 @@ cf_add_encapsulation_type(capture_file *cf, int encap)
void
cf_close(capture_file *cf)
{
- cf->stop_flag = FALSE;
+ cf->stop_flag = false;
if (cf->state == FILE_CLOSED || cf->state == FILE_READ_PENDING)
return; /* Nothing to do */
@@ -369,7 +374,7 @@ cf_close(capture_file *cf)
cf->filename = NULL;
}
/* ...which means we have no changes to that file to save. */
- cf->unsaved_changes = FALSE;
+ cf->unsaved_changes = false;
/* no open_routine type */
cf->open_type = WTAP_TYPE_AUTO;
@@ -425,32 +430,32 @@ cf_close(capture_file *cf)
}
/*
- * TRUE if the progress dialog doesn't exist and it looks like we'll
- * take > PROGBAR_SHOW_DELAY (500ms) to load, FALSE otherwise.
+ * true if the progress dialog doesn't exist and it looks like we'll
+ * take > PROGBAR_SHOW_DELAY (500ms) to load, false otherwise.
*/
-static inline gboolean
-progress_is_slow(progdlg_t *progdlg, GTimer *prog_timer, gint64 size, gint64 pos)
+static inline bool
+progress_is_slow(progdlg_t *progdlg, GTimer *prog_timer, int64_t size, int64_t pos)
{
double elapsed;
- if (progdlg) return FALSE;
+ if (progdlg) return false;
elapsed = g_timer_elapsed(prog_timer, NULL);
/* This only gets checked between reading records, which doesn't help if
* a single record takes a very long time, e.g., the first TLS packet if
* the SSLKEYLOGFILE is very large. (#17051) */
if ((elapsed * 2 > PROGBAR_SHOW_DELAY && (size / pos) >= 2) /* It looks like we're going to be slow. */
|| elapsed > PROGBAR_SHOW_DELAY) { /* We are indeed slow. */
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
static float
-calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
+calc_progbar_val(capture_file *cf, int64_t size, int64_t file_pos, char *status_str, unsigned long status_size)
{
float progbar_val;
- progbar_val = (gfloat) file_pos / (gfloat) size;
+ progbar_val = (float) file_pos / (float) size;
if (progbar_val > 1.0) {
/* The file probably grew while we were reading it.
@@ -459,7 +464,7 @@ calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_s
size = wtap_file_size(cf->provider.wth, NULL);
if (size >= 0)
- progbar_val = (gfloat) file_pos / (gfloat) size;
+ progbar_val = (float) file_pos / (float) size;
/* If it's still > 1, either "wtap_file_size()" failed (in which
* case there's not much we can do about it), or the file
@@ -478,25 +483,25 @@ calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_s
}
cf_read_status_t
-cf_read(capture_file *cf, gboolean reloading)
+cf_read(capture_file *cf, bool reloading)
{
int err = 0;
- gchar *err_info = NULL;
- volatile gboolean too_many_records = FALSE;
- gchar *name_ptr;
+ char *err_info = NULL;
+ volatile bool too_many_records = false;
+ char *name_ptr;
progdlg_t *volatile progbar = NULL;
GTimer *prog_timer = g_timer_new();
- gint64 size;
- gint64 start_time;
+ int64_t size;
+ int64_t start_time;
epan_dissect_t edt;
wtap_rec rec;
Buffer buf;
dfilter_t *dfcode = NULL;
column_info *cinfo;
- volatile gboolean create_proto_tree;
- guint tap_flags;
- gboolean compiled _U_;
- volatile gboolean is_read_aborted = FALSE;
+ volatile bool create_proto_tree;
+ unsigned tap_flags;
+ bool compiled _U_;
+ volatile bool is_read_aborted = false;
/* The update_progress_dlg call below might end up accepting a user request to
* trigger redissection/rescans which can modify/destroy the dissection
@@ -508,17 +513,37 @@ cf_read(capture_file *cf, gboolean reloading)
cf->filename, reloading);
return CF_READ_ERROR;
}
- cf->read_lock = TRUE;
+ /* This is a full dissection, so clear any pending request for one. */
+ cf->redissection_queued = RESCAN_NONE;
+ cf->read_lock = true;
/* Compile the current display filter.
+ * The code it compiles to might have changed, e.g. if a display
+ * filter macro used has changed.
+ *
* We assume this will not fail since cf->dfilter is only set in
* cf_filter IFF the filter was valid.
+ * XXX - This is not necessarily true, if the filter has a FT_IPv4
+ * or FT_IPv6 field compared to a resolved hostname in it, because
+ * we do a new host lookup, and that *could* timeout this time
+ * (though with the read lock above we shouldn't have many lookups at
+ * once, reducing the chances of that)... (#19612)
*/
if (cf->dfilter) {
compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
ws_assert(compiled && dfcode);
}
+ dfilter_free(cf->dfcode);
+ cf->dfcode = dfcode;
+
+ /* The compiled dfilter might have a field reference; recompiling it
+ * means that the field references won't match anything. That's what
+ * we want since this is a new sequential read and we don't have
+ * a selected frame with a tree. (Will taps with filters with display
+ * references also have cleared display references?)
+ */
+
/* Get the union of the flags for all tap listeners. */
tap_flags = union_of_tap_listener_flags();
@@ -536,7 +561,7 @@ cf_read(capture_file *cf, gboolean reloading)
* the first pass.
*/
create_proto_tree =
- (dfcode != NULL || have_filtering_tap_listeners() ||
+ (cf->dfcode != NULL || have_filtering_tap_listeners() ||
(tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
reset_tap_listeners();
@@ -555,15 +580,15 @@ cf_read(capture_file *cf, gboolean reloading)
/* The packet list window will be empty until the file is completely loaded */
packet_list_freeze();
- cf->stop_flag = FALSE;
+ cf->stop_flag = false;
start_time = g_get_monotonic_time();
- epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
+ epan_dissect_init(&edt, cf->epan, create_proto_tree, false);
/* If the display filter or any tap listeners require the columns,
* construct them. */
cinfo = (tap_listeners_require_columns() ||
- dfilter_requires_columns(dfcode)) ? &cf->cinfo : NULL;
+ dfilter_requires_columns(cf->dfcode)) ? &cf->cinfo : NULL;
/* Find the size of the file. */
size = wtap_file_size(cf->provider.wth, NULL);
@@ -584,11 +609,11 @@ cf_read(capture_file *cf, gboolean reloading)
ws_buffer_init(&buf, 1514);
TRY {
- gint64 file_pos;
- gint64 data_offset;
+ int64_t file_pos;
+ int64_t data_offset;
float progbar_val;
- gchar status_str[100];
+ char status_str[100];
while ((wtap_read(cf->provider.wth, &rec, &buf, &err, &err_info,
&data_offset))) {
@@ -598,7 +623,7 @@ cf_read(capture_file *cf, gboolean reloading)
* Quit if we've already read the maximum number of
* records allowed.
*/
- too_many_records = TRUE;
+ too_many_records = true;
break;
}
file_pos = wtap_read_so_far(cf->provider.wth);
@@ -606,7 +631,7 @@ cf_read(capture_file *cf, gboolean reloading)
/* Create the progress bar if necessary. */
if (progress_is_slow(progbar, prog_timer, size, file_pos)) {
progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
- progbar = delayed_create_progress_dlg(cf->window, NULL, NULL, TRUE,
+ progbar = delayed_create_progress_dlg(cf->window, NULL, NULL, true,
&cf->stop_flag, progbar_val);
}
@@ -637,7 +662,7 @@ cf_read(capture_file *cf, gboolean reloading)
/* Well, the user decided to exit Wireshark. Break out of the
loop, and let the code below (which is called even if there
aren't any packets left to read) exit. */
- is_read_aborted = TRUE;
+ is_read_aborted = true;
break;
}
if (cf->stop_flag) {
@@ -649,7 +674,7 @@ cf_read(capture_file *cf, gboolean reloading)
hours even on fast machines) just to see that it was the wrong file. */
break;
}
- read_record(cf, &rec, &buf, dfcode, &edt, cinfo, data_offset, &frame_dup_cache, cksum);
+ read_record(cf, &rec, &buf, cf->dfcode, &edt, cinfo, data_offset, &frame_dup_cache, cksum);
wtap_rec_reset(&rec);
}
}
@@ -686,9 +711,6 @@ cf_read(capture_file *cf, gboolean reloading)
/* Free the display name */
g_free(name_ptr);
- /* Cleanup and release all dfilter resources */
- dfilter_free(dfcode);
-
epan_dissect_cleanup(&edt);
wtap_rec_cleanup(&rec);
ws_buffer_free(&buf);
@@ -715,7 +737,7 @@ cf_read(capture_file *cf, gboolean reloading)
/* It is safe again to execute redissections or sort. */
ws_assert(cf->read_lock);
- cf->read_lock = FALSE;
+ cf->read_lock = false;
if (reloading)
cf_callback_invoke(cf_cb_file_reload_finished, cf);
@@ -741,7 +763,7 @@ cf_read(capture_file *cf, gboolean reloading)
if (cf->redissection_queued != RESCAN_NONE) {
/* Redissection was queued up. Clear the request and perform it now. */
- gboolean redissect = cf->redissection_queued == RESCAN_REDISSECT;
+ bool redissect = cf->redissection_queued == RESCAN_REDISSECT;
rescan_packets(cf, NULL, NULL, redissect);
}
@@ -782,22 +804,38 @@ cf_read_status_t
cf_continue_tail(capture_file *cf, volatile int to_read, wtap_rec *rec,
Buffer *buf, int *err, fifo_string_cache_t *frame_dup_cache, GChecksum *frame_cksum)
{
- gchar *err_info;
+ char *err_info;
volatile int newly_displayed_packets = 0;
- dfilter_t *dfcode = NULL;
epan_dissect_t edt;
- gboolean create_proto_tree;
- guint tap_flags;
- gboolean compiled _U_;
+ bool create_proto_tree;
+ unsigned tap_flags;
- /* Compile the current display filter.
- * We assume this will not fail since cf->dfilter is only set in
- * cf_filter IFF the filter was valid.
+ /* Don't compile the current display filter. The current display filter
+ * text might compile to different code than when the capture started:
+ *
+ * If it has a IP address resolved name, calling get_host_ipaddr every
+ * time new packets arrive can mean a *lot* of gethostbyname calls
+ * in flight at once, eventually leading to a timeout (#19612).
+ * addr_resolv.c says that ares_gethostbyname is "usually interactive",
+ * unlike ares_gethostbyaddr (used in dissection), and violating that
+ * expectation is bad.
+ *
+ * If it has a display filter macro, the definition might have changed.
+ *
+ * If it has a field reference, the selected frame / current proto tree
+ * might have changed, and we don't have the old one. If we recompile,
+ * we can't set the field references to the old values.
+ *
+ * For a rescan, redissection, reload, retap, or opening a new file, we
+ * want to compile. What about here, when new frames have arrived in a live
+ * capture? We might be able to cache the host lookup, and a user might want
+ * the new display filter macro definition, but the user almost surely wants
+ * the field references to refer to values from the proto tree when the
+ * filter was applied, not whatever it happens to be now if the user has
+ * clicked on a different packet.
+ *
+ * To get the new compiled filter, the user should refilter.
*/
- if (cf->dfilter) {
- compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
- ws_assert(compiled && dfcode);
- }
/* Get the union of the flags for all tap listeners. */
tap_flags = union_of_tap_listener_flags();
@@ -816,7 +854,7 @@ cf_continue_tail(capture_file *cf, volatile int to_read, wtap_rec *rec,
* the first pass.
*/
create_proto_tree =
- (dfcode != NULL || have_filtering_tap_listeners() ||
+ (cf->dfcode != NULL || have_filtering_tap_listeners() ||
(tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
*err = 0;
@@ -824,16 +862,16 @@ cf_continue_tail(capture_file *cf, volatile int to_read, wtap_rec *rec,
/* Don't freeze/thaw the list when doing live capture */
/*packet_list_freeze();*/
- epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
+ epan_dissect_init(&edt, cf->epan, create_proto_tree, false);
TRY {
- gint64 data_offset = 0;
+ int64_t data_offset = 0;
column_info *cinfo;
/* If the display filter or any tap listeners require the columns,
* construct them. */
cinfo = (tap_listeners_require_columns() ||
- dfilter_requires_columns(dfcode)) ? &cf->cinfo : NULL;
+ dfilter_requires_columns(cf->dfcode)) ? &cf->cinfo : NULL;
while (to_read != 0) {
wtap_cleareof(cf->provider.wth);
@@ -847,7 +885,7 @@ cf_continue_tail(capture_file *cf, volatile int to_read, wtap_rec *rec,
aren't any packets left to read) exit. */
break;
}
- if (read_record(cf, rec, buf, dfcode, &edt, cinfo, data_offset, frame_dup_cache, frame_cksum)) {
+ if (read_record(cf, rec, buf, cf->dfcode, &edt, cinfo, data_offset, frame_dup_cache, frame_cksum)) {
newly_displayed_packets++;
}
to_read--;
@@ -873,9 +911,6 @@ cf_continue_tail(capture_file *cf, volatile int to_read, wtap_rec *rec,
packets we've read. */
cf->lnk_t = wtap_file_encap(cf->provider.wth);
- /* Cleanup and release all dfilter resources */
- dfilter_free(dfcode);
-
epan_dissect_cleanup(&edt);
/* Don't freeze/thaw the list when doing live capture */
@@ -921,23 +956,16 @@ cf_read_status_t
cf_finish_tail(capture_file *cf, wtap_rec *rec, Buffer *buf, int *err,
fifo_string_cache_t *frame_dup_cache, GChecksum *frame_cksum)
{
- gchar *err_info;
- gint64 data_offset;
- dfilter_t *dfcode = NULL;
+ char *err_info;
+ int64_t data_offset;
column_info *cinfo;
epan_dissect_t edt;
- gboolean create_proto_tree;
- guint tap_flags;
- gboolean compiled _U_;
+ bool create_proto_tree;
+ unsigned tap_flags;
- /* Compile the current display filter.
- * We assume this will not fail since cf->dfilter is only set in
- * cf_filter IFF the filter was valid.
+ /* All the comments above in cf_continue_tail apply regarding the
+ * current display filter.
*/
- if (cf->dfilter) {
- compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
- ws_assert(compiled && dfcode);
- }
/* Get the union of the flags for all tap listeners. */
tap_flags = union_of_tap_listener_flags();
@@ -945,7 +973,7 @@ cf_finish_tail(capture_file *cf, wtap_rec *rec, Buffer *buf, int *err,
/* If the display filter or any tap listeners require the columns,
* construct them. */
cinfo = (tap_listeners_require_columns() ||
- dfilter_requires_columns(dfcode)) ? &cf->cinfo : NULL;
+ dfilter_requires_columns(cf->dfcode)) ? &cf->cinfo : NULL;
/*
* Determine whether we need to create a protocol tree.
@@ -961,7 +989,7 @@ cf_finish_tail(capture_file *cf, wtap_rec *rec, Buffer *buf, int *err,
* the first pass.
*/
create_proto_tree =
- (dfcode != NULL || have_filtering_tap_listeners() ||
+ (cf->dfcode != NULL || have_filtering_tap_listeners() ||
(tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
if (cf->provider.wth == NULL) {
@@ -972,7 +1000,7 @@ cf_finish_tail(capture_file *cf, wtap_rec *rec, Buffer *buf, int *err,
/* Don't freeze/thaw the list when doing live capture */
/*packet_list_freeze();*/
- epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
+ epan_dissect_init(&edt, cf->epan, create_proto_tree, false);
while ((wtap_read(cf->provider.wth, rec, buf, err, &err_info, &data_offset))) {
if (cf->state == FILE_READ_ABORTED) {
@@ -981,13 +1009,10 @@ cf_finish_tail(capture_file *cf, wtap_rec *rec, Buffer *buf, int *err,
aren't any packets left to read) exit. */
break;
}
- read_record(cf, rec, buf, dfcode, &edt, cinfo, data_offset, frame_dup_cache, frame_cksum);
+ read_record(cf, rec, buf, cf->dfcode, &edt, cinfo, data_offset, frame_dup_cache, frame_cksum);
wtap_rec_reset(rec);
}
- /* Cleanup and release all dfilter resources */
- dfilter_free(dfcode);
-
epan_dissect_cleanup(&edt);
/* Don't freeze/thaw the list when doing live capture */
@@ -1040,10 +1065,10 @@ cf_finish_tail(capture_file *cf, wtap_rec *rec, Buffer *buf, int *err,
}
#endif /* HAVE_LIBPCAP */
-gchar *
+char *
cf_get_display_name(capture_file *cf)
{
- gchar *displayname;
+ char *displayname;
/* Return a name to use in displays */
if (!cf->is_tempfile) {
@@ -1066,10 +1091,10 @@ cf_get_display_name(capture_file *cf)
return displayname;
}
-gchar *
+char *
cf_get_basename(capture_file *cf)
{
- gchar *displayname;
+ char *displayname;
/* Return a name to use in the GUI for the basename for files to
which we save statistics */
@@ -1114,7 +1139,7 @@ cf_get_basename(capture_file *cf)
}
void
-cf_set_tempfile_source(capture_file *cf, gchar *source)
+cf_set_tempfile_source(capture_file *cf, char *source)
{
if (cf->source) {
g_free(cf->source);
@@ -1127,7 +1152,7 @@ cf_set_tempfile_source(capture_file *cf, gchar *source)
}
}
-const gchar *
+const char *
cf_get_tempfile_source(capture_file *cf)
{
if (!cf->source) {
@@ -1145,14 +1170,14 @@ cf_get_packet_count(capture_file *cf)
}
/* XXX - use a macro instead? */
-gboolean
+bool
cf_is_tempfile(capture_file *cf)
{
return cf->is_tempfile;
}
void
-cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
+cf_set_tempfile(capture_file *cf, bool is_tempfile)
{
cf->is_tempfile = is_tempfile;
}
@@ -1160,27 +1185,27 @@ cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
/* XXX - use a macro instead? */
void
-cf_set_drops_known(capture_file *cf, gboolean drops_known)
+cf_set_drops_known(capture_file *cf, bool drops_known)
{
cf->drops_known = drops_known;
}
/* XXX - use a macro instead? */
void
-cf_set_drops(capture_file *cf, guint32 drops)
+cf_set_drops(capture_file *cf, uint32_t drops)
{
cf->drops = drops;
}
/* XXX - use a macro instead? */
-gboolean
+bool
cf_get_drops_known(capture_file *cf)
{
return cf->drops_known;
}
/* XXX - use a macro instead? */
-guint32
+uint32_t
cf_get_drops(capture_file *cf)
{
return cf->drops;
@@ -1195,7 +1220,7 @@ cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
static void
add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
- wtap_rec *rec, Buffer *buf, gboolean add_to_packet_list)
+ wtap_rec *rec, Buffer *buf, bool add_to_packet_list)
{
frame_data_set_before_dissect(fdata, &cf->elapsed_time,
&cf->provider.ref, cf->provider.prev_dis);
@@ -1220,13 +1245,16 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
prime_epan_dissect_with_postdissector_wanted_hfids(edt);
}
+ /* Initialize passed_dfilter here so that dissectors can hide packets. */
+ /* XXX We might want to add a separate "visible" bit to frame_data instead. */
+ fdata->passed_dfilter = 1;
+
/* Dissect the frame. */
epan_dissect_run_with_taps(edt, cf->cd_t, rec,
frame_tvbuff_new_buffer(&cf->provider, fdata, buf),
fdata, cinfo);
- /* If we don't have a display filter, set "passed_dfilter" to 1. */
- if (dfcode != NULL) {
+ if (fdata->passed_dfilter && dfcode != NULL) {
fdata->passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
if (fdata->passed_dfilter && edt->pi.fd->dependent_frames) {
@@ -1236,8 +1264,7 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
*/
g_hash_table_foreach(edt->pi.fd->dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
}
- } else
- fdata->passed_dfilter = 1;
+ }
if (fdata->passed_dfilter || fdata->ref_time)
cf->displayed_count++;
@@ -1274,20 +1301,20 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
/*
* Read in a new record.
- * Returns TRUE if the packet was added to the packet (record) list,
- * FALSE otherwise.
+ * Returns true if the packet was added to the packet (record) list,
+ * false otherwise.
*/
-static gboolean
+static bool
read_record(capture_file *cf, wtap_rec *rec, Buffer *buf, dfilter_t *dfcode,
- epan_dissect_t *edt, column_info *cinfo, gint64 offset,
+ epan_dissect_t *edt, column_info *cinfo, int64_t offset,
fifo_string_cache_t *frame_dup_cache, GChecksum *frame_cksum)
{
frame_data fdlocal;
frame_data *fdata;
- gboolean passed = TRUE;
- gboolean added = FALSE;
- const gchar *cksum_string;
- gboolean was_in_cache;
+ bool passed = true;
+ bool added = false;
+ const char *cksum_string;
+ bool was_in_cache;
/* Add this packet's link-layer encapsulation type to cf->linktypes, if
it's not already there.
@@ -1307,7 +1334,7 @@ read_record(capture_file *cf, wtap_rec *rec, Buffer *buf, dfilter_t *dfcode,
epan_dissect_t rf_edt;
column_info *rf_cinfo = NULL;
- epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
+ epan_dissect_init(&rf_edt, cf->epan, true, false);
epan_dissect_prime_with_dfilter(&rf_edt, cf->rfcode);
if (dfilter_requires_columns(cf->rfcode)) {
rf_cinfo = &cf->cinfo;
@@ -1320,7 +1347,7 @@ read_record(capture_file *cf, wtap_rec *rec, Buffer *buf, dfilter_t *dfcode,
}
if (passed) {
- added = TRUE;
+ added = true;
/* This does a shallow copy of fdlocal, which is good enough. */
fdata = frame_data_sequence_add(cf->provider.frames, &fdlocal);
@@ -1338,8 +1365,8 @@ read_record(capture_file *cf, wtap_rec *rec, Buffer *buf, dfilter_t *dfcode,
cksum_string = g_strdup(g_checksum_get_string(frame_cksum));
was_in_cache = fifo_string_cache_insert(frame_dup_cache, cksum_string);
if (was_in_cache) {
- g_free((gpointer)cksum_string);
- fdata->ignored = TRUE;
+ g_free((void *)cksum_string);
+ fdata->ignored = true;
cf->ignored_count++;
}
}
@@ -1347,7 +1374,7 @@ read_record(capture_file *cf, wtap_rec *rec, Buffer *buf, dfilter_t *dfcode,
/* When a redissection is in progress (or queued), do not process packets.
* This will be done once all (new) packets have been scanned. */
if (!cf->redissecting && cf->redissection_queued == RESCAN_NONE) {
- add_packet_to_packet_list(fdata, cf, edt, dfcode, cinfo, rec, buf, TRUE);
+ add_packet_to_packet_list(fdata, cf, edt, dfcode, cinfo, rec, buf, true);
}
}
@@ -1356,20 +1383,20 @@ read_record(capture_file *cf, wtap_rec *rec, Buffer *buf, dfilter_t *dfcode,
typedef struct _callback_data_t {
- gpointer pd_window;
- gint64 f_len;
+ void * pd_window;
+ int64_t f_len;
progdlg_t *progbar;
GTimer *prog_timer;
- gboolean stop_flag;
+ bool stop_flag;
} callback_data_t;
-static gboolean
+static bool
merge_callback(merge_event event, int num _U_,
- const merge_in_file_t in_files[], const guint in_file_count,
+ const merge_in_file_t in_files[], const unsigned in_file_count,
void *data)
{
- guint i;
+ unsigned i;
callback_data_t *cb_data = (callback_data_t*) data;
ws_assert(cb_data != NULL);
@@ -1402,7 +1429,7 @@ merge_callback(merge_event event, int num _U_,
time in order to get to the next progress bar step). */
if (cb_data->progbar == NULL) {
cb_data->progbar = delayed_create_progress_dlg(cb_data->pd_window, NULL, NULL,
- FALSE, &cb_data->stop_flag, 0.0f);
+ false, &cb_data->stop_flag, 0.0f);
}
/*
@@ -1414,12 +1441,12 @@ merge_callback(merge_event event, int num _U_,
*/
if (g_timer_elapsed(cb_data->prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
float progbar_val;
- gint64 file_pos = 0;
+ int64_t 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;
+ progbar_val = (float) file_pos / (float) 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
@@ -1428,7 +1455,7 @@ merge_callback(merge_event event, int num _U_,
}
if (cb_data->progbar != NULL) {
- gchar status_str[100];
+ char status_str[100];
snprintf(status_str, sizeof(status_str),
"%" PRId64 "KB of %" PRId64 "KB",
file_pos / 1024, cb_data->f_len / 1024);
@@ -1453,15 +1480,11 @@ merge_callback(merge_event event, int num _U_,
cf_status_t
-cf_merge_files_to_tempfile(gpointer pd_window, const char *temp_dir, char **out_filenamep,
+cf_merge_files_to_tempfile(void *pd_window, const char *temp_dir, char **out_filenamep,
int in_file_count, const char *const *in_filenames,
- int file_type, gboolean do_append)
+ int file_type, bool do_append)
{
- int err = 0;
- gchar *err_info = NULL;
- guint err_fileno;
- guint32 err_framenum;
- merge_result status;
+ bool status;
merge_progress_callback_t cb;
callback_data_t *cb_data = g_new0(callback_data_t, 1);
@@ -1477,65 +1500,23 @@ cf_merge_files_to_tempfile(gpointer pd_window, const char *temp_dir, char **out_
in_filenames,
in_file_count, do_append,
IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */,
- "Wireshark", &cb, &err, &err_info,
- &err_fileno, &err_framenum);
+ "Wireshark", &cb);
g_free(cb.data);
- switch (status) {
- case MERGE_OK:
- break;
-
- case MERGE_USER_ABORTED:
- /* this isn't really an error, though we will return CF_ERROR later */
- break;
-
- case MERGE_ERR_CANT_OPEN_INFILE:
- cfile_open_failure_alert_box(in_filenames[err_fileno], err, err_info);
- break;
-
- case MERGE_ERR_CANT_OPEN_OUTFILE:
- cfile_dump_open_failure_alert_box(*out_filenamep, err, err_info,
- file_type);
- break;
-
- case MERGE_ERR_CANT_READ_INFILE:
- cfile_read_failure_alert_box(in_filenames[err_fileno], err, err_info);
- break;
-
- case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
- simple_error_message_box("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.",
- err_framenum, in_filenames[err_fileno]);
- break;
-
- case MERGE_ERR_CANT_WRITE_OUTFILE:
- cfile_write_failure_alert_box(in_filenames[err_fileno],
- *out_filenamep, err, err_info,
- err_framenum, file_type);
- break;
-
- case MERGE_ERR_CANT_CLOSE_OUTFILE:
- cfile_close_failure_alert_box(*out_filenamep, err, err_info);
- break;
-
- default:
- simple_error_message_box("Unknown merge_files error %d", status);
- break;
- }
-
cf_callback_invoke(cf_cb_file_merge_finished, NULL);
- if (status != MERGE_OK) {
+ if (!status) {
/* 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. */
+ differently - the merge code puts up error dialogs itself, so
+ they don't have to. */
return CF_ERROR;
} else
return CF_OK;
}
cf_status_t
-cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
+cf_filter_packets(capture_file *cf, char *dftext, bool force)
{
const char *filter_new = dftext ? dftext : "";
const char *filter_old = cf->dfilter ? cf->dfilter : "";
@@ -1543,6 +1524,9 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
df_error_t *df_err;
/* if new filter equals old one, do nothing unless told to do so */
+ /* XXX - The text can be the same without compiling to the same code.
+ * (Macros, field references, etc.)
+ */
if (!force && strcmp(filter_new, filter_old) == 0) {
return CF_OK;
}
@@ -1582,6 +1566,12 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
g_free(cf->dfilter);
cf->dfilter = dftext;
+ /* We'll recompile this when the rescan starts, or in cf_read()
+ * if no file is open currently. However, if no file is open and
+ * we start a new capture, we want to use this rather than
+ * recompiling in cf_continue_tail() */
+ dfilter_free(cf->dfcode);
+ cf->dfcode = dfcode;
/* Now rescan the packet list, applying the new filter, but not
* throwing away information constructed on a previous pass.
@@ -1592,16 +1582,13 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
cf->redissection_queued = RESCAN_SCAN;
} else if (cf->state != FILE_CLOSED) {
if (dftext == NULL) {
- rescan_packets(cf, "Resetting", "filter", FALSE);
+ rescan_packets(cf, "Resetting", "filter", false);
} else {
- rescan_packets(cf, "Filtering", dftext, FALSE);
+ rescan_packets(cf, "Filtering", dftext, false);
}
}
}
- /* Cleanup and release all dfilter resources */
- dfilter_free(dfcode);
-
return CF_OK;
}
@@ -1618,44 +1605,48 @@ cf_redissect_packets(capture_file *cf)
}
if (cf->redissection_queued != RESCAN_NONE) {
/* Redissection is (already) queued, wait for "cf_read" to finish. */
+ /* XXX - what if whatever set and later clears read_lock is *not*
+ * cf_read, e.g. process_specified_records ? We need to handle a
+ * queued redissection there too like we do in cf_read.
+ */
return;
}
if (cf->state != FILE_CLOSED) {
/* Restart dissection in case no cf_read is pending. */
- rescan_packets(cf, "Reprocessing", "all packets", TRUE);
+ rescan_packets(cf, "Reprocessing", "all packets", true);
}
}
-gboolean
+bool
cf_read_record(capture_file *cf, const frame_data *fdata,
wtap_rec *rec, Buffer *buf)
{
int err;
- gchar *err_info;
+ char *err_info;
if (!wtap_seek_read(cf->provider.wth, fdata->file_off, rec, buf, &err, &err_info)) {
cfile_read_failure_alert_box(cf->filename, err, err_info);
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
-gboolean
+bool
cf_read_record_no_alert(capture_file *cf, const frame_data *fdata,
wtap_rec *rec, Buffer *buf)
{
int err;
- gchar *err_info;
+ char *err_info;
if (!wtap_seek_read(cf->provider.wth, fdata->file_off, rec, buf, &err, &err_info)) {
g_free(err_info);
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
-gboolean
+bool
cf_read_current_record(capture_file *cf)
{
return cf_read_record(cf, cf->current_frame, &cf->rec, &cf->buf);
@@ -1669,15 +1660,15 @@ cf_read_current_record(capture_file *cf)
"action_item" describes what we're doing; it's used in the progress
dialog box.
- "redissect" is TRUE if we need to make the dissectors reconstruct
+ "redissect" is true if we need to make the dissectors reconstruct
any state information they have (because a preference that affects
some dissector has changed, meaning some dissector might construct
its state differently from the way it was constructed the last time). */
static void
-rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
+rescan_packets(capture_file *cf, const char *action, const char *action_item, bool redissect)
{
/* Rescan packets new packet list */
- guint32 framenum;
+ uint32_t framenum;
frame_data *fdata;
wtap_rec rec;
Buffer buf;
@@ -1686,20 +1677,20 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
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;
- gboolean selected_frame_seen;
+ bool selected_frame_seen;
float progbar_val;
- gint64 start_time;
- gchar status_str[100];
+ int64_t start_time;
+ char status_str[100];
epan_dissect_t edt;
dfilter_t *dfcode = NULL;
column_info *cinfo;
- gboolean create_proto_tree;
- gboolean filtering_tap_listeners = FALSE;
- guint tap_flags;
- gboolean add_to_packet_list = FALSE;
- gboolean compiled _U_;
- guint32 frames_count;
- gboolean queued_rescan_type = RESCAN_NONE;
+ bool create_proto_tree;
+ bool filtering_tap_listeners = false;
+ unsigned tap_flags;
+ bool add_to_packet_list = false;
+ bool compiled _U_;
+ uint32_t frames_count;
+ rescan_type queued_rescan_type = RESCAN_NONE;
if (cf->state == FILE_CLOSED || cf->state == FILE_READ_PENDING) {
return;
@@ -1708,35 +1699,46 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
/* Rescan in progress, clear pending actions. */
cf->redissection_queued = RESCAN_NONE;
ws_assert(!cf->read_lock);
- cf->read_lock = TRUE;
+ cf->read_lock = true;
wtap_rec_init(&rec);
ws_buffer_init(&buf, 1514);
/* Compile the current display filter.
+ * The code it compiles to might have changed, e.g. if a display
+ * filter macro used has changed.
+ *
* We assume this will not fail since cf->dfilter is only set in
* cf_filter IFF the filter was valid.
+ * XXX - This is not necessarily true, if the filter has a FT_IPv4
+ * or FT_IPv6 field compared to a resolved hostname in it, because
+ * we do a new host lookup, and that *could* timeout this time
+ * (though with the read lock above we shouldn't have many lookups at
+ * once, reducing the chances of that)... (#19612)
*/
if (cf->dfilter) {
compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
ws_assert(compiled && dfcode);
}
+ dfilter_free(cf->dfcode);
+ cf->dfcode = dfcode;
+
/* Do we have any tap listeners with filters? */
filtering_tap_listeners = have_filtering_tap_listeners();
/* Update references in filters (if any) for the protocol
* tree corresponding to the currently selected frame in the GUI. */
if (cf->edt != NULL && cf->edt->tree != NULL) {
- if (dfcode)
- dfilter_load_field_references(dfcode, cf->edt->tree);
+ if (cf->dfcode)
+ dfilter_load_field_references(cf->dfcode, cf->edt->tree);
if (filtering_tap_listeners)
tap_listeners_load_field_references(cf->edt);
}
- if (dfcode != NULL) {
+ if (cf->dfcode != NULL) {
dfilter_log_full(LOG_DOMAIN_DFILTER, LOG_LEVEL_NOISY, NULL, -1, NULL,
- dfcode, "Rescanning packets with display filter");
+ cf->dfcode, "Rescanning packets with display filter");
}
/* Get the union of the flags for all tap listeners. */
@@ -1745,7 +1747,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
/* If the display filter or any tap listeners require the columns,
* construct them. */
cinfo = (tap_listeners_require_columns() ||
- dfilter_requires_columns(dfcode)) ? &cf->cinfo : NULL;
+ dfilter_requires_columns(cf->dfcode)) ? &cf->cinfo : NULL;
/*
* Determine whether we need to create a protocol tree.
@@ -1761,7 +1763,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
* values or protocols on the first pass.
*/
create_proto_tree =
- (dfcode != NULL || filtering_tap_listeners ||
+ (cf->dfcode != NULL || filtering_tap_listeners ||
(tap_flags & TL_REQUIRES_PROTO_TREE) ||
(redissect && postdissectors_want_hfids()));
@@ -1787,7 +1789,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
/* We might receive new packets while redissecting, and we don't
want to dissect those before their time. */
- cf->redissecting = TRUE;
+ cf->redissecting = true;
/* 'reset' dissection session */
epan_free(cf->epan);
@@ -1803,7 +1805,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
/* A new Lua tap listener may be registered in lua_prime_all_fields()
called via epan_new() / init_dissection() when reloading Lua plugins. */
if (!create_proto_tree && have_filtering_tap_listeners()) {
- create_proto_tree = TRUE;
+ create_proto_tree = true;
}
if (!cinfo && tap_listeners_require_columns()) {
cinfo = &cf->cinfo;
@@ -1812,7 +1814,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
/* We need to redissect the packets so we have to discard our old
* packet list store. */
packet_list_clear();
- add_to_packet_list = TRUE;
+ add_to_packet_list = true;
}
/* We don't yet know which will be the first and last frames displayed. */
@@ -1838,7 +1840,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
/* Progress so far. */
progbar_val = 0.0f;
- cf->stop_flag = FALSE;
+ cf->stop_flag = false;
start_time = g_get_monotonic_time();
/* no previous row yet */
@@ -1850,11 +1852,11 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
following_frame_num = -1;
following_frame = NULL;
- selected_frame_seen = FALSE;
+ selected_frame_seen = false;
frames_count = cf->count;
- epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
+ epan_dissect_init(&edt, cf->epan, create_proto_tree, false);
if (redissect) {
/*
@@ -1880,7 +1882,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
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(cf->window, action, action_item, TRUE,
+ progbar = delayed_create_progress_dlg(cf->window, action, action_item, true,
&cf->stop_flag,
progbar_val);
@@ -1895,7 +1897,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
* with count == 0, so let's assert that
*/
ws_assert(cf->count > 0);
- progbar_val = (gfloat) count / frames_count;
+ progbar_val = (float) count / frames_count;
if (progbar != NULL) {
snprintf(status_str, sizeof(status_str),
@@ -1954,7 +1956,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
preceding_frame = prev_frame;
}
- add_packet_to_packet_list(fdata, cf, &edt, dfcode,
+ add_packet_to_packet_list(fdata, cf, &edt, cf->dfcode,
cinfo, &rec, &buf,
add_to_packet_list);
@@ -1967,7 +1969,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
following_frame = fdata;
}
if (fdata == selected_frame) {
- selected_frame_seen = TRUE;
+ selected_frame_seen = true;
if (fdata->passed_dfilter)
selected_frame_num = fdata->num;
}
@@ -1984,7 +1986,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
ws_buffer_free(&buf);
/* We are done redissecting the packet list. */
- cf->redissecting = FALSE;
+ cf->redissecting = false;
if (redissect) {
frames_count = cf->count;
@@ -2020,7 +2022,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
/* It is safe again to execute redissections or sort. */
ws_assert(cf->read_lock);
- cf->read_lock = FALSE;
+ cf->read_lock = false;
cf_callback_invoke(cf_cb_file_rescan_finished, cf);
@@ -2082,9 +2084,6 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
}
}
- /* Cleanup and release all dfilter resources */
- dfilter_free(dfcode);
-
/* If another rescan (due to dfilter change) or redissection (due to profile
* change) was requested, the rescan above is aborted and restarted here. */
if (queued_rescan_type != RESCAN_NONE) {
@@ -2102,7 +2101,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb
void
cf_reftime_packets(capture_file* cf)
{
- guint32 framenum;
+ uint32_t framenum;
frame_data *fdata;
nstime_t rel_ts;
@@ -2138,8 +2137,8 @@ cf_reftime_packets(capture_file* cf)
/* If it's greater than the current elapsed time, set the elapsed
time to it (we check for "greater than" so as not to be
confused by time moving backwards). */
- if ((gint32)cf->elapsed_time.secs < rel_ts.secs
- || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
+ if ((int32_t)cf->elapsed_time.secs < rel_ts.secs
+ || ((int32_t)cf->elapsed_time.secs == rel_ts.secs && (int32_t)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
cf->elapsed_time = rel_ts;
}
@@ -2199,13 +2198,13 @@ typedef enum {
static psp_return_t
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 *,
+ const char *string1, const char *string2, bool terminate_is_stop,
+ bool (*callback)(capture_file *, frame_data *,
wtap_rec *, Buffer *, void *),
void *callback_args,
- gboolean show_progress_bar)
+ bool show_progress_bar)
{
- guint32 framenum;
+ uint32_t framenum;
frame_data *fdata;
wtap_rec rec;
Buffer buf;
@@ -2215,7 +2214,7 @@ process_specified_records(capture_file *cf, packet_range_t *range,
GTimer *prog_timer = g_timer_new();
int progbar_count;
float progbar_val;
- gchar progbar_status_str[100];
+ char progbar_status_str[100];
range_process_e process_this;
wtap_rec_init(&rec);
@@ -2227,13 +2226,21 @@ process_specified_records(capture_file *cf, packet_range_t *range,
/* Progress so far. */
progbar_val = 0.0f;
+ /* XXX - It should be ok to have multiple readers, so long as nothing
+ * frees the epan context, e.g. rescan_packets with redissect true,
+ * or anything that closes the file (including reload and certain forms
+ * of saving.) This is mostly to stop cf_save_records but should probably
+ * be handled by callers in order to allow multiple readers (e.g.,
+ * restarting taps after adding or changing one.) We should probably
+ * make this a real reader-writer lock.
+ */
if (cf->read_lock) {
ws_warning("Failing due to nested process_specified_records(\"%s\") call!", cf->filename);
return PSP_FAILED;
}
- cf->read_lock = TRUE;
+ cf->read_lock = true;
- cf->stop_flag = FALSE;
+ cf->stop_flag = false;
if (range != NULL)
packet_range_process_init(range);
@@ -2265,7 +2272,7 @@ process_specified_records(capture_file *cf, packet_range_t *range,
* with count == 0, so let's assert that
*/
ws_assert(cf->count > 0);
- progbar_val = (gfloat) progbar_count / cf->count;
+ progbar_val = (float) progbar_count / cf->count;
snprintf(progbar_status_str, sizeof(progbar_status_str),
"%4u of %u packets", progbar_count, cf->count);
@@ -2318,7 +2325,7 @@ process_specified_records(capture_file *cf, packet_range_t *range,
g_timer_destroy(prog_timer);
ws_assert(cf->read_lock);
- cf->read_lock = FALSE;
+ cf->read_lock = false;
wtap_rec_cleanup(&rec);
ws_buffer_free(&buf);
@@ -2331,7 +2338,7 @@ typedef struct {
column_info *cinfo;
} retap_callback_args_t;
-static gboolean
+static bool
retap_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, Buffer *buf,
void *argsp)
{
@@ -2342,7 +2349,7 @@ retap_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, Buffer *buf,
fdata, args->cinfo);
epan_dissect_reset(&args->edt);
- return TRUE;
+ return true;
}
cf_read_status_t
@@ -2350,9 +2357,9 @@ cf_retap_packets(capture_file *cf)
{
packet_range_t range;
retap_callback_args_t callback_args;
- gboolean create_proto_tree;
- gboolean filtering_tap_listeners;
- guint tap_flags;
+ bool create_proto_tree;
+ bool filtering_tap_listeners;
+ unsigned tap_flags;
psp_return_t ret;
/* Presumably the user closed the capture file. */
@@ -2360,6 +2367,15 @@ cf_retap_packets(capture_file *cf)
return CF_READ_ABORTED;
}
+ /* XXX - If cf->read_lock is true, process_specified_records will fail
+ * due to a nested call. We fail here so that we don't reset the tap
+ * listeners if this tap isn't going to succeed.
+ */
+ if (cf->read_lock) {
+ ws_warning("Failing due to nested process_specified_records(\"%s\") call!", cf->filename);
+ return CF_READ_ERROR;
+ }
+
cf_callback_invoke(cf_cb_file_retap_started, cf);
/* Do we have any tap listeners with filters? */
@@ -2367,6 +2383,11 @@ cf_retap_packets(capture_file *cf)
/* Update references in filters (if any) for the protocol
* tree corresponding to the currently selected frame in the GUI. */
+ /* XXX - What if we *don't* have a currently selected frame in the GUI,
+ * but we did the last time we loaded field references? Then they'll
+ * match something instead of nothing (unless they've been recompiled).
+ * Should we have a way to clear the field references even with a NULL tree?
+ */
if (cf->edt != NULL && cf->edt->tree != NULL) {
if (filtering_tap_listeners)
tap_listeners_load_field_references(cf->edt);
@@ -2391,17 +2412,46 @@ cf_retap_packets(capture_file *cf)
/* Reset the tap listeners. */
reset_tap_listeners();
+ uint32_t count = cf->count;
- epan_dissect_init(&callback_args.edt, cf->epan, create_proto_tree, FALSE);
+ epan_dissect_init(&callback_args.edt, cf->epan, create_proto_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);
+ if (cf->state == FILE_READ_IN_PROGRESS) {
+ /* We're not done with the sequential read of the file and might
+ * add more frames while process_specified_records is going. We
+ * don't want to tap new frames twice, so limit the range to the
+ * frames already here.
+ *
+ * cf_read sets read_lock so we don't tap in case of an offline
+ * file, but cf_continue_tail and cf_finish_tail don't, and we
+ * don't want them to, because tapping new packets in a live
+ * capture is a common use case.
+ *
+ * Note that most other users of process_specified_records (saving,
+ * printing) do want to process new packets, unlike taps.
+ */
+ if (count) {
+ char* range_str = g_strdup_printf("-%u", count);
+ packet_range_convert_str(&range, range_str);
+ g_free(range_str);
+ } else {
+ /* range_t treats a missing number as meaning 1, not 0, and
+ * reverses the order if backwards; thus the syntax -0 means
+ * 0-1, so to only take zero packets we do this.
+ */
+ packet_range_convert_str(&range, "0");
+ }
+ range.process = range_process_user_range;
+ }
+
ret = process_specified_records(cf, &range, "Recalculating statistics on",
- "all packets", TRUE, retap_packet,
- &callback_args, TRUE);
+ "all packets", true, retap_packet,
+ &callback_args, true);
packet_range_cleanup(&range);
epan_dissect_cleanup(&callback_args.edt);
@@ -2429,20 +2479,20 @@ cf_retap_packets(capture_file *cf)
typedef struct {
print_args_t *print_args;
- gboolean print_header_line;
+ bool print_header_line;
char *header_line_buf;
int header_line_buf_len;
- gboolean print_formfeed;
- gboolean print_separator;
+ bool print_formfeed;
+ bool print_separator;
char *line_buf;
int line_buf_len;
- gint *col_widths;
+ int *col_widths;
int num_visible_cols;
- gint *visible_cols;
+ int *visible_cols;
epan_dissect_t edt;
} print_callback_args_t;
-static gboolean
+static bool
print_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, Buffer *buf,
void *argsp)
{
@@ -2455,7 +2505,7 @@ print_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, Buffer *buf,
char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
col_item_t* col_item;
- const gchar* col_text;
+ const char* col_text;
/* Fill in the column information if we're printing the summary
information. */
@@ -2464,7 +2514,7 @@ print_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, Buffer *buf,
epan_dissect_run(&args->edt, cf->cd_t, rec,
frame_tvbuff_new_buffer(&cf->provider, fdata, buf),
fdata, &cf->cinfo);
- epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
+ epan_dissect_fill_in_columns(&args->edt, false, true);
} else
epan_dissect_run(&args->edt, cf->cd_t, rec,
frame_tvbuff_new_buffer(&cf->provider, fdata, buf),
@@ -2479,7 +2529,7 @@ print_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, Buffer *buf,
* new page.
*/
if (args->print_args->print_col_headings)
- args->print_header_line = TRUE;
+ args->print_header_line = true;
} else {
if (args->print_separator) {
if (!print_line(args->print_args->stream, 0, ""))
@@ -2495,11 +2545,11 @@ print_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, Buffer *buf,
if (args->print_args->print_summary) {
if (!args->print_args->print_col_headings)
- args->print_header_line = FALSE;
+ args->print_header_line = false;
if (args->print_header_line) {
if (!print_line(args->print_args->stream, 0, args->header_line_buf))
goto fail;
- args->print_header_line = FALSE; /* we might not need to print any more */
+ args->print_header_line = false; /* we might not need to print any more */
}
cp = &args->line_buf[0];
line_len = 0;
@@ -2566,11 +2616,11 @@ print_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, Buffer *buf,
goto fail;
/* Print a blank line if we print anything after this (aka more than one packet). */
- args->print_separator = TRUE;
+ args->print_separator = true;
/* Print a header line if we print any more packet summaries */
if (args->print_args->print_col_headings)
- args->print_header_line = TRUE;
+ args->print_header_line = true;
}
if (args->print_args->print_hex) {
@@ -2583,47 +2633,47 @@ print_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, Buffer *buf,
goto fail;
/* Print a blank line if we print anything after this (aka more than one packet). */
- args->print_separator = TRUE;
+ args->print_separator = true;
/* Print a header line if we print any more packet summaries */
if (args->print_args->print_col_headings)
- args->print_header_line = TRUE;
+ args->print_header_line = true;
} /* if (args->print_args->print_dissections != print_dissections_none) */
epan_dissect_reset(&args->edt);
/* do we want to have a formfeed between each packet from now on? */
if (args->print_args->print_formfeed) {
- args->print_formfeed = TRUE;
+ args->print_formfeed = true;
}
- return TRUE;
+ return true;
fail:
epan_dissect_reset(&args->edt);
- return FALSE;
+ return false;
}
cf_print_status_t
cf_print_packets(capture_file *cf, print_args_t *print_args,
- gboolean show_progress_bar)
+ bool show_progress_bar)
{
print_callback_args_t callback_args;
- gint data_width;
+ int data_width;
char *cp;
int i, cp_off, column_len, line_len;
int num_visible_col = 0, last_visible_col = 0, visible_col_count;
psp_return_t ret;
GList *clp;
fmt_data *cfmt;
- gboolean proto_tree_needed;
+ bool proto_tree_needed;
callback_args.print_args = print_args;
callback_args.print_header_line = print_args->print_col_headings;
callback_args.header_line_buf = NULL;
callback_args.header_line_buf_len = 256;
- callback_args.print_formfeed = FALSE;
- callback_args.print_separator = FALSE;
+ callback_args.print_formfeed = false;
+ callback_args.print_separator = false;
callback_args.line_buf = NULL;
callback_args.line_buf_len = 256;
callback_args.col_widths = NULL;
@@ -2664,8 +2714,8 @@ cf_print_packets(capture_file *cf, print_args_t *print_args,
width of the title and the width of the data - and construct
a buffer with a line containing the column titles. */
callback_args.num_visible_cols = num_visible_col;
- callback_args.col_widths = g_new(gint, num_visible_col);
- callback_args.visible_cols = g_new(gint, num_visible_col);
+ callback_args.col_widths = g_new(int, num_visible_col);
+ callback_args.visible_cols = g_new(int, num_visible_col);
cp = &callback_args.header_line_buf[0];
line_len = 0;
visible_col_count = 0;
@@ -2676,7 +2726,7 @@ cf_print_packets(capture_file *cf, print_args_t *print_args,
continue;
cfmt = (fmt_data *) clp->data;
- if (cfmt->visible == FALSE)
+ if (cfmt->visible == false)
continue;
/* Save the order of visible columns */
@@ -2686,7 +2736,7 @@ cf_print_packets(capture_file *cf, print_args_t *print_args,
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.columns[i].col_title);
+ callback_args.col_widths[visible_col_count] = (int) 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;
@@ -2739,7 +2789,7 @@ cf_print_packets(capture_file *cf, print_args_t *print_args,
/* Iterate through the list of packets, printing the packets we were
told to print. */
ret = process_specified_records(cf, &print_args->range, "Printing",
- "selected packets", TRUE, print_packet,
+ "selected packets", true, print_packet,
&callback_args, show_progress_bar);
epan_dissect_cleanup(&callback_args.edt);
g_free(callback_args.header_line_buf);
@@ -2791,7 +2841,7 @@ typedef struct {
json_dumper jdumper;
} write_packet_callback_args_t;
-static gboolean
+static bool
write_pdml_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
Buffer *buf, void *argsp)
{
@@ -2803,7 +2853,7 @@ write_pdml_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
fdata, NULL);
/* Write out the information in that tree. */
- write_pdml_proto_tree(NULL, &args->edt, &cf->cinfo, args->fh, FALSE);
+ write_pdml_proto_tree(NULL, &args->edt, &cf->cinfo, args->fh, false);
epan_dissect_reset(&args->edt);
@@ -2829,13 +2879,13 @@ cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
callback_args.fh = fh;
callback_args.print_args = print_args;
- epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
+ 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_records(cf, &print_args->range, "Writing PDML",
- "selected packets", TRUE,
- write_pdml_packet, &callback_args, TRUE);
+ "selected packets", true,
+ write_pdml_packet, &callback_args, true);
epan_dissect_cleanup(&callback_args.edt);
@@ -2867,7 +2917,7 @@ cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
return CF_PRINT_OK;
}
-static gboolean
+static bool
write_psml_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
Buffer *buf, void *argsp)
{
@@ -2878,10 +2928,10 @@ write_psml_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
epan_dissect_run(&args->edt, cf->cd_t, rec,
frame_tvbuff_new_buffer(&cf->provider, fdata, buf),
fdata, &cf->cinfo);
- epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
+ epan_dissect_fill_in_columns(&args->edt, false, true);
/* Write out the column information. */
- write_psml_columns(&args->edt, args->fh, FALSE);
+ write_psml_columns(&args->edt, args->fh, false);
epan_dissect_reset(&args->edt);
@@ -2895,7 +2945,7 @@ cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
FILE *fh;
psp_return_t ret;
- gboolean proto_tree_needed;
+ bool proto_tree_needed;
fh = ws_fopen(print_args->file, "w");
if (fh == NULL)
@@ -2918,8 +2968,8 @@ cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
/* Iterate through the list of packets, printing the packets we were
told to print. */
ret = process_specified_records(cf, &print_args->range, "Writing PSML",
- "selected packets", TRUE,
- write_psml_packet, &callback_args, TRUE);
+ "selected packets", true,
+ write_psml_packet, &callback_args, true);
epan_dissect_cleanup(&callback_args.edt);
@@ -2951,7 +3001,7 @@ cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
return CF_PRINT_OK;
}
-static gboolean
+static bool
write_csv_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
Buffer *buf, void *argsp)
{
@@ -2962,7 +3012,7 @@ write_csv_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
epan_dissect_run(&args->edt, cf->cd_t, rec,
frame_tvbuff_new_buffer(&cf->provider, fdata, buf),
fdata, &cf->cinfo);
- epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
+ epan_dissect_fill_in_columns(&args->edt, false, true);
/* Write out the column information. */
write_csv_columns(&args->edt, args->fh);
@@ -2976,7 +3026,7 @@ 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;
+ bool proto_tree_needed;
FILE *fh;
psp_return_t ret;
@@ -3000,8 +3050,8 @@ cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
/* Iterate through the list of packets, printing the packets we were
told to print. */
ret = process_specified_records(cf, &print_args->range, "Writing CSV",
- "selected packets", TRUE,
- write_csv_packet, &callback_args, TRUE);
+ "selected packets", true,
+ write_csv_packet, &callback_args, true);
epan_dissect_cleanup(&callback_args.edt);
@@ -3027,7 +3077,7 @@ cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
return CF_PRINT_OK;
}
-static gboolean
+static bool
carrays_write_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
Buffer *buf, void *argsp)
{
@@ -3061,14 +3111,14 @@ cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
callback_args.fh = fh;
callback_args.print_args = print_args;
- epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
+ 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_records(cf, &print_args->range,
"Writing C Arrays",
- "selected packets", TRUE,
- carrays_write_packet, &callback_args, TRUE);
+ "selected packets", true,
+ carrays_write_packet, &callback_args, true);
epan_dissect_cleanup(&callback_args.edt);
@@ -3089,7 +3139,7 @@ cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
return CF_PRINT_OK;
}
-static gboolean
+static bool
write_json_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
Buffer *buf, void *argsp)
{
@@ -3130,13 +3180,13 @@ cf_write_json_packets(capture_file *cf, print_args_t *print_args)
callback_args.fh = fh;
callback_args.print_args = print_args;
- epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
+ 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_records(cf, &print_args->range, "Writing JSON",
- "selected packets", TRUE,
- write_json_packet, &callback_args, TRUE);
+ "selected packets", true,
+ write_json_packet, &callback_args, true);
epan_dissect_cleanup(&callback_args.edt);
@@ -3168,14 +3218,29 @@ cf_write_json_packets(capture_file *cf, print_args_t *print_args)
return CF_PRINT_OK;
}
-gboolean
+bool
cf_find_packet_protocol_tree(capture_file *cf, const char *string,
- search_direction dir)
+ search_direction dir, bool multiple)
{
match_data mdata;
+ mdata.frame_matched = false;
+ mdata.halt = false;
mdata.string = string;
mdata.string_len = strlen(string);
+ mdata.cf = cf;
+ mdata.prev_finfo = cf->finfo_selected;
+ if (multiple && cf->finfo_selected && cf->edt) {
+ if (dir == SD_FORWARD) {
+ proto_tree_children_foreach(cf->edt->tree, match_subtree_text, &mdata);
+ } else {
+ proto_tree_children_foreach(cf->edt->tree, match_subtree_text_reverse, &mdata);
+ }
+ if (mdata.frame_matched) {
+ packet_list_select_finfo(mdata.finfo);
+ return true;
+ }
+ }
return find_packet(cf, match_protocol_tree, &mdata, dir);
}
@@ -3183,12 +3248,18 @@ field_info*
cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree)
{
match_data mdata;
- mdata.frame_matched = FALSE;
+ mdata.frame_matched = false;
+ mdata.halt = false;
mdata.string = convert_string_case(cf->sfilter, cf->case_type);
mdata.string_len = strlen(mdata.string);
mdata.cf = cf;
+ mdata.prev_finfo = NULL;
/* Iterate through all the nodes looking for matching text */
- proto_tree_children_foreach(tree, match_subtree_text, &mdata);
+ if (cf->dir == SD_FORWARD) {
+ proto_tree_children_foreach(tree, match_subtree_text, &mdata);
+ } else {
+ proto_tree_children_foreach(tree, match_subtree_text_reverse, &mdata);
+ }
g_free((char *)mdata.string);
return mdata.frame_matched ? mdata.finfo : NULL;
}
@@ -3207,7 +3278,7 @@ match_protocol_tree(capture_file *cf, frame_data *fdata,
}
/* Construct the protocol tree, including the displayed text */
- epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
+ epan_dissect_init(&edt, cf->epan, true, true);
/* We don't need the column information */
epan_dissect_run(&edt, cf->cd_t, rec,
frame_tvbuff_new_buffer(&cf->provider, fdata, buf),
@@ -3215,25 +3286,31 @@ match_protocol_tree(capture_file *cf, frame_data *fdata,
/* Iterate through all the nodes, seeing if they have text that matches. */
mdata->cf = cf;
- mdata->frame_matched = FALSE;
+ mdata->frame_matched = false;
+ mdata->halt = false;
+ mdata->prev_finfo = NULL;
+ /* We don't care about the direction here, because we're just looking
+ * for one match and we'll destroy this tree anyway. (We find the actual
+ * field later in PacketList::selectionChanged().) Forwards is faster.
+ */
proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
epan_dissect_cleanup(&edt);
return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
}
static void
-match_subtree_text(proto_node *node, gpointer data)
+match_subtree_text(proto_node *node, void *data)
{
match_data *mdata = (match_data *) data;
- const gchar *string = mdata->string;
+ const char *string = mdata->string;
size_t string_len = mdata->string_len;
capture_file *cf = mdata->cf;
field_info *fi = PNODE_FINFO(node);
- gchar label_str[ITEM_LABEL_LENGTH];
- gchar *label_ptr;
+ char label_str[ITEM_LABEL_LENGTH];
+ char *label_ptr;
size_t label_len;
- guint32 i, i_restart;
- guint8 c_char;
+ uint32_t i, i_restart;
+ uint8_t c_char;
size_t c_match = 0;
/* dissection with an invisible proto tree? */
@@ -3248,6 +3325,107 @@ match_subtree_text(proto_node *node, gpointer data)
if (proto_item_is_hidden(node))
return;
+ if (mdata->prev_finfo) {
+ /* Haven't found the old match, so don't match this node. */
+ if (fi == mdata->prev_finfo) {
+ /* Found the old match, look for the next one after this. */
+ mdata->prev_finfo = NULL;
+ }
+ } else {
+ /* was a free format label produced? */
+ if (fi->rep) {
+ label_ptr = fi->rep->representation;
+ } else {
+ /* no, make a generic label */
+ label_ptr = label_str;
+ proto_item_fill_label(fi, label_str);
+ }
+
+ if (cf->regex) {
+ if (ws_regex_matches(cf->regex, label_ptr)) {
+ mdata->frame_matched = true;
+ mdata->finfo = fi;
+ return;
+ }
+ } else if (cf->case_type) {
+ /* Case insensitive match */
+ label_len = strlen(label_ptr);
+ i_restart = 0;
+ for (i = 0; i < label_len; i++) {
+ if (i_restart == 0 && c_match == 0 && (label_len - i < string_len))
+ break;
+ c_char = label_ptr[i];
+ c_char = g_ascii_toupper(c_char);
+ /* If c_match is non-zero, save candidate for retrying full match. */
+ if (c_match > 0 && i_restart == 0 && c_char == string[0])
+ i_restart = i;
+ if (c_char == string[c_match]) {
+ c_match++;
+ if (c_match == string_len) {
+ mdata->frame_matched = true;
+ mdata->finfo = fi;
+ /* No need to look further; we have a match */
+ return;
+ }
+ } else if (i_restart) {
+ i = i_restart;
+ c_match = 1;
+ i_restart = 0;
+ } else
+ c_match = 0;
+ }
+ } else if (strstr(label_ptr, string) != NULL) {
+ /* Case sensitive match */
+ mdata->frame_matched = true;
+ mdata->finfo = fi;
+ return;
+ }
+ }
+
+ /* Recurse into the subtree, if it exists */
+ if (node->first_child != NULL)
+ proto_tree_children_foreach(node, match_subtree_text, mdata);
+}
+
+static void
+match_subtree_text_reverse(proto_node *node, void *data)
+{
+ match_data *mdata = (match_data *) data;
+ const char *string = mdata->string;
+ size_t string_len = mdata->string_len;
+ capture_file *cf = mdata->cf;
+ field_info *fi = PNODE_FINFO(node);
+ char label_str[ITEM_LABEL_LENGTH];
+ char *label_ptr;
+ size_t label_len;
+ uint32_t i, i_restart;
+ uint8_t c_char;
+ size_t c_match = 0;
+
+ /* dissection with an invisible proto tree? */
+ ws_assert(fi);
+
+ /* We don't have an easy way to search backwards in the tree
+ * (see also, proto_find_field_from_offset()) because we don't
+ * have a previous node pointer, so we search backwards by
+ * searching forwards, only stopping if we see the old match
+ * (if we have one).
+ */
+
+ if (mdata->halt) {
+ return;
+ }
+
+ /* Don't match invisible entries. */
+ if (proto_item_is_hidden(node))
+ return;
+
+ if (mdata->prev_finfo && fi == mdata->prev_finfo) {
+ /* Found the old match, use the previous match. */
+ mdata->halt = true;
+ return;
+ }
+
/* was a free format label produced? */
if (fi->rep) {
label_ptr = fi->rep->representation;
@@ -3259,9 +3437,8 @@ match_subtree_text(proto_node *node, gpointer data)
if (cf->regex) {
if (ws_regex_matches(cf->regex, label_ptr)) {
- mdata->frame_matched = TRUE;
+ mdata->frame_matched = true;
mdata->finfo = fi;
- return;
}
} else if (cf->case_type) {
/* Case insensitive match */
@@ -3278,10 +3455,9 @@ match_subtree_text(proto_node *node, gpointer data)
if (c_char == string[c_match]) {
c_match++;
if (c_match == string_len) {
- /* No need to look further; we have a match */
- mdata->frame_matched = TRUE;
+ mdata->frame_matched = true;
mdata->finfo = fi;
- return;
+ break;
}
} else if (i_restart) {
i = i_restart;
@@ -3292,17 +3468,16 @@ match_subtree_text(proto_node *node, gpointer data)
}
} else if (strstr(label_ptr, string) != NULL) {
/* Case sensitive match */
- mdata->frame_matched = TRUE;
+ mdata->frame_matched = true;
mdata->finfo = fi;
- return;
}
/* Recurse into the subtree, if it exists */
if (node->first_child != NULL)
- proto_tree_children_foreach(node, match_subtree_text, mdata);
+ proto_tree_children_foreach(node, match_subtree_text_reverse, mdata);
}
-gboolean
+bool
cf_find_packet_summary_line(capture_file *cf, const char *string,
search_direction dir)
{
@@ -3318,15 +3493,15 @@ match_summary_line(capture_file *cf, frame_data *fdata,
wtap_rec *rec, Buffer *buf, void *criterion)
{
match_data *mdata = (match_data *)criterion;
- const gchar *string = mdata->string;
+ const char *string = mdata->string;
size_t string_len = mdata->string_len;
epan_dissect_t edt;
const char *info_column;
size_t info_column_len;
match_result result = MR_NOTMATCHED;
- gint colx;
- guint32 i, i_restart;
- guint8 c_char;
+ int colx;
+ uint32_t i, i_restart;
+ uint8_t c_char;
size_t c_match = 0;
/* Load the frame's data. */
@@ -3336,7 +3511,7 @@ match_summary_line(capture_file *cf, frame_data *fdata,
}
/* Don't bother constructing the protocol tree */
- epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
+ epan_dissect_init(&edt, cf->epan, false, false);
/* Get the column information */
epan_dissect_run(&edt, cf->cd_t, rec,
frame_tvbuff_new_buffer(&cf->provider, fdata, buf),
@@ -3389,7 +3564,7 @@ match_summary_line(capture_file *cf, frame_data *fdata,
}
typedef struct {
- const guint8 *data;
+ const uint8_t *data;
size_t data_len;
ws_mempbrk_pattern *pattern;
} cbs_t; /* "Counted byte string" */
@@ -3410,13 +3585,14 @@ typedef struct {
* search.
*/
-gboolean
-cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
- search_direction dir)
+bool
+cf_find_packet_data(capture_file *cf, const uint8_t *string, size_t string_size,
+ search_direction dir, bool multiple)
{
cbs_t info;
- guint8 needles[3];
- ws_mempbrk_pattern pattern;
+ uint8_t needles[3];
+ ws_mempbrk_pattern pattern = {0};
+ ws_match_function match_function;
info.data = string;
info.data_len = string_size;
@@ -3424,7 +3600,7 @@ cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
/* Regex, String or hex search? */
if (cf->regex) {
/* Regular Expression search */
- return find_packet(cf, match_regex, NULL, dir);
+ match_function = (cf->dir == SD_FORWARD) ? match_regex : match_regex_reverse;
} else if (cf->string) {
/* String search - what type of string? */
if (cf->case_type) {
@@ -3436,38 +3612,71 @@ cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
switch (cf->scs_type) {
case SCS_NARROW_AND_WIDE:
- return find_packet(cf, match_narrow_and_wide_case, &info, dir);
+ match_function = (cf->dir == SD_FORWARD) ? match_narrow_and_wide_case : match_narrow_and_wide_case_reverse;
+ break;
case SCS_NARROW:
- return find_packet(cf, match_narrow_case, &info, dir);
+ match_function = (cf->dir == SD_FORWARD) ? match_narrow_case : match_narrow_case_reverse;
+ break;
case SCS_WIDE:
- return find_packet(cf, match_wide_case, &info, dir);
+ match_function = (cf->dir == SD_FORWARD) ? match_wide_case : match_wide_case_reverse;
+ break;
default:
ws_assert_not_reached();
- return FALSE;
+ return false;
}
} else {
switch (cf->scs_type) {
case SCS_NARROW_AND_WIDE:
- return find_packet(cf, match_narrow_and_wide, &info, dir);
+ match_function = (cf->dir == SD_FORWARD) ? match_narrow_and_wide : match_narrow_and_wide_reverse;
+ break;
case SCS_NARROW:
- return find_packet(cf, match_narrow, &info, dir);
+ /* Narrow, case-sensitive match is the same as looking
+ * for a converted hexstring. */
+ match_function = (cf->dir == SD_FORWARD) ? match_binary : match_binary_reverse;
+ break;
case SCS_WIDE:
- return find_packet(cf, match_wide, &info, dir);
+ match_function = (cf->dir == SD_FORWARD) ? match_wide : match_wide_reverse;
+ break;
default:
ws_assert_not_reached();
- return FALSE;
+ return false;
}
}
- } else
- return find_packet(cf, match_binary, &info, dir);
+ } else {
+ match_function = (cf->dir == SD_FORWARD) ? match_binary : match_binary_reverse;
+ }
+
+ if (multiple && cf->current_frame && (cf->search_pos || cf->search_len)) {
+ /* Use the current frame (this will perform the equivalent of
+ * cf_read_current_record() in match_function).
+ */
+ if (match_function(cf, cf->current_frame, &cf->rec, &cf->buf, &info)) {
+ cf->search_in_progress = true;
+ if (cf->edt) {
+ field_info *fi = NULL;
+ /* The regex match can match an empty string. */
+ if (cf->search_len) {
+ fi = proto_find_field_from_offset(cf->edt->tree, cf->search_pos + cf->search_len - 1, cf->edt->tvb);
+ }
+ packet_list_select_finfo(fi);
+ } else {
+ packet_list_select_row_from_data(cf->current_frame);
+ }
+ cf->search_in_progress = false;
+ return true;
+ }
+ }
+ cf->search_pos = 0; /* Reset the position */
+ cf->search_len = 0; /* Reset length */
+ return find_packet(cf, match_function, &info, dir);
}
static match_result
@@ -3475,13 +3684,88 @@ match_narrow_and_wide(capture_file *cf, frame_data *fdata,
wtap_rec *rec, Buffer *buf, void *criterion)
{
cbs_t *info = (cbs_t *)criterion;
- const guint8 *ascii_text = info->data;
+ const uint8_t *ascii_text = info->data;
+ size_t textlen = info->data_len;
+ match_result result;
+ uint32_t buf_len;
+ uint8_t *pd, *buf_start, *buf_end;
+ uint32_t i;
+ uint8_t c_char;
+ size_t c_match = 0;
+
+ /* Load the frame's data. */
+ if (!cf_read_record(cf, fdata, rec, buf)) {
+ /* Attempt to get the packet failed. */
+ return MR_ERROR;
+ }
+
+ result = MR_NOTMATCHED;
+ buf_len = fdata->cap_len;
+ buf_start = ws_buffer_start_ptr(buf);
+ buf_end = buf_start + buf_len;
+ pd = buf_start;
+ if (cf->search_len || cf->search_pos) {
+ /* we want to start searching one byte past the previous match start */
+ pd += cf->search_pos + 1;
+ }
+ for (; pd < buf_end; pd++) {
+ pd = (uint8_t *)memchr(pd, ascii_text[0], buf_end - pd);
+ if (pd == NULL) break;
+ /* Try narrow match at this start location */
+ c_match = 0;
+ for (i = 0; pd + i < buf_end; i++) {
+ c_char = pd[i];
+ if (c_char == ascii_text[c_match]) {
+ c_match++;
+ if (c_match == textlen) {
+ result = MR_MATCHED;
+ /* Save position and length for highlighting the field. */
+ cf->search_pos = (uint32_t)(pd - buf_start);
+ cf->search_len = (uint32_t)(i + 1);
+ goto done;
+ }
+ } else {
+ break;
+ }
+ }
+
+ /* Now try wide match at the same start location. */
+ c_match = 0;
+ for (i = 0; pd + i < buf_end; i++) {
+ c_char = pd[i];
+ if (c_char == ascii_text[c_match]) {
+ c_match++;
+ if (c_match == textlen) {
+ result = MR_MATCHED;
+ /* Save position and length for highlighting the field. */
+ cf->search_pos = (uint32_t)(pd - buf_start);
+ cf->search_len = (uint32_t)(i + 1);
+ goto done;
+ }
+ i++;
+ if (pd + i >= buf_end || pd[i] != '\0') break;
+ } else {
+ break;
+ }
+ }
+ }
+
+done:
+ return result;
+}
+
+static match_result
+match_narrow_and_wide_reverse(capture_file *cf, frame_data *fdata,
+ wtap_rec *rec, Buffer *buf, void *criterion)
+{
+ cbs_t *info = (cbs_t *)criterion;
+ const uint8_t *ascii_text = info->data;
size_t textlen = info->data_len;
match_result result;
- guint32 buf_len;
- guint8 *pd, *buf_start, *buf_end;
- guint32 i;
- guint8 c_char;
+ uint32_t buf_len;
+ uint8_t *pd, *buf_start, *buf_end;
+ uint32_t i;
+ uint8_t c_char;
size_t c_match = 0;
/* Load the frame's data. */
@@ -3491,11 +3775,20 @@ match_narrow_and_wide(capture_file *cf, frame_data *fdata,
}
result = MR_NOTMATCHED;
+ /* Has to be room to hold the sought data. */
+ if (textlen > fdata->cap_len) {
+ return result;
+ }
buf_len = fdata->cap_len;
buf_start = ws_buffer_start_ptr(buf);
buf_end = buf_start + buf_len;
- for (pd = buf_start; pd < buf_end; pd++) {
- pd = (guint8 *)memchr(pd, ascii_text[0], buf_end - pd);
+ pd = buf_end - textlen;
+ if (cf->search_len || cf->search_pos) {
+ /* we want to start searching one byte before the previous match start */
+ pd = buf_start + cf->search_pos - 1;
+ }
+ for (; pd < buf_end; pd++) {
+ pd = (uint8_t *)ws_memrchr(buf_start, ascii_text[0], pd - buf_start + 1);
if (pd == NULL) break;
/* Try narrow match at this start location */
c_match = 0;
@@ -3505,10 +3798,9 @@ match_narrow_and_wide(capture_file *cf, frame_data *fdata,
c_match++;
if (c_match == textlen) {
result = MR_MATCHED;
- cf->search_pos = i + (guint32)(pd - buf_start);
- /* Save the position of the last character
- for highlighting the field. */
- cf->search_len = i + 1;
+ /* Save position and length for highlighting the field. */
+ cf->search_pos = (uint32_t)(pd - buf_start);
+ cf->search_len = (uint32_t)(i + 1);
goto done;
}
} else {
@@ -3524,10 +3816,9 @@ match_narrow_and_wide(capture_file *cf, frame_data *fdata,
c_match++;
if (c_match == textlen) {
result = MR_MATCHED;
- cf->search_pos = i + (guint32)(pd - buf_start);
- /* Save the position of the last character
- for highlighting the field. */
- cf->search_len = i + 1;
+ /* Save position and length for highlighting the field. */
+ cf->search_pos = (uint32_t)(pd - buf_start);
+ cf->search_len = (uint32_t)(i + 1);
goto done;
}
i++;
@@ -3548,14 +3839,14 @@ match_narrow_and_wide_case(capture_file *cf, frame_data *fdata,
wtap_rec *rec, Buffer *buf, void *criterion)
{
cbs_t *info = (cbs_t *)criterion;
- const guint8 *ascii_text = info->data;
+ const uint8_t *ascii_text = info->data;
size_t textlen = info->data_len;
ws_mempbrk_pattern *pattern = info->pattern;
match_result result;
- guint32 buf_len;
- guint8 *pd, *buf_start, *buf_end;
- guint32 i;
- guint8 c_char;
+ uint32_t buf_len;
+ uint8_t *pd, *buf_start, *buf_end;
+ uint32_t i;
+ uint8_t c_char;
size_t c_match = 0;
/* Load the frame's data. */
@@ -3570,8 +3861,13 @@ match_narrow_and_wide_case(capture_file *cf, frame_data *fdata,
buf_len = fdata->cap_len;
buf_start = ws_buffer_start_ptr(buf);
buf_end = buf_start + buf_len;
- for (pd = buf_start; pd < buf_end; pd++) {
- pd = (guint8 *)ws_mempbrk_exec(pd, buf_end - pd, pattern, &c_char);
+ pd = buf_start;
+ if (cf->search_len || cf->search_pos) {
+ /* we want to start searching one byte past the previous match start */
+ pd += cf->search_pos + 1;
+ }
+ for (; pd < buf_end; pd++) {
+ pd = (uint8_t *)ws_mempbrk_exec(pd, buf_end - pd, pattern, &c_char);
if (pd == NULL) break;
/* Try narrow match at this start location */
c_match = 0;
@@ -3581,10 +3877,9 @@ match_narrow_and_wide_case(capture_file *cf, frame_data *fdata,
c_match++;
if (c_match == textlen) {
result = MR_MATCHED;
- cf->search_pos = i + (guint32)(pd - buf_start);
- /* Save the position of the last character
- for highlighting the field. */
- cf->search_len = i + 1;
+ /* Save position and length for highlighting the field. */
+ cf->search_pos = (uint32_t)(pd - buf_start);
+ cf->search_len = (uint32_t)(i + 1);
goto done;
}
} else {
@@ -3600,10 +3895,9 @@ match_narrow_and_wide_case(capture_file *cf, frame_data *fdata,
c_match++;
if (c_match == textlen) {
result = MR_MATCHED;
- cf->search_pos = i + (guint32)(pd - buf_start);
- /* Save the position of the last character
- for highlighting the field. */
- cf->search_len = i + 1;
+ /* Save position and length for highlighting the field. */
+ cf->search_pos = (uint32_t)(pd - buf_start);
+ cf->search_len = (uint32_t)(i + 1);
goto done;
}
i++;
@@ -3619,17 +3913,18 @@ done:
}
static match_result
-match_narrow(capture_file *cf, frame_data *fdata,
+match_narrow_and_wide_case_reverse(capture_file *cf, frame_data *fdata,
wtap_rec *rec, Buffer *buf, void *criterion)
{
cbs_t *info = (cbs_t *)criterion;
- const guint8 *ascii_text = info->data;
+ const uint8_t *ascii_text = info->data;
size_t textlen = info->data_len;
+ ws_mempbrk_pattern *pattern = info->pattern;
match_result result;
- guint32 buf_len;
- guint8 *pd, *buf_start, *buf_end;
- guint32 i;
- guint8 c_char;
+ uint32_t buf_len;
+ uint8_t *pd, *buf_start, *buf_end;
+ uint32_t i;
+ uint8_t c_char;
size_t c_match = 0;
/* Load the frame's data. */
@@ -3638,30 +3933,61 @@ match_narrow(capture_file *cf, frame_data *fdata,
return MR_ERROR;
}
+ ws_assert(pattern != NULL);
+
result = MR_NOTMATCHED;
+ /* Has to be room to hold the sought data. */
+ if (textlen > fdata->cap_len) {
+ return result;
+ }
buf_len = fdata->cap_len;
buf_start = ws_buffer_start_ptr(buf);
buf_end = buf_start + buf_len;
- for (pd = buf_start; pd < buf_end; pd++) {
- pd = (guint8 *)memchr(pd, ascii_text[0], buf_end - pd);
+ pd = buf_end - textlen;
+ if (cf->search_len || cf->search_pos) {
+ /* we want to start searching one byte before the previous match start */
+ pd = buf_start + cf->search_pos - 1;
+ }
+ for (; pd >= buf_start; pd--) {
+ pd = (uint8_t *)ws_memrpbrk_exec(buf_start, pd - buf_start + 1, pattern, &c_char);
if (pd == NULL) break;
+ /* Try narrow match at this start location */
c_match = 0;
for (i = 0; pd + i < buf_end; i++) {
- c_char = pd[i];
+ c_char = g_ascii_toupper(pd[i]);
if (c_char == ascii_text[c_match]) {
c_match++;
if (c_match == textlen) {
result = MR_MATCHED;
- cf->search_pos = i + (guint32)(pd - buf_start);
- /* Save the position of the last character
- for highlighting the field. */
- cf->search_len = i + 1;
+ /* Save position and length for highlighting the field. */
+ cf->search_pos = (uint32_t)(pd - buf_start);
+ cf->search_len = (uint32_t)(i + 1);
goto done;
}
} else {
break;
}
}
+
+ /* Now try wide match at the same start location. */
+ c_match = 0;
+ for (i = 0; pd + i < buf_end; i++) {
+ c_char = g_ascii_toupper(pd[i]);
+ if (c_char == ascii_text[c_match]) {
+ c_match++;
+ if (c_match == textlen) {
+ result = MR_MATCHED;
+ /* Save position and length for highlighting the field. */
+ cf->search_pos = (uint32_t)(pd - buf_start);
+ cf->search_len = (uint32_t)(i + 1);
+ goto done;
+ }
+ i++;
+ if (pd + i >= buf_end || pd[i] != '\0') break;
+ } else {
+ break;
+ }
+ }
}
done:
@@ -3674,14 +4000,71 @@ match_narrow_case(capture_file *cf, frame_data *fdata,
wtap_rec *rec, Buffer *buf, void *criterion)
{
cbs_t *info = (cbs_t *)criterion;
- const guint8 *ascii_text = info->data;
+ const uint8_t *ascii_text = info->data;
+ size_t textlen = info->data_len;
+ ws_mempbrk_pattern *pattern = info->pattern;
+ match_result result;
+ uint32_t buf_len;
+ uint8_t *pd, *buf_start, *buf_end;
+ uint32_t i;
+ uint8_t c_char;
+ size_t c_match = 0;
+
+ /* Load the frame's data. */
+ if (!cf_read_record(cf, fdata, rec, buf)) {
+ /* Attempt to get the packet failed. */
+ return MR_ERROR;
+ }
+
+ ws_assert(pattern != NULL);
+
+ result = MR_NOTMATCHED;
+ buf_len = fdata->cap_len;
+ buf_start = ws_buffer_start_ptr(buf);
+ buf_end = buf_start + buf_len;
+ pd = buf_start;
+ if (cf->search_len || cf->search_pos) {
+ /* we want to start searching one byte past the previous match start */
+ pd += cf->search_pos + 1;
+ }
+ for (; pd < buf_end; pd++) {
+ pd = (uint8_t *)ws_mempbrk_exec(pd, buf_end - pd, pattern, &c_char);
+ if (pd == NULL) break;
+ c_match = 0;
+ for (i = 0; pd + i < buf_end; i++) {
+ c_char = g_ascii_toupper(pd[i]);
+ if (c_char == ascii_text[c_match]) {
+ c_match++;
+ if (c_match == textlen) {
+ /* Save position and length for highlighting the field. */
+ result = MR_MATCHED;
+ cf->search_pos = (uint32_t)(pd - buf_start);
+ cf->search_len = (uint32_t)(i + 1);
+ goto done;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+done:
+ return result;
+}
+
+static match_result
+match_narrow_case_reverse(capture_file *cf, frame_data *fdata,
+ wtap_rec *rec, Buffer *buf, void *criterion)
+{
+ cbs_t *info = (cbs_t *)criterion;
+ const uint8_t *ascii_text = info->data;
size_t textlen = info->data_len;
ws_mempbrk_pattern *pattern = info->pattern;
match_result result;
- guint32 buf_len;
- guint8 *pd, *buf_start, *buf_end;
- guint32 i;
- guint8 c_char;
+ uint32_t buf_len;
+ uint8_t *pd, *buf_start, *buf_end;
+ uint32_t i;
+ uint8_t c_char;
size_t c_match = 0;
/* Load the frame's data. */
@@ -3693,11 +4076,20 @@ match_narrow_case(capture_file *cf, frame_data *fdata,
ws_assert(pattern != NULL);
result = MR_NOTMATCHED;
+ /* Has to be room to hold the sought data. */
+ if (textlen > fdata->cap_len) {
+ return result;
+ }
buf_len = fdata->cap_len;
buf_start = ws_buffer_start_ptr(buf);
buf_end = buf_start + buf_len;
- for (pd = buf_start; pd < buf_end; pd++) {
- pd = (guint8 *)ws_mempbrk_exec(pd, buf_end - pd, pattern, &c_char);
+ pd = buf_end - textlen;
+ if (cf->search_len || cf->search_pos) {
+ /* we want to start searching one byte before the previous match start */
+ pd = buf_start + cf->search_pos - 1;
+ }
+ for (; pd >= buf_start; pd--) {
+ pd = (uint8_t *)ws_memrpbrk_exec(buf_start, pd - buf_start + 1, pattern, &c_char);
if (pd == NULL) break;
c_match = 0;
for (i = 0; pd + i < buf_end; i++) {
@@ -3705,11 +4097,10 @@ match_narrow_case(capture_file *cf, frame_data *fdata,
if (c_char == ascii_text[c_match]) {
c_match++;
if (c_match == textlen) {
+ /* Save position and length for highlighting the field. */
result = MR_MATCHED;
- cf->search_pos = i + (guint32)(pd - buf_start);
- /* Save the position of the last character
- for highlighting the field. */
- cf->search_len = i + 1;
+ cf->search_pos = (uint32_t)(pd - buf_start);
+ cf->search_len = (uint32_t)(i + 1);
goto done;
}
} else {
@@ -3727,13 +4118,13 @@ match_wide(capture_file *cf, frame_data *fdata,
wtap_rec *rec, Buffer *buf, void *criterion)
{
cbs_t *info = (cbs_t *)criterion;
- const guint8 *ascii_text = info->data;
+ const uint8_t *ascii_text = info->data;
size_t textlen = info->data_len;
match_result result;
- guint32 buf_len;
- guint8 *pd, *buf_start, *buf_end;
- guint32 i;
- guint8 c_char;
+ uint32_t buf_len;
+ uint8_t *pd, *buf_start, *buf_end;
+ uint32_t i;
+ uint8_t c_char;
size_t c_match = 0;
/* Load the frame's data. */
@@ -3746,8 +4137,13 @@ match_wide(capture_file *cf, frame_data *fdata,
buf_len = fdata->cap_len;
buf_start = ws_buffer_start_ptr(buf);
buf_end = buf_start + buf_len;
- for (pd = buf_start; pd < buf_end; pd++) {
- pd = (guint8 *)memchr(pd, ascii_text[0], buf_end - pd);
+ pd = buf_start;
+ if (cf->search_len || cf->search_pos) {
+ /* we want to start searching one byte past the previous match start */
+ pd += cf->search_pos + 1;
+ }
+ for (; pd < buf_end; pd++) {
+ pd = (uint8_t *)memchr(pd, ascii_text[0], buf_end - pd);
if (pd == NULL) break;
c_match = 0;
for (i = 0; pd + i < buf_end; i++) {
@@ -3756,10 +4152,69 @@ match_wide(capture_file *cf, frame_data *fdata,
c_match++;
if (c_match == textlen) {
result = MR_MATCHED;
- cf->search_pos = i + (guint32)(pd - buf_start);
- /* Save the position of the last character
- for highlighting the field. */
- cf->search_len = i + 1;
+ /* Save position and length for highlighting the field. */
+ cf->search_pos = (uint32_t)(pd - buf_start);
+ cf->search_len = (uint32_t)(i + 1);
+ goto done;
+ }
+ i++;
+ if (pd + i >= buf_end || pd[i] != '\0') break;
+ } else {
+ break;
+ }
+ }
+ }
+
+done:
+ return result;
+}
+
+static match_result
+match_wide_reverse(capture_file *cf, frame_data *fdata,
+ wtap_rec *rec, Buffer *buf, void *criterion)
+{
+ cbs_t *info = (cbs_t *)criterion;
+ const uint8_t *ascii_text = info->data;
+ size_t textlen = info->data_len;
+ match_result result;
+ uint32_t buf_len;
+ uint8_t *pd, *buf_start, *buf_end;
+ uint32_t i;
+ uint8_t c_char;
+ size_t c_match = 0;
+
+ /* Load the frame's data. */
+ if (!cf_read_record(cf, fdata, rec, buf)) {
+ /* Attempt to get the packet failed. */
+ return MR_ERROR;
+ }
+
+ result = MR_NOTMATCHED;
+ /* Has to be room to hold the sought data. */
+ if (textlen > fdata->cap_len) {
+ return result;
+ }
+ buf_len = fdata->cap_len;
+ buf_start = ws_buffer_start_ptr(buf);
+ buf_end = buf_start + buf_len;
+ pd = buf_end - textlen;
+ if (cf->search_len || cf->search_pos) {
+ /* we want to start searching one byte before the previous match start */
+ pd = buf_start + cf->search_pos - 1;
+ }
+ for (; pd < buf_end; pd++) {
+ pd = (uint8_t *)ws_memrchr(buf_start, ascii_text[0], pd - buf_start + 1);
+ if (pd == NULL) break;
+ c_match = 0;
+ for (i = 0; pd + i < buf_end; i++) {
+ c_char = pd[i];
+ if (c_char == ascii_text[c_match]) {
+ c_match++;
+ if (c_match == textlen) {
+ result = MR_MATCHED;
+ /* Save position and length for highlighting the field. */
+ cf->search_pos = (uint32_t)(pd - buf_start);
+ cf->search_len = (uint32_t)(i + 1);
goto done;
}
i++;
@@ -3780,14 +4235,14 @@ match_wide_case(capture_file *cf, frame_data *fdata,
wtap_rec *rec, Buffer *buf, void *criterion)
{
cbs_t *info = (cbs_t *)criterion;
- const guint8 *ascii_text = info->data;
+ const uint8_t *ascii_text = info->data;
size_t textlen = info->data_len;
ws_mempbrk_pattern *pattern = info->pattern;
match_result result;
- guint32 buf_len;
- guint8 *pd, *buf_start, *buf_end;
- guint32 i;
- guint8 c_char;
+ uint32_t buf_len;
+ uint8_t *pd, *buf_start, *buf_end;
+ uint32_t i;
+ uint8_t c_char;
size_t c_match = 0;
/* Load the frame's data. */
@@ -3802,8 +4257,13 @@ match_wide_case(capture_file *cf, frame_data *fdata,
buf_len = fdata->cap_len;
buf_start = ws_buffer_start_ptr(buf);
buf_end = buf_start + buf_len;
- for (pd = buf_start; pd < buf_end; pd++) {
- pd = (guint8 *)ws_mempbrk_exec(pd, buf_end - pd, pattern, &c_char);
+ pd = buf_start;
+ if (cf->search_len || cf->search_pos) {
+ /* we want to start searching one byte past the previous match start */
+ pd += cf->search_pos + 1;
+ }
+ for (; pd < buf_end; pd++) {
+ pd = (uint8_t *)ws_mempbrk_exec(pd, buf_end - pd, pattern, &c_char);
if (pd == NULL) break;
c_match = 0;
for (i = 0; pd + i < buf_end; i++) {
@@ -3812,10 +4272,9 @@ match_wide_case(capture_file *cf, frame_data *fdata,
c_match++;
if (c_match == textlen) {
result = MR_MATCHED;
- cf->search_pos = i + (guint32)(pd - buf_start);
- /* Save the position of the last character
- for highlighting the field. */
- cf->search_len = i + 1;
+ /* Save position and length for highlighting the field. */
+ cf->search_pos = (uint32_t)(pd - buf_start);
+ cf->search_len = (uint32_t)(i + 1);
goto done;
}
i++;
@@ -3830,18 +4289,21 @@ done:
return result;
}
+/* Case insensitive match */
static match_result
-match_binary(capture_file *cf, frame_data *fdata,
+match_wide_case_reverse(capture_file *cf, frame_data *fdata,
wtap_rec *rec, Buffer *buf, void *criterion)
{
- cbs_t *info = (cbs_t *)criterion;
- const guint8 *binary_data = info->data;
- size_t datalen = info->data_len;
+ cbs_t *info = (cbs_t *)criterion;
+ const uint8_t *ascii_text = info->data;
+ size_t textlen = info->data_len;
+ ws_mempbrk_pattern *pattern = info->pattern;
match_result result;
- guint32 buf_len;
- guint8 *pd, *buf_start, *buf_end;
- guint32 i;
- size_t c_match = 0;
+ uint32_t buf_len;
+ uint8_t *pd, *buf_start, *buf_end;
+ uint32_t i;
+ uint8_t c_char;
+ size_t c_match = 0;
/* Load the frame's data. */
if (!cf_read_record(cf, fdata, rec, buf)) {
@@ -3849,28 +4311,38 @@ match_binary(capture_file *cf, frame_data *fdata,
return MR_ERROR;
}
+ ws_assert(pattern != NULL);
+
result = MR_NOTMATCHED;
+ /* Has to be room to hold the sought data. */
+ if (textlen > fdata->cap_len) {
+ return result;
+ }
buf_len = fdata->cap_len;
buf_start = ws_buffer_start_ptr(buf);
buf_end = buf_start + buf_len;
- /* Not clear if using memcmp() is faster. memmem() on systems that
- * have it should be faster, though.
- */
- for (pd = buf_start; pd < buf_end; pd++) {
- pd = (guint8 *)memchr(pd, binary_data[0], buf_end - pd);
+ pd = buf_end - textlen;
+ if (cf->search_len || cf->search_pos) {
+ /* we want to start searching one byte before the previous match start */
+ pd = buf_start + cf->search_pos - 1;
+ }
+ for (; pd >= buf_start; pd--) {
+ pd = (uint8_t *)ws_memrpbrk_exec(buf_start, pd - buf_start + 1, pattern, &c_char);
if (pd == NULL) break;
c_match = 0;
for (i = 0; pd + i < buf_end; i++) {
- if (pd[i] == binary_data[c_match]) {
+ c_char = g_ascii_toupper(pd[i]);
+ if (c_char == ascii_text[c_match]) {
c_match++;
- if (c_match == datalen) {
+ if (c_match == textlen) {
result = MR_MATCHED;
- cf->search_pos = i + (guint32)(pd - buf_start);
- /* Save the position of the last character
- for highlighting the field. */
- cf->search_len = i + 1;
+ /* Save position and length for highlighting the field. */
+ cf->search_pos = (uint32_t)(pd - buf_start);
+ cf->search_len = (uint32_t)(i + 1);
goto done;
}
+ i++;
+ if (pd + i >= buf_end || pd[i] != '\0') break;
} else {
break;
}
@@ -3882,6 +4354,82 @@ done:
}
static match_result
+match_binary(capture_file *cf, frame_data *fdata,
+ wtap_rec *rec, Buffer *buf, void *criterion)
+{
+ cbs_t *info = (cbs_t *)criterion;
+ size_t datalen = info->data_len;
+ match_result result;
+ const uint8_t *pd = NULL, *buf_start;
+
+ /* Load the frame's data. */
+ if (!cf_read_record(cf, fdata, rec, buf)) {
+ /* Attempt to get the packet failed. */
+ return MR_ERROR;
+ }
+
+ result = MR_NOTMATCHED;
+ buf_start = ws_buffer_start_ptr(buf);
+ size_t offset = 0;
+ if (cf->search_len || cf->search_pos) {
+ /* we want to start searching one byte past the previous match start */
+ offset = cf->search_pos + 1;
+ }
+ if (offset < fdata->cap_len) {
+ pd = ws_memmem(buf_start + offset, fdata->cap_len - offset, info->data, datalen);
+ }
+ if (pd != NULL) {
+ result = MR_MATCHED;
+ /* Save position and length for highlighting the field. */
+ cf->search_pos = (uint32_t)(pd - buf_start);
+ cf->search_len = (uint32_t)datalen;
+ }
+
+ return result;
+}
+
+static match_result
+match_binary_reverse(capture_file *cf, frame_data *fdata,
+ wtap_rec *rec, Buffer *buf, void *criterion)
+{
+ cbs_t *info = (cbs_t *)criterion;
+ size_t datalen = info->data_len;
+ match_result result;
+ const uint8_t *pd = NULL, *buf_start;
+
+ /* Load the frame's data. */
+ if (!cf_read_record(cf, fdata, rec, buf)) {
+ /* Attempt to get the packet failed. */
+ return MR_ERROR;
+ }
+
+ result = MR_NOTMATCHED;
+ buf_start = ws_buffer_start_ptr(buf);
+ /* Has to be room to hold the sought data. */
+ if (datalen > fdata->cap_len) {
+ return result;
+ }
+ pd = buf_start + fdata->cap_len - datalen;
+ if (cf->search_len || cf->search_pos) {
+ /* we want to start searching one byte before the previous match start */
+ pd = buf_start + cf->search_pos - 1;
+ }
+ for (; pd >= buf_start; pd--) {
+ pd = (uint8_t *)ws_memrchr(buf_start, info->data[0], pd - buf_start + 1);
+ if (pd == NULL) break;
+ if (memcmp(pd, info->data, datalen) == 0) {
+ result = MR_MATCHED;
+ /* Save position and length for highlighting the field. */
+ cf->search_pos = (uint32_t)(pd - buf_start);
+ cf->search_len = (uint32_t)datalen;
+ break;
+ }
+ }
+
+ return result;
+}
+
+static match_result
match_regex(capture_file *cf, frame_data *fdata,
wtap_rec *rec, Buffer *buf, void *criterion _U_)
{
@@ -3894,45 +4442,93 @@ match_regex(capture_file *cf, frame_data *fdata,
return MR_ERROR;
}
- if (ws_regex_matches_pos(cf->regex,
- (const gchar *)ws_buffer_start_ptr(buf),
- fdata->cap_len,
- result_pos)) {
- //TODO: Fix cast.
- cf->search_pos = (guint32)(result_pos[1] - 1); /* last byte = end position - 1 */
- cf->search_len = (guint32)(result_pos[1] - result_pos[0]);
- result = MR_MATCHED;
+ size_t offset = 0;
+ if (cf->search_len || cf->search_pos) {
+ /* we want to start searching one byte past the previous match start */
+ offset = cf->search_pos + 1;
+ }
+ if (offset < fdata->cap_len) {
+ if (ws_regex_matches_pos(cf->regex,
+ (const char *)ws_buffer_start_ptr(buf),
+ fdata->cap_len, offset,
+ result_pos)) {
+ //TODO: A chosen regex can match the empty string (zero length)
+ // which doesn't make a lot of sense for searching the packet bytes.
+ // Should we search with the PCRE2_NOTEMPTY option?
+ //TODO: Fix cast.
+ /* Save position and length for highlighting the field. */
+ cf->search_pos = (uint32_t)(result_pos[0]);
+ cf->search_len = (uint32_t)(result_pos[1] - result_pos[0]);
+ result = MR_MATCHED;
+ }
+ }
+ return result;
+}
+
+static match_result
+match_regex_reverse(capture_file *cf, frame_data *fdata,
+ wtap_rec *rec, Buffer *buf, void *criterion _U_)
+{
+ match_result result = MR_NOTMATCHED;
+ size_t result_pos[2] = {0, 0};
+
+ /* Load the frame's data. */
+ if (!cf_read_record(cf, fdata, rec, buf)) {
+ /* Attempt to get the packet failed. */
+ return MR_ERROR;
+ }
+
+ size_t offset = fdata->cap_len - 1;
+ if (cf->search_pos) {
+ /* we want to start searching one byte before the previous match */
+ offset = cf->search_pos - 1;
+ }
+ for (; offset > 0; offset--) {
+ if (ws_regex_matches_pos(cf->regex,
+ (const char *)ws_buffer_start_ptr(buf),
+ fdata->cap_len, offset,
+ result_pos)) {
+ //TODO: A chosen regex can match the empty string (zero length)
+ // which doesn't make a lot of sense for searching the packet bytes.
+ // Should we search with the PCRE2_NOTEMPTY option?
+ //TODO: Fix cast.
+ /* Save position and length for highlighting the field. */
+ cf->search_pos = (uint32_t)(result_pos[0]);
+ cf->search_len = (uint32_t)(result_pos[1] - result_pos[0]);
+ result = MR_MATCHED;
+ break;
+ }
}
return result;
}
-gboolean
+bool
cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
search_direction dir)
{
return find_packet(cf, match_dfilter, sfcode, dir);
}
-gboolean
+bool
cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
search_direction dir)
{
dfilter_t *sfcode;
- gboolean result;
+ bool result;
if (!dfilter_compile(filter, &sfcode, NULL)) {
/*
* XXX - this shouldn't happen, as the filter string is machine
* generated
*/
- return FALSE;
+ return false;
}
if (sfcode == NULL) {
/*
* XXX - this shouldn't happen, as the filter string is machine
* generated.
*/
- return FALSE;
+ return false;
}
result = find_packet(cf, match_dfilter, sfcode, dir);
dfilter_free(sfcode);
@@ -3953,7 +4549,7 @@ match_dfilter(capture_file *cf, frame_data *fdata,
return MR_ERROR;
}
- epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
+ epan_dissect_init(&edt, cf->epan, true, false);
epan_dissect_prime_with_dfilter(&edt, sfcode);
epan_dissect_run(&edt, cf->cd_t, rec,
frame_tvbuff_new_buffer(&cf->provider, fdata, buf),
@@ -3963,7 +4559,7 @@ match_dfilter(capture_file *cf, frame_data *fdata,
return result;
}
-gboolean
+bool
cf_find_packet_marked(capture_file *cf, search_direction dir)
{
return find_packet(cf, match_marked, NULL, dir);
@@ -3976,7 +4572,7 @@ match_marked(capture_file *cf _U_, frame_data *fdata, wtap_rec *rec _U_,
return fdata->marked ? MR_MATCHED : MR_NOTMATCHED;
}
-gboolean
+bool
cf_find_packet_time_reference(capture_file *cf, search_direction dir)
{
return find_packet(cf, match_time_reference, NULL, dir);
@@ -3989,13 +4585,13 @@ match_time_reference(capture_file *cf _U_, frame_data *fdata, wtap_rec *rec _U_,
return fdata->ref_time ? MR_MATCHED : MR_NOTMATCHED;
}
-static gboolean
+static bool
find_packet(capture_file *cf, ws_match_function match_function,
void *criterion, search_direction dir)
{
frame_data *start_fd;
- guint32 framenum;
- guint32 prev_framenum;
+ uint32_t framenum;
+ uint32_t prev_framenum;
frame_data *fdata;
wtap_rec rec;
Buffer buf;
@@ -4003,9 +4599,9 @@ find_packet(capture_file *cf, ws_match_function match_function,
progdlg_t *progbar = NULL;
GTimer *prog_timer = g_timer_new();
int count;
- gboolean succeeded;
+ bool succeeded;
float progbar_val;
- gchar status_str[100];
+ char status_str[100];
match_result result;
wtap_rec_init(&rec);
@@ -4028,7 +4624,7 @@ find_packet(capture_file *cf, ws_match_function match_function,
/* Progress so far. */
progbar_val = 0.0f;
- cf->stop_flag = FALSE;
+ cf->stop_flag = false;
for (;;) {
/* Create the progress bar if necessary.
@@ -4038,7 +4634,7 @@ find_packet(capture_file *cf, ws_match_function match_function,
time in order to get to the next progress bar step). */
if (progbar == NULL)
progbar = delayed_create_progress_dlg(cf->window, NULL, NULL,
- FALSE, &cf->stop_flag, progbar_val);
+ false, &cf->stop_flag, progbar_val);
/*
* Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
@@ -4052,7 +4648,7 @@ find_packet(capture_file *cf, ws_match_function match_function,
*/
ws_assert(cf->count > 0);
- progbar_val = (gfloat) count / cf->count;
+ progbar_val = (float) count / cf->count;
snprintf(status_str, sizeof(status_str),
"%4u of %u packets", count, cf->count);
@@ -4139,39 +4735,39 @@ find_packet(capture_file *cf, ws_match_function match_function,
if (new_fd != NULL) {
/* We found a frame that's displayed and that matches.
Try to find and select the packet summary list row for that frame. */
- gboolean found_row;
+ bool found_row;
- cf->search_in_progress = TRUE;
+ cf->search_in_progress = true;
found_row = packet_list_select_row_from_data(new_fd);
- cf->search_in_progress = FALSE;
- cf->search_pos = 0; /* Reset the position */
- cf->search_len = 0; /* Reset length */
+ cf->search_in_progress = false;
if (!found_row) {
/* We didn't find a row corresponding to this frame.
This means that the frame isn't being displayed currently,
so we can't select it. */
+ cf->search_pos = 0; /* Reset the position */
+ cf->search_len = 0; /* Reset length */
simple_message_box(ESD_TYPE_INFO, NULL,
"The capture file is probably not fully dissected.",
"End of capture exceeded.");
- succeeded = FALSE; /* The search succeeded but we didn't find the row */
+ succeeded = false; /* The search succeeded but we didn't find the row */
} else
- succeeded = TRUE; /* The search succeeded and we found the row */
+ succeeded = true; /* The search succeeded and we found the row */
} else
- succeeded = FALSE; /* The search failed */
+ succeeded = false; /* The search failed */
wtap_rec_cleanup(&rec);
ws_buffer_free(&buf);
return succeeded;
}
-gboolean
-cf_goto_frame(capture_file *cf, guint fnumber)
+bool
+cf_goto_frame(capture_file *cf, unsigned fnumber, bool exact)
{
frame_data *fdata;
if (cf == NULL || cf->provider.frames == NULL) {
/* we don't have a loaded capture file - fix for bugs 11810 & 11989 */
statusbar_push_temporary_msg("There is no file loaded");
- return FALSE; /* we failed to go to that packet */
+ return false; /* we failed to go to that packet */
}
fdata = frame_data_sequence_find(cf->provider.frames, fnumber);
@@ -4179,13 +4775,73 @@ cf_goto_frame(capture_file *cf, guint fnumber)
if (fdata == NULL) {
/* we didn't find a packet with that packet number */
statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
- return FALSE; /* we failed to go to that packet */
+ return false; /* we failed to go to that packet */
}
if (!fdata->passed_dfilter) {
/* that packet currently isn't displayed */
/* XXX - add it to the set of displayed packets? */
- statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
- return FALSE; /* we failed to go to that packet */
+ if (cf->first_displayed == 0 || exact) {
+ /* We only want that exact frame, or no frames are displayed. */
+ statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
+ return false; /* we failed to go to that packet */
+ }
+ if (fdata->prev_dis_num == 0) {
+ /* There is no previous displayed frame, so this frame is
+ * before the first displayed frame. Go to the first line,
+ * which is the closest frame.
+ */
+ fdata = NULL; /* This will select the first row. */
+ statusbar_push_temporary_msg("Packet number %u isn't displayed, going to the first displayed packet, %u.", fnumber, cf->first_displayed);
+ } else {
+ uint32_t delta = fnumber - fdata->prev_dis_num;
+ /* The next displayed frame might be closer, we can do an
+ * O(log n) binary search for the earliest displayed frame
+ * in the open interval (fnumber, fnumber + delta).
+ *
+ * This is possibly overkill, we could just go to the previous
+ * displayed frame.
+ */
+ frame_data *fdata2;
+ uint32_t lower_bound = fnumber + 1;
+ uint32_t upper_bound = fnumber + delta - 1;
+ bool found = false;
+ while (lower_bound <= upper_bound) {
+ uint32_t middle = (lower_bound + upper_bound) / 2;
+ fdata2 = frame_data_sequence_find(cf->provider.frames, middle);
+ if (fdata2 == NULL) {
+ /* We don't have a frame of that number, so search before it. */
+ upper_bound = middle - 1;
+ continue;
+ }
+ /* We have a frame of that number. What's the displayed
+ * frame before it? */
+ if (fdata2->prev_dis_num > fnumber) {
+ /* The previous frame that passed the filter is also after
+ * our target, so our answer is no later than that.
+ */
+ upper_bound = fdata2->prev_dis_num;
+ } else {
+ /* The previous displayed frame is before fnumber.
+ * (We already know fnumber itself is not displayed.)
+ * Is this frame itself displayed?
+ */
+ if (fdata2->passed_dfilter) {
+ /* Yes. So this is our answer. */
+ found = true;
+ break;
+ }
+ /* No. So our answer, if any, is after this frame. */
+ lower_bound = middle + 1;
+ }
+ }
+ if (found) {
+ fdata = fdata2;
+ statusbar_push_temporary_msg("Packet number %u isn't displayed, going to the next displayed packet, %u.", fnumber, fdata->num);
+ } else {
+ statusbar_push_temporary_msg("Packet number %u isn't displayed, going to the previous displayed packet, %u.", fnumber, fdata->prev_dis_num);
+ fdata = frame_data_sequence_find(cf->provider.frames, fdata->prev_dis_num);
+ }
+ }
}
if (!packet_list_select_row_from_data(fdata)) {
@@ -4195,31 +4851,35 @@ cf_goto_frame(capture_file *cf, guint fnumber)
simple_message_box(ESD_TYPE_INFO, NULL,
"The capture file is probably not fully dissected.",
"End of capture exceeded.");
- return FALSE;
+ return false;
}
- return TRUE; /* we got to that packet */
+ return true; /* we got to that packet */
}
/*
* Go to frame specified by currently selected protocol tree item.
*/
-gboolean
+bool
cf_goto_framenum(capture_file *cf)
{
- header_field_info *hfinfo;
- guint32 framenum;
+ const header_field_info *hfinfo;
+ uint32_t framenum;
if (cf->finfo_selected) {
hfinfo = cf->finfo_selected->hfinfo;
ws_assert(hfinfo);
if (hfinfo->type == FT_FRAMENUM) {
framenum = fvalue_get_uinteger(cf->finfo_selected->value);
- if (framenum != 0)
- return cf_goto_frame(cf, framenum);
+ if (framenum != 0) {
+ /* We probably only want to go to the exact match,
+ * even though "Go to Previous Packet in History" exists.
+ */
+ return cf_goto_frame(cf, framenum, true);
+ }
}
}
- return FALSE;
+ return false;
}
/* Select the packet on a given row. */
@@ -4263,7 +4923,7 @@ cf_select_packet(capture_file *cf, frame_data *fdata)
old_edt = cf->edt;
/* Create the logical protocol tree. */
/* We don't need the columns here. */
- cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
+ cf->edt = epan_dissect_new(cf->epan, true, true);
tap_build_interesting(cf->edt);
epan_dissect_run(cf->edt, cf->cd_t, &cf->rec,
@@ -4301,7 +4961,7 @@ void
cf_mark_frame(capture_file *cf, frame_data *frame)
{
if (! frame->marked) {
- frame->marked = TRUE;
+ frame->marked = true;
if (cf->count > cf->marked_count)
cf->marked_count++;
}
@@ -4314,7 +4974,7 @@ void
cf_unmark_frame(capture_file *cf, frame_data *frame)
{
if (frame->marked) {
- frame->marked = FALSE;
+ frame->marked = false;
if (cf->marked_count > 0)
cf->marked_count--;
}
@@ -4327,7 +4987,7 @@ void
cf_ignore_frame(capture_file *cf, frame_data *frame)
{
if (! frame->ignored) {
- frame->ignored = TRUE;
+ frame->ignored = true;
if (cf->count > cf->ignored_count)
cf->ignored_count++;
}
@@ -4340,7 +5000,7 @@ void
cf_unignore_frame(capture_file *cf, frame_data *frame)
{
if (frame->ignored) {
- frame->ignored = FALSE;
+ frame->ignored = false;
if (cf->ignored_count > 0)
cf->ignored_count--;
}
@@ -4350,10 +5010,10 @@ cf_unignore_frame(capture_file *cf, frame_data *frame)
* Modify the section comment.
*/
void
-cf_update_section_comment(capture_file *cf, gchar *comment)
+cf_update_section_comment(capture_file *cf, char *comment)
{
wtap_block_t shb_inf;
- gchar *shb_comment;
+ char *shb_comment;
/* Get the first SHB. */
/* XXX - support multiple SHBs */
@@ -4375,7 +5035,53 @@ cf_update_section_comment(capture_file *cf, gchar *comment)
wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment));
}
/* Mark the file as having unsaved changes */
- cf->unsaved_changes = TRUE;
+ cf->unsaved_changes = true;
+}
+
+/*
+ * Modify the section comments for a given section.
+ */
+void
+cf_update_section_comments(capture_file *cf, unsigned shb_idx, char **comments)
+{
+ wtap_block_t shb_inf;
+ char *shb_comment;
+
+ shb_inf = wtap_file_get_shb(cf->provider.wth, shb_idx);
+ if (shb_inf == NULL) {
+ /* Shouldn't happen. XXX: Report it if it does? */
+ return;
+ }
+
+ unsigned n_comments = g_strv_length(comments);
+ unsigned i;
+ char* comment;
+
+ for (i = 0; i < n_comments; i++) {
+ comment = comments[i];
+ if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, i, &shb_comment) != WTAP_OPTTYPE_SUCCESS) {
+ /* There's no comment - add one. */
+ wtap_block_add_string_option_owned(shb_inf, OPT_COMMENT, comment);
+ cf->unsaved_changes = true;
+ } else {
+ /* See if the comment has changed or not */
+ if (strcmp(shb_comment, comment) != 0) {
+ /* The comment has changed, let's update it */
+ wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment));
+ cf->unsaved_changes = true;
+ }
+ g_free(comment);
+ }
+ }
+ /* We either transferred ownership of the comments or freed them
+ * above, so free the array of strings but not the strings themselves. */
+ g_free(comments);
+
+ /* If there are extra old comments, remove them. Start at the end. */
+ for (i = wtap_block_count_option(shb_inf, OPT_COMMENT); i > n_comments; i--) {
+ wtap_block_remove_nth_option_instance(shb_inf, OPT_COMMENT, i - 1);
+ cf->unsaved_changes = true;
+ }
}
/*
@@ -4414,7 +5120,7 @@ cf_get_packet_block(capture_file *cf, const frame_data *fd)
/*
* Update(replace) the block on a capture from a frame
*/
-gboolean
+bool
cf_set_modified_block(capture_file *cf, frame_data *fd, const wtap_block_t new_block)
{
wtap_block_t pkt_block = cf_get_packet_block(cf, fd);
@@ -4431,7 +5137,7 @@ cf_set_modified_block(capture_file *cf, frame_data *fd, const wtap_block_t new_b
* in the block before the caller modified it, so tell the caller
* it is its responsibility to update the comment count.
*/
- return FALSE;
+ return false;
}
else {
if (pkt_block)
@@ -4447,22 +5153,22 @@ cf_set_modified_block(capture_file *cf, frame_data *fd, const wtap_block_t new_b
/* Either way, we have unsaved changes. */
wtap_block_unref(pkt_block);
- cf->unsaved_changes = TRUE;
- return TRUE;
+ cf->unsaved_changes = true;
+ return true;
}
/*
* What types of comments does this capture file have?
*/
-guint32
+uint32_t
cf_comment_types(capture_file *cf)
{
- guint32 comment_types = 0;
+ uint32_t comment_types = 0;
/*
* Does this file have any sections with at least one comment?
*/
- for (guint section_number = 0;
+ for (unsigned section_number = 0;
section_number < wtap_file_get_num_shbs(cf->provider.wth);
section_number++) {
wtap_block_t shb_inf;
@@ -4488,7 +5194,7 @@ cf_comment_types(capture_file *cf)
/*
* Add a resolved address to this file's list of resolved addresses.
*/
-gboolean
+bool
cf_add_ip_name_from_string(capture_file *cf, const char *addr, const char *name)
{
/*
@@ -4496,35 +5202,35 @@ cf_add_ip_name_from_string(capture_file *cf, const char *addr, const char *name)
* attached to this file?
*/
if (!add_ip_name_from_string(addr, name))
- return FALSE;
+ return false;
/* OK, we have unsaved changes. */
- cf->unsaved_changes = TRUE;
- return TRUE;
+ cf->unsaved_changes = true;
+ return true;
}
typedef struct {
wtap_dumper *pdh;
const char *fname;
int file_type;
- gboolean export;
+ bool export;
} save_callback_args_t;
/*
* Save a capture to a file, in a particular format, saving either
* all packets, all currently-displayed packets, or all marked packets.
*
- * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
+ * Returns true if it succeeds, false otherwise; if it fails, it pops
* up a message box for the failure.
*/
-static gboolean
+static bool
save_record(capture_file *cf, frame_data *fdata, wtap_rec *rec,
Buffer *buf, void *argsp)
{
save_callback_args_t *args = (save_callback_args_t *)argsp;
wtap_rec new_rec;
int err;
- gchar *err_info;
+ char *err_info;
wtap_block_t pkt_block;
/* Copy the record information from what was read in from the file. */
@@ -4537,7 +5243,7 @@ save_record(capture_file *cf, frame_data *fdata, wtap_rec *rec,
else
pkt_block = rec->block;
new_rec.block = pkt_block;
- new_rec.block_was_modified = fdata->has_modified_block ? TRUE : FALSE;
+ new_rec.block_was_modified = fdata->has_modified_block ? true : false;
if (!nstime_is_zero(&fdata->shift_offset)) {
if (new_rec.presence_flags & WTAP_HAS_TS) {
@@ -4549,7 +5255,7 @@ save_record(capture_file *cf, frame_data *fdata, wtap_rec *rec,
if (!wtap_dump(args->pdh, &new_rec, ws_buffer_start_ptr(buf), &err, &err_info)) {
cfile_write_failure_alert_box(NULL, args->fname, err, err_info, fdata->num,
args->file_type);
- return FALSE;
+ return false;
}
/* If we are saving (i.e., replacing the current file with the one we're
@@ -4567,14 +5273,14 @@ save_record(capture_file *cf, frame_data *fdata, wtap_rec *rec,
nstime_set_zero(&fdata->shift_offset);
}
- return TRUE;
+ return true;
}
/*
* Can this capture file be written out in any format using Wiretap
* rather than by copying the raw data?
*/
-gboolean
+bool
cf_can_write_with_wiretap(capture_file *cf)
{
/* We don't care whether we support the comments in this file or not;
@@ -4603,12 +5309,12 @@ cf_can_write_with_wiretap(capture_file *cf)
* if we can't, we'll offer the user the option of discarding the
* comments.
*/
-gboolean
+bool
cf_can_save(capture_file *cf)
{
if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
/* Saved changes, and we can write it out with Wiretap. */
- return TRUE;
+ return true;
}
if (cf->is_tempfile && !cf->unsaved_changes) {
@@ -4616,11 +5322,11 @@ cf_can_save(capture_file *cf)
* Temporary file with no unsaved changes, so we can just do a
* raw binary copy.
*/
- return TRUE;
+ return true;
}
/* Nothing to save. */
- return FALSE;
+ return false;
}
/*
@@ -4642,12 +5348,12 @@ cf_can_save(capture_file *cf)
* if we can't, we'll offer the user the option of discarding the
* comments.
*/
-gboolean
+bool
cf_can_save_as(capture_file *cf)
{
if (wtap_dump_can_write(cf->linktypes, 0)) {
/* We can write it out with Wiretap. */
- return TRUE;
+ return true;
}
if (cf->is_tempfile && !cf->unsaved_changes) {
@@ -4655,17 +5361,17 @@ cf_can_save_as(capture_file *cf)
* Temporary file with no unsaved changes, so we can just do a
* raw binary copy.
*/
- return TRUE;
+ return true;
}
/* Nothing to save. */
- return FALSE;
+ return false;
}
/*
* Does this file have unsaved data?
*/
-gboolean
+bool
cf_has_unsaved_data(capture_file *cf)
{
/*
@@ -4679,21 +5385,21 @@ cf_has_unsaved_data(capture_file *cf)
* Quick scan to find packet offsets.
*/
static cf_read_status_t
-rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile)
+rescan_file(capture_file *cf, const char *fname, bool is_tempfile)
{
wtap_rec rec;
Buffer buf;
int err;
- gchar *err_info;
- gchar *name_ptr;
- gint64 data_offset;
+ char *err_info;
+ char *name_ptr;
+ int64_t data_offset;
progdlg_t *progbar = NULL;
GTimer *prog_timer = g_timer_new();
- gint64 size;
+ int64_t size;
float progbar_val;
- gint64 start_time;
- gchar status_str[100];
- guint32 framenum;
+ int64_t start_time;
+ char status_str[100];
+ uint32_t framenum;
frame_data *fdata;
/* Close the old handle. */
@@ -4706,7 +5412,7 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile)
reader to use (only which format to save it in), so doing this makes
sense for now. (XXX: Now it is also used when saving a changed file,
e.g. comments or time-shifted frames.) */
- cf->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
+ cf->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, true);
if (cf->provider.wth == NULL) {
cfile_open_failure_alert_box(fname, err, err_info);
return CF_READ_ERROR;
@@ -4728,13 +5434,13 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile)
cf->is_tempfile = is_tempfile;
/* No user changes yet. */
- cf->unsaved_changes = FALSE;
+ cf->unsaved_changes = false;
cf->cd_t = wtap_file_type_subtype(cf->provider.wth);
if (cf->linktypes != NULL) {
g_array_free(cf->linktypes, TRUE);
}
- cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
+ cf->linktypes = g_array_sized_new(FALSE, FALSE, (unsigned) sizeof(int), 1);
cf->snap = wtap_snapshot_length(cf->provider.wth);
@@ -4751,7 +5457,7 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile)
g_timer_start(prog_timer);
- cf->stop_flag = FALSE;
+ cf->stop_flag = false;
start_time = g_get_monotonic_time();
framenum = 0;
@@ -4771,7 +5477,7 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile)
if (progress_is_slow(progbar, prog_timer, size, cf->f_datalen)) {
progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
progbar = delayed_create_progress_dlg(cf->window, NULL, NULL,
- TRUE, &cf->stop_flag, progbar_val);
+ true, &cf->stop_flag, progbar_val);
}
/*
@@ -4852,19 +5558,19 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile)
}
cf_write_status_t
-cf_save_records(capture_file *cf, const char *fname, guint save_format,
+cf_save_records(capture_file *cf, const char *fname, unsigned save_format,
wtap_compression_type compression_type,
- gboolean discard_comments, gboolean dont_reopen)
+ bool discard_comments, bool dont_reopen)
{
- gchar *err_info;
- gchar *fname_new = NULL;
+ char *err_info = "Unknown error";
+ char *fname_new = NULL;
wtap_dumper *pdh;
frame_data *fdata;
addrinfo_lists_t *addr_lists;
- guint framenum;
+ unsigned framenum;
int err;
#ifdef _WIN32
- gchar *display_basename;
+ char *display_basename;
#endif
enum {
SAVE_WITH_MOVE,
@@ -4872,8 +5578,8 @@ cf_save_records(capture_file *cf, const char *fname, guint save_format,
SAVE_WITH_WTAP
} how_to_save;
save_callback_args_t callback_args;
- callback_args.export = FALSE;
- gboolean needs_reload = FALSE;
+ callback_args.export = false;
+ bool needs_reload = false;
/* XXX caller should avoid saving the file while a read is pending
* (e.g. by delaying the save action) */
@@ -4881,7 +5587,7 @@ cf_save_records(capture_file *cf, const char *fname, guint save_format,
ws_warning("cf_save_records(\"%s\") while the file is being read, potential crash ahead", fname);
}
- cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
+ cf_callback_invoke(cf_cb_file_save_started, (void *)fname);
addr_lists = get_addrinfo_list();
@@ -5014,7 +5720,7 @@ cf_save_records(capture_file *cf, const char *fname, guint save_format,
callback_args.fname = fname;
callback_args.file_type = save_format;
switch (process_specified_records(cf, NULL, "Saving", "packets",
- TRUE, save_record, &callback_args, TRUE)) {
+ true, save_record, &callback_args, true)) {
case PSP_FINISHED:
/* Completed successfully. */
@@ -5071,7 +5777,7 @@ cf_save_records(capture_file *cf, const char *fname, guint save_format,
/* Oh, well, we're screwed. */
display_basename = g_filename_display_basename(cf->filename);
simple_error_message_box(
- file_open_error_message(err, FALSE), display_basename);
+ file_open_error_message(err, false), display_basename);
g_free(display_basename);
}
#endif
@@ -5089,7 +5795,7 @@ cf_save_records(capture_file *cf, const char *fname, guint save_format,
}
cf_callback_invoke(cf_cb_file_save_finished, NULL);
- cf->unsaved_changes = FALSE;
+ cf->unsaved_changes = false;
if (!dont_reopen) {
switch (how_to_save) {
@@ -5101,7 +5807,7 @@ cf_save_records(capture_file *cf, const char *fname, guint save_format,
update that. */
g_free(cf->filename);
cf->filename = g_strdup(fname);
- cf->is_tempfile = FALSE;
+ cf->is_tempfile = false;
cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
break;
@@ -5119,7 +5825,7 @@ cf_save_records(capture_file *cf, const char *fname, guint save_format,
} else {
g_free(cf->filename);
cf->filename = g_strdup(fname);
- cf->is_tempfile = FALSE;
+ cf->is_tempfile = false;
}
cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
break;
@@ -5150,8 +5856,8 @@ cf_save_records(capture_file *cf, const char *fname, guint save_format,
being written to the file, e.g ERF records
In that case, we need to reload the whole file */
if(needs_reload) {
- if (cf_open(cf, fname, WTAP_TYPE_AUTO, FALSE, &err) == CF_OK) {
- if (cf_read(cf, /*reloading=*/TRUE) != CF_READ_OK) {
+ if (cf_open(cf, fname, WTAP_TYPE_AUTO, false, &err) == CF_OK) {
+ if (cf_read(cf, /*reloading=*/true) != CF_READ_OK) {
/* The rescan failed; just close the file. Either
a dialog was popped up for the failure, so the
user knows what happened, or they stopped the
@@ -5162,7 +5868,7 @@ cf_save_records(capture_file *cf, const char *fname, guint save_format,
}
}
else {
- if (rescan_file(cf, fname, FALSE) != CF_READ_OK) {
+ if (rescan_file(cf, fname, false) != CF_READ_OK) {
/* The rescan failed; just close the file. Either
a dialog was popped up for the failure, so the
user knows what happened, or they stopped the
@@ -5183,7 +5889,7 @@ cf_save_records(capture_file *cf, const char *fname, guint save_format,
fdata = frame_data_sequence_find(cf->provider.frames, framenum);
// XXX: This also ignores non-comment options like verdict
- fdata->has_modified_block = FALSE;
+ fdata->has_modified_block = false;
}
if (cf->provider.frames_modified_blocks) {
@@ -5213,18 +5919,18 @@ fail:
cf_write_status_t
cf_export_specified_packets(capture_file *cf, const char *fname,
- packet_range_t *range, guint save_format,
+ packet_range_t *range, unsigned save_format,
wtap_compression_type compression_type)
{
- gchar *fname_new = NULL;
+ char *fname_new = NULL;
int err;
- gchar *err_info;
+ char *err_info;
wtap_dumper *pdh;
save_callback_args_t callback_args;
wtap_dump_params params;
int encap;
- callback_args.export = TRUE;
+ callback_args.export = true;
packet_range_process_init(range);
/* We're writing out specified packets from the specified capture
@@ -5279,7 +5985,7 @@ cf_export_specified_packets(capture_file *cf, const char *fname,
callback_args.fname = fname;
callback_args.file_type = save_format;
switch (process_specified_records(cf, range, "Writing", "specified records",
- TRUE, save_record, &callback_args, TRUE)) {
+ true, save_record, &callback_args, true)) {
case PSP_FINISHED:
/* Completed successfully. */
@@ -5298,7 +6004,6 @@ cf_export_specified_packets(capture_file *cf, const char *fname,
wtap_dump_params_cleanup(&params);
return CF_WRITE_ABORTED;
- break;
case PSP_FAILED:
/* Error while saving. */
@@ -5354,7 +6059,7 @@ fail:
static void
cf_rename_failure_alert_box(const char *filename, int err)
{
- gchar *display_basename;
+ char *display_basename;
display_basename = g_filename_display_basename(filename);
switch (err) {
@@ -5388,8 +6093,8 @@ cf_rename_failure_alert_box(const char *filename, int err)
cf_status_t
cf_reload(capture_file *cf)
{
- gchar *filename;
- gboolean is_tempfile;
+ char *filename;
+ bool is_tempfile;
cf_status_t cf_status = CF_OK;
int err;
@@ -5410,9 +6115,9 @@ cf_reload(capture_file *cf)
a copy of it first. */
filename = g_strdup(cf->filename);
is_tempfile = cf->is_tempfile;
- cf->is_tempfile = FALSE;
+ cf->is_tempfile = false;
if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
- switch (cf_read(cf, /*reloading=*/TRUE)) {
+ switch (cf_read(cf, /*reloading=*/true)) {
case CF_READ_OK:
case CF_READ_ERROR: