diff options
Diffstat (limited to 'file.c')
-rw-r--r-- | file.c | 1903 |
1 files changed, 1304 insertions, 599 deletions
@@ -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(¶ms); 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: |