diff options
author | Pascal Quantin <pascal.quantin@gmail.com> | 2017-04-11 11:23:03 +0200 |
---|---|---|
committer | Michael Mann <mmann78@netscape.net> | 2017-04-11 11:40:24 +0000 |
commit | 87fc4cc5d7d7838d9fb708ca0c00166014d4ace8 (patch) | |
tree | 883e16e65feca78a96713ab195f7fda43859762e /epan/dissectors/packet-gsm_sms.c | |
parent | 5bcd2f681e1507d7a9ddcfc89b5303178f9b7e75 (diff) |
GSM SMS: take into consideration TP-OA/TP-DA fields and direction for reassembly
Bug: 13572
Change-Id: Ieb1b972f95bc5c445597dd9aa2a0d8e7e9985238
Reviewed-on: https://code.wireshark.org/review/21013
Reviewed-by: Michael Mann <mmann78@netscape.net>
Diffstat (limited to 'epan/dissectors/packet-gsm_sms.c')
-rw-r--r-- | epan/dissectors/packet-gsm_sms.c | 170 |
1 files changed, 154 insertions, 16 deletions
diff --git a/epan/dissectors/packet-gsm_sms.c b/epan/dissectors/packet-gsm_sms.c index 0298fa2431..cb3bde0b23 100644 --- a/epan/dissectors/packet-gsm_sms.c +++ b/epan/dissectors/packet-gsm_sms.c @@ -41,6 +41,7 @@ #include <epan/prefs.h> #include <epan/reassemble.h> #include <epan/charsets.h> +#include <epan/proto_data.h> #include "packet-gsm_sms.h" void proto_register_gsm_sms(void); @@ -335,6 +336,120 @@ typedef struct { guint8 fill_bits; } sm_fragment_params; +typedef struct { + const gchar *address; + int p2p_dir; + guint32 id; +} sm_fragment_params_key; + +static guint +sm_fragment_params_hash(gconstpointer k) +{ + const sm_fragment_params_key* key = (const sm_fragment_params_key*) k; + guint hash_val; + + hash_val = (wmem_str_hash(key->address) ^ key->id) + key->p2p_dir; + + return hash_val; +} + +static gboolean +sm_fragment_params_equal(gconstpointer v1, gconstpointer v2) +{ + const sm_fragment_params_key *key1 = (const sm_fragment_params_key*)v1; + const sm_fragment_params_key *key2 = (const sm_fragment_params_key*)v2; + + return (key1->id == key2->id) && + (key1->p2p_dir == key2->p2p_dir) && + !g_strcmp0(key1->address, key2->address); +} + +typedef struct { + const gchar *address; + int p2p_dir; + guint32 id; +} sm_fragment_key; + +static guint +sm_fragment_hash(gconstpointer k) +{ + const sm_fragment_key* key = (const sm_fragment_key*) k; + guint hash_val; + + hash_val = (wmem_str_hash(key->address) ^ key->id) + key->p2p_dir; + + return hash_val; +} + +static gint +sm_fragment_equal(gconstpointer k1, gconstpointer k2) +{ + const sm_fragment_key* key1 = (const sm_fragment_key*) k1; + const sm_fragment_key* key2 = (const sm_fragment_key*) k2; + + return (key1->id == key2->id) && + (key1->p2p_dir == key2->p2p_dir) && + !g_strcmp0(key1->address, key2->address); +} + +static gpointer +sm_fragment_temporary_key(const packet_info *pinfo, + const guint32 id, const void *data) +{ + const gchar* addr = (const char*)data; + sm_fragment_key *key = g_slice_new(sm_fragment_key); + + key->address = addr; + key->p2p_dir = pinfo->p2p_dir; + key->id = id; + + return (gpointer)key; +} + +static gpointer +sm_fragment_persistent_key(const packet_info *pinfo, + const guint32 id, const void *data) +{ + const gchar* addr = (const char*)data; + sm_fragment_key *key = g_slice_new(sm_fragment_key); + + key->address = wmem_strdup(NULL, addr); + key->p2p_dir = pinfo->p2p_dir; + key->id = id; + + return (gpointer)key; +} + +static void +sm_fragment_free_temporary_key(gpointer ptr) +{ + sm_fragment_key *key = (sm_fragment_key *)ptr; + + if(key) + g_slice_free(sm_fragment_key, key); +} + +static void +sm_fragment_free_persistent_key(gpointer ptr) +{ + sm_fragment_key *key = (sm_fragment_key *)ptr; + + if(key) { + wmem_free(NULL, (void*)key->address); + g_slice_free(sm_fragment_key, key); + } +} + +const reassembly_table_functions +sm_reassembly_table_functions = { + sm_fragment_hash, + sm_fragment_equal, + sm_fragment_temporary_key, + sm_fragment_persistent_key, + sm_fragment_free_temporary_key, + sm_fragment_free_persistent_key +}; + /* * this is the GSM 03.40 definition with the bit 2 * set to 1 for uplink messages @@ -526,9 +641,13 @@ dis_field_addr(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, guint32 *off if (g_ascii_strncasecmp(title, "TP-O", 4) == 0) { proto_tree_add_string(subtree, hf_gsm_sms_tp_oa, tvb, offset, numdigocts, addrstr); + p_add_proto_data(pinfo->pool, pinfo, proto_gsm_sms, 0, + wmem_strdup(pinfo->pool, addrstr)); } else if (g_ascii_strncasecmp(title, "TP-D", 4) == 0) { proto_tree_add_string(subtree, hf_gsm_sms_tp_da, tvb, offset, numdigocts, addrstr); + p_add_proto_data(pinfo->pool, pinfo, proto_gsm_sms, 0, + wmem_strdup(pinfo->pool, addrstr)); } else if (g_ascii_strncasecmp(title, "TP-R", 4) == 0) { proto_tree_add_string(subtree, hf_gsm_sms_tp_ra, tvb, offset, numdigocts, addrstr); @@ -1824,11 +1943,16 @@ dis_field_ud(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset gboolean is_fragmented = FALSE; gboolean save_fragmented = FALSE, try_gsm_sms_ud_reassemble = FALSE; - sm_fragment_params *p_frag_params; - gsm_sms_udh_fields_t udh_fields; + sm_fragment_params *p_frag_params; + sm_fragment_params_key *p_frag_params_key, frag_params_key; + const gchar *addr; + gsm_sms_udh_fields_t udh_fields; memset(&udh_fields, 0, sizeof(udh_fields)); fill_bits = 0; + addr = (gchar*)p_get_proto_data(pinfo->pool, pinfo, proto_gsm_sms, 0); + if (addr == NULL) + addr = ""; subtree = proto_tree_add_subtree(tree, tvb, @@ -1862,7 +1986,7 @@ dis_field_ud(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset fd_sm = fragment_add_seq_check (&g_sm_reassembly_table, tvb, offset, pinfo, udh_fields.sm_id, /* guint32 ID for fragments belonging together */ - NULL, + addr, udh_fields.frag-1, /* guint32 fragment sequence number */ length, /* guint32 fragment length */ (udh_fields.frag != udh_fields.frags)); /* More fragments? */ @@ -1889,14 +2013,18 @@ dis_field_ud(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset " (Short Message fragment %u of %u)", udh_fields.frag, udh_fields.frags); } - /* Store udl and length for later decoding of reassembled SMS */ - p_frag_params = wmem_new0(wmem_file_scope(), sm_fragment_params); - p_frag_params->udl = udl; - p_frag_params->fill_bits = fill_bits; - p_frag_params->length = length; - wmem_map_insert(g_sm_fragment_params_table, - GUINT_TO_POINTER((guint)((udh_fields.sm_id<<16)|(udh_fields.frag-1))), - p_frag_params); + if (!PINFO_FD_VISITED(pinfo)) { + /* Store udl and length for later decoding of reassembled SMS */ + p_frag_params_key = wmem_new(wmem_file_scope(), sm_fragment_params_key); + p_frag_params_key->address = wmem_strdup(wmem_file_scope(), addr); + p_frag_params_key->p2p_dir = pinfo->p2p_dir; + p_frag_params_key->id = (udh_fields.sm_id<<16)|(udh_fields.frag-1); + p_frag_params = wmem_new0(wmem_file_scope(), sm_fragment_params); + p_frag_params->udl = udl; + p_frag_params->fill_bits = fill_bits; + p_frag_params->length = length; + wmem_map_insert(g_sm_fragment_params_table, p_frag_params_key, p_frag_params); + } } /* Else: not fragmented */ if (! sm_tvb) /* One single Short Message, or not reassembled */ sm_tvb = tvb_new_subset_remaining (tvb, offset); @@ -1938,8 +2066,11 @@ dis_field_ud(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset total_sms_len = 0; for(i = 0 ; i < udh_fields.frags; i++) { + frag_params_key.address = addr; + frag_params_key.p2p_dir = pinfo->p2p_dir; + frag_params_key.id = (udh_fields.sm_id<<16)|i; p_frag_params = (sm_fragment_params*)wmem_map_lookup(g_sm_fragment_params_table, - GUINT_TO_POINTER((guint)((udh_fields.sm_id<<16)|i))); + &frag_params_key); if (p_frag_params) { proto_tree_add_item(subtree, hf_gsm_sms_text, sm_tvb, total_sms_len, @@ -1966,8 +2097,11 @@ dis_field_ud(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset total_sms_len = 0; for(i = 0 ; i < udh_fields.frags; i++) { + frag_params_key.address = addr; + frag_params_key.p2p_dir = pinfo->p2p_dir; + frag_params_key.id = (udh_fields.sm_id<<16)|i; p_frag_params = (sm_fragment_params*)wmem_map_lookup(g_sm_fragment_params_table, - GUINT_TO_POINTER((guint)((udh_fields.sm_id<<16)|i))); + &frag_params_key); if (p_frag_params) { proto_tree_add_ts_23_038_7bits_item(subtree, hf_gsm_sms_text, sm_tvb, @@ -2011,8 +2145,11 @@ dis_field_ud(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset total_sms_len = 0; for(i = 0 ; i < udh_fields.frags; i++) { + frag_params_key.address = addr; + frag_params_key.p2p_dir = pinfo->p2p_dir; + frag_params_key.id = (udh_fields.sm_id<<16)|i; p_frag_params = (sm_fragment_params*)wmem_map_lookup(g_sm_fragment_params_table, - GUINT_TO_POINTER((guint)((udh_fields.sm_id<<16)|i))); + &frag_params_key); if (p_frag_params) { proto_tree_add_item(subtree, hf_gsm_sms_text, sm_tvb, total_sms_len, @@ -3345,10 +3482,11 @@ proto_register_gsm_sms(void) register_dissector("gsm_sms", dissect_gsm_sms, proto_gsm_sms); - g_sm_fragment_params_table = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), g_direct_hash, g_direct_equal); + g_sm_fragment_params_table = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), + sm_fragment_params_hash, sm_fragment_params_equal); reassembly_table_register(&g_sm_reassembly_table, - &addresses_reassembly_table_functions); + &sm_reassembly_table_functions); } |