diff --git a/epan/dissectors/packet-dcerpc.c b/epan/dissectors/packet-dcerpc.c index 8d31002d09..19818c83b5 100644 --- a/epan/dissectors/packet-dcerpc.c +++ b/epan/dissectors/packet-dcerpc.c @@ -26,6 +26,7 @@ #include "config.h" +#include #include /* for sscanf() */ #include #include @@ -1658,6 +1659,28 @@ dissect_dcerpc_guid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *d return tvb_captured_length(tvb); } +static void +dcerpc_init_finalize(dissector_handle_t guid_handle, guid_key *key, dcerpc_uuid_value *value) +{ + module_t *samr_module; + const char *filter_name = proto_get_protocol_filter_name(value->proto_id); + + g_hash_table_insert(dcerpc_uuids, key, value); + + /* Register the GUID with the dissector table */ + dissector_add_guid( "dcerpc.uuid", key, guid_handle ); + + /* add this GUID to the global name resolving */ + guids_add_uuid(&key->guid, proto_get_protocol_short_name(value->proto)); + + /* Register the samr.nt_password preference as obsolete */ + /* This should be in packet-dcerpc-samr.c */ + if (strcmp(filter_name, "samr") == 0) { + samr_module = prefs_register_protocol_obsolete(value->proto_id); + prefs_register_obsolete_preference(samr_module, "nt_password"); + } +} + void dcerpc_init_uuid(int proto, int ett, e_guid_t *uuid, guint16 ver, dcerpc_sub_dissector *procs, int opnum_hf) @@ -1665,8 +1688,6 @@ dcerpc_init_uuid(int proto, int ett, e_guid_t *uuid, guint16 ver, guid_key *key = (guid_key *)g_malloc(sizeof (*key)); dcerpc_uuid_value *value = (dcerpc_uuid_value *)g_malloc(sizeof (*value)); header_field_info *hf_info; - module_t *samr_module; - const char *filter_name = proto_get_protocol_filter_name(proto); dissector_handle_t guid_handle; key->guid = *uuid; @@ -1679,24 +1700,37 @@ dcerpc_init_uuid(int proto, int ett, e_guid_t *uuid, guint16 ver, value->procs = procs; value->opnum_hf = opnum_hf; - g_hash_table_insert(dcerpc_uuids, key, value); - hf_info = proto_registrar_get_nth(opnum_hf); hf_info->strings = value_string_from_subdissectors(procs); /* Register the GUID with the dissector table */ guid_handle = create_dissector_handle( dissect_dcerpc_guid, proto); - dissector_add_guid( "dcerpc.uuid", key, guid_handle ); - /* add this GUID to the global name resolving */ - guids_add_uuid(uuid, proto_get_protocol_short_name(value->proto)); + dcerpc_init_finalize(guid_handle, key, value); +} - /* Register the samr.nt_password preference as obsolete */ - /* This should be in packet-dcerpc-samr.c */ - if (strcmp(filter_name, "samr") == 0) { - samr_module = prefs_register_protocol_obsolete(proto); - prefs_register_obsolete_preference(samr_module, "nt_password"); +void +dcerpc_init_from_handle(int proto, e_guid_t *uuid, guint16 ver, + dissector_handle_t guid_handle) +{ + guid_key *key = (guid_key *)g_malloc(sizeof (*key)); + dcerpc_uuid_value *value = (dcerpc_uuid_value *)g_malloc(sizeof (*value)); + + key->guid = *uuid; + key->ver = ver; + + value->proto = find_protocol_by_id(proto); + value->proto_id = proto; + value->ett = -1; + value->name = proto_get_protocol_short_name(value->proto); + value->opnum_hf = 0; + + if (g_hash_table_contains(dcerpc_uuids, key)) { + g_hash_table_remove(dcerpc_uuids, key); + guids_delete_guid(uuid); } + + dcerpc_init_finalize(guid_handle, key, value); } /* Function to find the name of a registered protocol diff --git a/epan/dissectors/packet-dcerpc.h b/epan/dissectors/packet-dcerpc.h index f1759111e3..05159e8f73 100644 --- a/epan/dissectors/packet-dcerpc.h +++ b/epan/dissectors/packet-dcerpc.h @@ -392,6 +392,8 @@ typedef struct _dcerpc_sub_dissector { WS_DLL_PUBLIC void dcerpc_init_uuid (int proto, int ett, e_guid_t *uuid, guint16 ver, dcerpc_sub_dissector *procs, int opnum_hf); WS_DLL_PUBLIC +void dcerpc_init_from_handle(int proto, e_guid_t *uuid, guint16 ver, dissector_handle_t guid_handle); +WS_DLL_PUBLIC const char *dcerpc_get_proto_name(e_guid_t *uuid, guint16 ver); WS_DLL_PUBLIC int dcerpc_get_proto_hf_opnum(e_guid_t *uuid, guint16 ver); diff --git a/epan/guid-utils.c b/epan/guid-utils.c index 2e99085a04..fd0807dddd 100644 --- a/epan/guid-utils.c +++ b/epan/guid-utils.c @@ -106,6 +106,47 @@ guids_add_guid(const e_guid_t *guid, const gchar *name) wmem_tree_insert32_array(guid_to_name_tree, &guidkey[0], (gchar *) name); } +/* remove a guid to name mapping */ +void +guids_delete_guid(const e_guid_t *guid) +{ + wmem_tree_key_t guidkey[2]; + guint32 g[4]; + + g[0] = guid->data1; + + g[1] = guid->data2; + g[1] <<= 16; + g[1] |= guid->data3; + + g[2] = guid->data4[0]; + g[2] <<= 8; + g[2] |= guid->data4[1]; + g[2] <<= 8; + g[2] |= guid->data4[2]; + g[2] <<= 8; + g[2] |= guid->data4[3]; + + g[3] = guid->data4[4]; + g[3] <<= 8; + g[3] |= guid->data4[5]; + g[3] <<= 8; + g[3] |= guid->data4[6]; + g[3] <<= 8; + g[3] |= guid->data4[7]; + + guidkey[0].key = g; + guidkey[0].length = 4; + guidkey[1].length = 0; + + void *data = wmem_tree_lookup32_array(guid_to_name_tree, &guidkey[0]); + + if (data != NULL) { + // This will "remove" the entry by setting its data to NULL + wmem_tree_insert32_array(guid_to_name_tree, &guidkey[0], NULL); + } + +} /* retrieve the registered name for this GUID; uses the scope for the fallback case only */ const gchar * diff --git a/epan/guid-utils.h b/epan/guid-utils.h index 87e7c85aa1..f00cbf5dac 100644 --- a/epan/guid-utils.h +++ b/epan/guid-utils.h @@ -35,6 +35,9 @@ WS_DLL_PUBLIC void guids_init(void); /* add a GUID */ WS_DLL_PUBLIC void guids_add_guid(const e_guid_t *guid, const gchar *name); +/* remove a guid to name mapping */ +WS_DLL_PUBLIC void guids_delete_guid(const e_guid_t *guid); + /* try to get registered name for this GUID */ WS_DLL_PUBLIC const gchar *guids_get_guid_name(const e_guid_t *guid, wmem_allocator_t *scope); diff --git a/epan/packet.c b/epan/packet.c index 70507045af..d0690c61f6 100644 --- a/epan/packet.c +++ b/epan/packet.c @@ -1381,6 +1381,36 @@ void dissector_delete_uint_range(const char *name, range_t *range, } } +/* Remove an entry from a guid dissector table. */ +void dissector_delete_guid(const char *name, guid_key* guid_val, dissector_handle_t handle) +{ + dissector_table_t sub_dissectors; + dtbl_entry_t *dtbl_entry; + + sub_dissectors = find_dissector_table(name); + + /* sanity check */ + ws_assert(sub_dissectors); + + /* Find the table entry */ + dtbl_entry = (dtbl_entry_t *)g_hash_table_lookup(sub_dissectors->hash_table, guid_val); + + if (dtbl_entry == NULL) { + fprintf(stderr, "OOPS: guid not found in dissector table \"%s\"\n", name); + return; + } + + /* Make sure the handles match */ + if (dtbl_entry->current != handle) { + fprintf(stderr, "OOPS: handle does not match for guid in dissector table \"%s\"\n", name); + return; + } + + /* Remove the table entry */ + g_hash_table_remove(sub_dissectors->hash_table, guid_val); +} + + static gboolean dissector_delete_all_check (gpointer key _U_, gpointer value, gpointer user_data) { diff --git a/epan/packet.h b/epan/packet.h index 2484cd6a14..805e99ac8d 100644 --- a/epan/packet.h +++ b/epan/packet.h @@ -383,6 +383,10 @@ WS_DLL_PUBLIC int dissector_try_guid(dissector_table_t sub_dissectors, WS_DLL_PUBLIC int dissector_try_guid_new(dissector_table_t sub_dissectors, guid_key* guid_val, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const gboolean add_proto_name, void *data); +/* Delete a GUID from a dissector table. */ +WS_DLL_PUBLIC void dissector_delete_guid(const char *name, guid_key* guid_val, + dissector_handle_t handle); + /** Look for a given value in a given guid dissector table and, if found, * return the current dissector handle for that value. * diff --git a/epan/wslua/wslua_dissector.c b/epan/wslua/wslua_dissector.c index 5b18930827..b2a4330d9b 100644 --- a/epan/wslua/wslua_dissector.c +++ b/epan/wslua/wslua_dissector.c @@ -17,11 +17,15 @@ #include "config.h" +#include "epan/guid-utils.h" +#include "epan/proto.h" #include "wslua.h" #include #include #include +#include +#include /* WSLUA_CONTINUE_MODULE Proto */ @@ -166,8 +170,8 @@ WSLUA_CONSTRUCTOR DissectorTable_new (lua_State *L) { #define WSLUA_OPTARG_DissectorTable_new_UINAME 2 /* The name of the table in the user interface. Defaults to the name given in `tablename`, but can be any string. */ #define WSLUA_OPTARG_DissectorTable_new_TYPE 3 /* One of `ftypes.UINT8`, `ftypes.UINT16`, - `ftypes.UINT24`, `ftypes.UINT32`, or - `ftypes.STRING`. + `ftypes.UINT24`, `ftypes.UINT32`, + `ftypes.STRING`, or `ftypes.GUID`. Defaults to `ftypes.UINT32`. */ #define WSLUA_OPTARG_DissectorTable_new_BASE 4 /* One of `base.NONE`, `base.DEC`, `base.HEX`, `base.OCT`, `base.DEC_HEX` or `base.HEX_DEC`. @@ -194,12 +198,16 @@ WSLUA_CONSTRUCTOR DissectorTable_new (lua_State *L) { case FT_UINT32: break; + case FT_GUID: + base = BASE_HEX; + break; + default: /* Calling WSLUA_OPTARG_ERROR raises a Lua error and returns from this function. */ WSLUA_OPTARG_ERROR( DissectorTable_new, TYPE, - "must be ftypes.UINT{8,16,24,32}, ftypes.STRING or ftypes.NONE"); + "must be ftypes.UINT{8,16,24,32}, ftypes.STRING, ftypes.GUID or ftypes.NONE"); break; } @@ -397,6 +405,21 @@ WSLUA_METHOD DissectorTable_add (lua_State *L) { gchar* pattern = g_strdup(luaL_checkstring(L,WSLUA_ARG_DissectorTable_add_PATTERN)); dissector_add_string(dt->name, pattern,handle); g_free (pattern); + } else if (type == FT_GUID) { + /* Handle GUID type (assuming it is represented as a string in Lua) */ + const gchar* guid_str = luaL_checkstring(L,WSLUA_ARG_DissectorTable_add_PATTERN); + fvalue_t* fval = fvalue_from_literal(type, guid_str, 0, NULL); + const e_guid_t* guid = fvalue_get_guid(fval); + guid_key gk = {*guid, 0}; + /* The dcerpc.uuid table requires its own initializer */ + if(strcmp(DCERPC_TABLE_NAME, dt->name) == 0) { + e_guid_t uuid; + memcpy(&uuid, guid, sizeof(e_guid_t)); + dcerpc_init_from_handle(dissector_handle_get_protocol_index(handle), &uuid, 0, handle); + } else { + dissector_add_guid(dt->name, &gk, handle); + guids_add_uuid(guid, dissector_handle_get_protocol_short_name(handle)); + } } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) { if (lua_isnumber(L, WSLUA_ARG_DissectorTable_add_PATTERN)) { int port = (int)luaL_checkinteger(L, WSLUA_ARG_DissectorTable_add_PATTERN); @@ -459,6 +482,21 @@ WSLUA_METHOD DissectorTable_set (lua_State *L) { const gchar* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_set_PATTERN); dissector_delete_all(dt->name, handle); dissector_add_string(dt->name, pattern,handle); + } else if (type == FT_GUID) { + /* Handle GUID type (assuming it is represented as a string in Lua) */ + const gchar* guid_str = luaL_checkstring(L,WSLUA_ARG_DissectorTable_set_PATTERN); + fvalue_t* fval = fvalue_from_literal(type, guid_str, 0, NULL); + const e_guid_t* guid = fvalue_get_guid(fval); + guid_key gk = {*guid, 0}; + /* The dcerpc.uuid table requires its own initializer */ + if(strcmp(DCERPC_TABLE_NAME, dt->name) == 0) { + e_guid_t uuid; + memcpy(&uuid, guid, sizeof(e_guid_t)); + dcerpc_init_from_handle(dissector_handle_get_protocol_index(handle), &uuid, 0, handle); + } else { + dissector_add_guid(dt->name, &gk, handle); + guids_add_uuid(guid, dissector_handle_get_protocol_short_name(handle)); + } } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) { if (lua_isnumber(L, WSLUA_ARG_DissectorTable_set_PATTERN)) { int port = (int)luaL_checkinteger(L, WSLUA_ARG_DissectorTable_set_PATTERN); @@ -515,6 +553,14 @@ WSLUA_METHOD DissectorTable_remove (lua_State *L) { gchar* pattern = g_strdup(luaL_checkstring(L,WSLUA_ARG_DissectorTable_remove_PATTERN)); dissector_delete_string(dt->name, pattern,handle); g_free (pattern); + } else if (type == FT_GUID) { + // Handle GUID type (assuming it is represented as a string in Lua) + const gchar* guid_str = luaL_checkstring(L,WSLUA_ARG_DissectorTable_remove_PATTERN); + fvalue_t* fval = fvalue_from_literal(type, guid_str, 0, NULL); + const e_guid_t* guid = fvalue_get_guid(fval); + guid_key gk = {*guid, 0}; + guids_delete_guid(guid); + dissector_delete_guid(dt->name, &gk, handle); } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) { if (lua_isnumber(L, WSLUA_ARG_DissectorTable_remove_PATTERN)) { int port = (int)luaL_checkinteger(L, WSLUA_ARG_DissectorTable_remove_PATTERN); @@ -596,6 +642,16 @@ WSLUA_METHOD DissectorTable_try (lua_State *L) { if (len > 0) { handled = TRUE; } + } else if ( type == FT_GUID ) { + const gchar* guid_str = luaL_checkstring(L,WSLUA_ARG_DissectorTable_try_PATTERN); + fvalue_t* fval = fvalue_from_literal(type, guid_str, 0, NULL); + const e_guid_t* guid = fvalue_get_guid(fval); + guid_key gk = {*guid, 0}; + + len = dissector_try_guid(dt->table, &gk,tvb->ws_tvb,pinfo->ws_pinfo,ti->tree); + if (len > 0) { + handled = TRUE; + } } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) { int port = (int)luaL_checkinteger(L, WSLUA_ARG_DissectorTable_try_PATTERN); @@ -639,6 +695,12 @@ WSLUA_METHOD DissectorTable_get_dissector (lua_State *L) { if (type == FT_STRING) { const gchar* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_get_dissector_PATTERN); handle = dissector_get_string_handle(dt->table,pattern); + } else if ( type == FT_GUID ) { + const gchar* guid_str = luaL_checkstring(L,WSLUA_ARG_DissectorTable_get_dissector_PATTERN); + fvalue_t* fval = fvalue_from_literal(type, guid_str, 0, NULL); + const e_guid_t* guid = fvalue_get_guid(fval); + guid_key gk = {*guid, 0}; + handle = dissector_get_guid_handle(dt->table,&gk); } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) { int port = (int)luaL_checkinteger(L, WSLUA_ARG_DissectorTable_get_dissector_PATTERN); handle = dissector_get_uint_handle(dt->table,port); @@ -703,6 +765,11 @@ WSLUA_METAMETHOD DissectorTable__tostring(lua_State* L) { g_string_append_printf(s,"%s Integer(%i):\n",dt->name,base); break; } + case FT_GUID: + { + g_string_append_printf(s,"%s GUID:\n",dt->name); + break; + } case FT_NONE: { g_string_append_printf(s,"%s only for Decode As:\n",dt->name);