diff options
-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; |