aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPascal Quantin <pascal.quantin@gmail.com>2013-06-12 16:59:59 +0000
committerPascal Quantin <pascal.quantin@gmail.com>2013-06-12 16:59:59 +0000
commit0975d03e8df9b1dd24215ccec50fbb93d6f18a1f (patch)
treecf12d5d45948d43612123fbff35080adf945db08
parent855870768130ba53bcaaa61b243b4ba79cf5edc1 (diff)
Fix dissection of 3GPP2 SMS messages when the User Data Header field is present (for fragmented SMS)
svn path=/trunk/; revision=49910
-rw-r--r--epan/dissectors/packet-ansi_637.c133
-rw-r--r--epan/dissectors/packet-gsm_sms.c111
-rw-r--r--epan/dissectors/packet-gsm_sms.h3
3 files changed, 168 insertions, 79 deletions
diff --git a/epan/dissectors/packet-ansi_637.c b/epan/dissectors/packet-ansi_637.c
index 404b41e1ec..78cf5b027a 100644
--- a/epan/dissectors/packet-ansi_637.c
+++ b/epan/dissectors/packet-ansi_637.c
@@ -185,6 +185,7 @@ static int hf_ansi_637_trans_bin_addr = -1;
static int hf_ansi_637_tele_msg_type = -1;
static int hf_ansi_637_tele_msg_id = -1;
static int hf_ansi_637_tele_msg_status = -1;
+static int hf_ansi_637_tele_msg_ind = -1;
static int hf_ansi_637_tele_msg_rsvd = -1;
static int hf_ansi_637_tele_subparam_id = -1;
static int hf_ansi_637_tele_user_data_text = -1;
@@ -321,20 +322,18 @@ decode_7_bits(tvbuff_t *tvb, guint32 *offset, guint8 num_fields, guint8 *last_oc
static void
tele_param_msg_id(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
{
- guint32 octs;
-
EXACT_DATA_CHECK(len, 3);
- octs = tvb_get_ntoh24(tvb, offset);
+ proto_tree_add_item(tree, hf_ansi_637_tele_msg_type, tvb, offset, 3, ENC_BIG_ENDIAN);
- proto_tree_add_uint(tree, hf_ansi_637_tele_msg_type,
- tvb, offset, 3, octs);
+ proto_tree_add_item(tree, hf_ansi_637_tele_msg_id, tvb, offset, 3, ENC_BIG_ENDIAN);
- proto_tree_add_uint(tree, hf_ansi_637_tele_msg_id,
- tvb, offset, 3, octs);
+ proto_tree_add_item(tree, hf_ansi_637_tele_msg_ind, tvb, offset, 3, ENC_BIG_ENDIAN);
+ if ((tvb_get_guint8(tvb, offset+2) & 0x08) == 0x08) {
+ g_pinfo->private_data = GUINT_TO_POINTER((guint) TRUE);
+ }
- proto_tree_add_uint(tree, hf_ansi_637_tele_msg_rsvd,
- tvb, offset, 3, octs);
+ proto_tree_add_item(tree, hf_ansi_637_tele_msg_rsvd, tvb, offset, 3, ENC_BIG_ENDIAN);
}
/* Adamek Jan - IS637C Message status decoding procedure */
@@ -451,6 +450,8 @@ tele_param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
guint32 saved_offset;
guint32 i , out_len;
const gchar *str = NULL;
+ gchar *buf;
+ tvbuff_t * tvb_out = NULL;
/*add more translation UCS , IA5 , latin , latin \ hebrew ,gsm 7BIT*/
gchar *utf8_text = NULL;
@@ -566,12 +567,30 @@ tele_param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
return;
}
- bit = 3;
+ saved_offset = offset - 1;
+ i = num_fields * 7;
+ required_octs = (i / 8) + ((i % 8) ? 1 : 0);
+ buf = (gchar*)ep_alloc(required_octs);
+ for (i=0; i < required_octs; i++)
+ {
+ oct = tvb_get_guint8(tvb, saved_offset);
+ oct2 = tvb_get_guint8(tvb, saved_offset + 1);
+ buf[i] = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3);
+ saved_offset++;
+ }
+ tvb_out = tvb_new_child_real_data(tvb, buf, required_octs, required_octs);
+ add_new_data_source(g_pinfo, tvb_out, "Characters");
+ offset = 0;
+ bit = 0;
+ if (g_pinfo->private_data && (GPOINTER_TO_UINT(g_pinfo->private_data) == TRUE)) {
+ dis_field_udh(tvb_out, tree, &offset, &required_octs, &num_fields, TRUE, &bit);
+ }
+
saved_offset = offset;
- decode_7_bits(tvb, &offset, num_fields, &oct, &bit, ansi_637_bigbuf);
+ decode_7_bits(tvb_out, &offset, num_fields, &oct, &bit, ansi_637_bigbuf);
- proto_tree_add_unicode_string(tree, hf_ansi_637_tele_user_data_text, tvb, saved_offset,
+ proto_tree_add_unicode_string(tree, hf_ansi_637_tele_user_data_text, tvb_out, saved_offset,
offset - saved_offset, ansi_637_bigbuf);
switch (bit)
@@ -607,12 +626,29 @@ tele_param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
return;
}
- bit = 3;
+ saved_offset = offset - 1;
+ i = num_fields * 7;
+ required_octs = (i / 8) + ((i % 8) ? 1 : 0);
+ buf = (gchar*)ep_alloc(required_octs);
+ for (i=0; i < required_octs; i++)
+ {
+ oct = tvb_get_guint8(tvb, saved_offset);
+ oct2 = tvb_get_guint8(tvb, saved_offset + 1);
+ buf[i] = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3);
+ saved_offset++;
+ }
+ tvb_out = tvb_new_child_real_data(tvb, buf, required_octs, required_octs);
+ add_new_data_source(g_pinfo, tvb_out, "Characters");
+ offset = 0;
+ bit = 0;
+ if (g_pinfo->private_data && (GPOINTER_TO_UINT(g_pinfo->private_data) == TRUE)) {
+ dis_field_udh(tvb_out, tree, &offset, &required_octs, &num_fields, TRUE, &bit);
+ }
saved_offset = offset;
- out_len = decode_7_bits(tvb, &offset, num_fields, &oct, &bit, ansi_637_bigbuf);
+ out_len = decode_7_bits(tvb_out, &offset, num_fields, &oct, &bit, ansi_637_bigbuf);
IA5_7BIT_decode(ia5_637_bigbuf, ansi_637_bigbuf, out_len);
- proto_tree_add_unicode_string(tree, hf_ansi_637_tele_user_data_text, tvb, saved_offset,
+ proto_tree_add_unicode_string(tree, hf_ansi_637_tele_user_data_text, tvb_out, saved_offset,
offset - saved_offset, ia5_637_bigbuf);
}
@@ -622,25 +658,33 @@ tele_param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
else if (encoding == 0x07)/* Latin/Hebrew */
{
saved_offset = offset - 1;
+ buf = (gchar*)ep_alloc(num_fields);
for (i=0; i < num_fields; i++)
{
oct = tvb_get_guint8(tvb, saved_offset);
oct2 = tvb_get_guint8(tvb, saved_offset + 1);
- ansi_637_bigbuf[i] = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3);
+ buf[i] = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3);
saved_offset++;
}
+ tvb_out = tvb_new_child_real_data(tvb, buf, num_fields, num_fields);
+ add_new_data_source(g_pinfo, tvb_out, "Characters");
+ offset = 0;
+ required_octs = len - used;
+ if (g_pinfo->private_data && (GPOINTER_TO_UINT(g_pinfo->private_data) == TRUE)) {
+ dis_field_udh(tvb_out, tree, &offset, &required_octs, &num_fields, FALSE, &bit);
+ }
if ((cd = g_iconv_open("UTF-8","iso-8859-8")) != (GIConv)-1)
{
- utf8_text = g_convert_with_iconv(tvb_get_ptr(tvb, offset, num_fields), num_fields , cd , NULL , NULL , &l_conv_error);
+ utf8_text = g_convert_with_iconv(tvb_get_ptr(tvb_out, offset, num_fields), num_fields , cd , NULL , NULL , &l_conv_error);
if(!l_conv_error)
{
- proto_tree_add_unicode_string(tree, hf_ansi_637_tele_user_data_text, tvb, offset,
+ proto_tree_add_unicode_string(tree, hf_ansi_637_tele_user_data_text, tvb_out, offset,
num_fields, utf8_text);
}
else
{
- proto_tree_add_text(tree, tvb, offset, num_fields, "%s", "Failed on iso-8859-8 contact Wireshark developers");
+ proto_tree_add_text(tree, tvb_out, offset, num_fields, "%s", "Failed on iso-8859-8 contact Wireshark developers");
}
if(utf8_text)
g_free(utf8_text);
@@ -650,25 +694,33 @@ tele_param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
else if (encoding == 0x08) /* Latin */
{
saved_offset = offset - 1;
+ buf = (gchar*)ep_alloc(num_fields);
for (i=0; i < num_fields; i++)
{
oct = tvb_get_guint8(tvb, saved_offset);
oct2 = tvb_get_guint8(tvb, saved_offset + 1);
- ansi_637_bigbuf[i] = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3);
+ buf[i] = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3);
saved_offset++;
}
+ tvb_out = tvb_new_child_real_data(tvb, buf, num_fields, num_fields);
+ add_new_data_source(g_pinfo, tvb_out, "Characters");
+ offset = 0;
+ required_octs = len - used;
+ if (g_pinfo->private_data && (GPOINTER_TO_UINT(g_pinfo->private_data) == TRUE)) {
+ dis_field_udh(tvb_out, tree, &offset, &required_octs, &num_fields, FALSE, &bit);
+ }
if ((cd = g_iconv_open("UTF-8","iso-8859-1")) != (GIConv)-1)
{
- utf8_text = g_convert_with_iconv(ansi_637_bigbuf , num_fields , cd , NULL , NULL , &l_conv_error);
+ utf8_text = g_convert_with_iconv(tvb_get_ptr(tvb_out, offset, num_fields) , num_fields , cd , NULL , NULL , &l_conv_error);
if(!l_conv_error)
{
- proto_tree_add_unicode_string(tree, hf_ansi_637_tele_user_data_text, tvb, offset,
+ proto_tree_add_unicode_string(tree, hf_ansi_637_tele_user_data_text, tvb_out, offset,
num_fields, utf8_text);
}
else
{
- proto_tree_add_text(tree, tvb, offset, num_fields, "%s", "Failed on iso-8859-1 contact Wireshark developers");
+ proto_tree_add_text(tree, tvb_out, offset, num_fields, "%s", "Failed on iso-8859-1 contact Wireshark developers");
}
if(utf8_text)
g_free(utf8_text);
@@ -690,18 +742,29 @@ tele_param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
}
saved_offset = offset - 1;
+ i = num_fields * 7;
+ required_octs = (i / 8) + ((i % 8) ? 1 : 0);
+ buf = (gchar*)ep_alloc(required_octs);
for (i=0; i < required_octs; i++)
{
oct = tvb_get_guint8(tvb, saved_offset);
oct2 = tvb_get_guint8(tvb, saved_offset + 1);
- ansi_637_bigbuf[i] = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3);
+ buf[i] = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3);
saved_offset++;
}
+ tvb_out = tvb_new_child_real_data(tvb, buf, required_octs, required_octs);
+ add_new_data_source(g_pinfo, tvb_out, "Characters");
+ offset = 0;
+ bit = 0;
+ if (g_pinfo->private_data && (GPOINTER_TO_UINT(g_pinfo->private_data) == TRUE)) {
+ dis_field_udh(tvb_out, tree, &offset, &required_octs, &num_fields, TRUE, &bit);
+ }
- out_len = gsm_sms_char_7bit_unpack(0, required_octs+1, num_fields, ansi_637_bigbuf, gsm_637_bigbuf);
+ out_len = gsm_sms_char_7bit_unpack(bit, required_octs, num_fields,
+ tvb_get_ptr(tvb_out, offset, required_octs), gsm_637_bigbuf);
gsm_637_bigbuf[out_len] = '\0';
- proto_tree_add_unicode_string(tree, hf_ansi_637_tele_user_data_text, tvb, offset,
+ proto_tree_add_unicode_string(tree, hf_ansi_637_tele_user_data_text, tvb_out, offset,
required_octs, gsm_sms_chars_to_utf8(gsm_637_bigbuf, num_fields));
}
else
@@ -1855,6 +1918,7 @@ dissect_ansi_637_tele(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
proto_tree *ansi_637_tree = NULL;
const gchar *str = NULL;
guint32 value;
+ void* pd_save;
col_set_str(pinfo->cinfo, COL_PROTOCOL, ansi_proto_name_short);
@@ -1863,6 +1927,11 @@ dissect_ansi_637_tele(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
*/
if (tree)
{
+ pd_save = pinfo->private_data;
+ pinfo->private_data = NULL;
+ g_pinfo = pinfo;
+ g_tree = tree;
+
value = pinfo->match_uint;
/*
@@ -1947,6 +2016,7 @@ dissect_ansi_637_tele(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
proto_item_add_subtree(ansi_637_item, ett_ansi_637_tele);
dissect_ansi_637_tele_message(tvb, ansi_637_tree);
+ pinfo->private_data = pd_save;
}
}
@@ -2034,6 +2104,7 @@ dissect_ansi_637_trans(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
const gchar *str = NULL;
guint8 oct;
guint8 len;
+ void* pd_save;
col_set_str(pinfo->cinfo, COL_PROTOCOL, ansi_proto_name_short);
@@ -2042,6 +2113,8 @@ dissect_ansi_637_trans(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
*/
if (tree)
{
+ pd_save = pinfo->private_data;
+ pinfo->private_data = NULL;
g_pinfo = pinfo;
g_tree = tree;
@@ -2104,6 +2177,7 @@ dissect_ansi_637_trans(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
break;
}
}
+ pinfo->private_data = pd_save;
}
}
/* Dissect SMS embedded in SIP */
@@ -2160,10 +2234,15 @@ proto_register_ansi_637(void)
"ansi_637_tele.msg_status",
FT_UINT8, BASE_DEC, VALS(ansi_tele_msg_status_strings), 0,
NULL, HFILL }},
+ { &hf_ansi_637_tele_msg_ind,
+ { "Header Indicator",
+ "ansi_637_tele.msg_ind",
+ FT_UINT24, BASE_DEC, NULL, 0x000008,
+ NULL, HFILL }},
{ &hf_ansi_637_tele_msg_rsvd,
{ "Reserved",
"ansi_637_tele.msg_rsvd",
- FT_UINT24, BASE_DEC, NULL, 0x00000f,
+ FT_UINT24, BASE_DEC, NULL, 0x000007,
NULL, HFILL }},
{ &hf_ansi_637_tele_length,
{ "Length", "ansi_637_tele.len",
diff --git a/epan/dissectors/packet-gsm_sms.c b/epan/dissectors/packet-gsm_sms.c
index a29529f44d..b695aaaf01 100644
--- a/epan/dissectors/packet-gsm_sms.c
+++ b/epan/dissectors/packet-gsm_sms.c
@@ -2576,6 +2576,63 @@ dis_field_ud_iei(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
}
}
+void
+dis_field_udh(tvbuff_t *tvb, proto_tree *tree, guint32 *offset, guint32 *length,
+ guint8 *udl, gboolean uncomp_7bits, guint8 *fill_bits)
+{
+ guint8 oct;
+ proto_item *udh_item;
+ proto_tree *udh_subtree = NULL;
+ static guint8 fill_bits_mask[7] = { 0x0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f };
+
+ /* step over header */
+
+ oct = tvb_get_guint8(tvb, *offset);
+
+ udh_item =
+ proto_tree_add_text(tree, tvb,
+ *offset, oct + 1,
+ "User-Data Header");
+
+ udh_subtree = proto_item_add_subtree(udh_item, ett_udh);
+
+ proto_tree_add_text(udh_subtree,
+ tvb, *offset, 1,
+ "User Data Header Length (%u)",
+ oct);
+
+ (*offset)++;
+ (*length)--;
+
+ dis_field_ud_iei(tvb, udh_subtree, *offset, oct);
+
+ *offset += oct;
+ *length -= oct;
+
+ if (uncomp_7bits)
+ {
+ /* step over fill bits ? */
+
+ *fill_bits = 6 - ((oct * 8) % 7);
+ *udl -= (((oct + 1)*8) + *fill_bits) / 7;
+ if (*fill_bits)
+ {
+ oct = tvb_get_guint8(tvb, *offset);
+
+ other_decode_bitfield_value(bigbuf, oct, fill_bits_mask[*fill_bits], 8);
+ proto_tree_add_text(udh_subtree,
+ tvb, *offset, 1,
+ "%s : Fill bits",
+ bigbuf);
+ /* Note: Could add an expert item here if ((oct & fill_bits_mask[*fill_bits]) != 0) */
+ }
+ }
+ else
+ {
+ *udl -= oct + 1;
+ }
+}
+
/* 9.2.3.24 */
#define SMS_MAX_MESSAGE_SIZE 160
static char messagebuf[SMS_MAX_MESSAGE_SIZE+1];
@@ -2583,15 +2640,11 @@ static void
dis_field_ud(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset, guint32 length, gboolean udhi, guint8 udl,
gboolean seven_bit, gboolean eight_bit, gboolean ucs2, gboolean compressed)
{
- static guint8 fill_bits_mask[7] =
- { 0x0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f };
proto_item *item;
- proto_item *udh_item;
proto_tree *subtree = NULL;
- proto_tree *udh_subtree = NULL;
tvbuff_t *sm_tvb = NULL;
fragment_data *fd_sm = NULL;
- guint8 oct, fill_bits;
+ guint8 fill_bits;
guint32 out_len, total_sms_len, len_sms, length_ucs2, i;
char *ustr;
proto_item *ucs2_item;
@@ -2616,55 +2669,9 @@ dis_field_ud(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset
"TP-User-Data");
subtree = proto_item_add_subtree(item, ett_ud);
- oct = tvb_get_guint8(tvb, offset);
-
if (udhi)
{
-
- /* step over header */
-
- udh_item =
- proto_tree_add_text(subtree, tvb,
- offset, oct + 1,
- "User-Data Header");
-
- udh_subtree = proto_item_add_subtree(udh_item, ett_udh);
-
- proto_tree_add_text(udh_subtree,
- tvb, offset, 1,
- "User Data Header Length (%u)",
- oct);
-
- offset++;
- length--;
-
- dis_field_ud_iei(tvb, udh_subtree, offset, oct);
-
- offset += oct;
- length -= oct;
-
- if (seven_bit && !compressed)
- {
- /* step over fill bits ? */
-
- fill_bits = 6 - ((oct * 8) % 7);
- udl -= (((oct + 1)*8) + fill_bits) / 7;
- if (fill_bits)
- {
- oct = tvb_get_guint8(tvb, offset);
-
- other_decode_bitfield_value(bigbuf, oct, fill_bits_mask[fill_bits], 8);
- proto_tree_add_text(udh_subtree,
- tvb, offset, 1,
- "%s : Fill bits",
- bigbuf);
- /* Note: Could add an expert item here if ((oct & fill_bits_mask[fill_bits]) != 0) */
- }
- }
- else
- {
- udl -= oct + 1;
- }
+ dis_field_udh(tvb, subtree, &offset, &length, &udl, (seven_bit && !compressed), &fill_bits);
}
if (g_frags > 1)
diff --git a/epan/dissectors/packet-gsm_sms.h b/epan/dissectors/packet-gsm_sms.h
index 8a1547a4f6..6836ac76f7 100644
--- a/epan/dissectors/packet-gsm_sms.h
+++ b/epan/dissectors/packet-gsm_sms.h
@@ -48,3 +48,6 @@ extern int gsm_sms_char_7bit_unpack(unsigned int offset, unsigned int in_length,
*/
extern gchar *gsm_sms_chars_to_utf8(const unsigned char* src, int len);
+
+void dis_field_udh(tvbuff_t *tvb, proto_tree *tree, guint32 *offset, guint32 *length,
+ guint8 *udl, gboolean uncomp_7bits, guint8 *fill_bits);