Add a function to dissect an E.164 (MSISDN) number in UTF8 format and use it

in the Diameter dissector.

This new API adds a filter for the MSISDN as well as a subtree and filter for
the Country Code.

Change-Id: Ibcbf4b5f72178b7e4af63efa7496188d608a9de7
Reviewed-on: https://code.wireshark.org/review/3760
Petri-Dish: Jeff Morriss <jeff.morriss.ws@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
Reviewed-by: Jeff Morriss <jeff.morriss.ws@gmail.com>
This commit is contained in:
Jeff Morriss 2014-08-20 22:47:22 -04:00
parent c7c4abaab0
commit a3d8f31ad0
11 changed files with 186 additions and 119 deletions

View File

@ -965,7 +965,7 @@ if (!actx->value_ptr)
proto_tree_add_string(tree, hf_gsm_map_locationnumber_digits, tvb, 1, -1, digit_str);
if ((na == 3) && (np==1))/*International Number & E164*/
dissect_e164_cc(tvb, tree, 1, TRUE);
dissect_e164_cc(tvb, tree, 1, E164_ENC_BCD);
#.FN_BODY EnhancedCheckIMEI-Arg/locationInformation VAL_PTR = &parameter_tvb
tvbuff_t *parameter_tvb;

View File

@ -836,7 +836,7 @@ dissect_gsm_map_msisdn(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
na = (octet & 0x70)>>4;
np = octet & 0x0f;
if ((na == 1) && (np==1))/*International Number & E164*/
dissect_e164_cc(tvb, tree, 1, TRUE);
dissect_e164_cc(tvb, tree, 1, E164_ENC_BCD);
else if(np==6)
dissect_e212_mcc_mnc_in_address(tvb, pinfo, tree, 1);

View File

@ -65,6 +65,7 @@
#include "packet-tcp.h"
#include "packet-diameter.h"
#include "packet-e212.h"
#include "packet-e164.h"
void proto_register_diameter(void);
void proto_reg_handoff_diameter(void);
@ -514,9 +515,9 @@ dissect_diameter_subscription_id_data(tvbuff_t *tvb, packet_info *pinfo, proto_t
dissect_e212_utf8_imsi(tvb, pinfo, tree, 0, str_len);
return str_len;
case SUBSCRIPTION_ID_TYPE_E164:
/* TODO:
* dissect_e164_utf8_number()
*/
str_len = tvb_reported_length(tvb);
dissect_e164_utf8_number(tvb, tree, 0, str_len);
return str_len;
break;
}

View File

@ -541,7 +541,7 @@ dissect_diameter_3gpp_msisdn(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *
item = proto_tree_add_item(tree, hf_diameter_3gpp_msisdn, tvb, offset, length, ENC_NA);
sub_tree = proto_item_add_subtree(item,diameter_3gpp_msisdn_ett);
dissect_e164_cc(tvb, sub_tree, offset, TRUE);
dissect_e164_cc(tvb, sub_tree, offset, E164_ENC_BCD);
digit_str = unpack_digits(tvb, 1);
proto_tree_add_string(sub_tree, hf_diameter_address_digits, tvb, 1, -1, digit_str);

View File

@ -345,6 +345,7 @@ const value_string E164_country_code_value[] = {
{ 0, NULL }
};
static value_string_ext E164_country_code_value_ext = VALUE_STRING_EXT_INIT(E164_country_code_value);
const value_string E164_GMSS_vals[] = {
{ 0x6, "Iridium Satellite LLC"},
{ 0x7, "Iridium Satellite LLC"},
@ -352,6 +353,7 @@ const value_string E164_GMSS_vals[] = {
{ 0x9, "Globalstar"},
{ 0, NULL }
};
const value_string E164_International_Networks_882_vals[] = {
{ 0x10, "Global Office Application"},
{ 0x12, "HyperStream International (HSI) Data Network"},
@ -384,6 +386,7 @@ const value_string E164_International_Networks_882_vals[] = {
{ 0, NULL }
};
static value_string_ext E164_International_Networks_882_vals_ext = VALUE_STRING_EXT_INIT(E164_International_Networks_882_vals);
const value_string E164_International_Networks_883_vals[] = {
{ 0x100, "MediaLincc Ltd"},
{ 0x110, "Aicent Inc"},
@ -397,24 +400,25 @@ const value_string E164_International_Networks_883_vals[] = {
{ 0, NULL }
};
static int proto_e164 = -1;
static int proto_e164 = -1;
static int hf_E164_calling_party_number = -1;
static int hf_E164_called_party_number = -1;
static int hf_E164_number = -1;
static int hf_E164_identification_code = -1;
static int hf_E164_country_code = -1;
static int hf_E164_country_code = -1;
static int ett_e164_msisdn = -1;
void
dissect_e164_number(tvbuff_t *tvb, proto_tree *tree, int offset, int length,e164_info_t e164_info)
{
switch (e164_info.e164_number_type){
case CALLING_PARTY_NUMBER :
switch (e164_info.e164_number_type) {
case CALLING_PARTY_NUMBER:
proto_tree_add_string(tree, hf_E164_calling_party_number, tvb, offset,
length, e164_info.E164_number_str);
break;
case CALLED_PARTY_NUMBER :
case CALLED_PARTY_NUMBER:
proto_tree_add_string(tree, hf_E164_called_party_number, tvb, offset,
length, e164_info.E164_number_str);
break;
@ -424,206 +428,247 @@ dissect_e164_number(tvbuff_t *tvb, proto_tree *tree, int offset, int length,e164
}
}
void
dissect_e164_cc(tvbuff_t *tvb, proto_tree *tree, int offset, gboolean bcd_coded){
void
dissect_e164_cc(tvbuff_t *tvb, proto_tree *tree, int offset, e164_encoding_t encoding)
{
int cc_offset;
guint8 address_digit_pair;
guint16 id_code;
guint16 id_code = 0;
guint8 cc_length;
guint8 length;
guint16 cc;
guint16 cc = 0;
cc_offset = offset;
address_digit_pair = tvb_get_guint8(tvb, cc_offset);
if(!bcd_coded){
/* Get the first 3 digits of the MSISDN */
switch (encoding) {
case E164_ENC_BINARY:
/* Dissect country code after removing non significant zeros */
while ( address_digit_pair == 0 ) {
while (address_digit_pair == 0) {
cc_offset = cc_offset + 1;
address_digit_pair = tvb_get_guint8(tvb, cc_offset);
}
cc = tvb_get_ntohs(tvb, cc_offset);
if (( address_digit_pair & 0xf0 ) != 0 ){
if ((address_digit_pair & 0xf0) != 0) {
cc = cc >> 4;
}
}else{
break;
case E164_ENC_BCD:
cc = address_digit_pair &0x0f;
cc = cc << 4;
cc = cc | (address_digit_pair &0xf0)>>4;
cc = cc << 4;
if (tvb_bytes_exist(tvb, cc_offset+1, 1)){
if (tvb_bytes_exist(tvb, cc_offset+1, 1)) {
address_digit_pair = tvb_get_guint8(tvb, cc_offset+1);
cc = cc | (address_digit_pair &0x0f);
}
break;
case E164_ENC_UTF8:
/* XXX - do we need to worry about leading 0s? */
cc = (tvb_get_guint8(tvb, cc_offset) - '0') << 8;
cc |= (tvb_get_guint8(tvb, cc_offset+1) - '0') << 4;
cc |= (tvb_get_guint8(tvb, cc_offset+2) - '0');
break;
}
switch ( cc & 0x0f00 ) {
/* Determine how many of those digits are the Country Code */
switch (cc & 0x0f00) {
case 0x0:
cc_length = 1;
break;
case 0x0100:
cc_length = 1;
break;
case 0x0200:
switch ( cc & 0x00f0 ) {
switch (cc & 0x00f0) {
case 0:
case 0x70 :
case 0x70:
cc_length = 2;
break;
default :
default:
cc_length = 3;
break;
}
break;
case 0x0300 :
switch ( cc & 0x00f0 ) {
case 0 :
case 0x10 :
case 0x20 :
case 0x30 :
case 0x40 :
case 0x60 :
case 0x90 :
case 0x0300:
switch (cc & 0x00f0) {
case 0:
case 0x10:
case 0x20:
case 0x30:
case 0x40:
case 0x60:
case 0x90:
cc_length = 2;
break;
default :
default:
cc_length = 3;
break;
}
break;
case 0x0400 :
switch ( cc & 0x00f0 ) {
case 0x20 :
case 0x0400:
switch (cc & 0x00f0) {
case 0x20:
cc_length = 3;
break;
default :
default:
cc_length = 2;
break;
}
break;
case 0x0500 :
switch ( cc & 0x00f0 ) {
case 0 :
case 0x90 :
case 0x0500:
switch (cc & 0x00f0) {
case 0:
case 0x90:
cc_length = 3;
break;
default :
default:
cc_length = 2;
break;
}
break;
case 0x0600 :
switch ( cc & 0x00f0 ) {
case 0x70 :
case 0x80 :
case 0x90 :
case 0x0600:
switch (cc & 0x00f0) {
case 0x70:
case 0x80:
case 0x90:
cc_length = 3;
break;
default :
default:
cc_length = 2;
break;
}
break;
case 0x0700 :
case 0x0700:
cc_length = 1;
break;
case 0x0800 :
switch ( cc & 0x00f0 ) {
case 0x0800:
switch (cc & 0x00f0) {
case 0x10:
case 0x20:
case 0x40:
case 0x60:
cc_length = 2;
break;
default :
default:
cc_length = 3;
break;
}
break;
case 0x0900 :
switch ( cc & 0x00f0 ) {
case 0 :
case 0x10 :
case 0x20 :
case 0x30 :
case 0x40 :
case 0x50 :
case 0x80 :
case 0x0900:
switch (cc & 0x00f0) {
case 0:
case 0x10:
case 0x20:
case 0x30:
case 0x40:
case 0x50:
case 0x80:
cc_length = 2;
break;
default :
default:
cc_length = 3;
break;
}
break;
default :
default:
cc_length = 0;
break;
}/* End switch cc */
} /* End switch cc */
switch ( cc_length ) {
case 1 :
/* (Now that we know how long the CC is,)
* shift off any extra digits we got.
*/
switch (cc_length) {
case 1:
cc = cc >> 8;
length = 1;
break;
case 2 :
case 2:
cc = cc >> 4;
length = 1;
break;
default:
length = 2;
break;
}/* end switch cc_length */
} /* end switch cc_length */
proto_tree_add_uint(tree, hf_E164_country_code, tvb, cc_offset, length, cc);
/* Display the CC */
if (encoding == E164_ENC_UTF8)
proto_tree_add_uint(tree, hf_E164_country_code, tvb, cc_offset, cc_length, cc);
else
proto_tree_add_uint(tree, hf_E164_country_code, tvb, cc_offset, length, cc);
switch ( cc ) {
case 0x881 :
if (!bcd_coded) {
/* Handle special Country Codes */
switch (cc) {
case 0x881:
/* Get the 1-digit ID code */
switch (encoding) {
case E164_ENC_BINARY:
id_code = tvb_get_guint8(tvb, cc_offset + 1) & 0x0f;
} else {
break;
case E164_ENC_BCD:
id_code = (tvb_get_guint8(tvb, cc_offset + 1) & 0xf0) >> 4;
break;
case E164_ENC_UTF8:
id_code = tvb_get_guint8(tvb, cc_offset + cc_length) - '0';
break;
}
proto_tree_add_uint_format_value(tree, hf_E164_identification_code, tvb, (cc_offset + 1), 1,
id_code, "%x %s", id_code, val_to_str_const(id_code, E164_GMSS_vals, "Unknown"));
break;
case 0x882 :
if (!bcd_coded) {
case 0x882:
/* Get the 2-digit ID code */
switch (encoding) {
case E164_ENC_BINARY:
id_code = tvb_get_ntohs(tvb, cc_offset + 1);
id_code = (id_code & 0x0ff0) >> 4;
} else {
break;
case E164_ENC_BCD:
id_code = tvb_get_guint8(tvb, cc_offset + 1) & 0xf0;
id_code |= tvb_get_guint8(tvb, cc_offset + 2) & 0x0f;
break;
case E164_ENC_UTF8:
id_code = (tvb_get_guint8(tvb, cc_offset+cc_length) - '0') << 4;
id_code |= (tvb_get_guint8(tvb, cc_offset+cc_length+1) - '0');
break;
}
proto_tree_add_uint_format_value(tree, hf_E164_identification_code, tvb, (cc_offset + 1), 2,
id_code, "%x %s", id_code, val_to_str_ext_const(id_code, &E164_International_Networks_882_vals_ext, "Unknown"));
break;
case 0x883 :
if (!bcd_coded) {
case 0x883:
/* Get the 3-digit ID code */
switch (encoding) {
case E164_ENC_BINARY:
id_code = tvb_get_ntohs(tvb, cc_offset + 1);
id_code = id_code & 0x0fff;
} else {
break;
case E164_ENC_BCD:
id_code = (tvb_get_guint8(tvb, cc_offset + 1) & 0xf0) << 4;
id_code |= (tvb_get_guint8(tvb, cc_offset + 2) & 0x0f) << 4;
id_code |= (tvb_get_guint8(tvb, cc_offset + 2) & 0xf0) >> 4;
break;
case E164_ENC_UTF8:
id_code = (tvb_get_guint8(tvb, cc_offset+cc_length) - '0') << 8;
id_code |= (tvb_get_guint8(tvb, cc_offset+cc_length+1) - '0') << 4;
id_code |= (tvb_get_guint8(tvb, cc_offset+cc_length+2) - '0');
break;
}
if ((id_code & 0x0ff0) == 0x510) {
if (!bcd_coded) {
/* Get the 4th digit of the ID code */
switch (encoding) {
case E164_ENC_BINARY:
id_code = (id_code << 4) | ((tvb_get_guint8(tvb, cc_offset + 3) & 0xf0) >> 4);
} else {
break;
case E164_ENC_BCD:
id_code = (id_code << 4) | (tvb_get_guint8(tvb, cc_offset + 3) & 0x0f);
break;
case E164_ENC_UTF8:
id_code = (id_code << 4) | (tvb_get_guint8(tvb, cc_offset + cc_length + 3) - '0');
break;
}
proto_tree_add_uint_format_value(tree, hf_E164_identification_code, tvb, (cc_offset + 1), 3,
id_code, "%x %s", id_code, val_to_str_const(id_code, E164_International_Networks_883_vals, "Unknown"));
@ -638,6 +683,23 @@ dissect_e164_cc(tvbuff_t *tvb, proto_tree *tree, int offset, gboolean bcd_coded)
}
const gchar *
dissect_e164_utf8_number(tvbuff_t *tvb, proto_tree *tree, int offset, int length)
{
proto_item *pi;
proto_tree *subtree;
gchar *msisdn_str;
msisdn_str = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, length, ENC_UTF_8);
pi = proto_tree_add_string(tree, hf_E164_number, tvb, offset, length, msisdn_str);
subtree = proto_item_add_subtree(pi, ett_e164_msisdn);
dissect_e164_cc(tvb, subtree, offset, E164_ENC_UTF8);
return msisdn_str;
}
/*
* Register the protocol with Wireshark.
*
@ -661,6 +723,11 @@ proto_register_e164(void)
FT_STRING, BASE_NONE, NULL, 0x0,
NULL, HFILL }},
{ &hf_E164_number,
{ "E.164 number (MSISDN)", "e164.msisdn",
FT_STRING, BASE_NONE, NULL, 0x0,
NULL, HFILL }},
{ &hf_E164_identification_code,
{ "Identification Code", "e164.identification_code",
FT_UINT32, BASE_HEX, NULL, 0x0,
@ -672,18 +739,12 @@ proto_register_e164(void)
NULL, HFILL }},
};
/*
* Register the protocol name and description
*/
proto_e164 = proto_register_protocol(
"ITU-T E.164 number",
"E.164",
"e164");
static gint *ett_e164_array[] = {
&ett_e164_msisdn,
};
proto_e164 = proto_register_protocol("ITU-T E.164 number", "E.164", "e164");
/*
* Required function calls to register
* the header fields and subtrees used.
*/
proto_register_field_array(proto_e164, hf, array_length(hf));
proto_register_subtree_array(ett_e164_array, array_length(ett_e164_array));
}

View File

@ -34,7 +34,7 @@ typedef enum {
NONE,
CALLING_PARTY_NUMBER,
CALLED_PARTY_NUMBER
} e164_number_type_t;
} e164_number_type_t;
typedef struct {
e164_number_type_t e164_number_type;
@ -43,8 +43,13 @@ typedef struct {
guint E164_number_length; /* Length of the E164_number string */
} e164_info_t;
typedef enum {
E164_ENC_BINARY,
E164_ENC_BCD,
E164_ENC_UTF8
} e164_encoding_t;
extern void dissect_e164_number(tvbuff_t *tvb, proto_tree *tree, int offset, int length,
e164_info_t e164_info);
WS_DLL_PUBLIC void dissect_e164_cc(tvbuff_t *tvb, proto_tree *tree, int offset, gboolean bcd_coded);
extern void dissect_e164_number(tvbuff_t *tvb, proto_tree *tree, int offset, int length, e164_info_t e164_info);
WS_DLL_PUBLIC void dissect_e164_cc(tvbuff_t *tvb, proto_tree *tree, int offset, e164_encoding_t encoding);
WS_DLL_PUBLIC const gchar * dissect_e164_utf8_number(tvbuff_t *tvb, proto_tree *tree, int offset, int length);
#endif

View File

@ -3258,7 +3258,7 @@ dissect_gsm_map_msisdn(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
na = (octet & 0x70)>>4;
np = octet & 0x0f;
if ((na == 1) && (np==1))/*International Number & E164*/
dissect_e164_cc(tvb, tree, 1, TRUE);
dissect_e164_cc(tvb, tree, 1, E164_ENC_BCD);
else if(np==6)
dissect_e212_mcc_mnc_in_address(tvb, pinfo, tree, 1);
@ -3858,8 +3858,8 @@ dissect_gsm_map_IMSI(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U
if(tvb_reported_length(parameter_tvb)==0)
return offset;
/* Hide the octet string dfault printout */
PROTO_ITEM_SET_HIDDEN(actx->created_item);
/* Hide the octet string default printout */
PROTO_ITEM_SET_HIDDEN(actx->created_item);
dissect_e212_imsi(parameter_tvb, actx->pinfo, tree, 0, tvb_reported_length(parameter_tvb), FALSE);
@ -4943,7 +4943,7 @@ dissect_gsm_map_ss_USSD_String(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int
if (!parameter_tvb)
return offset;
length = tvb_ensure_length_remaining(parameter_tvb,0);
length = tvb_ensure_captured_length_remaining(parameter_tvb,0);
switch(sms_encoding){
case SMS_ENCODING_7BIT:
case SMS_ENCODING_7BIT_LANG:
@ -8189,7 +8189,7 @@ dissect_gsm_map_ms_LocationNumber(gboolean implicit_tag _U_, tvbuff_t *tvb _U_,
proto_tree_add_string(tree, hf_gsm_map_locationnumber_digits, tvb, 1, -1, digit_str);
if ((na == 3) && (np==1))/*International Number & E164*/
dissect_e164_cc(tvb, tree, 1, TRUE);
dissect_e164_cc(tvb, tree, 1, E164_ENC_BCD);

View File

@ -1573,7 +1573,7 @@ dissect_gtpv2_msisdn(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, pr
* When there is an odd number of digits, bits 8 to 5 of the last octet are encoded with
* the filler "1111".
*/
dissect_e164_cc(tvb, tree, 0, TRUE);
dissect_e164_cc(tvb, tree, 0, E164_ENC_BCD);
/* Fetch the BCD encoded digits from tvb low half byte, formating the digits according to
* a default digit set of 0-9 returning "?" for overdecadic digits a pointer to the EP
* allocated string will be returned.

View File

@ -4121,7 +4121,7 @@ dissect_nsap(tvbuff_t *parameter_tvb, gint offset, gint len, proto_tree *paramet
offset = offset +1;
/* Dissect country code */
cc_offset = offset;
dissect_e164_cc(parameter_tvb, parameter_tree, 3, TRUE);
dissect_e164_cc(parameter_tvb, parameter_tree, 3, E164_ENC_BCD);
proto_tree_add_text(parameter_tree, parameter_tvb, cc_offset, length, "DSP length %u(len %u -9)", (len-9), len);
@ -6870,7 +6870,7 @@ dissect_isup_generic_number_parameter(tvbuff_t *parameter_tvb, proto_tree *param
indicators1 = indicators1 & 0x7f;
indicators2 = (indicators2 & 0x70)>>4;
if ((indicators1 == ISUP_CALLED_PARTY_NATURE_INTERNATNL_NR) && (indicators2 == ISDN_NUMBERING_PLAN))
dissect_e164_cc(parameter_tvb, address_digits_tree, 3, TRUE);
dissect_e164_cc(parameter_tvb, address_digits_tree, 3, E164_ENC_BCD);
proto_item_append_text(address_digits_item, ": %s", calling_number);
proto_item_set_text(parameter_item, "Generic number: %s", calling_number);

View File

@ -1805,7 +1805,7 @@ dissect_mip6_opt_vsm_3gpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, v
break;
/* 12, MSISDN */
case 12:
dissect_e164_cc(tvb, tree, offset, TRUE);
dissect_e164_cc(tvb, tree, offset, E164_ENC_BCD);
digit_str = tvb_bcd_dig_to_wmem_packet_str( tvb, offset, len, NULL, FALSE);
proto_tree_add_string(tree, hf_mip6_opt_3gpp_msisdn, tvb, offset, len, digit_str);
proto_item_append_text(hdr_item, " %s", digit_str);

View File

@ -1780,7 +1780,7 @@ dissect_sccp_global_title(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
case GT_NP_ISDN:
case GT_NP_ISDN_MOBILE:
if (nai == GT_NAI_INTERNATIONAL_NUM) {
dissect_e164_cc(signals_tvb, digits_tree, 0, TRUE);
dissect_e164_cc(signals_tvb, digits_tree, 0, E164_ENC_BCD);
}
break;
case GT_NP_LAND_MOBILE: