aboutsummaryrefslogtreecommitdiffstats
path: root/epan
diff options
context:
space:
mode:
authorJohn Thacker <johnthacker@gmail.com>2022-11-20 07:56:42 -0500
committerAndersBroman <a.broman58@gmail.com>2022-11-30 11:04:05 +0000
commit10c84b6450de7167f775d34bc99fe662927d0427 (patch)
tree8487c62cd3db440bb74f1454bdc2d9a83ed391d6 /epan
parent5b8cb733facd97b46710fc635a19ea758c128fcf (diff)
HTTP2: Load dynamic hf entries when UAT is changed
The dynamic hf entries for HTTP2 read from the UAT should be changed when the UAT is changed or reset, not on each file load and file close. If a field is added as a column, coloring rule, or filter, and the capture file is changed, deregistering the field and reregistering it can cause a crash. Use the same approach as with HTTP and SIP, slightly modified because in HTTP2 the header fields hash contains the static headers as well, to prevent adding duplicate entries via the UAT. Fix #14768
Diffstat (limited to 'epan')
-rw-r--r--epan/dissectors/packet-http2.c127
1 files changed, 75 insertions, 52 deletions
diff --git a/epan/dissectors/packet-http2.c b/epan/dissectors/packet-http2.c
index c58d6a27e2..abfb520f51 100644
--- a/epan/dissectors/packet-http2.c
+++ b/epan/dissectors/packet-http2.c
@@ -632,6 +632,79 @@ header_fields_free_cb(void*r)
}
+static hf_register_info* hf_uat = NULL;
+
+static void
+deregister_header_fields(void)
+{
+ if (hf_uat) {
+ for (guint i = 0; i < num_header_fields_cleanup; ++i) {
+ proto_deregister_field(proto_http2, *(hf_uat[i].p_id));
+ g_free(hf_uat[i].p_id);
+ }
+ proto_add_deregistered_data(hf_uat);
+ hf_uat = NULL;
+ num_header_fields_cleanup = 0;
+ }
+
+ /* header_fields_hash also contains the static header list (used for
+ * look ups to avoid duplicate entries, so we don't destroy it here.
+ * The dynamic entries are removed from the hash table in
+ * header_fields_free_cb().
+ */
+}
+
+static void
+header_fields_post_update_cb(void)
+{
+ gint* hf_id;
+ gchar* header_name;
+ gchar* header_name_key;
+
+ deregister_header_fields();
+
+ /* Add to hash table headers from UAT */
+ if (num_header_fields) {
+ hf_uat = g_new0(hf_register_info, num_header_fields);
+ num_header_fields_cleanup = num_header_fields;
+
+ for (guint i = 0; i < num_header_fields; i++) {
+ hf_id = g_new(gint,1);
+ *hf_id = -1;
+ header_name = g_strdup(header_fields[i].header_name);
+ header_name_key = g_ascii_strdown(header_name, -1);
+
+ hf_uat[i].p_id = hf_id;
+ hf_uat[i].hfinfo.name = header_name;
+ hf_uat[i].hfinfo.abbrev = ws_strdup_printf("http2.headers.%s", header_name);
+ switch(header_fields[i].header_type) {
+ case val_uint64:
+ hf_uat[i].hfinfo.type = FT_UINT64;
+ hf_uat[i].hfinfo.display = BASE_DEC;
+ break;
+ default: // string
+ hf_uat[i].hfinfo.type = FT_STRING;
+ hf_uat[i].hfinfo.display = BASE_NONE;
+ break;
+ }
+ hf_uat[i].hfinfo.strings = NULL;
+ hf_uat[i].hfinfo.bitmask = 0;
+ hf_uat[i].hfinfo.blurb = g_strdup(header_fields[i].header_desc);
+ HFILL_INIT(hf_uat[i]);
+
+ g_hash_table_insert(header_fields_hash, header_name_key, hf_id);
+ }
+
+ proto_register_field_array(proto_http2, hf_uat, num_header_fields);
+ }
+}
+
+static void
+header_fields_reset_cb(void)
+{
+ deregister_header_fields();
+}
+
static void
register_static_headers(void) {
header_fields_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
@@ -954,8 +1027,6 @@ UAT_CSTRING_CB_DEF(header_fields, header_name, header_field_t)
UAT_VS_DEF(header_fields, header_type, header_field_t, enum header_field_type, val_string, "string")
UAT_CSTRING_CB_DEF(header_fields, header_desc, header_field_t)
-static hf_register_info* hf_uat = NULL;
-
/* message/stream direction (to or from server) vals */
#define http2_direction_type_vals_VALUE_STRING_LIST(XXX) \
XXX(DIRECTION_IN, 0, "IN") \
@@ -1096,60 +1167,12 @@ get_fake_header_value(packet_info* pinfo, const gchar* name, gboolean the_other_
static void
http2_init_protocol(void)
{
-#if HAVE_NGHTTP2
- gint* hf_id;
- guint i;
- gchar* header_name;
- gchar* header_name_key;
-
- /* Add to hash table headers from UAT */
- if (num_header_fields) {
- hf_uat = g_new0(hf_register_info, num_header_fields);
- num_header_fields_cleanup = num_header_fields;
-
- for (i = 0; i < num_header_fields; i++) {
- hf_id = g_new(gint,1);
- *hf_id = -1;
- header_name = g_strdup(header_fields[i].header_name);
- header_name_key = g_ascii_strdown(header_name, -1);
-
- hf_uat[i].p_id = hf_id;
- hf_uat[i].hfinfo.name = header_name;
- hf_uat[i].hfinfo.abbrev = ws_strdup_printf("http2.headers.%s", header_name);
- switch(header_fields[i].header_type) {
- case val_uint64:
- hf_uat[i].hfinfo.type = FT_UINT64;
- hf_uat[i].hfinfo.display = BASE_DEC;
- break;
- default: // string
- hf_uat[i].hfinfo.type = FT_STRING;
- hf_uat[i].hfinfo.display = BASE_NONE;
- break;
- }
- hf_uat[i].hfinfo.strings = NULL;
- hf_uat[i].hfinfo.bitmask = 0;
- hf_uat[i].hfinfo.blurb = g_strdup(header_fields[i].header_desc);
- HFILL_INIT(hf_uat[i]);
-
- g_hash_table_insert(header_fields_hash, header_name_key, hf_id);
- }
-
- proto_register_field_array(proto_http2, hf_uat, num_header_fields);
- }
-#endif
/* Init hash table with mapping of stream id -> frames count for Follow HTTP2 */
streamid_hash = g_hash_table_new_full(NULL, NULL, NULL, (GDestroyNotify)g_hash_table_destroy);
}
static void
http2_cleanup_protocol(void) {
-#if HAVE_NGHTTP2
- for (guint i = 0; i < num_header_fields_cleanup; ++i) {
- proto_deregister_field(proto_http2, *(hf_uat[i].p_id));
- }
- proto_add_deregistered_data(hf_uat);
- proto_free_deregistered_fields();
-#endif
g_hash_table_destroy(streamid_hash);
}
@@ -4536,8 +4559,8 @@ proto_register_http2(void)
header_fields_copy_cb,
header_fields_update_cb,
header_fields_free_cb,
- NULL,
- NULL,
+ header_fields_post_update_cb,
+ header_fields_reset_cb,
custom_header_uat_fields
);