diff --git a/epan/dissectors/packet-radius.c b/epan/dissectors/packet-radius.c index 4c80452949..c57aeae894 100644 --- a/epan/dissectors/packet-radius.c +++ b/epan/dissectors/packet-radius.c @@ -2137,6 +2137,29 @@ dissect_radius(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _ return tvb_captured_length(tvb); } +void +free_radius_attr_info(gpointer data) +{ + radius_attr_info_t* attr = (radius_attr_info_t*)data; + + g_free(attr->name); + if (attr->tlvs_by_id) + g_hash_table_destroy(attr->tlvs_by_id); + + g_free(attr); +} + +static void +free_radius_vendor_info(gpointer data) +{ + radius_vendor_info_t* vendor = (radius_vendor_info_t*)data; + + g_free(vendor->name); + if (vendor->attrs_by_id) + g_hash_table_destroy(vendor->attrs_by_id); + + g_free(vendor); +} static void register_attrs(gpointer k _U_, gpointer v, gpointer p) @@ -2313,7 +2336,7 @@ radius_register_avp_dissector(guint32 vendor_id, guint32 attribute_id, radius_av val_to_str_ext_const(vendor_id, &sminmpec_values_ext, "Unknown"), vendor_id); vendor->code = vendor_id; - vendor->attrs_by_id = g_hash_table_new(g_direct_hash, g_direct_equal); + vendor->attrs_by_id = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_radius_attr_info); vendor->ett = no_vendor.ett; /* XXX: Default "standard" values: Should be parameters ? */ @@ -2369,6 +2392,19 @@ radius_init_protocol(void) } } +static void +radius_shutdown(void) +{ + if (dict != NULL) { + g_hash_table_destroy(dict->attrs_by_id); + g_hash_table_destroy(dict->attrs_by_name); + g_hash_table_destroy(dict->vendors_by_id); + g_hash_table_destroy(dict->vendors_by_name); + g_hash_table_destroy(dict->tlvs_by_name); + g_free(dict); + } +} + static void register_radius_fields(const char *unused _U_) { @@ -2634,6 +2670,7 @@ proto_register_radius(void) proto_radius = proto_register_protocol("RADIUS Protocol", "RADIUS", "radius"); radius_handle = register_dissector("radius", dissect_radius, proto_radius); register_init_routine(&radius_init_protocol); + register_shutdown_routine(radius_shutdown); radius_module = prefs_register_protocol(proto_radius, NULL); prefs_register_string_preference(radius_module, "shared_secret", "Shared Secret", "Shared secret used to decode User Passwords and validate Response Authenticators", @@ -2650,11 +2687,13 @@ proto_register_radius(void) proto_register_prefix("radius", register_radius_fields); dict = (radius_dictionary_t *)g_malloc(sizeof(radius_dictionary_t)); - dict->attrs_by_id = g_hash_table_new(g_direct_hash, g_direct_equal); - dict->attrs_by_name = g_hash_table_new(g_str_hash, g_str_equal); - dict->vendors_by_id = g_hash_table_new(g_direct_hash, g_direct_equal); + dict->attrs_by_id = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_radius_attr_info); + dict->attrs_by_name = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, free_radius_attr_info); + dict->vendors_by_id = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_radius_vendor_info); + /* Both vendors_by_id and vendors_by_name share the same data, so only worry about + cleaning up the data from one of them. The other will just clean up its own hash entries */ dict->vendors_by_name = g_hash_table_new(g_str_hash, g_str_equal); - dict->tlvs_by_name = g_hash_table_new(g_str_hash, g_str_equal); + dict->tlvs_by_name = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, free_radius_attr_info); radius_calls = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), radius_call_hash, radius_call_equal); diff --git a/epan/dissectors/packet-radius.h b/epan/dissectors/packet-radius.h index c53bb87818..9393f73111 100644 --- a/epan/dissectors/packet-radius.h +++ b/epan/dissectors/packet-radius.h @@ -81,7 +81,7 @@ typedef struct _radius_vendor_info_t { - const gchar *name; + gchar *name; guint code; GHashTable* attrs_by_id; gint ett; @@ -96,7 +96,7 @@ typedef void (radius_attr_dissector_t)(radius_attr_info_t*, proto_tree*, packet_ typedef const gchar* (radius_avp_dissector_t)(proto_tree*,tvbuff_t*, packet_info*); struct _radius_attr_info_t { - const gchar *name; + gchar *name; guint code; guint encrypt; /* 0 or value for "encrypt=" option */ gboolean tagged; @@ -138,6 +138,7 @@ radius_attr_dissector_t radius_tlv; extern void radius_register_avp_dissector(guint32 vendor_id, guint32 attribute_id, radius_avp_dissector_t dissector); void dissect_attribute_value_pairs(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset, guint length); +extern void free_radius_attr_info(gpointer data); /* from radius_dict.l */ gboolean radius_load_dictionary (radius_dictionary_t* dict, gchar* directory, const gchar* filename, gchar** err_str); diff --git a/epan/radius_dict.l b/epan/radius_dict.l index 6ca0008dfb..fd4771e0b6 100644 --- a/epan/radius_dict.l +++ b/epan/radius_dict.l @@ -403,7 +403,7 @@ static void add_vendor(Radius_scanner_state_t* state, const gchar* name, guint32 * by-name hash tables. */ v = g_new(radius_vendor_info_t,1); - v->attrs_by_id = g_hash_table_new(g_direct_hash,g_direct_equal); + v->attrs_by_id = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_radius_attr_info); v->code = id; v->ett = -1; v->name = g_strdup(name);