diff options
author | Jeff Morriss <jeff.morriss.ws@gmail.com> | 2013-02-01 02:42:01 +0000 |
---|---|---|
committer | Jeff Morriss <jeff.morriss.ws@gmail.com> | 2013-02-01 02:42:01 +0000 |
commit | 21b1b0c5daf9b4217698dc523d122fefdec968f8 (patch) | |
tree | cbc638089f16de3afd311c9642f1a49436597afe /epan | |
parent | 5754564be8ea7c1da7f269d98068028c524aaa26 (diff) |
Add heuristic MTP3 standard detection to M3UA (not for the draft M3UA versions).
The SCCP heuristics actually don't work all that well here but checking the PCs
(in M3UA) seems to do a decent job at least of differentiating ANSI from ITU.
svn path=/trunk/; revision=47407
Diffstat (limited to 'epan')
-rw-r--r-- | epan/dissectors/packet-m3ua.c | 88 | ||||
-rw-r--r-- | epan/dissectors/packet-mtp3.c | 3 | ||||
-rw-r--r-- | epan/dissectors/packet-mtp3.h | 1 |
3 files changed, 83 insertions, 9 deletions
diff --git a/epan/dissectors/packet-m3ua.c b/epan/dissectors/packet-m3ua.c index 943f096462..c444bd4a38 100644 --- a/epan/dissectors/packet-m3ua.c +++ b/epan/dissectors/packet-m3ua.c @@ -41,9 +41,13 @@ #include <epan/sctpppids.h> #include <epan/emem.h> #include "packet-mtp3.h" +#include "packet-sccp.h" +#include "packet-frame.h" #include "packet-q708.h" #include <epan/tap.h> +static gint m3ua_pref_mtp3_standard; + #define SCTP_PORT_M3UA 2905 #define ADD_PADDING(x) ((((x) + 3) >> 2) << 2) @@ -1109,24 +1113,92 @@ dissect_circuit_range_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_t #define DATA_SLS_OFFSET (DATA_MP_OFFSET + DATA_MP_LENGTH) #define DATA_ULP_OFFSET (DATA_SLS_OFFSET + DATA_SLS_LENGTH) +static guint +m3ua_heur_mtp3_standard(tvbuff_t *tvb, packet_info *pinfo, guint32 opc, guint32 dpc, guint8 si) +{ + switch (si) { + case MTP_SI_SCCP: + { + if (opc < ITU_PC_MASK && dpc < ITU_PC_MASK && + looks_like_valid_sccp(PINFO_FD_NUM(pinfo), tvb, ITU_STANDARD)) { + + return ITU_STANDARD; + } + /* Network 0 is reserved in ANSI */ + /* Could also check that cluster!=0 for small networks (networks 1-5) */ + if ((opc & ANSI_NETWORK_MASK) > 0 && (dpc & ANSI_NETWORK_MASK) > 0 && + looks_like_valid_sccp(PINFO_FD_NUM(pinfo), tvb, ANSI_STANDARD)) { + + return ANSI_STANDARD; + } + if (looks_like_valid_sccp(PINFO_FD_NUM(pinfo), tvb, CHINESE_ITU_STANDARD)) { + return CHINESE_ITU_STANDARD; + } + if (opc < JAPAN_PC_MASK && dpc < JAPAN_PC_MASK && + looks_like_valid_sccp(PINFO_FD_NUM(pinfo), tvb, JAPAN_STANDARD)) { + + return JAPAN_STANDARD; + } + + return HEURISTIC_FAILED_STANDARD; + + } + default: + return HEURISTIC_FAILED_STANDARD; + } +} + +static void +m3ua_reset_mtp3_standard(void) +{ + mtp3_standard = m3ua_pref_mtp3_standard; +} + static void dissect_protocol_data_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *parameter_tree, proto_item *parameter_item) { guint16 ulp_length; tvbuff_t *payload_tvb; - proto_item *item; + proto_item *item, *gen_item; mtp3_tap_rec_t* mtp3_tap = ep_alloc0(sizeof(mtp3_tap_rec_t)); proto_tree *q708_tree; + gint heuristic_standard; + guint8 si; + guint32 opc, dpc; + si = tvb_get_guint8(parameter_tvb, DATA_SI_OFFSET); + ulp_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - DATA_HDR_LENGTH; + payload_tvb = tvb_new_subset(parameter_tvb, DATA_ULP_OFFSET, ulp_length, ulp_length); + dpc = tvb_get_ntohl(parameter_tvb, DATA_DPC_OFFSET); + opc = tvb_get_ntohl(parameter_tvb, DATA_OPC_OFFSET); + + m3ua_pref_mtp3_standard = mtp3_standard; + + if (mtp3_heuristic_standard) { + heuristic_standard = m3ua_heur_mtp3_standard(payload_tvb, pinfo, opc, dpc, si); + if (heuristic_standard == HEURISTIC_FAILED_STANDARD) { + gen_item = proto_tree_add_text(tree, parameter_tvb, 0, 0, "Could not determine Heuristic using %s", val_to_str_const(mtp3_standard, mtp3_standard_vals, "unknown")); + } else { + gen_item = proto_tree_add_text(tree, parameter_tvb, 0, 0, "%s", val_to_str_const(heuristic_standard, mtp3_standard_vals, "unknown")); + + mtp3_standard = heuristic_standard; + + /* Register a frame-end routine to ensure mtp3_standard is set + * back even if an exception is thrown. + */ + register_frame_end_routine(pinfo, m3ua_reset_mtp3_standard); + } + PROTO_ITEM_SET_GENERATED(gen_item); + } mtp3_tap->addr_dpc.type = mtp3_standard; - mtp3_tap->addr_dpc.pc = tvb_get_ntohl(parameter_tvb,DATA_DPC_OFFSET); + mtp3_tap->addr_dpc.pc = dpc; mtp3_tap->addr_dpc.ni = tvb_get_guint8(parameter_tvb, DATA_NI_OFFSET); SET_ADDRESS(&pinfo->dst, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) &mtp3_tap->addr_dpc); mtp3_tap->addr_opc.type = mtp3_standard; - mtp3_tap->addr_opc.pc = tvb_get_ntohl(parameter_tvb,DATA_OPC_OFFSET); + mtp3_tap->addr_opc.pc = opc; mtp3_tap->addr_opc.ni = tvb_get_guint8(parameter_tvb, DATA_NI_OFFSET); SET_ADDRESS(&pinfo->src, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) &mtp3_tap->addr_opc); @@ -1140,19 +1212,19 @@ dissect_protocol_data_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, pro if (parameter_tree) { item = proto_tree_add_item(parameter_tree, hf_protocol_data_opc, parameter_tvb, DATA_OPC_OFFSET, DATA_OPC_LENGTH, ENC_BIG_ENDIAN); if (mtp3_pc_structured()) - proto_item_append_text(item, " (%s)", mtp3_pc_to_str(tvb_get_ntohl(parameter_tvb, DATA_OPC_OFFSET))); + proto_item_append_text(item, " (%s)", mtp3_pc_to_str(opc)); if(mtp3_tap->addr_opc.ni == MTP3_NI_INT0) { q708_tree = proto_item_add_subtree(item,ett_q708_opc); /* Q.708 (1984-10) Numbering of International Signalling Point Codes */ - analyze_q708_ispc(parameter_tvb, q708_tree, DATA_OPC_OFFSET, DATA_OPC_LENGTH, mtp3_tap->addr_opc.pc); + analyze_q708_ispc(parameter_tvb, q708_tree, DATA_OPC_OFFSET, DATA_OPC_LENGTH, opc); } item = proto_tree_add_item(parameter_tree, hf_protocol_data_dpc, parameter_tvb, DATA_DPC_OFFSET, DATA_DPC_LENGTH, ENC_BIG_ENDIAN); if (mtp3_pc_structured()) - proto_item_append_text(item, " (%s)", mtp3_pc_to_str(tvb_get_ntohl(parameter_tvb, DATA_DPC_OFFSET))); + proto_item_append_text(item, " (%s)", mtp3_pc_to_str(dpc)); if(mtp3_tap->addr_dpc.ni == MTP3_NI_INT0) { q708_tree = proto_item_add_subtree(item,ett_q708_dpc); - analyze_q708_ispc(parameter_tvb, q708_tree, DATA_DPC_OFFSET, DATA_DPC_LENGTH, mtp3_tap->addr_dpc.pc); + analyze_q708_ispc(parameter_tvb, q708_tree, DATA_DPC_OFFSET, DATA_DPC_LENGTH, dpc); } proto_tree_add_item(parameter_tree, hf_protocol_data_si, parameter_tvb, DATA_SI_OFFSET, DATA_SI_LENGTH, ENC_BIG_ENDIAN); @@ -1185,6 +1257,8 @@ dissect_protocol_data_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, pro payload_tvb = tvb_new_subset(parameter_tvb, DATA_ULP_OFFSET, ulp_length, ulp_length); if (!dissector_try_uint(si_dissector_table, tvb_get_guint8(parameter_tvb, DATA_SI_OFFSET), payload_tvb, pinfo, tree)) call_dissector(data_handle, payload_tvb, pinfo, tree); + + mtp3_standard = m3ua_pref_mtp3_standard; } #define CORR_ID_OFFSET PARAMETER_VALUE_OFFSET diff --git a/epan/dissectors/packet-mtp3.c b/epan/dissectors/packet-mtp3.c index c902f2a649..bcfe0e7d27 100644 --- a/epan/dissectors/packet-mtp3.c +++ b/epan/dissectors/packet-mtp3.c @@ -651,7 +651,6 @@ dissect_mtp3_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) call_dissector(data_handle, payload_tvb, pinfo, tree); } -#define HEURISTIC_FAILED_STANDARD 0xffff static guint heur_mtp3_standard(tvbuff_t *tvb, packet_info *pinfo, guint8 si) { @@ -721,7 +720,7 @@ dissect_mtp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) mtp3_standard = heuristic_standard; /* Register a frame-end routine to ensure mtp3_standard is set - * back, even if an exception is thrown. + * back even if an exception is thrown. */ register_frame_end_routine(pinfo, reset_mtp3_standard); } diff --git a/epan/dissectors/packet-mtp3.h b/epan/dissectors/packet-mtp3.h index b9b09d9eda..33b2c8c1bd 100644 --- a/epan/dissectors/packet-mtp3.h +++ b/epan/dissectors/packet-mtp3.h @@ -29,6 +29,7 @@ typedef enum { CHINESE_ITU_STANDARD = 3, JAPAN_STANDARD = 4 } Standard_Type; +#define HEURISTIC_FAILED_STANDARD 0xffff extern gint mtp3_standard; extern gboolean mtp3_heuristic_standard; |