diff options
author | Jeff Morriss <jeff.morriss@ulticom.com> | 2012-02-03 04:09:10 +0000 |
---|---|---|
committer | Jeff Morriss <jeff.morriss@ulticom.com> | 2012-02-03 04:09:10 +0000 |
commit | 73ce69dcd475b6bb31147c582cdf4022bca00364 (patch) | |
tree | e2e8ac3f7279f70f289451f1602cd17d58469d98 | |
parent | e150c5799200d29da2349dc442524295dfc1d901 (diff) |
Improve heuristic standard detection:
- Fix various bugs.
- Add some optional debug.
- Enable checking of the Calling address.
- Check that the Called/Calling address has at least a minimum number of
octets.
- Handle XUDTS.
- Reject messages whose mandatory variable pointers are 0 (meaning not
present).
- Reject Class-2 messages whose Class-spare bits are non-zero.
- For (Class-2) messages that have no variable parameters but an optional
pointer, only accept messages whose optional pointer is 0 (no optional
parameters) or 1 (optional parameter immediately follows the pointer).
- (For some of those Class-2 messages) if there are no optional parameters,
reject messages if we didn't reach the end of the message.
svn path=/trunk/; revision=40819
-rw-r--r-- | epan/dissectors/packet-mtp3.c | 331 | ||||
-rw-r--r-- | epan/dissectors/packet-sccp.c | 1046 | ||||
-rw-r--r-- | epan/dissectors/packet-sccp.h | 2 |
3 files changed, 736 insertions, 643 deletions
diff --git a/epan/dissectors/packet-mtp3.c b/epan/dissectors/packet-mtp3.c index f63c295dc9..c39161d4d0 100644 --- a/epan/dissectors/packet-mtp3.c +++ b/epan/dissectors/packet-mtp3.c @@ -172,49 +172,49 @@ static mtp3_addr_pc_t* mtp3_addr_opc; /* the higher values are taken from the M3UA RFC */ static const value_string mtp3_service_indicator_code_vals[] = { - { 0x0, "Signalling Network Management Message (SNM)" }, - { 0x1, "Maintenance Regular Message (MTN)" }, - { 0x2, "Maintenance Special Message (MTNS)" }, - { 0x3, "SCCP" }, - { 0x4, "TUP" }, - { 0x5, "ISUP" }, - { 0x6, "DUP (call and circuit related messages)" }, - { 0x7, "DUP (facility registration and cancellation message)" }, - { 0x8, "MTP testing user part" }, - { 0x9, "Broadband ISUP" }, - { 0xa, "Satellite ISUP" }, - { 0xb, "Spare" }, - { 0xc, "AAL type2 Signaling" }, - { 0xd, "Bearer Independent Call Control (BICC)" }, - { 0xe, "Gateway Control Protocol" }, - { 0xf, "Spare" }, - { 0, NULL } + { 0x0, "Signalling Network Management Message (SNM)" }, + { 0x1, "Maintenance Regular Message (MTN)" }, + { 0x2, "Maintenance Special Message (MTNS)" }, + { 0x3, "SCCP" }, + { 0x4, "TUP" }, + { 0x5, "ISUP" }, + { 0x6, "DUP (call and circuit related messages)" }, + { 0x7, "DUP (facility registration and cancellation message)" }, + { 0x8, "MTP testing user part" }, + { 0x9, "Broadband ISUP" }, + { 0xa, "Satellite ISUP" }, + { 0xb, "Spare" }, + { 0xc, "AAL type2 Signaling" }, + { 0xd, "Bearer Independent Call Control (BICC)" }, + { 0xe, "Gateway Control Protocol" }, + { 0xf, "Spare" }, + { 0, NULL } }; const value_string mtp3_service_indicator_code_short_vals[] = { - { 0x0, "SNM" }, - { 0x1, "MTN" }, - { 0x2, "MTNS" }, - { 0x3, "SCCP" }, - { 0x4, "TUP" }, - { 0x5, "ISUP" }, - { 0x6, "DUP (CC)" }, - { 0x7, "DUP (FAC/CANC)" }, - { 0x8, "MTP Test" }, - { 0x9, "ISUP-b" }, - { 0xa, "ISUP-s" }, - { 0xc, "AAL type 2" }, - { 0xd, "BICC" }, - { 0xe, "GCP" }, - { 0, NULL } + { 0x0, "SNM" }, + { 0x1, "MTN" }, + { 0x2, "MTNS" }, + { 0x3, "SCCP" }, + { 0x4, "TUP" }, + { 0x5, "ISUP" }, + { 0x6, "DUP (CC)" }, + { 0x7, "DUP (FAC/CANC)" }, + { 0x8, "MTP Test" }, + { 0x9, "ISUP-b" }, + { 0xa, "ISUP-s" }, + { 0xc, "AAL type 2" }, + { 0xd, "BICC" }, + { 0xe, "GCP" }, + { 0, NULL } }; static const value_string network_indicator_vals[] = { - { 0x0, "International network" }, - { 0x1, "Spare (for international use only)" }, - { 0x2, "National network" }, - { 0x3, "Reserved for national use" }, - { 0, NULL } + { 0x0, "International network" }, + { 0x1, "Spare (for international use only)" }, + { 0x2, "National network" }, + { 0x3, "Reserved for national use" }, + { 0, NULL } }; static dissector_handle_t data_handle; @@ -231,19 +231,19 @@ mtp3_pc_to_str_buf(const guint32 pc, gchar *buf, int buf_len) { case ITU_STANDARD: switch (itu_pc_structure) { - case ITU_PC_STRUCTURE_NONE: - g_snprintf(buf, buf_len, "%u", pc); - break; - case ITU_PC_STRUCTURE_3_8_3: - /* this format is used in international ITU networks */ - g_snprintf(buf, buf_len, "%u-%u-%u", (pc & 0x3800)>>11, (pc & 0x7f8) >> 3, (pc & 0x07) >> 0); - break; - case ITU_PC_STRUCTURE_4_3_4_3: - /* this format is used in some national ITU networks, the German one for example. */ - g_snprintf(buf, buf_len, "%u-%u-%u-%u", (pc & 0x3c00) >>10, (pc & 0x0380) >> 7, (pc & 0x0078) >> 3, (pc & 0x0007) >> 0); - break; - default: - DISSECTOR_ASSERT_NOT_REACHED(); + case ITU_PC_STRUCTURE_NONE: + g_snprintf(buf, buf_len, "%u", pc); + break; + case ITU_PC_STRUCTURE_3_8_3: + /* this format is used in international ITU networks */ + g_snprintf(buf, buf_len, "%u-%u-%u", (pc & 0x3800)>>11, (pc & 0x7f8) >> 3, (pc & 0x07) >> 0); + break; + case ITU_PC_STRUCTURE_4_3_4_3: + /* this format is used in some national ITU networks, the German one for example. */ + g_snprintf(buf, buf_len, "%u-%u-%u-%u", (pc & 0x3c00) >>10, (pc & 0x0380) >> 7, (pc & 0x0078) >> 3, (pc & 0x0007) >> 0); + break; + default: + DISSECTOR_ASSERT_NOT_REACHED(); } break; case ANSI_STANDARD: @@ -252,24 +252,24 @@ mtp3_pc_to_str_buf(const guint32 pc, gchar *buf, int buf_len) break; case JAPAN_STANDARD: switch (japan_pc_structure) { - case JAPAN_PC_STRUCTURE_NONE: + case JAPAN_PC_STRUCTURE_NONE: g_snprintf(buf, buf_len, "%u", pc); break; - case JAPAN_PC_STRUCTURE_7_4_5: + case JAPAN_PC_STRUCTURE_7_4_5: /* This format is specified by NTT */ g_snprintf(buf, buf_len, "%u-%u-%u", (pc & 0xfe00)>>9, (pc & 0x1e0)>>5, (pc & 0x1f)); break; - case JAPAN_PC_STRUCTURE_3_4_4_5: + case JAPAN_PC_STRUCTURE_3_4_4_5: /* Where does this format come from? */ g_snprintf(buf, buf_len, "%u-%u-%u-%u", (pc & 0xe000)>>13, (pc & 0x1e00)>>9, (pc & 0x1e0)>>5, (pc & 0x1f)); break; - default: - DISSECTOR_ASSERT_NOT_REACHED(); + default: + DISSECTOR_ASSERT_NOT_REACHED(); } break; default: DISSECTOR_ASSERT_NOT_REACHED(); - } + } } #define MAX_STRUCTURED_PC_LENGTH 20 @@ -300,10 +300,8 @@ mtp3_pc_structured(void) */ void -mtp3_addr_to_str_buf( - const mtp3_addr_pc_t *addr_pc_p, - gchar *buf, - int buf_len) +mtp3_addr_to_str_buf(const mtp3_addr_pc_t *addr_pc_p, + gchar *buf, int buf_len) { switch (mtp3_addr_fmt) { @@ -380,21 +378,22 @@ mtp3_addr_to_str_buf( } } -guint32 mtp3_pc_hash(const mtp3_addr_pc_t *addr_pc_p) { - guint32 pc; +guint32 +mtp3_pc_hash(const mtp3_addr_pc_t *addr_pc_p) { + guint32 pc; - switch (addr_pc_p->type) - { - case ITU_STANDARD: - pc = (addr_pc_p->pc & ITU_PC_MASK) | ((addr_pc_p->ni % 4) << 14) ; - break; - default: - /* assuming 24-bit */ - pc = (addr_pc_p->pc & ANSI_PC_MASK) | ((addr_pc_p->ni) << 24) ; - break; - } + switch (addr_pc_p->type) + { + case ITU_STANDARD: + pc = (addr_pc_p->pc & ITU_PC_MASK) | ((addr_pc_p->ni % 4) << 14) ; + break; + default: + /* assuming 24-bit */ + pc = (addr_pc_p->pc & ANSI_PC_MASK) | ((addr_pc_p->ni) << 24) ; + break; + } - return pc; + return pc; } /* Common function for dissecting 3-byte (ANSI or China) PCs. */ @@ -564,9 +563,9 @@ dissect_mtp3_routing_label(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mtp3_t /* SLS */ if (mtp3_standard == ANSI_STANDARD) { if (mtp3_use_ansi_5_bit_sls) - proto_tree_add_item(label_tree, hf_mtp3_ansi_5_bit_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA); + proto_tree_add_item(label_tree, hf_mtp3_ansi_5_bit_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA); else - proto_tree_add_item(label_tree, hf_mtp3_ansi_8_bit_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA); + proto_tree_add_item(label_tree, hf_mtp3_ansi_8_bit_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA); } else /* CHINESE_ITU_STANDARD */ { proto_tree_add_item(label_tree, hf_mtp3_chinese_itu_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA); } @@ -648,7 +647,7 @@ dissect_mtp3_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) #define HEURISTIC_FAILED_STANDARD 0xffff static guint -heur_mtp3_standard(tvbuff_t *tvb, packet_info *pinfo _U_, guint8 si) +heur_mtp3_standard(tvbuff_t *tvb, packet_info *pinfo, guint8 si) { guint32 len; @@ -657,39 +656,39 @@ heur_mtp3_standard(tvbuff_t *tvb, packet_info *pinfo _U_, guint8 si) len = tvb_length(tvb); switch (si) { case 3: - { - payload = tvb_new_subset(tvb, ITU_HEADER_LENGTH, len-ITU_HEADER_LENGTH, len-ITU_HEADER_LENGTH); - if (looks_like_valid_sccp(payload, ITU_STANDARD)) { - return ITU_STANDARD; - } - payload = tvb_new_subset(tvb, ANSI_HEADER_LENGTH, len-ANSI_HEADER_LENGTH, len-ANSI_HEADER_LENGTH); - if (looks_like_valid_sccp(payload, ANSI_STANDARD)) { - return ANSI_STANDARD; - } - payload = tvb_new_subset(tvb, ANSI_HEADER_LENGTH, len-ANSI_HEADER_LENGTH, len-ANSI_HEADER_LENGTH); - if (looks_like_valid_sccp(payload, CHINESE_ITU_STANDARD)) { - return CHINESE_ITU_STANDARD; - } - payload = tvb_new_subset(tvb, JAPAN_HEADER_LENGTH, len-JAPAN_HEADER_LENGTH, len-JAPAN_HEADER_LENGTH); - if (looks_like_valid_sccp(payload, JAPAN_STANDARD)) { - return JAPAN_STANDARD; - } - - return HEURISTIC_FAILED_STANDARD; - - } + { + payload = tvb_new_subset(tvb, ITU_HEADER_LENGTH, len-ITU_HEADER_LENGTH, len-ITU_HEADER_LENGTH); + if (looks_like_valid_sccp(PINFO_FD_NUM(pinfo), payload, ITU_STANDARD)) { + return ITU_STANDARD; + } + payload = tvb_new_subset(tvb, ANSI_HEADER_LENGTH, len-ANSI_HEADER_LENGTH, len-ANSI_HEADER_LENGTH); + if (looks_like_valid_sccp(PINFO_FD_NUM(pinfo), payload, ANSI_STANDARD)) { + return ANSI_STANDARD; + } + payload = tvb_new_subset(tvb, ANSI_HEADER_LENGTH, len-ANSI_HEADER_LENGTH, len-ANSI_HEADER_LENGTH); + if (looks_like_valid_sccp(PINFO_FD_NUM(pinfo), payload, CHINESE_ITU_STANDARD)) { + return CHINESE_ITU_STANDARD; + } + payload = tvb_new_subset(tvb, JAPAN_HEADER_LENGTH, len-JAPAN_HEADER_LENGTH, len-JAPAN_HEADER_LENGTH); + if (looks_like_valid_sccp(PINFO_FD_NUM(pinfo), payload, JAPAN_STANDARD)) { + return JAPAN_STANDARD; + } + + return HEURISTIC_FAILED_STANDARD; + + } default: - return HEURISTIC_FAILED_STANDARD; + return HEURISTIC_FAILED_STANDARD; } } static const value_string mtp3_standard_vals[] = { - { ITU_STANDARD, "ITU_STANDARD" }, - { ANSI_STANDARD, "ANSI_STANDARD" }, - { CHINESE_ITU_STANDARD, "CHINESE_ITU_STANDARD" }, - { JAPAN_STANDARD, "JAPAN_STANDARD" }, - { 0, NULL } + { ITU_STANDARD, "ITU_STANDARD" }, + { ANSI_STANDARD, "ANSI_STANDARD" }, + { CHINESE_ITU_STANDARD, "CHINESE_ITU_STANDARD" }, + { JAPAN_STANDARD, "JAPAN_STANDARD" }, + { 0, NULL } }; /* Code to actually dissect the packets */ @@ -711,39 +710,39 @@ dissect_mtp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) si = tvb_get_guint8(tvb, SIO_OFFSET) & SERVICE_INDICATOR_MASK; if (mtp3_heuristic_standard) { - heuristic_standard = heur_mtp3_standard(tvb, pinfo, si); - if(heuristic_standard==HEURISTIC_FAILED_STANDARD){ - gen_item = proto_tree_add_text(tree, tvb, 0, 0, "Could not determine Heuristic using %s", val_to_str(mtp3_standard, mtp3_standard_vals, "unknown")); - }else{ - gen_item = proto_tree_add_text(tree, tvb, 0, 0, "%s", val_to_str(heuristic_standard, mtp3_standard_vals, "unknown")); - mtp3_standard = heuristic_standard; - } - PROTO_ITEM_SET_GENERATED(gen_item); - } + heuristic_standard = heur_mtp3_standard(tvb, pinfo, si); + if (heuristic_standard == HEURISTIC_FAILED_STANDARD) { + gen_item = proto_tree_add_text(tree, tvb, 0, 0, "Could not determine Heuristic using %s", val_to_str(mtp3_standard, mtp3_standard_vals, "unknown")); + } else { + gen_item = proto_tree_add_text(tree, tvb, 0, 0, "%s", val_to_str(heuristic_standard, mtp3_standard_vals, "unknown")); + mtp3_standard = heuristic_standard; + } + PROTO_ITEM_SET_GENERATED(gen_item); +} /* Make entries in Protocol column on summary display */ switch(mtp3_standard) { case ITU_STANDARD: - col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (Int. ITU)"); - proto_item_set_len(mtp3_item, ITU_HEADER_LENGTH); - break; + col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (Int. ITU)"); + proto_item_set_len(mtp3_item, ITU_HEADER_LENGTH); + break; case ANSI_STANDARD: - col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (ANSI)"); - proto_item_set_len(mtp3_item, ANSI_HEADER_LENGTH); - break; + col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (ANSI)"); + proto_item_set_len(mtp3_item, ANSI_HEADER_LENGTH); + break; case CHINESE_ITU_STANDARD: - col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (Chin. ITU)"); - proto_item_set_len(mtp3_item, ANSI_HEADER_LENGTH); - break; + col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (Chin. ITU)"); + proto_item_set_len(mtp3_item, ANSI_HEADER_LENGTH); + break; case JAPAN_STANDARD: - col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (Japan)"); - proto_item_set_len(mtp3_item, JAPAN_HEADER_LENGTH); - break; + col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (Japan)"); + proto_item_set_len(mtp3_item, JAPAN_HEADER_LENGTH); + break; }; if (tree) { - /* create display subtree for the protocol */ - mtp3_tree = proto_item_add_subtree(mtp3_item, ett_mtp3); + /* create display subtree for the protocol */ + mtp3_tree = proto_item_add_subtree(mtp3_item, ett_mtp3); } mtp3_addr_opc = ep_alloc0(sizeof(mtp3_addr_pc_t)); @@ -819,39 +818,39 @@ proto_register_mtp3(void) }; static enum_val_t mtp3_options[] = { - { "itu", "ITU", ITU_STANDARD }, - { "ansi", "ANSI", ANSI_STANDARD }, - { "chinese-itu", "Chinese ITU", CHINESE_ITU_STANDARD }, - { "japan", "Japan", JAPAN_STANDARD }, + { "itu", "ITU", ITU_STANDARD }, + { "ansi", "ANSI", ANSI_STANDARD }, + { "chinese-itu", "Chinese ITU", CHINESE_ITU_STANDARD }, + { "japan", "Japan", JAPAN_STANDARD }, { NULL, NULL, 0 } }; static enum_val_t mtp3_addr_fmt_str_e[] = { - { "decimal", "Decimal", MTP3_ADDR_FMT_DEC }, - { "hexadecimal", "Hexadecimal", MTP3_ADDR_FMT_HEX }, - { "ni-decimal", "NI-Decimal", MTP3_ADDR_FMT_NI_DEC }, + { "decimal", "Decimal", MTP3_ADDR_FMT_DEC }, + { "hexadecimal", "Hexadecimal", MTP3_ADDR_FMT_HEX }, + { "ni-decimal", "NI-Decimal", MTP3_ADDR_FMT_NI_DEC }, { "ni-hexadecimal", "NI-Hexadecimal", MTP3_ADDR_FMT_NI_HEX }, - { "dashed", "Dashed", MTP3_ADDR_FMT_DASHED }, - { NULL, NULL, 0 } + { "dashed", "Dashed", MTP3_ADDR_FMT_DASHED }, + { NULL, NULL, 0 } }; static enum_val_t itu_pc_structures[] = { - { "unstructured", "Unstructured", ITU_PC_STRUCTURE_NONE}, - { "3-8-3", "3-8-3", ITU_PC_STRUCTURE_3_8_3 }, - { "4-3-4-3", "4-3-4-3", ITU_PC_STRUCTURE_4_3_4_3 }, - { NULL, NULL, 0 } + { "unstructured", "Unstructured", ITU_PC_STRUCTURE_NONE}, + { "3-8-3", "3-8-3", ITU_PC_STRUCTURE_3_8_3 }, + { "4-3-4-3", "4-3-4-3", ITU_PC_STRUCTURE_4_3_4_3 }, + { NULL, NULL, 0 } }; static enum_val_t japan_pc_structures[] = { - { "unstructured", "Unstructured", JAPAN_PC_STRUCTURE_NONE}, - { "7-4-5", "7-4-5", JAPAN_PC_STRUCTURE_7_4_5 }, - { "3-4-4-5", "3-4-4-5", JAPAN_PC_STRUCTURE_3_4_4_5 }, - { NULL, NULL, 0 } + { "unstructured", "Unstructured", JAPAN_PC_STRUCTURE_NONE}, + { "7-4-5", "7-4-5", JAPAN_PC_STRUCTURE_7_4_5 }, + { "3-4-4-5", "3-4-4-5", JAPAN_PC_STRUCTURE_3_4_4_5 }, + { NULL, NULL, 0 } }; /* Register the protocol name and description */ proto_mtp3 = proto_register_protocol("Message Transfer Part Level 3", - "MTP3", "mtp3"); + "MTP3", "mtp3"); register_dissector("mtp3", dissect_mtp3, proto_mtp3); /* Required function calls to register the header fields and subtrees used */ @@ -859,48 +858,48 @@ proto_register_mtp3(void) proto_register_subtree_array(ett, array_length(ett)); mtp3_sio_dissector_table = register_dissector_table("mtp3.service_indicator", - "MTP3 Service indicator", - FT_UINT8, BASE_HEX); + "MTP3 Service indicator", + FT_UINT8, BASE_HEX); mtp3_tap = register_tap("mtp3"); mtp3_module = prefs_register_protocol(proto_mtp3, NULL); prefs_register_bool_preference(mtp3_module, "heuristic_standard", - "Try to determine the MTP3 standard heuristically", - "This only works for SCCP traffic for now", - &mtp3_heuristic_standard); + "Try to determine the MTP3 standard heuristically", + "This only works for SCCP traffic for now", + &mtp3_heuristic_standard); prefs_register_enum_preference(mtp3_module, "standard", "MTP3 standard", - "The SS7 standard used in MTP3 packets", - &mtp3_standard, mtp3_options, FALSE); + "The SS7 standard used in MTP3 packets", + &mtp3_standard, mtp3_options, FALSE); prefs_register_enum_preference(mtp3_module, "itu_pc_structure", "ITU Pointcode structure", - "The structure of the pointcodes in ITU networks", - &itu_pc_structure, itu_pc_structures, FALSE); + "The structure of the pointcodes in ITU networks", + &itu_pc_structure, itu_pc_structures, FALSE); prefs_register_enum_preference(mtp3_module, "japan_pc_structure", "Japan Pointcode structure", - "The structure of the pointcodes in Japan networks", - &japan_pc_structure, japan_pc_structures, FALSE); + "The structure of the pointcodes in Japan networks", + &japan_pc_structure, japan_pc_structures, FALSE); prefs_register_bool_preference(mtp3_module, "ansi_5_bit_sls", - "Use 5-bit SLS (ANSI only)", - "Use 5-bit (instead of 8-bit) SLS in ANSI MTP3 packets", - &mtp3_use_ansi_5_bit_sls); + "Use 5-bit SLS (ANSI only)", + "Use 5-bit (instead of 8-bit) SLS in ANSI MTP3 packets", + &mtp3_use_ansi_5_bit_sls); prefs_register_bool_preference(mtp3_module, "japan_5_bit_sls", - "Use 5-bit SLS (Japan only)", - "Use 5-bit (instead of 4-bit) SLS in Japan MTP3 packets", - &mtp3_use_japan_5_bit_sls); + "Use 5-bit SLS (Japan only)", + "Use 5-bit (instead of 4-bit) SLS in Japan MTP3 packets", + &mtp3_use_japan_5_bit_sls); prefs_register_enum_preference(mtp3_module, "addr_format", "Address Format", - "Format for point code in the address columns", - &mtp3_addr_fmt, mtp3_addr_fmt_str_e, FALSE); + "Format for point code in the address columns", + &mtp3_addr_fmt, mtp3_addr_fmt_str_e, FALSE); prefs_register_bool_preference(mtp3_module, "itu_priority", - "Show MSU priority (national option, ITU and China ITU only)", - "Decode the spare bits of the SIO as the MSU priority (a national option in ITU)", - &mtp3_show_itu_priority); + "Show MSU priority (national option, ITU and China ITU only)", + "Decode the spare bits of the SIO as the MSU priority (a national option in ITU)", + &mtp3_show_itu_priority); } diff --git a/epan/dissectors/packet-sccp.c b/epan/dissectors/packet-sccp.c index 3f2206faea..75519cbc69 100644 --- a/epan/dissectors/packet-sccp.c +++ b/epan/dissectors/packet-sccp.c @@ -819,57 +819,79 @@ static const value_string assoc_protos[] = { }; #define is_connectionless(m) \ - ( m == SCCP_MSG_TYPE_UDT || m == SCCP_MSG_TYPE_UDTS \ - || m == SCCP_MSG_TYPE_XUDT|| m == SCCP_MSG_TYPE_XUDTS \ - || m == SCCP_MSG_TYPE_LUDT|| m == SCCP_MSG_TYPE_LUDTS) + ( m == SCCP_MSG_TYPE_UDT || m == SCCP_MSG_TYPE_UDTS \ + || m == SCCP_MSG_TYPE_XUDT|| m == SCCP_MSG_TYPE_XUDTS \ + || m == SCCP_MSG_TYPE_LUDT|| m == SCCP_MSG_TYPE_LUDTS) + +#define RETURN_FALSE \ + { \ + /*g_warning("Frame %d not protocol %d @ line %d", frame_num, my_mtp3_standard, __LINE__);*/ \ + return FALSE; \ + } static gboolean -sccp_called_calling_looks_valid(tvbuff_t *tvb, guint8 my_mtp3_standard, gboolean is_co) +sccp_called_calling_looks_valid(guint32 frame_num _U_, tvbuff_t *tvb, guint8 my_mtp3_standard, gboolean is_co) { - guint8 ai, ri, gti, ssni /* , pci */; + guint8 ai, ri, gti, ssni, pci; + guint8 len_needed = 1; /* need at least the Address Indicator */ + guint len = tvb_length(tvb); - /* TVB starts with parameter length */ - ai = tvb_get_guint8(tvb, 1); + ai = tvb_get_guint8(tvb, 0); if (my_mtp3_standard == ANSI_STANDARD && (ai & ANSI_NATIONAL_MASK) == 0) - return FALSE; + RETURN_FALSE; gti = (ai & GTI_MASK) >> GTI_SHIFT; if (my_mtp3_standard == ANSI_STANDARD) { - if (gti > 2) - return FALSE; + if (gti > 2) + RETURN_FALSE; } else { - if (gti > 4) - return FALSE; + if (gti > 4) + RETURN_FALSE; } - ri = ai & ROUTING_INDICATOR_MASK >> ROUTING_INDICATOR_SHIFT; + ri = (ai & ROUTING_INDICATOR_MASK) >> ROUTING_INDICATOR_SHIFT; if (my_mtp3_standard == ANSI_STANDARD) { - /* pci = ai & ANSI_PC_INDICATOR_MASK; */ + pci = ai & ANSI_PC_INDICATOR_MASK; ssni = ai & ANSI_SSN_INDICATOR_MASK; } else { ssni = ai & ITU_SSN_INDICATOR_MASK; - /* pci = ai & ITU_PC_INDICATOR_MASK; */ + pci = ai & ITU_PC_INDICATOR_MASK; } /* Route on SSN with no SSN? */ if (ri == ROUTE_ON_SSN && ssni == 0) - return FALSE; + RETURN_FALSE; /* Route on GT with no GT? */ if (ri == ROUTE_ON_GT && gti == AI_GTI_NO_GT) - return FALSE; + RETURN_FALSE; /* GT routed and connection-oriented (Class-2)? * Yes, that's theoretically possible, but it's not used. */ if (ri == ROUTE_ON_GT && is_co) - return FALSE; + RETURN_FALSE; + + if (ssni) + len_needed += ADDRESS_SSN_LENGTH; + if (pci) { + if (my_mtp3_standard == ANSI_STANDARD || + my_mtp3_standard == CHINESE_ITU_STANDARD) + len_needed += ANSI_PC_LENGTH; + else + len_needed += ITU_PC_LENGTH; + } + if (gti) + len_needed += 2; + + if (len_needed > len) + RETURN_FALSE; return TRUE; } gboolean -looks_like_valid_sccp(tvbuff_t *tvb, guint8 my_mtp3_standard) +looks_like_valid_sccp(guint32 frame_num _U_, tvbuff_t *tvb, guint8 my_mtp3_standard) { guint offset; guint8 msgtype, msg_class, cause; @@ -884,17 +906,16 @@ looks_like_valid_sccp(tvbuff_t *tvb, guint8 my_mtp3_standard) * we don't want to throw an exception in here... */ if (len < 6) - return FALSE; + RETURN_FALSE; msgtype = tvb_get_guint8(tvb, SCCP_MSG_TYPE_OFFSET); if (!match_strval(msgtype, sccp_message_type_acro_values)) { - return FALSE; + RETURN_FALSE; } offset = SCCP_MSG_TYPE_LENGTH; /* Still to be done: - SCCP_MSG_TYPE_XUDTS SCCP_MSG_TYPE_LUDT SCCP_MSG_TYPE_LUDTS */ @@ -907,143 +928,212 @@ looks_like_valid_sccp(tvbuff_t *tvb, guint8 my_mtp3_standard) case SCCP_MSG_TYPE_RSC: case SCCP_MSG_TYPE_RSR: /* Class-3 is never actually used in the real world */ - return FALSE; - break; + RETURN_FALSE; + break; case SCCP_MSG_TYPE_UDT: case SCCP_MSG_TYPE_XUDT: /* 0x11 */ case SCCP_MSG_TYPE_UDTS: - { + case SCCP_MSG_TYPE_XUDTS: + { + if (msgtype == SCCP_MSG_TYPE_XUDT || msgtype == SCCP_MSG_TYPE_XUDTS) { + if (SCCP_MSG_TYPE_LENGTH + + PROTOCOL_CLASS_LENGTH + /* or Cause for XUDTS */ + HOP_COUNTER_LENGTH + + POINTER_LENGTH + + POINTER_LENGTH + + POINTER_LENGTH + + POINTER_LENGTH > len) + RETURN_FALSE; + } + if (msgtype == SCCP_MSG_TYPE_UDT || msgtype == SCCP_MSG_TYPE_XUDT) { - /* Class lower four bits */ msg_class = tvb_get_guint8(tvb, offset) & CLASS_CLASS_MASK; if (msg_class > 1) - return FALSE; + RETURN_FALSE; offset += PROTOCOL_CLASS_LENGTH; } - if (msgtype == SCCP_MSG_TYPE_XUDT) - offset += HOP_COUNTER_LENGTH; + if (msgtype == SCCP_MSG_TYPE_XUDT) + offset += HOP_COUNTER_LENGTH; - if (msgtype == SCCP_MSG_TYPE_UDTS) { + if (msgtype == SCCP_MSG_TYPE_UDTS || + msgtype == SCCP_MSG_TYPE_XUDTS) { cause = tvb_get_guint8(tvb, offset); if (!match_strval(cause, sccp_return_cause_values)) - return FALSE; + RETURN_FALSE; offset += RETURN_CAUSE_LENGTH; } - called_ptr = tvb_get_guint8(tvb, offset) + offset; + if (msgtype == SCCP_MSG_TYPE_XUDTS) + offset += HOP_COUNTER_LENGTH; + + called_ptr = tvb_get_guint8(tvb, offset); + if (called_ptr == 0) /* Mandatory variable parameters must be present */ + RETURN_FALSE; + called_ptr += offset; offset += POINTER_LENGTH; - calling_ptr = tvb_get_guint8(tvb, offset) + offset; + + calling_ptr = tvb_get_guint8(tvb, offset); + if (calling_ptr == 0) /* Mandatory variable parameters must be present */ + RETURN_FALSE; + calling_ptr += offset; offset += POINTER_LENGTH; - data_ptr = tvb_get_guint8(tvb, offset) + offset; + + data_ptr = tvb_get_guint8(tvb, offset); + if (data_ptr == 0) /* Mandatory variable parameters must be present */ + RETURN_FALSE; + data_ptr += offset; offset += POINTER_LENGTH; - if (msgtype == SCCP_MSG_TYPE_XUDT) { - opt_ptr = tvb_get_guint8(tvb, offset); - if (opt_ptr) - opt_ptr += offset; + + if (msgtype == SCCP_MSG_TYPE_XUDT || msgtype == SCCP_MSG_TYPE_XUDTS) { + opt_ptr = tvb_get_guint8(tvb, offset); offset += POINTER_LENGTH; } - /* Check that all the pointers are within bounds */ - if (called_ptr > len || calling_ptr > len || data_ptr > len || opt_ptr > len) - return FALSE; - - /* Check that the lengths of the variable parameters are within bounds */ - if (tvb_get_guint8(tvb, called_ptr)+offset > len || - tvb_get_guint8(tvb, calling_ptr)+offset > len || - tvb_get_guint8(tvb, data_ptr)+offset > len) - return FALSE; - } - break; + /* Check that the variable pointers are within bounds */ + if (called_ptr > len || calling_ptr > len || data_ptr > len) + RETURN_FALSE; + + /* Check that the lengths of the variable parameters are within bounds */ + if (tvb_get_guint8(tvb, called_ptr)+called_ptr > len || + tvb_get_guint8(tvb, calling_ptr)+calling_ptr > len || + tvb_get_guint8(tvb, data_ptr)+data_ptr > len) + RETURN_FALSE; + } + break; case SCCP_MSG_TYPE_CR: - { + { offset += DESTINATION_LOCAL_REFERENCE_LENGTH; - msg_class = tvb_get_guint8(tvb, offset) & CLASS_CLASS_MASK; - if (msg_class != 2) - return FALSE; - } - break; + /* Class is only the lower 4 bits, but the upper 4 bits are spare + * in Class-2. Don't mask them off so the below comparison also + * fails if any of those spare bits are set. + */ + msg_class = tvb_get_guint8(tvb, offset); + if (msg_class != 2) + RETURN_FALSE; + } + break; case SCCP_MSG_TYPE_CC: /* 2 */ - { + { if (len < SCCP_MSG_TYPE_LENGTH + DESTINATION_LOCAL_REFERENCE_LENGTH + SOURCE_LOCAL_REFERENCE_LENGTH + PROTOCOL_CLASS_LENGTH + POINTER_LENGTH) - return FALSE; + RETURN_FALSE; offset += DESTINATION_LOCAL_REFERENCE_LENGTH; offset += SOURCE_LOCAL_REFERENCE_LENGTH; - msg_class = tvb_get_guint8(tvb, offset) & CLASS_CLASS_MASK; - if (msg_class != 2) - return FALSE; + /* Class is only the lower 4 bits, but the upper 4 bits are spare + * in Class-2. Don't mask them off so the below comparison also + * fails if any of those spare bits are set. + */ + msg_class = tvb_get_guint8(tvb, offset); + if (msg_class != 2) + RETURN_FALSE; offset += PROTOCOL_CLASS_LENGTH; opt_ptr = tvb_get_guint8(tvb, offset); - if (opt_ptr) - opt_ptr += offset; - } - break; + offset += POINTER_LENGTH; + + /* If the pointer isn't 0 (no optional parameters) or 1 (optional + * parameter starts immediately after the pointer) then what would + * be between the pointer and the parameter? + */ + if (opt_ptr > 1) + RETURN_FALSE; + + /* If there are no optional parameters, are we at the end of the + * message? + */ + if (opt_ptr == 0 && offset != len) + RETURN_FALSE; + } + break; case SCCP_MSG_TYPE_CREF: - { + { offset += DESTINATION_LOCAL_REFERENCE_LENGTH; - cause = tvb_get_guint8(tvb, offset); - if (!match_strval(cause, sccp_refusal_cause_values)) - return FALSE; + cause = tvb_get_guint8(tvb, offset); + if (!match_strval(cause, sccp_refusal_cause_values)) + RETURN_FALSE; offset += REFUSAL_CAUSE_LENGTH; opt_ptr = tvb_get_guint8(tvb, offset); - if (opt_ptr) - opt_ptr += offset; - } - break; + offset += POINTER_LENGTH; + + /* If the pointer isn't 0 (no optional parameters) or 1 (optional + * parameter starts immediately after the pointer) then what would + * be between the pointer and the parameter? + */ + if (opt_ptr > 1) + RETURN_FALSE; + + /* If there are no optional parameters, are we at the end of the + * message? + */ + if (opt_ptr == 0 && offset != len) + RETURN_FALSE; + } + break; case SCCP_MSG_TYPE_RLSD: - { + { if (len < SCCP_MSG_TYPE_LENGTH + DESTINATION_LOCAL_REFERENCE_LENGTH + SOURCE_LOCAL_REFERENCE_LENGTH + RELEASE_CAUSE_LENGTH + POINTER_LENGTH) - return FALSE; + RETURN_FALSE; offset += DESTINATION_LOCAL_REFERENCE_LENGTH; offset += SOURCE_LOCAL_REFERENCE_LENGTH; - cause = tvb_get_guint8(tvb, offset); - if (!match_strval(cause, sccp_release_cause_values)) - return FALSE; + cause = tvb_get_guint8(tvb, offset); + if (!match_strval(cause, sccp_release_cause_values)) + RETURN_FALSE; offset += RELEASE_CAUSE_LENGTH; opt_ptr = tvb_get_guint8(tvb, offset); - if (opt_ptr) - opt_ptr += offset; - } - break; + offset += POINTER_LENGTH; + + /* If the pointer isn't 0 (no optional parameters) or 1 (optional + * parameter starts immediately after the pointer) then what would + * be between the pointer and the parameter? + */ + if (opt_ptr > 1) + RETURN_FALSE; + + /* If there are no optional parameters, are we at the end of the + * message? + */ + if (opt_ptr == 0 && offset != len) + RETURN_FALSE; + } + break; case SCCP_MSG_TYPE_RLC: - { + { if (len != SCCP_MSG_TYPE_LENGTH + DESTINATION_LOCAL_REFERENCE_LENGTH + SOURCE_LOCAL_REFERENCE_LENGTH) - return FALSE; - } - break; + RETURN_FALSE; + } + break; case SCCP_MSG_TYPE_ERR: - { + { if (len != SCCP_MSG_TYPE_LENGTH + DESTINATION_LOCAL_REFERENCE_LENGTH + ERROR_CAUSE_LENGTH) - return FALSE; + RETURN_FALSE; offset += DESTINATION_LOCAL_REFERENCE_LENGTH; - cause = tvb_get_guint8(tvb, offset); - if (!match_strval(cause, sccp_error_cause_values)) - return FALSE; - } - break; + cause = tvb_get_guint8(tvb, offset); + if (!match_strval(cause, sccp_error_cause_values)) + RETURN_FALSE; + } + break; case SCCP_MSG_TYPE_DT1: /* 6 */ { if (len < SCCP_MSG_TYPE_LENGTH @@ -1052,23 +1142,23 @@ looks_like_valid_sccp(tvbuff_t *tvb, guint8 my_mtp3_standard) + POINTER_LENGTH + PARAMETER_LENGTH_LENGTH + 1) /* At least 1 byte of payload */ - return FALSE; + RETURN_FALSE; offset += DESTINATION_LOCAL_REFERENCE_LENGTH; /* Are any of the spare bits in set? */ if (tvb_get_guint8(tvb, offset) & ~SEGMENTING_REASSEMBLING_MASK) - return FALSE; + RETURN_FALSE; offset += SEGMENTING_REASSEMBLING_LENGTH; data_ptr = tvb_get_guint8(tvb, offset) + offset; /* Verify the data pointer is within bounds */ if (data_ptr > len) - return FALSE; + RETURN_FALSE; offset += POINTER_LENGTH; /* Verify the data length uses the rest of the message */ if (tvb_get_guint8(tvb, data_ptr) + offset + 1U != len) - return FALSE; + RETURN_FALSE; } break; case SCCP_MSG_TYPE_IT: @@ -1079,72 +1169,76 @@ looks_like_valid_sccp(tvbuff_t *tvb, guint8 my_mtp3_standard) + PROTOCOL_CLASS_LENGTH + SEQUENCING_SEGMENTING_LENGTH + CREDIT_LENGTH) - return FALSE; + RETURN_FALSE; offset += DESTINATION_LOCAL_REFERENCE_LENGTH; offset += SOURCE_LOCAL_REFERENCE_LENGTH; - msg_class = tvb_get_guint8(tvb, offset) & CLASS_CLASS_MASK; - if (msg_class != 2) - return FALSE; + /* Class is only the lower 4 bits, but the upper 4 bits are spare + * in Class-2. Don't mask them off so the below comparison also + * fails if any of those spare bits are set. + */ + msg_class = tvb_get_guint8(tvb, offset); + if (msg_class != 2) + RETURN_FALSE; offset += PROTOCOL_CLASS_LENGTH; } break; default: - g_warning("Unhandled msg type %u", msgtype); - return FALSE; + g_warning("Unhandled msg type %u", msgtype); + RETURN_FALSE; } if (called_ptr) { - guint8 param_len = tvb_get_guint8(tvb, called_ptr); - tvbuff_t *param_tvb; + guint8 param_len = tvb_get_guint8(tvb, called_ptr); + tvbuff_t *param_tvb; if (param_len == 0) - return FALSE; - param_tvb = tvb_new_subset(tvb, called_ptr, param_len, param_len); + RETURN_FALSE; + param_tvb = tvb_new_subset(tvb, called_ptr+1, param_len, param_len); - if (!sccp_called_calling_looks_valid(param_tvb, my_mtp3_standard, !is_connectionless(msgtype))) - return FALSE; + if (!sccp_called_calling_looks_valid(frame_num, param_tvb, my_mtp3_standard, !is_connectionless(msgtype))) + RETURN_FALSE; } -#if 0 if (calling_ptr) { - guint8 param_len = tvb_get_guint8(tvb, calling_ptr); - tvbuff_t *param_tvb; + guint8 param_len = tvb_get_guint8(tvb, calling_ptr); + tvbuff_t *param_tvb; if (param_len == 0) - return FALSE; - param_tvb = tvb_new_subset(tvb, calling_ptr, param_len, param_len); + RETURN_FALSE; + param_tvb = tvb_new_subset(tvb, calling_ptr+1, param_len, param_len); - if (!sccp_called_calling_looks_valid(param_tvb, my_mtp3_standard, !is_connectionless(msgtype))) - return FALSE; + if (!sccp_called_calling_looks_valid(frame_num, param_tvb, my_mtp3_standard, !is_connectionless(msgtype))) + RETURN_FALSE; } -#endif if (opt_ptr) { guint8 opt_param; + opt_ptr += offset-1; /* (offset was already incremented) */ + /* Check that the optional pointer is within bounds */ - if (opt_ptr+1U > len) - return FALSE; + if (opt_ptr > len) + RETURN_FALSE; opt_param = tvb_get_guint8(tvb, opt_ptr); /* Check if the (1st) optional parameter tag is valid */ if (!match_strval(opt_param, sccp_parameter_values)) - return FALSE; + RETURN_FALSE; /* Check that the (1st) parameter length is within bounds */ if (opt_param != PARAMETER_END_OF_OPTIONAL_PARAMETERS && - opt_ptr+2U <= len && + opt_ptr+1U <= len && tvb_get_guint8(tvb, opt_ptr+1U)+offset > len) - return FALSE; + RETURN_FALSE; /* If we're at the end of the parameters, are we also at the end of the * message? */ if (opt_param == PARAMETER_END_OF_OPTIONAL_PARAMETERS && opt_ptr+1U != len) - return FALSE; + RETURN_FALSE; } return TRUE; @@ -1185,153 +1279,153 @@ get_sccp_assoc(packet_info* pinfo, guint offset, guint32 src_lr, guint32 dst_lr, guint framenum = PINFO_FD_NUM(pinfo); if(assoc) - return assoc; + return assoc; opck = opc->type == AT_SS7PC ? mtp3_pc_hash((const mtp3_addr_pc_t *)opc->data) : g_str_hash(ep_address_to_str(opc)); dpck = dpc->type == AT_SS7PC ? mtp3_pc_hash((const mtp3_addr_pc_t *)dpc->data) : g_str_hash(ep_address_to_str(dpc)); switch (msg_type) { - case SCCP_MSG_TYPE_CR: - { - /* CR contains the opc,dpc,dlr key of backward messages swapped as dpc,opc,slr */ - emem_tree_key_t bw_key[] = { - {1, &dpck}, + case SCCP_MSG_TYPE_CR: + { + /* CR contains the opc,dpc,dlr key of backward messages swapped as dpc,opc,slr */ + emem_tree_key_t bw_key[] = { + {1, &dpck}, {1, &opck}, {1, &src_lr}, {0, NULL} - }; - - if (! ( assoc = se_tree_lookup32_array(assocs,bw_key) ) && ! PINFO_FD_VISITED(pinfo) ) { - assoc = new_assoc(opck, dpck); - se_tree_insert32_array(assocs, bw_key, assoc); - assoc->has_bw_key = TRUE; - } + }; - pinfo->p2p_dir = P2P_DIR_SENT; + if (! ( assoc = se_tree_lookup32_array(assocs,bw_key) ) && ! PINFO_FD_VISITED(pinfo) ) { + assoc = new_assoc(opck, dpck); + se_tree_insert32_array(assocs, bw_key, assoc); + assoc->has_bw_key = TRUE; + } - break; - } - case SCCP_MSG_TYPE_CC: - { - emem_tree_key_t fw_key[] = { - {1, &dpck}, {1, &opck}, {1, &src_lr}, {0, NULL} - }; - emem_tree_key_t bw_key[] = { - {1, &opck}, {1, &dpck}, {1, &dst_lr}, {0, NULL} - }; + pinfo->p2p_dir = P2P_DIR_SENT; - if ( ( assoc = se_tree_lookup32_array(assocs, bw_key) ) ) { - goto got_assoc; - } + break; + } + case SCCP_MSG_TYPE_CC: + { + emem_tree_key_t fw_key[] = { + {1, &dpck}, {1, &opck}, {1, &src_lr}, {0, NULL} + }; + emem_tree_key_t bw_key[] = { + {1, &opck}, {1, &dpck}, {1, &dst_lr}, {0, NULL} + }; + + if ( ( assoc = se_tree_lookup32_array(assocs, bw_key) ) ) { + goto got_assoc; + } - if ( (assoc = se_tree_lookup32_array(assocs, fw_key) ) ) { - goto got_assoc; - } + if ( (assoc = se_tree_lookup32_array(assocs, fw_key) ) ) { + goto got_assoc; + } - assoc = new_assoc(dpck,opck); + assoc = new_assoc(dpck,opck); got_assoc: - pinfo->p2p_dir = P2P_DIR_RECV; - - if ( ! PINFO_FD_VISITED(pinfo) && ! assoc->has_bw_key ) { - se_tree_insert32_array(assocs, bw_key, assoc); - assoc->has_bw_key = TRUE; - } - - if ( ! PINFO_FD_VISITED(pinfo) && ! assoc->has_fw_key ) { - se_tree_insert32_array(assocs, fw_key, assoc); - assoc->has_fw_key = TRUE; - } - - break; - } - case SCCP_MSG_TYPE_RLC: - { - emem_tree_key_t bw_key[] = { - {1, &dpck}, {1, &opck}, {1, &src_lr}, {0, NULL} - }; - emem_tree_key_t fw_key[] = { - {1, &opck}, {1, &dpck}, {1, &dst_lr}, {0, NULL} - }; - if ( ( assoc = se_tree_lookup32_array(assocs, bw_key) ) ) { - goto got_assoc_rlc; - } - - if ( (assoc = se_tree_lookup32_array(assocs, fw_key) ) ) { - goto got_assoc_rlc; - } - - assoc = new_assoc(dpck, opck); + pinfo->p2p_dir = P2P_DIR_RECV; + + if ( ! PINFO_FD_VISITED(pinfo) && ! assoc->has_bw_key ) { + se_tree_insert32_array(assocs, bw_key, assoc); + assoc->has_bw_key = TRUE; + } + + if ( ! PINFO_FD_VISITED(pinfo) && ! assoc->has_fw_key ) { + se_tree_insert32_array(assocs, fw_key, assoc); + assoc->has_fw_key = TRUE; + } + + break; + } + case SCCP_MSG_TYPE_RLC: + { + emem_tree_key_t bw_key[] = { + {1, &dpck}, {1, &opck}, {1, &src_lr}, {0, NULL} + }; + emem_tree_key_t fw_key[] = { + {1, &opck}, {1, &dpck}, {1, &dst_lr}, {0, NULL} + }; + if ( ( assoc = se_tree_lookup32_array(assocs, bw_key) ) ) { + goto got_assoc_rlc; + } + + if ( (assoc = se_tree_lookup32_array(assocs, fw_key) ) ) { + goto got_assoc_rlc; + } + + assoc = new_assoc(dpck, opck); got_assoc_rlc: - pinfo->p2p_dir = P2P_DIR_SENT; - - if ( ! PINFO_FD_VISITED(pinfo) && ! assoc->has_bw_key ) { - se_tree_insert32_array(assocs, bw_key, assoc); - assoc->has_bw_key = TRUE; - } - - if ( ! PINFO_FD_VISITED(pinfo) && ! assoc->has_fw_key ) { - se_tree_insert32_array(assocs, fw_key, assoc); - assoc->has_fw_key = TRUE; - } - break; - } - default: - { - emem_tree_key_t key[] = { - {1, &opck}, {1, &dpck}, {1, &dst_lr}, {0, NULL} - }; - - assoc = se_tree_lookup32_array(assocs, key); - - if (assoc) { - if (assoc->calling_dpc == dpck) { - pinfo->p2p_dir = P2P_DIR_RECV; - } else { - pinfo->p2p_dir = P2P_DIR_SENT; - } - } - - break; - } + pinfo->p2p_dir = P2P_DIR_SENT; + + if ( ! PINFO_FD_VISITED(pinfo) && ! assoc->has_bw_key ) { + se_tree_insert32_array(assocs, bw_key, assoc); + assoc->has_bw_key = TRUE; + } + + if ( ! PINFO_FD_VISITED(pinfo) && ! assoc->has_fw_key ) { + se_tree_insert32_array(assocs, fw_key, assoc); + assoc->has_fw_key = TRUE; + } + break; + } + default: + { + emem_tree_key_t key[] = { + {1, &opck}, {1, &dpck}, {1, &dst_lr}, {0, NULL} + }; + + assoc = se_tree_lookup32_array(assocs, key); + + if (assoc) { + if (assoc->calling_dpc == dpck) { + pinfo->p2p_dir = P2P_DIR_RECV; + } else { + pinfo->p2p_dir = P2P_DIR_SENT; + } + } + + break; + } } if (assoc && trace_sccp) { - if ( ! PINFO_FD_VISITED(pinfo)) { - sccp_msg_info_t* msg = se_alloc0(sizeof(sccp_msg_info_t)); - msg->framenum = framenum; - msg->offset = offset; - msg->data.co.next = NULL; - msg->data.co.assoc = assoc; - msg->data.co.label = NULL; - msg->data.co.comment = NULL; - msg->type = msg_type; - - if (assoc->msgs) { - sccp_msg_info_t* m; - for (m = assoc->msgs; m->data.co.next; m = m->data.co.next) ; - m->data.co.next = msg; - } else { - assoc->msgs = msg; - } - - assoc->curr_msg = msg; - - } else { - - sccp_msg_info_t* m; - - for (m = assoc->msgs; m; m = m->data.co.next) { - if (m->framenum == framenum && m->offset == offset) { - assoc->curr_msg = m; - break; - } - } - } + if ( ! PINFO_FD_VISITED(pinfo)) { + sccp_msg_info_t* msg = se_alloc0(sizeof(sccp_msg_info_t)); + msg->framenum = framenum; + msg->offset = offset; + msg->data.co.next = NULL; + msg->data.co.assoc = assoc; + msg->data.co.label = NULL; + msg->data.co.comment = NULL; + msg->type = msg_type; + + if (assoc->msgs) { + sccp_msg_info_t* m; + for (m = assoc->msgs; m->data.co.next; m = m->data.co.next) ; + m->data.co.next = msg; + } else { + assoc->msgs = msg; + } + + assoc->curr_msg = msg; + + } else { + + sccp_msg_info_t* m; + + for (m = assoc->msgs; m; m = m->data.co.next) { + if (m->framenum == framenum && m->offset == offset) { + assoc->curr_msg = m; + break; + } + } + } } return assoc ? assoc : &no_assoc; @@ -1346,15 +1440,15 @@ dissect_sccp_unknown_message(tvbuff_t *message_tvb, proto_tree *sccp_tree) message_length = tvb_length(message_tvb); proto_tree_add_text(sccp_tree, message_tvb, 0, message_length, - "Unknown message (%u byte%s)", - message_length, plurality(message_length, "", "s")); + "Unknown message (%u byte%s)", + message_length, plurality(message_length, "", "s")); } static void dissect_sccp_unknown_param(tvbuff_t *tvb, proto_tree *tree, guint8 type, guint length) { proto_tree_add_text(tree, tvb, 0, length, "Unknown parameter 0x%x (%u byte%s)", - type, length, plurality(length, "", "s")); + type, length, plurality(length, "", "s")); } static void @@ -1622,227 +1716,227 @@ dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree, packet_info * const char *tcap_ssn_dissector_short_name = NULL; call_item = proto_tree_add_text(tree, tvb, 0, length, - "%s Party address (%u byte%s)", - called ? "Called" : "Calling", length, - plurality(length, "", "s")); + "%s Party address (%u byte%s)", + called ? "Called" : "Calling", length, + plurality(length, "", "s")); call_tree = proto_item_add_subtree(call_item, called ? ett_sccp_called : ett_sccp_calling); call_ai_item = proto_tree_add_text(call_tree, tvb, 0, - ADDRESS_INDICATOR_LENGTH, - "Address Indicator"); + ADDRESS_INDICATOR_LENGTH, + "Address Indicator"); call_ai_tree = proto_item_add_subtree(call_ai_item, called ? ett_sccp_called_ai : ett_sccp_calling_ai); if (decode_mtp3_standard == ANSI_STANDARD) { - national = tvb_get_guint8(tvb, 0) & ANSI_NATIONAL_MASK; - expert_item = proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_national_indicator - : hf_sccp_calling_national_indicator, - tvb, 0, ADDRESS_INDICATOR_LENGTH, national); - if (national == 0) - expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_WARN, "Address is coded to " - "international standards. This doesn't normally happen in ANSI " - "networks."); + national = tvb_get_guint8(tvb, 0) & ANSI_NATIONAL_MASK; + expert_item = proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_national_indicator + : hf_sccp_calling_national_indicator, + tvb, 0, ADDRESS_INDICATOR_LENGTH, national); + if (national == 0) + expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_WARN, "Address is coded to " + "international standards. This doesn't normally happen in ANSI " + "networks."); } routing_ind = tvb_get_guint8(tvb, 0) & ROUTING_INDICATOR_MASK; proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_routing_indicator : hf_sccp_calling_routing_indicator, - tvb, 0, ADDRESS_INDICATOR_LENGTH, routing_ind); + tvb, 0, ADDRESS_INDICATOR_LENGTH, routing_ind); /* Only shift off the other bits after adding the item */ routing_ind >>= ROUTING_INDICATOR_SHIFT; gti = tvb_get_guint8(tvb, 0) & GTI_MASK; if (decode_mtp3_standard == ITU_STANDARD || - decode_mtp3_standard == CHINESE_ITU_STANDARD || - decode_mtp3_standard == JAPAN_STANDARD || - national == 0) { - - proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_global_title_indicator : hf_sccp_calling_itu_global_title_indicator, - tvb, 0, ADDRESS_INDICATOR_LENGTH, gti); - - ssni = tvb_get_guint8(tvb, 0) & ITU_SSN_INDICATOR_MASK; - expert_item = proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_ssn_indicator : hf_sccp_calling_itu_ssn_indicator, - tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni); - if (routing_ind == ROUTE_ON_SSN && ssni == 0) { - expert_add_info_format(pinfo, expert_item, PI_PROTOCOL, PI_WARN, - "Message is routed on SSN, but SSN is not present"); - } - - pci = tvb_get_guint8(tvb, 0) & ITU_PC_INDICATOR_MASK; - proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_point_code_indicator : hf_sccp_calling_itu_point_code_indicator, - tvb, 0, ADDRESS_INDICATOR_LENGTH, pci); - - offset = ADDRESS_INDICATOR_LENGTH; - - /* Dissect PC (if present) */ - if (pci) { - if (decode_mtp3_standard == ITU_STANDARD || national == 0) { - if (length < offset + ITU_PC_LENGTH){ - expert_item = proto_tree_add_text(call_tree, tvb, 0, -1, "Wrong length indicated (%u) should be at least %u, PC is %u octets", length, offset + ITU_PC_LENGTH, ITU_PC_LENGTH); - expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated"); - PROTO_ITEM_SET_GENERATED(expert_item); - return; - } - proto_tree_add_item(call_tree, called ? hf_sccp_called_itu_pc : hf_sccp_calling_itu_pc, - tvb, offset, ITU_PC_LENGTH, ENC_LITTLE_ENDIAN); - offset += ITU_PC_LENGTH; - - } else if (decode_mtp3_standard == JAPAN_STANDARD) { - - if (length < offset + JAPAN_PC_LENGTH){ - expert_item = proto_tree_add_text(call_tree, tvb, 0, -1, "Wrong length indicated (%u) should be at least %u, PC is %u octets", length, offset + JAPAN_PC_LENGTH, JAPAN_PC_LENGTH); - expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated"); - PROTO_ITEM_SET_GENERATED(expert_item); - return; - } - proto_tree_add_item(call_tree, called ? hf_sccp_called_japan_pc : hf_sccp_calling_japan_pc, - tvb, offset, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); - - offset += JAPAN_PC_LENGTH; - - } else /* CHINESE_ITU_STANDARD */ { - - if (length < offset + ANSI_PC_LENGTH){ - expert_item = proto_tree_add_text(call_tree, tvb, 0, -1, "Wrong length indicated (%u) should be at least %u, PC is %u octets", length, offset + ANSI_PC_LENGTH, ANSI_PC_LENGTH); - expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated"); - PROTO_ITEM_SET_GENERATED(expert_item); - return; - } - offset = dissect_sccp_3byte_pc(tvb, call_tree, offset, called); - - } - } - - /* Dissect SSN (if present) */ - if (ssni) { - ssn = tvb_get_guint8(tvb, offset); - - if (routing_ind == ROUTE_ON_SSN && ssn == 0) { - expert_add_info_format(pinfo, expert_item, PI_PROTOCOL, PI_WARN, - "Message is routed on SSN, but SSN is zero (unspecified)"); - } - - if (called && assoc) - assoc->called_ssn = ssn; - else if (assoc) - assoc->calling_ssn = ssn; - - if (is_connectionless(message_type) && sccp_msg) { - guint *ssn_ptr = called ? &(sccp_msg->data.ud.called_ssn) : &(sccp_msg->data.ud.calling_ssn); - - *ssn_ptr = ssn; - } - - proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn - : hf_sccp_calling_ssn, - tvb, offset, ADDRESS_SSN_LENGTH, ssn); - hidden_item = proto_tree_add_uint(call_tree, hf_sccp_ssn, tvb, offset, - ADDRESS_SSN_LENGTH, ssn); - PROTO_ITEM_SET_HIDDEN(hidden_item); - - offset += ADDRESS_SSN_LENGTH; - - /* Get the dissector handle of the dissector registered for this ssn - * And print it's name. - */ - ssn_dissector = dissector_get_uint_handle(sccp_ssn_dissector_table, ssn); - - if (ssn_dissector) { - ssn_dissector_short_name = dissector_handle_get_short_name(ssn_dissector); - - if(ssn_dissector_short_name) { - item = proto_tree_add_text(call_tree, tvb, offset - 1, ADDRESS_SSN_LENGTH, "Linked to %s", ssn_dissector_short_name); - PROTO_ITEM_SET_GENERATED(item); - - if (g_ascii_strncasecmp("TCAP", ssn_dissector_short_name, 4)== 0) { - tcap_ssn_dissector = get_itu_tcap_subdissector(ssn); - - if(tcap_ssn_dissector) { - tcap_ssn_dissector_short_name = dissector_handle_get_short_name(tcap_ssn_dissector); - proto_item_append_text(item,", TCAP SSN linked to %s", tcap_ssn_dissector_short_name); - } - } - } /* short name */ - } /* ssn_dissector */ - } /* ssni */ - - /* Dissect GT (if present) */ - if (gti != AI_GTI_NO_GT) { - if (length < offset) - return; - - gt_tvb = tvb_new_subset(tvb, offset, (length - offset), - (length - offset)); - dissect_sccp_global_title(gt_tvb, pinfo, call_tree, (length - offset), gti, - (routing_ind == ROUTE_ON_GT), called); - } + decode_mtp3_standard == CHINESE_ITU_STANDARD || + decode_mtp3_standard == JAPAN_STANDARD || + national == 0) { + + proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_global_title_indicator : hf_sccp_calling_itu_global_title_indicator, + tvb, 0, ADDRESS_INDICATOR_LENGTH, gti); + + ssni = tvb_get_guint8(tvb, 0) & ITU_SSN_INDICATOR_MASK; + expert_item = proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_ssn_indicator : hf_sccp_calling_itu_ssn_indicator, + tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni); + if (routing_ind == ROUTE_ON_SSN && ssni == 0) { + expert_add_info_format(pinfo, expert_item, PI_PROTOCOL, PI_WARN, + "Message is routed on SSN, but SSN is not present"); + } + + pci = tvb_get_guint8(tvb, 0) & ITU_PC_INDICATOR_MASK; + proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_point_code_indicator : hf_sccp_calling_itu_point_code_indicator, + tvb, 0, ADDRESS_INDICATOR_LENGTH, pci); + + offset = ADDRESS_INDICATOR_LENGTH; + + /* Dissect PC (if present) */ + if (pci) { + if (decode_mtp3_standard == ITU_STANDARD || national == 0) { + if (length < offset + ITU_PC_LENGTH){ + expert_item = proto_tree_add_text(call_tree, tvb, 0, -1, "Wrong length indicated (%u) should be at least %u, PC is %u octets", length, offset + ITU_PC_LENGTH, ITU_PC_LENGTH); + expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated"); + PROTO_ITEM_SET_GENERATED(expert_item); + return; + } + proto_tree_add_item(call_tree, called ? hf_sccp_called_itu_pc : hf_sccp_calling_itu_pc, + tvb, offset, ITU_PC_LENGTH, ENC_LITTLE_ENDIAN); + offset += ITU_PC_LENGTH; + + } else if (decode_mtp3_standard == JAPAN_STANDARD) { + + if (length < offset + JAPAN_PC_LENGTH){ + expert_item = proto_tree_add_text(call_tree, tvb, 0, -1, "Wrong length indicated (%u) should be at least %u, PC is %u octets", length, offset + JAPAN_PC_LENGTH, JAPAN_PC_LENGTH); + expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated"); + PROTO_ITEM_SET_GENERATED(expert_item); + return; + } + proto_tree_add_item(call_tree, called ? hf_sccp_called_japan_pc : hf_sccp_calling_japan_pc, + tvb, offset, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); + + offset += JAPAN_PC_LENGTH; + + } else /* CHINESE_ITU_STANDARD */ { + + if (length < offset + ANSI_PC_LENGTH){ + expert_item = proto_tree_add_text(call_tree, tvb, 0, -1, "Wrong length indicated (%u) should be at least %u, PC is %u octets", length, offset + ANSI_PC_LENGTH, ANSI_PC_LENGTH); + expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated"); + PROTO_ITEM_SET_GENERATED(expert_item); + return; + } + offset = dissect_sccp_3byte_pc(tvb, call_tree, offset, called); + + } + } + + /* Dissect SSN (if present) */ + if (ssni) { + ssn = tvb_get_guint8(tvb, offset); + + if (routing_ind == ROUTE_ON_SSN && ssn == 0) { + expert_add_info_format(pinfo, expert_item, PI_PROTOCOL, PI_WARN, + "Message is routed on SSN, but SSN is zero (unspecified)"); + } + + if (called && assoc) + assoc->called_ssn = ssn; + else if (assoc) + assoc->calling_ssn = ssn; + + if (is_connectionless(message_type) && sccp_msg) { + guint *ssn_ptr = called ? &(sccp_msg->data.ud.called_ssn) : &(sccp_msg->data.ud.calling_ssn); + + *ssn_ptr = ssn; + } + + proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn + : hf_sccp_calling_ssn, + tvb, offset, ADDRESS_SSN_LENGTH, ssn); + hidden_item = proto_tree_add_uint(call_tree, hf_sccp_ssn, tvb, offset, + ADDRESS_SSN_LENGTH, ssn); + PROTO_ITEM_SET_HIDDEN(hidden_item); + + offset += ADDRESS_SSN_LENGTH; + + /* Get the dissector handle of the dissector registered for this ssn + * And print it's name. + */ + ssn_dissector = dissector_get_uint_handle(sccp_ssn_dissector_table, ssn); + + if (ssn_dissector) { + ssn_dissector_short_name = dissector_handle_get_short_name(ssn_dissector); + + if(ssn_dissector_short_name) { + item = proto_tree_add_text(call_tree, tvb, offset - 1, ADDRESS_SSN_LENGTH, "Linked to %s", ssn_dissector_short_name); + PROTO_ITEM_SET_GENERATED(item); + + if (g_ascii_strncasecmp("TCAP", ssn_dissector_short_name, 4)== 0) { + tcap_ssn_dissector = get_itu_tcap_subdissector(ssn); + + if(tcap_ssn_dissector) { + tcap_ssn_dissector_short_name = dissector_handle_get_short_name(tcap_ssn_dissector); + proto_item_append_text(item,", TCAP SSN linked to %s", tcap_ssn_dissector_short_name); + } + } + } /* short name */ + } /* ssn_dissector */ + } /* ssni */ + + /* Dissect GT (if present) */ + if (gti != AI_GTI_NO_GT) { + if (length < offset) + return; + + gt_tvb = tvb_new_subset(tvb, offset, (length - offset), + (length - offset)); + dissect_sccp_global_title(gt_tvb, pinfo, call_tree, (length - offset), gti, + (routing_ind == ROUTE_ON_GT), called); + } } else if (decode_mtp3_standard == ANSI_STANDARD) { - proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_global_title_indicator - : hf_sccp_calling_ansi_global_title_indicator, - tvb, 0, ADDRESS_INDICATOR_LENGTH, gti); - - pci = tvb_get_guint8(tvb, 0) & ANSI_PC_INDICATOR_MASK; - proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_point_code_indicator - : hf_sccp_calling_ansi_point_code_indicator, - tvb, 0, ADDRESS_INDICATOR_LENGTH, pci); - - ssni = tvb_get_guint8(tvb, 0) & ANSI_SSN_INDICATOR_MASK; - expert_item = proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_ssn_indicator - : hf_sccp_calling_ansi_ssn_indicator, - tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni); - if (routing_ind == ROUTE_ON_SSN && ssni == 0) { - expert_add_info_format(pinfo, expert_item, PI_PROTOCOL, PI_WARN, - "Message is routed on SSN, but SSN is not present"); - } - - offset = ADDRESS_INDICATOR_LENGTH; - - /* Dissect SSN (if present) */ - if (ssni) { - ssn = tvb_get_guint8(tvb, offset); - - if (routing_ind == ROUTE_ON_SSN && ssn == 0) { - expert_add_info_format(pinfo, expert_item, PI_PROTOCOL, PI_WARN, - "Message is routed on SSN, but SSN is zero (unspecified)"); - } - - if (called && assoc) { - assoc->called_ssn = ssn; - } else if (assoc) { - assoc->calling_ssn = ssn; - } - - if (is_connectionless(message_type) && sccp_msg) { - guint *ssn_ptr = called ? &(sccp_msg->data.ud.called_ssn) : &(sccp_msg->data.ud.calling_ssn); - - *ssn_ptr = ssn; - } - - proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn - : hf_sccp_calling_ssn, - tvb, offset, ADDRESS_SSN_LENGTH, ssn); - hidden_item = proto_tree_add_uint(call_tree, hf_sccp_ssn, tvb, offset, - ADDRESS_SSN_LENGTH, ssn); - PROTO_ITEM_SET_HIDDEN(hidden_item); - - offset += ADDRESS_SSN_LENGTH; - } - - /* Dissect PC (if present) */ - if (pci) { - offset = dissect_sccp_3byte_pc(tvb, call_tree, offset, called); - } - - /* Dissect GT (if present) */ - if (gti != AI_GTI_NO_GT) { - if (length < offset) - return; - gt_tvb = tvb_new_subset(tvb, offset, (length - offset), - (length - offset)); - dissect_sccp_global_title(gt_tvb, pinfo, call_tree, (length - offset), gti, - (routing_ind == ROUTE_ON_GT), called); - } + proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_global_title_indicator + : hf_sccp_calling_ansi_global_title_indicator, + tvb, 0, ADDRESS_INDICATOR_LENGTH, gti); + + pci = tvb_get_guint8(tvb, 0) & ANSI_PC_INDICATOR_MASK; + proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_point_code_indicator + : hf_sccp_calling_ansi_point_code_indicator, + tvb, 0, ADDRESS_INDICATOR_LENGTH, pci); + + ssni = tvb_get_guint8(tvb, 0) & ANSI_SSN_INDICATOR_MASK; + expert_item = proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_ssn_indicator + : hf_sccp_calling_ansi_ssn_indicator, + tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni); + if (routing_ind == ROUTE_ON_SSN && ssni == 0) { + expert_add_info_format(pinfo, expert_item, PI_PROTOCOL, PI_WARN, + "Message is routed on SSN, but SSN is not present"); + } + + offset = ADDRESS_INDICATOR_LENGTH; + + /* Dissect SSN (if present) */ + if (ssni) { + ssn = tvb_get_guint8(tvb, offset); + + if (routing_ind == ROUTE_ON_SSN && ssn == 0) { + expert_add_info_format(pinfo, expert_item, PI_PROTOCOL, PI_WARN, + "Message is routed on SSN, but SSN is zero (unspecified)"); + } + + if (called && assoc) { + assoc->called_ssn = ssn; + } else if (assoc) { + assoc->calling_ssn = ssn; + } + + if (is_connectionless(message_type) && sccp_msg) { + guint *ssn_ptr = called ? &(sccp_msg->data.ud.called_ssn) : &(sccp_msg->data.ud.calling_ssn); + + *ssn_ptr = ssn; + } + + proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn + : hf_sccp_calling_ssn, + tvb, offset, ADDRESS_SSN_LENGTH, ssn); + hidden_item = proto_tree_add_uint(call_tree, hf_sccp_ssn, tvb, offset, + ADDRESS_SSN_LENGTH, ssn); + PROTO_ITEM_SET_HIDDEN(hidden_item); + + offset += ADDRESS_SSN_LENGTH; + } + + /* Dissect PC (if present) */ + if (pci) { + offset = dissect_sccp_3byte_pc(tvb, call_tree, offset, called); + } + + /* Dissect GT (if present) */ + if (gti != AI_GTI_NO_GT) { + if (length < offset) + return; + gt_tvb = tvb_new_subset(tvb, offset, (length - offset), + (length - offset)); + dissect_sccp_global_title(gt_tvb, pinfo, call_tree, (length - offset), gti, + (routing_ind == ROUTE_ON_GT), called); + } } @@ -2109,39 +2203,39 @@ dissect_sccp_data_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) const mtp3_addr_pc_t* opc = NULL; if (trace_sccp && assoc && assoc != &no_assoc) { - pinfo->sccp_info = assoc->curr_msg; + pinfo->sccp_info = assoc->curr_msg; } else { - pinfo->sccp_info = NULL; + pinfo->sccp_info = NULL; } if (assoc) { - switch (pinfo->p2p_dir) { - case P2P_DIR_SENT: - ssn = assoc->calling_ssn; - other_ssn = assoc->called_ssn; - dpc = (const mtp3_addr_pc_t*)pinfo->dst.data; - opc = (const mtp3_addr_pc_t*)pinfo->src.data; - break; - case P2P_DIR_RECV: - ssn = assoc->called_ssn; - other_ssn = assoc->calling_ssn; - dpc = (const mtp3_addr_pc_t*)pinfo->src.data; - opc = (const mtp3_addr_pc_t*)pinfo->dst.data; - break; - default: - ssn = assoc->called_ssn; - other_ssn = assoc->calling_ssn; - dpc = (const mtp3_addr_pc_t*)pinfo->dst.data; - opc = (const mtp3_addr_pc_t*)pinfo->src.data; - break; - } + switch (pinfo->p2p_dir) { + case P2P_DIR_SENT: + ssn = assoc->calling_ssn; + other_ssn = assoc->called_ssn; + dpc = (const mtp3_addr_pc_t*)pinfo->dst.data; + opc = (const mtp3_addr_pc_t*)pinfo->src.data; + break; + case P2P_DIR_RECV: + ssn = assoc->called_ssn; + other_ssn = assoc->calling_ssn; + dpc = (const mtp3_addr_pc_t*)pinfo->src.data; + opc = (const mtp3_addr_pc_t*)pinfo->dst.data; + break; + default: + ssn = assoc->called_ssn; + other_ssn = assoc->calling_ssn; + dpc = (const mtp3_addr_pc_t*)pinfo->dst.data; + opc = (const mtp3_addr_pc_t*)pinfo->src.data; + break; + } } if (num_sccp_users && pinfo->src.type == AT_SS7PC) { guint i; dissector_handle_t handle = NULL; - gboolean uses_tcap = FALSE; + gboolean uses_tcap = FALSE; for (i=0; i < num_sccp_users; i++) { sccp_user_t* u = &(sccp_users[i]); @@ -2185,8 +2279,8 @@ dissect_sccp_data_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) /* try user default subdissector */ if (default_handle) { - call_dissector(default_handle, tvb, pinfo, tree); - return; + call_dissector(default_handle, tvb, pinfo, tree); + return; } /* No sub-dissection occured, treat it as raw data */ diff --git a/epan/dissectors/packet-sccp.h b/epan/dissectors/packet-sccp.h index d8cac11553..6dff85a63f 100644 --- a/epan/dissectors/packet-sccp.h +++ b/epan/dissectors/packet-sccp.h @@ -105,7 +105,7 @@ typedef struct _sccp_assoc_info_t { extern void reset_sccp_assoc(void); extern sccp_assoc_info_t* get_sccp_assoc(packet_info* pinfo, guint offset, guint32 src_lr, guint32 dst_lr, guint msg_type); -extern gboolean looks_like_valid_sccp(tvbuff_t *tvb, guint8 my_mtp3_standard); +extern gboolean looks_like_valid_sccp(guint32 frame_num, tvbuff_t *tvb, guint8 my_mtp3_standard); #define GT_SIGNAL_LENGTH 1 #define GT_ODD_SIGNAL_MASK 0x0f |