aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-m3ua.c
diff options
context:
space:
mode:
authorJeff Morriss <jeff.morriss.ws@gmail.com>2013-02-01 02:42:01 +0000
committerJeff Morriss <jeff.morriss.ws@gmail.com>2013-02-01 02:42:01 +0000
commit21b1b0c5daf9b4217698dc523d122fefdec968f8 (patch)
treecbc638089f16de3afd311c9642f1a49436597afe /epan/dissectors/packet-m3ua.c
parent5754564be8ea7c1da7f269d98068028c524aaa26 (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/dissectors/packet-m3ua.c')
-rw-r--r--epan/dissectors/packet-m3ua.c88
1 files changed, 81 insertions, 7 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