summaryrefslogtreecommitdiff
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
parent5754564be8ea7c1da7f269d98068028c524aaa26 (diff)
downloadwireshark-21b1b0c5daf9b4217698dc523d122fefdec968f8.tar.gz
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
-rw-r--r--epan/dissectors/packet-m3ua.c88
-rw-r--r--epan/dissectors/packet-mtp3.c3
-rw-r--r--epan/dissectors/packet-mtp3.h1
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;