aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Morriss <jeff.morriss@ulticom.com>2012-02-03 04:09:10 +0000
committerJeff Morriss <jeff.morriss@ulticom.com>2012-02-03 04:09:10 +0000
commit73ce69dcd475b6bb31147c582cdf4022bca00364 (patch)
treee2e8ac3f7279f70f289451f1602cd17d58469d98
parente150c5799200d29da2349dc442524295dfc1d901 (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.c331
-rw-r--r--epan/dissectors/packet-sccp.c1046
-rw-r--r--epan/dissectors/packet-sccp.h2
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