aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors
diff options
context:
space:
mode:
authorPascal Quantin <pascal.quantin@gmail.com>2017-04-11 11:23:03 +0200
committerMichael Mann <mmann78@netscape.net>2017-04-11 11:40:24 +0000
commit87fc4cc5d7d7838d9fb708ca0c00166014d4ace8 (patch)
tree883e16e65feca78a96713ab195f7fda43859762e /epan/dissectors
parent5bcd2f681e1507d7a9ddcfc89b5303178f9b7e75 (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')
-rw-r--r--epan/dissectors/packet-gsm_sms.c170
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);
}