diff options
author | dimeg <dimeg@f5534014-38df-0310-8fa8-9805f1628bb7> | 2010-02-01 21:19:56 +0000 |
---|---|---|
committer | dimeg <dimeg@f5534014-38df-0310-8fa8-9805f1628bb7> | 2010-02-01 21:19:56 +0000 |
commit | 0776c220ca53ce1bb7c57e9ec681ad90b390db8c (patch) | |
tree | c10f612290bac0f9b3fd9c377fe7671b67ea42a3 /epan/dissectors/packet-e212.c | |
parent | c90b9c935f3ba9f429fdd612e6322e2a380a28fb (diff) |
Fix for Bug 3116
wrong decoding IMSI with GSM MAP protocol
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@31764 f5534014-38df-0310-8fa8-9805f1628bb7
Diffstat (limited to 'epan/dissectors/packet-e212.c')
-rw-r--r-- | epan/dissectors/packet-e212.c | 96 |
1 files changed, 94 insertions, 2 deletions
diff --git a/epan/dissectors/packet-e212.c b/epan/dissectors/packet-e212.c index b74bdab4fb..e659b1b079 100644 --- a/epan/dissectors/packet-e212.c +++ b/epan/dissectors/packet-e212.c @@ -133,6 +133,7 @@ const value_string E212_codes[] = { { 401, "Kazakhstan (Republic of)" }, { 402, "Bhutan (Kingdom of)" }, { 404, "India (Republic of)" }, + { 405, "India (Republic of)" }, { 410, "Pakistan (Islamic Republic of)" }, { 412, "Afghanistan" }, { 413, "Sri Lanka (Democratic Socialist Republic of)" }, @@ -1604,8 +1605,6 @@ static int hf_E212_msin = -1; * | MNC digit 2 | MNC digit 1 | octet x+2 * +---------------+---------------+ */ - - int dissect_e212_mcc_mnc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset){ @@ -1650,6 +1649,99 @@ dissect_e212_mcc_mnc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int of return offset; } + +/* + * When we want to decode the MCC/MNC pair in an address that is encoded according to E.212 + * the main problem is that we do not know whether we are dealing with a length 2 or length 3 + * MNC. Initially, it was possible to find the length of the MNC by checking the MCC code. + * Originally each country employed a pure 2 digit or 3 digit MNC scheme. However, it is possible + * to find countries now that employ both lengths for the MNC (e.g. Canada, India). + * Since in these cases we can be sure that an MNC cannot possible be a prefix for another MNC, we + * initially assume that the MNC is 2 digits long. If the MCC/MNC combination gives a match in our + * mcc_mnc_codes list then we can be sure that we deal with an MNC that is 2 digits long. Otherwise, + * assume that the MNC is 3 digits long. + * + * MNC of length 2: + * + * 8 7 6 5 4 3 2 1 + * +---+---+---+---+---+---+---+---+ + * | MCC digit 2 | MCC digit 1 | octet x + * +---------------+---------------+ + * | MNC digit 1 | MCC digit 3 | octet x+1 + * +---------------+---------------+ + * | addr digit 1 | MNC digit 2 | octet x+2 + * +---------------+---------------+ + * + * MNC of length 3: + * + * 8 7 6 5 4 3 2 1 + * +---+---+---+---+---+---+---+---+ + * | MCC digit 2 | MCC digit 1 | octet x + * +---------------+---------------+ + * | MNC digit 1 | MCC digit 3 | octet x+1 + * +---------------+---------------+ + * | MNC digit 3 | MNC digit 2 | octet x+2 + * +---------------+---------------+ + * + * This function will consume either 2.5 or 3 octets. For this reason it returns + * the number of nibbles consumed, i.e. 5 or 6 (2 or 3 digits long MNC respectively) + */ +int +dissect_e212_mcc_mnc_in_address(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) +{ + guint32 start_offset; + guint8 octet; + guint16 mcc, mnc; + guint8 mcc1, mcc2, mcc3, mnc1, mnc2, mnc3; + proto_item *item; + gboolean long_mnc; + + long_mnc = FALSE; + start_offset = offset; + + /* MCC digits 1 and 2 */ + octet = tvb_get_guint8(tvb,offset); + mcc1 = octet & 0x0f; + mcc2 = octet >> 4; + offset++; + + /* MCC digit 3 and MNC digit 1 */ + octet = tvb_get_guint8(tvb,offset); + mcc3 = octet & 0x0f; + mnc1 = octet >> 4; + offset++; + + /* MNC digits 2 and 3 */ + octet = tvb_get_guint8(tvb,offset); + mnc2 = octet & 0x0f; + mnc3 = octet >> 4; + + mcc = 100 * mcc1 + 10 * mcc2 + mcc3; + mnc = 10 * mnc1 + mnc2; + + /* Try to match the MCC and 2 digits MNC with an entry in our list of operators */ + if (!match_strval(mcc * 1000 + mnc, mcc_mnc_codes)) { + mnc = 10 * mnc + mnc3; + long_mnc = TRUE; + } + + item = proto_tree_add_uint(tree, hf_E212_mcc , tvb, start_offset, 2, mcc ); + if ((mcc1 > 9) || (mcc2 > 9) || (mcc3 > 9)) + expert_add_info_format(pinfo, item, PI_MALFORMED, PI_WARN, "MCC contains non-decimal digits"); + + item = proto_tree_add_uint_format(tree, hf_E212_mnc , tvb, start_offset + 1, 2, mnc, + "Mobile Network Code (MNC): %s (%u)", + val_to_str(mcc * 1000 + mnc, mcc_mnc_codes, "Unknown"), + mnc); + if ((mnc1 > 9) || (mnc2 > 9) || (long_mnc && (mnc3 > 9))) + expert_add_info_format(pinfo, item, PI_MALFORMED, PI_WARN, "MNC contains non-decimal digits"); + + if(long_mnc) + return 6; + else + return 5; +} + /* * Register the protocol with Wireshark. * |