aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoretxrab <etxrab@f5534014-38df-0310-8fa8-9805f1628bb7>2006-09-27 20:06:06 +0000
committeretxrab <etxrab@f5534014-38df-0310-8fa8-9805f1628bb7>2006-09-27 20:06:06 +0000
commit55a9d05182b2e685200351ab718b95d444ab3a7f (patch)
treef7501d0fa31314193903026f42aae44fea9e359a
parente1815d883d28bbf88299d4f07a3b1c834e3ee8cb (diff)
From Florent Drouin:
Here are some patches and a new module to introduce the notion of Tcap context for a Tcap transaction. For each Tcap transaction, several parameters, like session identifier, start time or OID, will be saved in a hash table, to keep these informations available for the next messages. This context is then given to the upper layer, and can be used, for example, to generate transaction-associated statistics. Moreover, the Upper protocol, detected in the Begin of the TCAP transaction ( according to the OID ), is saved in the context, and will be reused for the next messages of the transaction. This help the decoding of SS7 messages, without any SSN configuration in the "wireshark preferences". You will have too, the possibility to apply a filter to see only the messages related to a TCAP transaction. (tcap.srt.session_id=XXX) To enable the use of the Tcap context, you have 2 new parameters in the preferences, - SRT, enable search for a Tcap context for any TCAP messages - persistentSRT, keep the Tcap context, even after the transaction has been closed. This is mandatory with Wireshark, to have a clean display of the stats. There is 2 new timers in the preferences for the statistics, to tune the retransmission timeout, and messages lost timeout. git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@19341 f5534014-38df-0310-8fa8-9805f1628bb7
-rw-r--r--asn1/camel/packet-camel-template.c11
-rw-r--r--asn1/gsmmap/GSMMAP.asn3
-rw-r--r--asn1/gsmmap/packet-gsm_map-template.c15
-rw-r--r--asn1/tcap/packet-tcap-template.c296
-rw-r--r--asn1/tcap/packet-tcap-template.h14
-rw-r--r--asn1/tcap/tcap.cnf120
-rw-r--r--epan/Makefile.common2
-rw-r--r--epan/dissectors/packet-camel.c15
-rw-r--r--epan/dissectors/packet-gsm_map.c19
-rw-r--r--epan/dissectors/packet-tcap.c452
-rw-r--r--epan/dissectors/packet-tcap.h14
-rw-r--r--epan/tcap-persistentdata.c1261
-rw-r--r--epan/tcap-persistentdata.h127
13 files changed, 2144 insertions, 205 deletions
diff --git a/asn1/camel/packet-camel-template.c b/asn1/camel/packet-camel-template.c
index 005ba7ecae..432f7a11a5 100644
--- a/asn1/camel/packet-camel-template.c
+++ b/asn1/camel/packet-camel-template.c
@@ -658,13 +658,17 @@ static int
dissect_camel_camelPDU(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
char *version_ptr;
+ struct tcap_private_t * p_private_tcap;
opcode = 0;
application_context_version = 0;
if (pinfo->private_data != NULL){
- version_ptr = strrchr(pinfo->private_data,'.');
- if (version_ptr) {
- application_context_version = atoi(version_ptr+1);
+ p_private_tcap=pinfo->private_data;
+
+ if (p_private_tcap->acv==TRUE ){
+ version_ptr = strrchr(p_private_tcap->oid,'.');
+ if (version_ptr)
+ application_context_version = atoi(version_ptr+1);
}
}
@@ -729,6 +733,7 @@ void proto_reg_handoff_camel(void) {
register_ber_oid_dissector_handle("0.4.0.0.1.0.51.1",camel_handle, proto_camel, "itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network|umts-Network(1) applicationContext(0) cap-assist-handoff-gsmssf-to-gsmscf(51) version2(1)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.52.1",camel_handle, proto_camel, "itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network|umts-Network(1) applicationContext(0) cap-gsmSRF-to-gsmscf(52) version2(1)" );
register_ber_oid_dissector_handle("0.4.0.0.1.21.3.50",camel_handle, proto_camel, "itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) cAP3OE(21) ac(3) id-ac-CAP-gprsSSF-gsmSCF-AC(50)" );
+ register_ber_oid_dissector_handle("0.4.0.0.1.21.3.61",camel_handle, proto_camel, "itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) cAP3OE(21) ac(3) id-ac-cap3-sms-AC(61)" );
register_ber_oid_dissector("0.4.0.0.1.1.5.2", dissect_camelext_CAPGPRSReferenceNumber, proto_camel, "itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) abstractSyntax(1) cap-GPRS-ReferenceNumber(5) version3(2)");
} else {
diff --git a/asn1/gsmmap/GSMMAP.asn b/asn1/gsmmap/GSMMAP.asn
index 7878fae39a..01394e1bd9 100644
--- a/asn1/gsmmap/GSMMAP.asn
+++ b/asn1/gsmmap/GSMMAP.asn
@@ -935,7 +935,8 @@ CheckIMEIArgV3 ::= SEQUENCE {
imei IMEI,
requestedEquipmentInfo RequestedEquipmentInfo,
extensionContainer ExtensionContainer OPTIONAL,
-...}
+ ...
+}
-- RESULT
-- equipmentStatus EquipmentStatus
diff --git a/asn1/gsmmap/packet-gsm_map-template.c b/asn1/gsmmap/packet-gsm_map-template.c
index 92f6cf5865..0f89e7fdf7 100644
--- a/asn1/gsmmap/packet-gsm_map-template.c
+++ b/asn1/gsmmap/packet-gsm_map-template.c
@@ -1474,14 +1474,17 @@ static int
dissect_gsm_map_GSMMAPPDU(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo , proto_tree *tree, int hf_index) {
char *version_ptr;
+ struct tcap_private_t * p_private_tcap;
opcode = 0;
application_context_version = 0;
if (pinfo->private_data != NULL){
- version_ptr = strrchr(pinfo->private_data,'.');
- if (version_ptr) {
- application_context_version = atoi(version_ptr+1);
- }
+ p_private_tcap=pinfo->private_data;
+ if (p_private_tcap->acv==TRUE ){
+ version_ptr = strrchr(p_private_tcap->oid,'.');
+ if (version_ptr)
+ application_context_version = atoi(version_ptr+1);
+ }
}
gsmmap_pdu_type = tvb_get_guint8(tvb, offset)&0x0f;
@@ -1863,10 +1866,11 @@ void proto_reg_handoff_gsm_map(void) {
register_ber_oid_dissector_handle("0.4.0.0.1.0.17.1", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) tracing(17) version1(1)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.18.2", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) networkFunctionalSs(18) version2(2)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.18.1", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) networkFunctionalSs(18) version1(1)" );
- register_ber_oid_dissector_handle("0.4.0.0.1.0.19.1", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) networkUnstructuredSs(19) version2(2)" );
+ register_ber_oid_dissector_handle("0.4.0.0.1.0.19.2", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) networkUnstructuredSs(19) version2(2)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.20.3", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) shortMsgGateway(20) version3(3)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.20.2", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) shortMsgGateway(20) version2(2)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.20.1", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) shortMsgGateway(20) version1(1)" );
+ register_ber_oid_dissector_handle("0.4.0.0.1.0.21.3", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) shortMsgMO-Relay(21) version3(3)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.21.2", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) shortMsgMO-Relay(21) version2(2)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.21.1", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) --shortMsgRelay--21 version1(1)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.22.3", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) subscriberDataModificationNotification(22) version3(3)" );
@@ -1879,6 +1883,7 @@ void proto_reg_handoff_gsm_map(void) {
register_ber_oid_dissector_handle("0.4.0.0.1.0.26.2", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) imsiRetrieval(26) version2(2)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.27.2", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) msPurging(27) version2(2)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.27.3", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) msPurging(27) version3(3)" );
+ register_ber_oid_dissector_handle("0.4.0.0.1.0.28.3", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) subscriberInfoEnquiry(28) version3(3)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.29.3", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) anyTimeInfoEnquiry(29) version3(3)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.31.2", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) oupCallControl(31) version3(3)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.32.3", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) gprsLocationUpdate(32) version3(3)" );
diff --git a/asn1/tcap/packet-tcap-template.c b/asn1/tcap/packet-tcap-template.c
index 0ff052a398..c619929398 100644
--- a/asn1/tcap/packet-tcap-template.c
+++ b/asn1/tcap/packet-tcap-template.c
@@ -33,11 +33,13 @@
#include <epan/prefs.h>
#include <epan/conversation.h>
#include <epan/oid_resolv.h>
+#include <epan/emem.h>
#include <stdio.h>
#include <string.h>
#include "packet-ber.h"
#include "packet-tcap.h"
+#include "epan/tcap-persistentdata.h"
#define PNAME "Transaction Capabilities Application Part"
#define PSNAME "TCAP"
@@ -50,6 +52,12 @@ static int hf_tcap_length = -1;
static int hf_tcap_data = -1;
static int hf_tcap_tid = -1;
+int hf_tcapsrt_SessionId=-1;
+int hf_tcapsrt_Duplicate=-1;
+int hf_tcapsrt_BeginSession=-1;
+int hf_tcapsrt_EndSession=-1;
+int hf_tcapsrt_SessionTime=-1;
+
#include "packet-tcap-hf.c"
/* Initialize the subtree pointers */
@@ -58,25 +66,42 @@ static gint ett_param = -1;
static gint ett_otid = -1;
static gint ett_dtid = -1;
+gint ett_tcap_stat = -1;
+static struct tcapsrt_info_t * gp_tcapsrt_info;
+static gboolean tcap_subdissector_used=FALSE;
+static struct tcaphash_context_t * gp_tcap_context=NULL;
#include "packet-tcap-ett.c"
#define MAX_SSN 254
static range_t *global_ssn_range;
static range_t *ssn_range;
+struct tcap_private_t tcap_private;
+
+gboolean gtcap_HandleSRT=FALSE;
+extern gboolean gtcap_PersistentSRT;
+extern gboolean gtcap_DisplaySRT;
+extern guint gtcap_RepetitionTimeout;
+extern guint gtcap_LostTimeout;
dissector_handle_t tcap_handle = NULL;
static dissector_table_t ber_oid_dissector_table=NULL;
static const char * cur_oid;
static const char * tcapext_oid;
-static proto_tree *tcap_top_tree=NULL;
+static proto_tree * tcap_top_tree=NULL;
+static proto_tree * tcap_stat_tree=NULL;
+static proto_item * tcap_stat_item=NULL;
+
static dissector_handle_t data_handle;
static dissector_table_t sccp_ssn_table;
+
+static void raz_tcap_private(struct tcap_private_t * p_tcap_private);
static int dissect_tcap_param(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
static int dissect_tcap_UserInformation(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_);
-
+static int dissect_tcap_TheComponent(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_);
+static int dissect_tcap_TheExternUserInfo(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_);
static GHashTable* ansi_sub_dissectors = NULL;
static GHashTable* itu_sub_dissectors = NULL;
@@ -130,6 +155,9 @@ dissect_tcap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
{
proto_item *item=NULL;
proto_tree *tree=NULL;
+ proto_item *stat_item=NULL;
+ proto_tree *stat_tree=NULL;
+ struct tcaphash_context_t * p_tcap_context;
tcap_top_tree = parent_tree;
if (check_col(pinfo->cinfo, COL_PROTOCOL))
@@ -139,15 +167,37 @@ dissect_tcap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
/* create display subtree for the protocol */
if(parent_tree){
- item = proto_tree_add_item(parent_tree, proto_tcap, tvb, 0, -1, FALSE);
- tree = proto_item_add_subtree(item, ett_tcap);
+ item = proto_tree_add_item(parent_tree, proto_tcap, tvb, 0, -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_tcap);
+ tcap_stat_item=item;
+ tcap_stat_tree=tree;
}
cur_oid = NULL;
tcapext_oid = NULL;
- pinfo->private_data = NULL;
- dissect_tcap_MessageType(FALSE, tvb, 0, pinfo, tree, -1);
-
-
+ raz_tcap_private(&tcap_private);
+
+ pinfo->private_data = &tcap_private;
+ gp_tcapsrt_info=tcapsrt_razinfo();
+ tcap_subdissector_used=FALSE;
+ gp_tcap_context=NULL;
+ dissect_tcap_MessageType(FALSE, tvb, 0, pinfo, tree, -1);
+
+ if (gtcap_HandleSRT &&
+ !tcap_subdissector_used ) {
+ if (gtcap_DisplaySRT && tree) {
+ stat_item = proto_tree_add_text(tree, tvb, 0, 0, "Stat");
+ stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+ }
+ p_tcap_context=tcapsrt_call_matching(tvb, pinfo, stat_tree, gp_tcapsrt_info);
+ tcap_private.context=p_tcap_context;
+
+ if (gtcap_HandleSRT &&
+ p_tcap_context &&
+ p_tcap_context->callback) {
+ /* Callback fonction for the upper layer */
+ (p_tcap_context->callback)(tvb, pinfo, stat_tree, p_tcap_context);
+ }
+ }
}
@@ -195,6 +245,37 @@ proto_register_tcap(void)
{ "Transaction Id", "tcap.tid",
FT_BYTES, BASE_HEX, NULL, 0,
"", HFILL }
+ },
+ /* Tcap Service Response Time */
+ { &hf_tcapsrt_SessionId,
+ { "Session Id",
+ "tcap.srt.session_id",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_tcapsrt_BeginSession,
+ { "Begin Session",
+ "tcap.srt.begin",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "SRT Begin of Session", HFILL }
+ },
+ { &hf_tcapsrt_EndSession,
+ { "End Session",
+ "tcap.srt.end",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "SRT End of Session", HFILL }
+ },
+ { &hf_tcapsrt_SessionTime,
+ { "Session duration",
+ "tcap.srt.sessiontime",
+ FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
+ "Duration of the TCAP session", HFILL }
+ },
+ { &hf_tcapsrt_Duplicate,
+ { "Request Duplicate",
+ "tcap.srt.duplicate",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }
},
#include "packet-tcap-hfarr.c"
};
@@ -205,6 +286,7 @@ proto_register_tcap(void)
&ett_param,
&ett_otid,
&ett_dtid,
+ &ett_tcap_stat,
#include "packet-tcap-ettarr.c"
};
@@ -248,6 +330,26 @@ proto_register_tcap(void)
prefs_register_range_preference(tcap_module, "ssn", "SCCP SSNs",
"SCCP (and SUA) SSNs to decode as TCAP",
&global_ssn_range, MAX_SSN);
+
+ prefs_register_bool_preference(tcap_module, "srt",
+ "Service Response Time Analyse",
+ "Activate the analyse for Response Time",
+ &gtcap_HandleSRT);
+
+ prefs_register_bool_preference(tcap_module, "persistentsrt",
+ "Persistent stats for SRT",
+ "Statistics for Response Time",
+ &gtcap_PersistentSRT);
+
+ prefs_register_uint_preference(tcap_module, "repetitiontimeout",
+ "Repetition timeout",
+ "Maximal delay for message repetion",
+ 10, &gtcap_RepetitionTimeout);
+
+ prefs_register_uint_preference(tcap_module, "losttimeout",
+ "lost timeout",
+ "Maximal delay for message lost",
+ 10, &gtcap_LostTimeout);
ansi_sub_dissectors = g_hash_table_new(g_direct_hash,g_direct_equal);
itu_sub_dissectors = g_hash_table_new(g_direct_hash,g_direct_equal);
@@ -284,7 +386,7 @@ static void init_tcap(void) {
ssn_range = range_copy(global_ssn_range);
range_foreach(ssn_range, range_add_callback);
-
+ tcapsrt_init_routine();
}
static int
@@ -353,3 +455,179 @@ dissect_tcap_param(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offs
}
return offset;
}
+
+static void raz_tcap_private(struct tcap_private_t * p_tcap_private)
+{
+ memset(p_tcap_private,0,sizeof(struct tcap_private_t) );
+}
+
+
+static int
+dissect_tcap_TheComponent(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_)
+{
+ tvbuff_t * next_tvb;
+ dissector_handle_t subdissector_handle;
+ gboolean is_subdissector=FALSE;
+ struct tcaphash_context_t * p_tcap_context=NULL;
+
+ gint8 class;
+ gboolean pc;
+ gint tag;
+ guint32 len, s_offset;
+ gint ind_field;
+ proto_tree * stat_tree=NULL;
+ proto_item * stat_item=NULL;
+ /*
+ * ok lets look at the oid and ssn and try and find a dissector, otherwise lets decode it.
+ */
+ ber_oid_dissector_table = find_dissector_table("ber.oid");
+ s_offset = offset;
+ offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
+ offset = get_ber_length(tree, tvb, offset, &len, &ind_field);
+ /* we can believe the length now */
+ next_tvb = tvb_new_subset(tvb, s_offset, len+(offset-s_offset), len+(offset-s_offset));
+ if (!next_tvb)
+ return offset+len;
+
+ dissect_ber_choice(pinfo, tree, next_tvb, 0,
+ Component_choice, hf_index, ett_tcap_Component,NULL);
+
+
+ /*
+ * Handle The TCAP Service Response Time
+ */
+ if ( gtcap_HandleSRT ) {
+ if (!tcap_subdissector_used) {
+ /* Create TCAP context and tree for display */
+ if (gtcap_DisplaySRT && tree) {
+ stat_item = proto_tree_add_text(tcap_stat_tree, tvb, offset, -1, "Stat");
+ stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+ }
+ p_tcap_context=tcapsrt_call_matching(tvb, pinfo, stat_tree, gp_tcapsrt_info);
+ tcap_subdissector_used=TRUE;
+ gp_tcap_context=p_tcap_context;
+ tcap_private.context=p_tcap_context;
+ } else {
+ /* Take the last TCAP context */
+ p_tcap_context = gp_tcap_context;
+ tcap_private.context=p_tcap_context;
+ }
+ }
+
+ if (p_tcap_context) {
+ if (cur_oid) {
+ if (p_tcap_context->oid_present) {
+ /* We have already an Application Context, check if we have
+ to fallback to a lower version */
+ if ( strncmp(p_tcap_context->oid,cur_oid, LENGTH_OID)!=0) {
+ /* ACN, changed, Fallback to lower version */
+ /* and update the subdissector (purely formal) */
+ strncpy(p_tcap_context->oid,cur_oid, LENGTH_OID);
+ if ( (subdissector_handle
+ = dissector_get_string_handle(ber_oid_dissector_table, cur_oid)) ) {
+ p_tcap_context->subdissector_handle=subdissector_handle;
+ }
+ }
+ } else {
+ /* We do not have the OID in the TCAP context, so store it */
+ strncpy(p_tcap_context->oid,cur_oid, LENGTH_OID);
+ if ( (subdissector_handle
+ = dissector_get_string_handle(ber_oid_dissector_table, cur_oid)) ) {
+ p_tcap_context->subdissector_handle=subdissector_handle;
+ p_tcap_context->oid_present=TRUE;
+ }
+ } /* context OID */
+ } else {
+ /* Copy the OID from the TCAP context to the current oid */
+ if (p_tcap_context->oid_present) {
+ tcap_private.oid= (void*) p_tcap_context->oid;
+ tcap_private.acv=TRUE;
+ }
+ } /* no OID */
+ } /* no TCAP context */
+
+ if ( p_tcap_context
+ && p_tcap_context->oid_present) {
+ /* Take the subdissector from the context */
+ subdissector_handle=p_tcap_context->subdissector_handle;
+ is_subdissector=TRUE;
+ }
+
+ if (!is_subdissector) {
+ /*
+ * If we do not currently know the subdissector, we have to find it
+ * - first, according to the OID
+ * - then according to the SSN
+ * - and at least, take the default Data handler
+ */
+ if (ber_oid_dissector_table && cur_oid) {
+ /* Search if we can find the sub protocol according to the A.C.N */
+ if ( (subdissector_handle
+ = dissector_get_string_handle(ber_oid_dissector_table, cur_oid)) ) {
+ /* found */
+ is_subdissector=TRUE;
+ } else {
+ /* Search if we can found the sub protocol according to the SSN table */
+ if ( (subdissector_handle
+ = get_itu_tcap_subdissector(pinfo->match_port))) {
+ /* Found according to SSN */
+ is_subdissector=TRUE;
+ } else {
+ /* Nothing found, take the Data handler */
+ subdissector_handle = data_handle;
+ is_subdissector=TRUE;
+ } /* SSN */
+ } /* ACN */
+ } else {
+ /* There is no A.C.N for this transaction, so search in the SSN table */
+ if ( (subdissector_handle = get_itu_tcap_subdissector(pinfo->match_port))) {
+ /* Found according to SSN */
+ is_subdissector=TRUE;
+ } else {
+ subdissector_handle = data_handle;
+ is_subdissector=TRUE;
+ }
+ } /* OID */
+ } else {
+ /* We have it already */
+ }
+ /* Call the sub dissector if present, and not already called */
+ if (is_subdissector)
+ call_dissector(subdissector_handle, next_tvb, pinfo, tcap_top_tree);
+
+ return offset+len;
+}
+
+
+static int
+dissect_tcap_TheExternUserInfo(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_)
+{
+ tvbuff_t *next_tvb;
+ gint8 class;
+ gboolean pc;
+ gint tag;
+ guint32 len, start_offset;
+ gint ind_field;
+
+ /*
+ * ok lets look at the oid and ssn and try and find a dissector, otherwise lets decode it.
+ */
+ ber_oid_dissector_table = find_dissector_table("ber.oid");
+ start_offset = offset;
+ offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
+ offset = get_ber_length(tree, tvb, offset, &len, &ind_field);
+
+ next_tvb = tvb_new_subset(tvb, start_offset, len +(offset - start_offset), len+(offset - start_offset));
+ if (!next_tvb)
+ return offset+len;
+
+ if (ber_oid_dissector_table && tcapext_oid){
+ if(!dissector_try_string(ber_oid_dissector_table, tcapext_oid, next_tvb, pinfo, tcap_top_tree))
+ {
+ }
+ }
+ dissect_tcap_param(pinfo,tree,next_tvb,0);
+ offset+=len;
+
+ return offset;
+}
diff --git a/asn1/tcap/packet-tcap-template.h b/asn1/tcap/packet-tcap-template.h
index b97e0c8c89..c77fb2b585 100644
--- a/asn1/tcap/packet-tcap-template.h
+++ b/asn1/tcap/packet-tcap-template.h
@@ -51,7 +51,17 @@
#define TCAP_CONSTRUCTOR(TCtag) (TCtag & 0x20)
-
+#define TC_BEGIN 1
+#define TC_CONT 2
+#define TC_END 3
+#define TC_ABORT 4
+
+struct tcap_private_t {
+ gboolean acv; /* Is the Application Context Version present */
+ void * oid;
+ guint32 session_id;
+ void * context;
+};
extern gint tcap_standard;
@@ -65,4 +75,4 @@ extern void add_itu_tcap_subdissector(guint32 ssn, dissector_handle_t dissector)
extern void delete_ansi_tcap_subdissector(guint32 ssn, dissector_handle_t dissector);
extern void delete_itu_tcap_subdissector(guint32 ssn, dissector_handle_t dissector);
-#endif /* PACKET_INAP_H */
+#endif /* PACKET_tcap_H */
diff --git a/asn1/tcap/tcap.cnf b/asn1/tcap/tcap.cnf
index 8e85962d4f..59c47b0bdc 100644
--- a/asn1/tcap/tcap.cnf
+++ b/asn1/tcap/tcap.cnf
@@ -92,86 +92,20 @@ dissect_tcap_UserInformation(TRUE, next_tvb, 0, pinfo, tree, -1);
return offset+len;
#.FN_BODY Component
-tvbuff_t *next_tvb;
-gint8 class;
- gboolean pc;
- gint tag;
- guint32 len, s_offset;
- gint ind_field;
-/*
- * ok lets look at the oid and ssn and try and find a dissector, otherwise lets decode it.
- */
-ber_oid_dissector_table = find_dissector_table("ber.oid");
-s_offset = offset;
-offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
-offset = get_ber_length(tree, tvb, offset, &len, &ind_field);
-/* we can believe the length now */
-next_tvb = tvb_new_subset(tvb, s_offset, len+(offset-s_offset), len+(offset-s_offset));
-if (!next_tvb)
- return offset+len;
-
-dissect_ber_choice(pinfo, tree, next_tvb, 0,
- Component_choice, hf_index, ett_tcap_Component,NULL);
-
-if (ber_oid_dissector_table && cur_oid){
-if(!dissector_try_string(ber_oid_dissector_table, cur_oid, next_tvb, pinfo, tcap_top_tree))
- {
- dissector_handle_t subdissector_handle;
-
- if (! (subdissector_handle = get_itu_tcap_subdissector(pinfo->match_port))) {
- subdissector_handle = data_handle;
- }
-
- call_dissector(subdissector_handle, next_tvb, pinfo, tcap_top_tree);
-
- }
-}
-else {
- dissector_handle_t subdissector_handle;
-
- if (! (subdissector_handle = get_itu_tcap_subdissector(pinfo->match_port))) {
- subdissector_handle = data_handle;
- }
-
- call_dissector(subdissector_handle, next_tvb, pinfo, tcap_top_tree);
-}
-
-return offset+len;
+dissect_tcap_TheComponent(implicit_tag, tvb, offset, pinfo, tree, hf_index);
#.FN_BODY Applicationcontext FN_VARIANT = _str VAL_PTR = &cur_oid
%(DEFAULT_BODY)s
- pinfo->private_data = (void*)cur_oid;
+ tcap_private.oid= (void*) cur_oid;
+ tcap_private.acv=TRUE;
#.FN_BODY UserInfoOID FN_VARIANT = _str VAL_PTR = &tcapext_oid
%(DEFAULT_BODY)s
- pinfo->private_data = (void*)tcapext_oid;
+ tcap_private.oid= (void*)tcapext_oid;
+ tcap_private.acv=TRUE;
#.FN_BODY ExternUserInfo
-tvbuff_t *next_tvb;
-gint8 class;
- gboolean pc;
- gint tag;
- guint32 len, start_offset;
- gint ind_field;
-/*
- * ok lets look at the oid and ssn and try and find a dissector, otherwise lets decode it.
- */
-ber_oid_dissector_table = find_dissector_table("ber.oid");
-start_offset = offset;
-offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
-offset = get_ber_length(tree, tvb, offset, &len, &ind_field);
-/* Use the recived length, XXX What if it was indefenet? length is good now */
-next_tvb = tvb_new_subset(tvb, start_offset, len +(offset - start_offset), len+(offset - start_offset));
-if (!next_tvb)
- return offset+len;
-if (ber_oid_dissector_table && tcapext_oid){
-if(!dissector_try_string(ber_oid_dissector_table, tcapext_oid, next_tvb, pinfo, tcap_top_tree))
- {
- }
- }
-dissect_tcap_param(pinfo,tree,next_tvb,0);
- offset+=len;
-
+dissect_tcap_TheExternUserInfo(implicit_tag, tvb, offset, pinfo, tree, hf_index);
#.FN_BODY ANSIParameters
/* we are doing the ParamSet here so need to look at the tags*/
@@ -193,6 +127,8 @@ next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), tvb_le
if (! (subdissector_handle = get_ansi_tcap_subdissector(pinfo->match_port))) {
subdissector_handle = data_handle;
}
+
+ tcap_subdissector_used=TRUE;
call_dissector(subdissector_handle, next_tvb, pinfo, tcap_top_tree);
@@ -206,11 +142,27 @@ proto_item *tid_item;
proto_tree *subtree;
tid_item = proto_tree_add_text(tree, tvb, offset, -1, "Source Transaction ID");
subtree = proto_item_add_subtree(tid_item, ett_otid);
+
offset = dissect_ber_octet_string(implicit_tag, pinfo, subtree, tvb, offset, hf_tcap_tid,
&parameter_tvb);
if (parameter_tvb){
len = tvb_length_remaining(parameter_tvb, 0);
+ switch(len) {
+ case 1:
+ gp_tcapsrt_info->src_tid=tvb_get_guint8(parameter_tvb, 0);
+ break;
+ case 2:
+ gp_tcapsrt_info->src_tid=tvb_get_ntohs(parameter_tvb, 0);
+ break;
+ case 4:
+ gp_tcapsrt_info->src_tid=tvb_get_ntohl(parameter_tvb, 0);
+ break;
+ default:
+ gp_tcapsrt_info->src_tid=0;
+ break;
+ }
+
if ((len)&&(check_col(pinfo->cinfo, COL_INFO))){
col_append_fstr(pinfo->cinfo, COL_INFO, "otid(");
for(i=0;i<len;i++)
@@ -228,11 +180,27 @@ proto_item *tid_item;
proto_tree *subtree;
tid_item = proto_tree_add_text(tree, tvb, offset, -1, "Destination Transaction ID");
subtree = proto_item_add_subtree(tid_item, ett_otid);
+
offset = dissect_ber_octet_string(implicit_tag, pinfo, subtree, tvb, offset, hf_tcap_tid,
&parameter_tvb);
if (parameter_tvb){
len = tvb_length_remaining(parameter_tvb, 0);
+ switch(len) {
+ case 1:
+ gp_tcapsrt_info->dst_tid=tvb_get_guint8(parameter_tvb, 0);
+ break;
+ case 2:
+ gp_tcapsrt_info->dst_tid=tvb_get_ntohs(parameter_tvb, 0);
+ break;
+ case 4:
+ gp_tcapsrt_info->dst_tid=tvb_get_ntohl(parameter_tvb, 0);
+ break;
+ default:
+ gp_tcapsrt_info->dst_tid=0;
+ break;
+ }
+
if ((len)&&(check_col(pinfo->cinfo, COL_INFO))){
col_append_fstr(pinfo->cinfo, COL_INFO, "dtid(");
for(i=0;i<len;i++)
@@ -241,21 +209,29 @@ if (parameter_tvb){
}
}
#.FN_BODY Begin
+gp_tcapsrt_info->ope=TC_BEGIN;
+
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, " Begin ");
offset = dissect_ber_sequence(implicit_tag, pinfo, tree, tvb, offset,
Begin_sequence, hf_index, ett_tcap_Begin);
#.FN_BODY End
+gp_tcapsrt_info->ope=TC_END;
+
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, " End ");
offset = dissect_ber_sequence(implicit_tag, pinfo, tree, tvb, offset,
End_sequence, hf_index, ett_tcap_End);
#.FN_BODY Continue
+gp_tcapsrt_info->ope=TC_CONT;
+
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, " Continue ");
offset = dissect_ber_sequence(implicit_tag, pinfo, tree, tvb, offset,
Continue_sequence, hf_index, ett_tcap_Continue);
#.FN_BODY Abort
+gp_tcapsrt_info->ope=TC_ABORT;
+
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, " Abort ");
offset = dissect_ber_sequence(implicit_tag, pinfo, tree, tvb, offset,
diff --git a/epan/Makefile.common b/epan/Makefile.common
index 446f68aa95..0eb3b6ac45 100644
--- a/epan/Makefile.common
+++ b/epan/Makefile.common
@@ -84,6 +84,7 @@ LIBWIRESHARK_SRC = \
stream.c \
t35.c \
tap.c \
+ tcap-persistentdata.c \
timestamp.c \
to_str.c \
tvbparse.c \
@@ -182,6 +183,7 @@ LIBWIRESHARK_INCLUDES = \
strutil.h \
t35.h \
tap.h \
+ tcap-persistentdata.h \
timestamp.h \
to_str.h \
tvbparse.h \
diff --git a/epan/dissectors/packet-camel.c b/epan/dissectors/packet-camel.c
index ccf37b8013..0227681f8c 100644
--- a/epan/dissectors/packet-camel.c
+++ b/epan/dissectors/packet-camel.c
@@ -8457,13 +8457,17 @@ static int
dissect_camel_camelPDU(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
char *version_ptr;
+ struct tcap_private_t * p_private_tcap;
opcode = 0;
application_context_version = 0;
if (pinfo->private_data != NULL){
- version_ptr = strrchr(pinfo->private_data,'.');
- if (version_ptr) {
- application_context_version = atoi(version_ptr+1);
+ p_private_tcap=pinfo->private_data;
+
+ if (p_private_tcap->acv==TRUE ){
+ version_ptr = strrchr(p_private_tcap->oid,'.');
+ if (version_ptr)
+ application_context_version = atoi(version_ptr+1);
}
}
@@ -8528,6 +8532,7 @@ void proto_reg_handoff_camel(void) {
register_ber_oid_dissector_handle("0.4.0.0.1.0.51.1",camel_handle, proto_camel, "itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network|umts-Network(1) applicationContext(0) cap-assist-handoff-gsmssf-to-gsmscf(51) version2(1)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.52.1",camel_handle, proto_camel, "itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network|umts-Network(1) applicationContext(0) cap-gsmSRF-to-gsmscf(52) version2(1)" );
register_ber_oid_dissector_handle("0.4.0.0.1.21.3.50",camel_handle, proto_camel, "itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) cAP3OE(21) ac(3) id-ac-CAP-gprsSSF-gsmSCF-AC(50)" );
+ register_ber_oid_dissector_handle("0.4.0.0.1.21.3.61",camel_handle, proto_camel, "itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) cAP3OE(21) ac(3) id-ac-cap3-sms-AC(61)" );
register_ber_oid_dissector("0.4.0.0.1.1.5.2", dissect_camelext_CAPGPRSReferenceNumber, proto_camel, "itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) abstractSyntax(1) cap-GPRS-ReferenceNumber(5) version3(2)");
} else {
@@ -10553,7 +10558,7 @@ void proto_register_camel(void) {
"", HFILL }},
/*--- End of included file: packet-camel-hfarr.c ---*/
-#line 833 "packet-camel-template.c"
+#line 838 "packet-camel-template.c"
};
/* List of subtrees */
@@ -10781,7 +10786,7 @@ void proto_register_camel(void) {
&ett_camel_CancelFailedPARAM,
/*--- End of included file: packet-camel-ettarr.c ---*/
-#line 851 "packet-camel-template.c"
+#line 856 "packet-camel-template.c"
};
/* Register protocol */
proto_camel = proto_register_protocol(PNAME, PSNAME, PFNAME);
diff --git a/epan/dissectors/packet-gsm_map.c b/epan/dissectors/packet-gsm_map.c
index 418a713d93..30bfccdac7 100644
--- a/epan/dissectors/packet-gsm_map.c
+++ b/epan/dissectors/packet-gsm_map.c
@@ -15674,14 +15674,17 @@ static int
dissect_gsm_map_GSMMAPPDU(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo , proto_tree *tree, int hf_index) {
char *version_ptr;
+ struct tcap_private_t * p_private_tcap;
opcode = 0;
application_context_version = 0;
if (pinfo->private_data != NULL){
- version_ptr = strrchr(pinfo->private_data,'.');
- if (version_ptr) {
- application_context_version = atoi(version_ptr+1);
- }
+ p_private_tcap=pinfo->private_data;
+ if (p_private_tcap->acv==TRUE ){
+ version_ptr = strrchr(p_private_tcap->oid,'.');
+ if (version_ptr)
+ application_context_version = atoi(version_ptr+1);
+ }
}
gsmmap_pdu_type = tvb_get_guint8(tvb, offset)&0x0f;
@@ -16063,10 +16066,11 @@ void proto_reg_handoff_gsm_map(void) {
register_ber_oid_dissector_handle("0.4.0.0.1.0.17.1", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) tracing(17) version1(1)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.18.2", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) networkFunctionalSs(18) version2(2)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.18.1", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) networkFunctionalSs(18) version1(1)" );
- register_ber_oid_dissector_handle("0.4.0.0.1.0.19.1", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) networkUnstructuredSs(19) version2(2)" );
+ register_ber_oid_dissector_handle("0.4.0.0.1.0.19.2", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) networkUnstructuredSs(19) version2(2)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.20.3", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) shortMsgGateway(20) version3(3)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.20.2", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) shortMsgGateway(20) version2(2)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.20.1", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) shortMsgGateway(20) version1(1)" );
+ register_ber_oid_dissector_handle("0.4.0.0.1.0.21.3", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) shortMsgMO-Relay(21) version3(3)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.21.2", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) shortMsgMO-Relay(21) version2(2)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.21.1", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) --shortMsgRelay--21 version1(1)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.22.3", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) subscriberDataModificationNotification(22) version3(3)" );
@@ -16079,6 +16083,7 @@ void proto_reg_handoff_gsm_map(void) {
register_ber_oid_dissector_handle("0.4.0.0.1.0.26.2", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) imsiRetrieval(26) version2(2)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.27.2", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) msPurging(27) version2(2)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.27.3", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) msPurging(27) version3(3)" );
+ register_ber_oid_dissector_handle("0.4.0.0.1.0.28.3", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) subscriberInfoEnquiry(28) version3(3)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.29.3", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) anyTimeInfoEnquiry(29) version3(3)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.31.2", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) oupCallControl(31) version3(3)" );
register_ber_oid_dissector_handle("0.4.0.0.1.0.32.3", map_handle, proto_gsm_map,"itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) map-ac(0) gprsLocationUpdate(32) version3(3)" );
@@ -19684,7 +19689,7 @@ void proto_register_gsm_map(void) {
"", HFILL }},
/*--- End of included file: packet-gsm_map-hfarr.c ---*/
-#line 2211 "packet-gsm_map-template.c"
+#line 2216 "packet-gsm_map-template.c"
};
/* List of subtrees */
@@ -20107,7 +20112,7 @@ void proto_register_gsm_map(void) {
&ett_gsm_map_AccessTypePriv,
/*--- End of included file: packet-gsm_map-ettarr.c ---*/
-#line 2233 "packet-gsm_map-template.c"
+#line 2238 "packet-gsm_map-template.c"
};
/* Register protocol */
diff --git a/epan/dissectors/packet-tcap.c b/epan/dissectors/packet-tcap.c
index 3a8aa0b6f3..281f2ed946 100644
--- a/epan/dissectors/packet-tcap.c
+++ b/epan/dissectors/packet-tcap.c
@@ -41,11 +41,13 @@
#include <epan/prefs.h>
#include <epan/conversation.h>
#include <epan/oid_resolv.h>
+#include <epan/emem.h>
#include <stdio.h>
#include <string.h>
#include "packet-ber.h"
#include "packet-tcap.h"
+#include "epan/tcap-persistentdata.h"
#define PNAME "Transaction Capabilities Application Part"
#define PSNAME "TCAP"
@@ -58,6 +60,12 @@ static int hf_tcap_length = -1;
static int hf_tcap_data = -1;
static int hf_tcap_tid = -1;
+int hf_tcapsrt_SessionId=-1;
+int hf_tcapsrt_Duplicate=-1;
+int hf_tcapsrt_BeginSession=-1;
+int hf_tcapsrt_EndSession=-1;
+int hf_tcapsrt_SessionTime=-1;
+
/*--- Included file: packet-tcap-hf.c ---*/
#line 1 "packet-tcap-hf.c"
@@ -186,7 +194,7 @@ static int hf_tcap_T_protocol_versionre_version1 = -1;
static int hf_tcap_T_protocol_version3_version1 = -1;
/*--- End of included file: packet-tcap-hf.c ---*/
-#line 54 "packet-tcap-template.c"
+#line 62 "packet-tcap-template.c"
/* Initialize the subtree pointers */
static gint ett_tcap = -1;
@@ -194,7 +202,11 @@ static gint ett_param = -1;
static gint ett_otid = -1;
static gint ett_dtid = -1;
+gint ett_tcap_stat = -1;
+static struct tcapsrt_info_t * gp_tcapsrt_info;
+static gboolean tcap_subdissector_used=FALSE;
+static struct tcaphash_context_t * gp_tcap_context=NULL;
/*--- Included file: packet-tcap-ett.c ---*/
@@ -251,23 +263,36 @@ static gint ett_tcap_OperationCode = -1;
static gint ett_tcap_ErrorCode = -1;
/*--- End of included file: packet-tcap-ett.c ---*/
-#line 64 "packet-tcap-template.c"
+#line 76 "packet-tcap-template.c"
#define MAX_SSN 254
static range_t *global_ssn_range;
static range_t *ssn_range;
+struct tcap_private_t tcap_private;
+
+gboolean gtcap_HandleSRT=FALSE;
+extern gboolean gtcap_PersistentSRT;
+extern gboolean gtcap_DisplaySRT;
+extern guint gtcap_RepetitionTimeout;
+extern guint gtcap_LostTimeout;
dissector_handle_t tcap_handle = NULL;
static dissector_table_t ber_oid_dissector_table=NULL;
static const char * cur_oid;
static const char * tcapext_oid;
-static proto_tree *tcap_top_tree=NULL;
+static proto_tree * tcap_top_tree=NULL;
+static proto_tree * tcap_stat_tree=NULL;
+static proto_item * tcap_stat_item=NULL;
+
static dissector_handle_t data_handle;
static dissector_table_t sccp_ssn_table;
+
+static void raz_tcap_private(struct tcap_private_t * p_tcap_private);
static int dissect_tcap_param(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
static int dissect_tcap_UserInformation(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_);
-
+static int dissect_tcap_TheComponent(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_);
+static int dissect_tcap_TheExternUserInfo(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_);
static GHashTable* ansi_sub_dissectors = NULL;
static GHashTable* itu_sub_dissectors = NULL;
@@ -331,10 +356,11 @@ static int dissect_protocol_versionrq_impl(packet_info *pinfo, proto_tree *tree,
static int
dissect_tcap_Applicationcontext(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
-#line 142 "tcap.cnf"
+#line 98 "tcap.cnf"
offset = dissect_ber_object_identifier_str(implicit_tag, pinfo, tree, tvb, offset, hf_index, &cur_oid);
- pinfo->private_data = (void*)cur_oid;
+ tcap_private.oid= (void*) cur_oid;
+ tcap_private.acv=TRUE;
@@ -643,10 +669,11 @@ dissect_tcap_ExternalPDU(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, p
static int
dissect_tcap_UserInfoOID(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
-#line 146 "tcap.cnf"
+#line 103 "tcap.cnf"
offset = dissect_ber_object_identifier_str(implicit_tag, pinfo, tree, tvb, offset, hf_index, &tcapext_oid);
- pinfo->private_data = (void*)tcapext_oid;
+ tcap_private.oid= (void*)tcapext_oid;
+ tcap_private.acv=TRUE;
@@ -660,32 +687,8 @@ static int dissect_useroid(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb,
static int
dissect_tcap_ExternUserInfo(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
-#line 150 "tcap.cnf"
-tvbuff_t *next_tvb;
-gint8 class;
- gboolean pc;
- gint tag;
- guint32 len, start_offset;
- gint ind_field;
-/*
- * ok lets look at the oid and ssn and try and find a dissector, otherwise lets decode it.
- */
-ber_oid_dissector_table = find_dissector_table("ber.oid");
-start_offset = offset;
-offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
-offset = get_ber_length(tree, tvb, offset, &len, &ind_field);
-/* Use the recived length, XXX What if it was indefenet? length is good now */
-next_tvb = tvb_new_subset(tvb, start_offset, len +(offset - start_offset), len+(offset - start_offset));
-if (!next_tvb)
- return offset+len;
-if (ber_oid_dissector_table && tcapext_oid){
-if(!dissector_try_string(ber_oid_dissector_table, tcapext_oid, next_tvb, pinfo, tcap_top_tree))
- {
- }
- }
-dissect_tcap_param(pinfo,tree,next_tvb,0);
- offset+=len;
-
+#line 108 "tcap.cnf"
+dissect_tcap_TheExternUserInfo(implicit_tag, tvb, offset, pinfo, tree, hf_index);
@@ -1299,51 +1302,7 @@ static const ber_choice_t Component_choice[] = {
static int
dissect_tcap_Component(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
#line 95 "tcap.cnf"
-tvbuff_t *next_tvb;
-gint8 class;
- gboolean pc;
- gint tag;
- guint32 len, s_offset;
- gint ind_field;
-/*
- * ok lets look at the oid and ssn and try and find a dissector, otherwise lets decode it.
- */
-ber_oid_dissector_table = find_dissector_table("ber.oid");
-s_offset = offset;
-offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
-offset = get_ber_length(tree, tvb, offset, &len, &ind_field);
-/* we can believe the length now */
-next_tvb = tvb_new_subset(tvb, s_offset, len+(offset-s_offset), len+(offset-s_offset));
-if (!next_tvb)
- return offset+len;
-
-dissect_ber_choice(pinfo, tree, next_tvb, 0,
- Component_choice, hf_index, ett_tcap_Component,NULL);
-
-if (ber_oid_dissector_table && cur_oid){
-if(!dissector_try_string(ber_oid_dissector_table, cur_oid, next_tvb, pinfo, tcap_top_tree))
- {
- dissector_handle_t subdissector_handle;
-
- if (! (subdissector_handle = get_itu_tcap_subdissector(pinfo->match_port))) {
- subdissector_handle = data_handle;
- }
-
- call_dissector(subdissector_handle, next_tvb, pinfo, tcap_top_tree);
-
- }
-}
-else {
- dissector_handle_t subdissector_handle;
-
- if (! (subdissector_handle = get_itu_tcap_subdissector(pinfo->match_port))) {
- subdissector_handle = data_handle;
- }
-
- call_dissector(subdissector_handle, next_tvb, pinfo, tcap_top_tree);
-}
-
-return offset+len;
+dissect_tcap_TheComponent(implicit_tag, tvb, offset, pinfo, tree, hf_index);
@@ -1391,18 +1350,34 @@ static int dissect_unidirectional_impl(packet_info *pinfo, proto_tree *tree, tvb
static int
dissect_tcap_OrigTransactionID(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
-#line 203 "tcap.cnf"
+#line 139 "tcap.cnf"
tvbuff_t *parameter_tvb;
guint8 len, i;
proto_item *tid_item;
proto_tree *subtree;
tid_item = proto_tree_add_text(tree, tvb, offset, -1, "Source Transaction ID");
subtree = proto_item_add_subtree(tid_item, ett_otid);
+
offset = dissect_ber_octet_string(implicit_tag, pinfo, subtree, tvb, offset, hf_tcap_tid,
&parameter_tvb);
if (parameter_tvb){
len = tvb_length_remaining(parameter_tvb, 0);
+ switch(len) {
+ case 1:
+ gp_tcapsrt_info->src_tid=tvb_get_guint8(parameter_tvb, 0);
+ break;
+ case 2:
+ gp_tcapsrt_info->src_tid=tvb_get_ntohs(parameter_tvb, 0);
+ break;
+ case 4:
+ gp_tcapsrt_info->src_tid=tvb_get_ntohl(parameter_tvb, 0);
+ break;
+ default:
+ gp_tcapsrt_info->src_tid=0;
+ break;
+ }
+
if ((len)&&(check_col(pinfo->cinfo, COL_INFO))){
col_append_fstr(pinfo->cinfo, COL_INFO, "otid(");
for(i=0;i<len;i++)
@@ -1431,7 +1406,9 @@ static const ber_sequence_t Begin_sequence[] = {
static int
dissect_tcap_Begin(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
-#line 244 "tcap.cnf"
+#line 212 "tcap.cnf"
+gp_tcapsrt_info->ope=TC_BEGIN;
+
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, " Begin ");
offset = dissect_ber_sequence(implicit_tag, pinfo, tree, tvb, offset,
@@ -1448,18 +1425,34 @@ static int dissect_begin_impl(packet_info *pinfo, proto_tree *tree, tvbuff_t *tv
static int
dissect_tcap_DestTransactionID(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
-#line 225 "tcap.cnf"
+#line 177 "tcap.cnf"
tvbuff_t *parameter_tvb;
guint8 len , i;
proto_item *tid_item;
proto_tree *subtree;
tid_item = proto_tree_add_text(tree, tvb, offset, -1, "Destination Transaction ID");
subtree = proto_item_add_subtree(tid_item, ett_otid);
+
offset = dissect_ber_octet_string(implicit_tag, pinfo, subtree, tvb, offset, hf_tcap_tid,
&parameter_tvb);
if (parameter_tvb){
len = tvb_length_remaining(parameter_tvb, 0);
+ switch(len) {
+ case 1:
+ gp_tcapsrt_info->dst_tid=tvb_get_guint8(parameter_tvb, 0);
+ break;
+ case 2:
+ gp_tcapsrt_info->dst_tid=tvb_get_ntohs(parameter_tvb, 0);
+ break;
+ case 4:
+ gp_tcapsrt_info->dst_tid=tvb_get_ntohl(parameter_tvb, 0);
+ break;
+ default:
+ gp_tcapsrt_info->dst_tid=0;
+ break;
+ }
+
if ((len)&&(check_col(pinfo->cinfo, COL_INFO))){
col_append_fstr(pinfo->cinfo, COL_INFO, "dtid(");
for(i=0;i<len;i++)
@@ -1485,7 +1478,9 @@ static const ber_sequence_t End_sequence[] = {
static int
dissect_tcap_End(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
-#line 249 "tcap.cnf"
+#line 219 "tcap.cnf"
+gp_tcapsrt_info->ope=TC_END;
+
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, " End ");
offset = dissect_ber_sequence(implicit_tag, pinfo, tree, tvb, offset,
@@ -1509,7 +1504,9 @@ static const ber_sequence_t Continue_sequence[] = {
static int
dissect_tcap_Continue(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
-#line 254 "tcap.cnf"
+#line 226 "tcap.cnf"
+gp_tcapsrt_info->ope=TC_CONT;
+
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, " Continue ");
offset = dissect_ber_sequence(implicit_tag, pinfo, tree, tvb, offset,
@@ -1578,7 +1575,9 @@ static const ber_sequence_t Abort_sequence[] = {
static int
dissect_tcap_Abort(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
-#line 259 "tcap.cnf"
+#line 233 "tcap.cnf"
+gp_tcapsrt_info->ope=TC_ABORT;
+
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, " Abort ");
offset = dissect_ber_sequence(implicit_tag, pinfo, tree, tvb, offset,
@@ -1797,7 +1796,7 @@ static int dissect_operationCode(packet_info *pinfo, proto_tree *tree, tvbuff_t
static int
dissect_tcap_ANSIParameters(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
-#line 177 "tcap.cnf"
+#line 111 "tcap.cnf"
/* we are doing the ParamSet here so need to look at the tags*/
guint32 len;
len = tvb_length_remaining(tvb, offset);
@@ -2063,7 +2062,7 @@ static const ber_choice_t ComponentPDU_choice[] = {
static int
dissect_tcap_ComponentPDU(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
-#line 188 "tcap.cnf"
+#line 122 "tcap.cnf"
tvbuff_t *next_tvb;
dissector_handle_t subdissector_handle;
@@ -2072,6 +2071,8 @@ next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), tvb_le
if (! (subdissector_handle = get_ansi_tcap_subdissector(pinfo->match_port))) {
subdissector_handle = data_handle;
}
+
+ tcap_subdissector_used=TRUE;
call_dissector(subdissector_handle, next_tvb, pinfo, tcap_top_tree);
@@ -2131,7 +2132,7 @@ static const ber_sequence_t TransactionPDU_sequence[] = {
static int
dissect_tcap_TransactionPDU(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
-#line 269 "tcap.cnf"
+#line 245 "tcap.cnf"
if ((hf_index == hf_tcap_ansiqueryWithPerm)&&(check_col(pinfo->cinfo, COL_INFO)))
col_append_fstr(pinfo->cinfo, COL_INFO, " QueryWithPerm");
@@ -2232,7 +2233,7 @@ static const ber_sequence_t AbortPDU_sequence[] = {
static int
dissect_tcap_AbortPDU(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
-#line 264 "tcap.cnf"
+#line 240 "tcap.cnf"
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, " Abort ");
offset = dissect_ber_sequence(implicit_tag, pinfo, tree, tvb, offset,
@@ -2311,7 +2312,7 @@ dissect_tcap_ERROR(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_
/*--- End of included file: packet-tcap-fn.c ---*/
-#line 116 "packet-tcap-template.c"
+#line 141 "packet-tcap-template.c"
@@ -2329,6 +2330,9 @@ dissect_tcap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
{
proto_item *item=NULL;
proto_tree *tree=NULL;
+ proto_item *stat_item=NULL;
+ proto_tree *stat_tree=NULL;
+ struct tcaphash_context_t * p_tcap_context;
tcap_top_tree = parent_tree;
if (check_col(pinfo->cinfo, COL_PROTOCOL))
@@ -2338,15 +2342,37 @@ dissect_tcap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
/* create display subtree for the protocol */
if(parent_tree){
- item = proto_tree_add_item(parent_tree, proto_tcap, tvb, 0, -1, FALSE);
- tree = proto_item_add_subtree(item, ett_tcap);
+ item = proto_tree_add_item(parent_tree, proto_tcap, tvb, 0, -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_tcap);
+ tcap_stat_item=item;
+ tcap_stat_tree=tree;
}
cur_oid = NULL;
tcapext_oid = NULL;
- pinfo->private_data = NULL;
- dissect_tcap_MessageType(FALSE, tvb, 0, pinfo, tree, -1);
-
-
+ raz_tcap_private(&tcap_private);
+
+ pinfo->private_data = &tcap_private;
+ gp_tcapsrt_info=tcapsrt_razinfo();
+ tcap_subdissector_used=FALSE;
+ gp_tcap_context=NULL;
+ dissect_tcap_MessageType(FALSE, tvb, 0, pinfo, tree, -1);
+
+ if (gtcap_HandleSRT &&
+ !tcap_subdissector_used ) {
+ if (gtcap_DisplaySRT && tree) {
+ stat_item = proto_tree_add_text(tree, tvb, 0, 0, "Stat");
+ stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+ }
+ p_tcap_context=tcapsrt_call_matching(tvb, pinfo, stat_tree, gp_tcapsrt_info);
+ tcap_private.context=p_tcap_context;
+
+ if (gtcap_HandleSRT &&
+ p_tcap_context &&
+ p_tcap_context->callback) {
+ /* Callback fonction for the upper layer */
+ (p_tcap_context->callback)(tvb, pinfo, stat_tree, p_tcap_context);
+ }
+ }
}
@@ -2394,6 +2420,37 @@ proto_register_tcap(void)
{ "Transaction Id", "tcap.tid",
FT_BYTES, BASE_HEX, NULL, 0,
"", HFILL }
+ },
+ /* Tcap Service Response Time */
+ { &hf_tcapsrt_SessionId,
+ { "Session Id",
+ "tcap.srt.session_id",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_tcapsrt_BeginSession,
+ { "Begin Session",
+ "tcap.srt.begin",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "SRT Begin of Session", HFILL }
+ },
+ { &hf_tcapsrt_EndSession,
+ { "End Session",
+ "tcap.srt.end",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "SRT End of Session", HFILL }
+ },
+ { &hf_tcapsrt_SessionTime,
+ { "Session duration",
+ "tcap.srt.sessiontime",
+ FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
+ "Duration of the TCAP session", HFILL }
+ },
+ { &hf_tcapsrt_Duplicate,
+ { "Request Duplicate",
+ "tcap.srt.duplicate",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }
},
/*--- Included file: packet-tcap-hfarr.c ---*/
@@ -2888,7 +2945,7 @@ proto_register_tcap(void)
"", HFILL }},
/*--- End of included file: packet-tcap-hfarr.c ---*/
-#line 200 "packet-tcap-template.c"
+#line 281 "packet-tcap-template.c"
};
/* Setup protocol subtree array */
@@ -2897,6 +2954,7 @@ proto_register_tcap(void)
&ett_param,
&ett_otid,
&ett_dtid,
+ &ett_tcap_stat,
/*--- Included file: packet-tcap-ettarr.c ---*/
#line 1 "packet-tcap-ettarr.c"
@@ -2952,7 +3010,7 @@ proto_register_tcap(void)
&ett_tcap_ErrorCode,
/*--- End of included file: packet-tcap-ettarr.c ---*/
-#line 209 "packet-tcap-template.c"
+#line 291 "packet-tcap-template.c"
};
/*static enum_val_t tcap_options[] = {
@@ -2995,6 +3053,26 @@ proto_register_tcap(void)
prefs_register_range_preference(tcap_module, "ssn", "SCCP SSNs",
"SCCP (and SUA) SSNs to decode as TCAP",
&global_ssn_range, MAX_SSN);
+
+ prefs_register_bool_preference(tcap_module, "srt",
+ "Service Response Time Analyse",
+ "Activate the analyse for Response Time",
+ &gtcap_HandleSRT);
+
+ prefs_register_bool_preference(tcap_module, "persistentsrt",
+ "Persistent stats for SRT",
+ "Statistics for Response Time",
+ &gtcap_PersistentSRT);
+
+ prefs_register_uint_preference(tcap_module, "repetitiontimeout",
+ "Repetition timeout",
+ "Maximal delay for message repetion",
+ 10, &gtcap_RepetitionTimeout);
+
+ prefs_register_uint_preference(tcap_module, "losttimeout",
+ "lost timeout",
+ "Maximal delay for message lost",
+ 10, &gtcap_LostTimeout);
ansi_sub_dissectors = g_hash_table_new(g_direct_hash,g_direct_equal);
itu_sub_dissectors = g_hash_table_new(g_direct_hash,g_direct_equal);
@@ -3031,7 +3109,7 @@ static void init_tcap(void) {
ssn_range = range_copy(global_ssn_range);
range_foreach(ssn_range, range_add_callback);
-
+ tcapsrt_init_routine();
}
static int
@@ -3100,3 +3178,179 @@ dissect_tcap_param(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offs
}
return offset;
}
+
+static void raz_tcap_private(struct tcap_private_t * p_tcap_private)
+{
+ memset(p_tcap_private,0,sizeof(struct tcap_private_t) );
+}
+
+
+static int
+dissect_tcap_TheComponent(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_)
+{
+ tvbuff_t * next_tvb;
+ dissector_handle_t subdissector_handle;
+ gboolean is_subdissector=FALSE;
+ struct tcaphash_context_t * p_tcap_context=NULL;
+
+ gint8 class;
+ gboolean pc;
+ gint tag;
+ guint32 len, s_offset;
+ gint ind_field;
+ proto_tree * stat_tree=NULL;
+ proto_item * stat_item=NULL;
+ /*
+ * ok lets look at the oid and ssn and try and find a dissector, otherwise lets decode it.
+ */
+ ber_oid_dissector_table = find_dissector_table("ber.oid");
+ s_offset = offset;
+ offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
+ offset = get_ber_length(tree, tvb, offset, &len, &ind_field);
+ /* we can believe the length now */
+ next_tvb = tvb_new_subset(tvb, s_offset, len+(offset-s_offset), len+(offset-s_offset));
+ if (!next_tvb)
+ return offset+len;
+
+ dissect_ber_choice(pinfo, tree, next_tvb, 0,
+ Component_choice, hf_index, ett_tcap_Component,NULL);
+
+
+ /*
+ * Handle The TCAP Service Response Time
+ */
+ if ( gtcap_HandleSRT ) {
+ if (!tcap_subdissector_used) {
+ /* Create TCAP context and tree for display */
+ if (gtcap_DisplaySRT && tree) {
+ stat_item = proto_tree_add_text(tcap_stat_tree, tvb, offset, -1, "Stat");
+ stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+ }
+ p_tcap_context=tcapsrt_call_matching(tvb, pinfo, stat_tree, gp_tcapsrt_info);
+ tcap_subdissector_used=TRUE;
+ gp_tcap_context=p_tcap_context;
+ tcap_private.context=p_tcap_context;
+ } else {
+ /* Take the last TCAP context */
+ p_tcap_context = gp_tcap_context;
+ tcap_private.context=p_tcap_context;
+ }
+ }
+
+ if (p_tcap_context) {
+ if (cur_oid) {
+ if (p_tcap_context->oid_present) {
+ /* We have already an Application Context, check if we have
+ to fallback to a lower version */
+ if ( strncmp(p_tcap_context->oid,cur_oid, LENGTH_OID)!=0) {
+ /* ACN, changed, Fallback to lower version */
+ /* and update the subdissector (purely formal) */
+ strncpy(p_tcap_context->oid,cur_oid, LENGTH_OID);
+ if ( (subdissector_handle
+ = dissector_get_string_handle(ber_oid_dissector_table, cur_oid)) ) {
+ p_tcap_context->subdissector_handle=subdissector_handle;
+ }
+ }
+ } else {
+ /* We do not have the OID in the TCAP context, so store it */
+ strncpy(p_tcap_context->oid,cur_oid, LENGTH_OID);
+ if ( (subdissector_handle
+ = dissector_get_string_handle(ber_oid_dissector_table, cur_oid)) ) {
+ p_tcap_context->subdissector_handle=subdissector_handle;
+ p_tcap_context->oid_present=TRUE;
+ }
+ } /* context OID */
+ } else {
+ /* Copy the OID from the TCAP context to the current oid */
+ if (p_tcap_context->oid_present) {
+ tcap_private.oid= (void*) p_tcap_context->oid;
+ tcap_private.acv=TRUE;
+ }
+ } /* no OID */
+ } /* no TCAP context */
+
+ if ( p_tcap_context
+ && p_tcap_context->oid_present) {
+ /* Take the subdissector from the context */
+ subdissector_handle=p_tcap_context->subdissector_handle;
+ is_subdissector=TRUE;
+ }
+
+ if (!is_subdissector) {
+ /*
+ * If we do not currently know the subdissector, we have to find it
+ * - first, according to the OID
+ * - then according to the SSN
+ * - and at least, take the default Data handler
+ */
+ if (ber_oid_dissector_table && cur_oid) {
+ /* Search if we can find the sub protocol according to the A.C.N */
+ if ( (subdissector_handle
+ = dissector_get_string_handle(ber_oid_dissector_table, cur_oid)) ) {
+ /* found */
+ is_subdissector=TRUE;
+ } else {
+ /* Search if we can found the sub protocol according to the SSN table */
+ if ( (subdissector_handle
+ = get_itu_tcap_subdissector(pinfo->match_port))) {
+ /* Found according to SSN */
+ is_subdissector=TRUE;
+ } else {
+ /* Nothing found, take the Data handler */
+ subdissector_handle = data_handle;
+ is_subdissector=TRUE;
+ } /* SSN */
+ } /* ACN */
+ } else {
+ /* There is no A.C.N for this transaction, so search in the SSN table */
+ if ( (subdissector_handle = get_itu_tcap_subdissector(pinfo->match_port))) {
+ /* Found according to SSN */
+ is_subdissector=TRUE;
+ } else {
+ subdissector_handle = data_handle;
+ is_subdissector=TRUE;
+ }
+ } /* OID */
+ } else {
+ /* We have it already */
+ }
+ /* Call the sub dissector if present, and not already called */
+ if (is_subdissector)
+ call_dissector(subdissector_handle, next_tvb, pinfo, tcap_top_tree);
+
+ return offset+len;
+}
+
+
+static int
+dissect_tcap_TheExternUserInfo(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_)
+{
+ tvbuff_t *next_tvb;
+ gint8 class;
+ gboolean pc;
+ gint tag;
+ guint32 len, start_offset;
+ gint ind_field;
+
+ /*
+ * ok lets look at the oid and ssn and try and find a dissector, otherwise lets decode it.
+ */
+ ber_oid_dissector_table = find_dissector_table("ber.oid");
+ start_offset = offset;
+ offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
+ offset = get_ber_length(tree, tvb, offset, &len, &ind_field);
+
+ next_tvb = tvb_new_subset(tvb, start_offset, len +(offset - start_offset), len+(offset - start_offset));
+ if (!next_tvb)
+ return offset+len;
+
+ if (ber_oid_dissector_table && tcapext_oid){
+ if(!dissector_try_string(ber_oid_dissector_table, tcapext_oid, next_tvb, pinfo, tcap_top_tree))
+ {
+ }
+ }
+ dissect_tcap_param(pinfo,tree,next_tvb,0);
+ offset+=len;
+
+ return offset;
+}
diff --git a/epan/dissectors/packet-tcap.h b/epan/dissectors/packet-tcap.h
index 21fbc491d2..78ef7036ce 100644
--- a/epan/dissectors/packet-tcap.h
+++ b/epan/dissectors/packet-tcap.h
@@ -59,7 +59,17 @@
#define TCAP_CONSTRUCTOR(TCtag) (TCtag & 0x20)
-
+#define TC_BEGIN 1
+#define TC_CONT 2
+#define TC_END 3
+#define TC_ABORT 4
+
+struct tcap_private_t {
+ gboolean acv; /* Is the Application Context Version present */
+ void * oid;
+ guint32 session_id;
+ void * context;
+};
extern gint tcap_standard;
@@ -73,4 +83,4 @@ extern void add_itu_tcap_subdissector(guint32 ssn, dissector_handle_t dissector)
extern void delete_ansi_tcap_subdissector(guint32 ssn, dissector_handle_t dissector);
extern void delete_itu_tcap_subdissector(guint32 ssn, dissector_handle_t dissector);
-#endif /* PACKET_INAP_H */
+#endif /* PACKET_tcap_H */
diff --git a/epan/tcap-persistentdata.c b/epan/tcap-persistentdata.c
new file mode 100644
index 0000000000..9db0abfaac
--- /dev/null
+++ b/epan/tcap-persistentdata.c
@@ -0,0 +1,1261 @@
+/*
+ * tcap-persistentdata.c
+ * Source for lists and hash tables used in wireshark's tcap dissector
+ * for calculation of delays in tcap-calls
+ * Copyright 2006 Florent Drouin (based on h225-persistentdata.c from Lars Roland)
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "epan/emem.h"
+#include "epan/packet.h"
+#include "epan/conversation.h"
+#include "epan/tcap-persistentdata.h"
+#include "epan/dissectors/packet-tcap.h"
+#include "epan/dissectors/packet-mtp3.h"
+
+static gint tcaphash_context_equal(gconstpointer k1, gconstpointer k2);
+static guint tcaphash_context_calchash(gconstpointer k);
+static gint tcaphash_begin_equal(gconstpointer k1, gconstpointer k2);
+static guint tcaphash_begin_calchash(gconstpointer k);
+static gint tcaphash_cont_equal(gconstpointer k1, gconstpointer k2);
+static guint tcaphash_cont_calchash(gconstpointer k);
+static gint tcaphash_end_equal(gconstpointer k1, gconstpointer k2);
+static guint tcaphash_end_calchash(gconstpointer k);
+
+static void update_tcaphash_begincall(struct tcaphash_begincall_t * p_tcaphash_begincall,
+ packet_info *pinfo );
+
+static struct tcaphash_begincall_t * append_tcaphash_begincall(struct tcaphash_begincall_t * prev_begincall,
+ struct tcaphash_context_t * p_tcaphash_context,
+ packet_info *pinfo);
+
+
+static struct tcaphash_begincall_t * find_tcaphash_begin(struct tcaphash_begin_info_key_t * p_tcaphash_begin_key,
+ packet_info *pinfo,
+ gboolean isBegin);
+
+
+static struct tcaphash_contcall_t * find_tcaphash_cont(struct tcaphash_cont_info_key_t * p_tcaphash_cont_key,
+ packet_info *pinfo);
+
+static struct tcaphash_endcall_t * find_tcaphash_end(struct tcaphash_end_info_key_t * p_tcaphash_end_key,
+ packet_info *pinfo,
+ gboolean isEnd);
+/* new key */
+static struct tcaphash_context_t * new_tcaphash_context(struct tcaphash_context_key_t * p_tcaphash_context_key,
+ packet_info *pinfo);
+
+static struct tcaphash_begincall_t * new_tcaphash_begin(struct tcaphash_begin_info_key_t * p_tcaphash_begin_key,
+ struct tcaphash_context_t * p_tcaphash_context,
+ packet_info *pinfo);
+
+static struct tcaphash_contcall_t * new_tcaphash_cont(struct tcaphash_cont_info_key_t * p_tcaphash_cont_key,
+ struct tcaphash_context_t * p_tcaphash_context,
+ packet_info *pinfo);
+
+static struct tcaphash_endcall_t * new_tcaphash_end(struct tcaphash_end_info_key_t * p_tcaphash_end_key,
+ struct tcaphash_context_t * p_tcaphash_context,
+ packet_info *pinfo);
+
+static struct tcaphash_context_t *
+tcaphash_begin_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct tcapsrt_info_t * p_tcapsrt_info);
+
+static struct tcaphash_context_t *
+tcaphash_cont_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct tcapsrt_info_t * p_tcapsrt_info);
+
+static struct tcaphash_context_t *
+tcaphash_end_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct tcapsrt_info_t * p_tcapsrt_info);
+
+struct tcapsrt_info_t * tcapsrt_razinfo(void);
+
+/* When several Tcap components are received in a single TCAP message,
+ we have to use several buffers for the stored parameters
+ because else this data are erased during TAP dissector call */
+#define MAX_TCAP_INSTANCE 10
+int tcapsrt_global_current=0;
+struct tcapsrt_info_t tcapsrt_global_info[MAX_TCAP_INSTANCE];
+
+/* These two timeout (in second) are used when some message are lost,
+ or when the same TCAP transcation identifier is reused */
+guint gtcap_RepetitionTimeout = 10;
+guint gtcap_LostTimeout = 30;
+extern gboolean gtcap_HandleSRT;
+gboolean gtcap_PersistentSRT=FALSE;
+gboolean gtcap_DisplaySRT=FALSE;
+gboolean gtcap_StatSRT=FALSE;
+
+extern int hf_tcapsrt_SessionId;
+extern int hf_tcapsrt_Duplicate;
+extern int hf_tcapsrt_BeginSession;
+extern int hf_tcapsrt_EndSession;
+extern int hf_tcapsrt_SessionTime;
+
+/* Global hash tables*/
+static GHashTable * tcaphash_context = NULL;
+static GHashTable * tcaphash_begin = NULL;
+static GHashTable * tcaphash_cont = NULL;
+static GHashTable * tcaphash_end = NULL;
+
+guint32 tcapsrt_global_SessionId=1;
+
+/*
+ * DEBUG fonctions
+ */
+
+#undef DEBUG_TCAPSRT
+/* #define DEBUG_TCAPSRT */
+
+#ifdef DEBUG_TCAPSRT
+#include <stdio.h>
+#include <stdarg.h>
+static unsigned debug_level = 99;
+
+static void dbg(unsigned level, char* fmt, ...) {
+ va_list ap;
+
+ if (level > debug_level) return;
+ va_start(ap,fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+#endif
+
+static gint tcaphash_context_equal(gconstpointer k1, gconstpointer k2)
+{
+ const struct tcaphash_context_key_t * key1 = (const struct tcaphash_context_key_t *) k1;
+ const struct tcaphash_context_key_t * key2 = (const struct tcaphash_context_key_t *) k2;
+
+ return (key1->session_id == key2->session_id);
+}
+
+/* calculate a hash key */
+static guint tcaphash_context_calchash(gconstpointer k)
+{
+ const struct tcaphash_context_key_t * key = (const struct tcaphash_context_key_t *) k;
+ return key->session_id;
+}
+
+
+static gint tcaphash_begin_equal(gconstpointer k1, gconstpointer k2)
+{
+ const struct tcaphash_begin_info_key_t * key1 = (const struct tcaphash_begin_info_key_t *) k1;
+ const struct tcaphash_begin_info_key_t * key2 = (const struct tcaphash_begin_info_key_t *) k2;
+
+ if (key1->hashKey == key2->hashKey) {
+
+ if ( ( (key1->opc_hash == key2->opc_hash) &&
+ (key1->dpc_hash == key2->dpc_hash) &&
+ (key1->tid == key2->tid) )
+ ||
+ ( (key1->opc_hash == key2->dpc_hash) &&
+ (key1->dpc_hash == key2->opc_hash) &&
+ (key1->tid == key2->tid) )
+ )
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* calculate a hash key */
+static guint tcaphash_begin_calchash(gconstpointer k)
+{
+ const struct tcaphash_begin_info_key_t * key = (const struct tcaphash_begin_info_key_t *) k;
+ guint hashkey;
+ /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
+ hashkey = key->tid;
+ return hashkey;
+}
+
+static gint tcaphash_cont_equal(gconstpointer k1, gconstpointer k2)
+{
+ const struct tcaphash_cont_info_key_t * key1 = (const struct tcaphash_cont_info_key_t *) k1;
+ const struct tcaphash_cont_info_key_t * key2 = (const struct tcaphash_cont_info_key_t *) k2;
+
+ if (key1->hashKey == key2->hashKey) {
+
+ if ( (key1->opc_hash == key2->opc_hash) &&
+ (key1->dpc_hash == key2->dpc_hash) &&
+ (key1->src_tid == key2->src_tid) &&
+ (key1->dst_tid == key2->dst_tid) ) {
+ return TRUE;
+ }
+ else if ( (key1->opc_hash == key2->dpc_hash) &&
+ (key1->dpc_hash == key2->opc_hash) &&
+ (key1->src_tid == key2->dst_tid) &&
+ (key1->dst_tid == key2->src_tid) ) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/* calculate a hash key */
+static guint tcaphash_cont_calchash(gconstpointer k)
+{
+ const struct tcaphash_cont_info_key_t * key = (const struct tcaphash_cont_info_key_t *) k;
+ guint hashkey;
+ hashkey = key->src_tid + key->dst_tid;
+ return hashkey;
+}
+
+
+static gint tcaphash_end_equal(gconstpointer k1, gconstpointer k2)
+{
+ const struct tcaphash_end_info_key_t * key1 = (const struct tcaphash_end_info_key_t *) k1;
+ const struct tcaphash_end_info_key_t * key2 = (const struct tcaphash_end_info_key_t *) k2;
+
+ if (key1->hashKey == key2->hashKey) {
+ if ( ( (key1->opc_hash == key2->opc_hash) &&
+ (key1->dpc_hash == key2->dpc_hash) &&
+ (key1->tid == key2->tid) )
+ ||
+ ( (key1->opc_hash == key2->dpc_hash) &&
+ (key1->dpc_hash == key2->opc_hash) &&
+ (key1->tid == key2->tid) ) )
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* calculate a hash key */
+static guint tcaphash_end_calchash(gconstpointer k)
+{
+ const struct tcaphash_end_info_key_t * key = (const struct tcaphash_end_info_key_t *) k;
+ guint hashkey;
+ hashkey = key->tid;
+ return hashkey;
+}
+
+/*
+ * Update a record with the data of the Request
+ */
+static void update_tcaphash_begincall(struct tcaphash_begincall_t * p_tcaphash_begincall,
+ packet_info *pinfo )
+{
+ p_tcaphash_begincall->context->first_frame = pinfo->fd->num;
+ p_tcaphash_begincall->context->last_frame = 0;
+ p_tcaphash_begincall->context->responded = FALSE;
+ p_tcaphash_begincall->context->begin_time = pinfo->fd->abs_ts;
+}
+
+/*
+ * Append a new dialogue, using the same Key, to the chained list
+ * The time is stored too
+ */
+static struct tcaphash_begincall_t * append_tcaphash_begincall(struct tcaphash_begincall_t * prev_begincall,
+ struct tcaphash_context_t * p_tcaphash_context,
+ packet_info *pinfo)
+
+{
+ struct tcaphash_begincall_t * p_new_tcaphash_begincall = NULL;
+
+ /* Append the transaction to the list, when the same key is found
+ This should append when the tcap-transaction Id is reused */
+
+ p_new_tcaphash_begincall = se_alloc0(sizeof(struct tcaphash_begincall_t));
+ p_new_tcaphash_begincall->context=p_tcaphash_context;
+ p_tcaphash_context->begincall=p_new_tcaphash_begincall;
+ p_new_tcaphash_begincall->beginkey=prev_begincall->beginkey;
+ p_new_tcaphash_begincall->context->first_frame = pinfo->fd->num;
+ p_new_tcaphash_begincall->next_begincall=NULL;
+ p_new_tcaphash_begincall->previous_begincall=prev_begincall;
+ p_new_tcaphash_begincall->father=FALSE;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"+B%d ", p_new_tcaphash_begincall->context->session_id);
+#endif
+ /* Insert in the chained list */
+ prev_begincall->next_begincall = p_new_tcaphash_begincall;
+ if (prev_begincall->context->last_frame == 0) {
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"last ");
+#endif
+ prev_begincall->context->last_frame = pinfo->fd->num-1;
+ }
+ return p_new_tcaphash_begincall;
+}
+
+static struct tcaphash_contcall_t * append_tcaphash_contcall(struct tcaphash_contcall_t * prev_contcall,
+ struct tcaphash_context_t * p_tcaphash_context,
+ packet_info *pinfo)
+
+{
+ struct tcaphash_contcall_t * p_new_tcaphash_contcall = NULL;
+
+ /* Append the transaction to the list, when the same key is found
+ This should append when the tcap-transaction Id is reused */
+
+ p_new_tcaphash_contcall = se_alloc0(sizeof(struct tcaphash_contcall_t));
+ p_new_tcaphash_contcall->context=p_tcaphash_context;
+ p_tcaphash_context->contcall=p_new_tcaphash_contcall;
+ p_new_tcaphash_contcall->contkey=prev_contcall->contkey;
+ p_new_tcaphash_contcall->next_contcall=NULL;
+ p_new_tcaphash_contcall->previous_contcall=prev_contcall;
+ p_new_tcaphash_contcall->father=FALSE;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"+C%d ", p_new_tcaphash_contcall->context->session_id);
+#endif
+ /* Insert in the chained list */
+ prev_contcall->next_contcall = p_new_tcaphash_contcall;
+ return p_new_tcaphash_contcall;
+}
+
+
+static struct tcaphash_endcall_t * append_tcaphash_endcall(struct tcaphash_endcall_t * prev_endcall,
+ struct tcaphash_context_t * p_tcaphash_context,
+ packet_info *pinfo)
+
+{
+ struct tcaphash_endcall_t * p_new_tcaphash_endcall = NULL;
+
+ /* Append the transaction to the list, when the same key is found
+ This should append when the tcap-transaction Id is reused */
+
+ p_new_tcaphash_endcall = se_alloc0(sizeof(struct tcaphash_endcall_t));
+ p_new_tcaphash_endcall->context=p_tcaphash_context;
+ p_tcaphash_context->endcall=p_new_tcaphash_endcall;
+ p_new_tcaphash_endcall->endkey=prev_endcall->endkey;
+ p_new_tcaphash_endcall->next_endcall=NULL;
+ p_new_tcaphash_endcall->previous_endcall=prev_endcall;
+ p_new_tcaphash_endcall->father=FALSE;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"+E%d ", p_new_tcaphash_endcall->context->session_id);
+#endif
+ /* Insert in the chained list */
+ prev_endcall->next_endcall = p_new_tcaphash_endcall;
+ return p_new_tcaphash_endcall;
+}
+
+
+/*
+ * Find the dialog by Key and Time
+ */
+static struct tcaphash_begincall_t * find_tcaphash_begin(struct tcaphash_begin_info_key_t * p_tcaphash_begin_key,
+ packet_info *pinfo,
+ gboolean isBegin)
+{
+ struct tcaphash_begincall_t * p_tcaphash_begincall = NULL;
+ p_tcaphash_begincall = (struct tcaphash_begincall_t *)g_hash_table_lookup(tcaphash_begin, p_tcaphash_begin_key);
+
+ if(p_tcaphash_begincall) {
+ do {
+ if ( p_tcaphash_begincall->context ) {
+ if ( ( isBegin &&
+ pinfo->fd->num == p_tcaphash_begincall->context->first_frame )
+ ||
+ ( !isBegin &&
+ pinfo->fd->num >= p_tcaphash_begincall->context->first_frame &&
+ ( p_tcaphash_begincall->context->last_frame?pinfo->fd->num <= p_tcaphash_begincall->context->last_frame:1 )
+ )
+ ) {
+ /* We have a dialogue, with this key, opened before this request */
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"B%d ", p_tcaphash_begincall->context->session_id);
+#endif
+ return p_tcaphash_begincall;
+ break;
+ }
+ }
+ /* Break when list end is reached */
+ if(p_tcaphash_begincall->next_begincall == NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(23,"End of Blist ");
+#endif
+ break;
+ }
+ p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
+ } while (p_tcaphash_begincall != NULL) ;
+ } else {
+#ifdef DEBUG_TCAPSRT
+ dbg(23,"Not in Bhash ");
+#endif
+ }
+ return NULL;
+}
+
+
+
+static struct tcaphash_contcall_t * find_tcaphash_cont(struct tcaphash_cont_info_key_t * p_tcaphash_cont_key,
+ packet_info *pinfo)
+{
+ struct tcaphash_contcall_t * p_tcaphash_contcall = NULL;
+ p_tcaphash_contcall = (struct tcaphash_contcall_t *)g_hash_table_lookup(tcaphash_cont, p_tcaphash_cont_key);
+
+ if(p_tcaphash_contcall) {
+ do {
+ if ( p_tcaphash_contcall->context &&
+ pinfo->fd->num >= p_tcaphash_contcall->context->first_frame &&
+ (p_tcaphash_contcall->context->last_frame?pinfo->fd->num <= p_tcaphash_contcall->context->last_frame:1) ) {
+ /* We have a dialogue, with this key, opened before this request */
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"C%d ", p_tcaphash_contcall->context->session_id);
+#endif
+ return p_tcaphash_contcall;
+ break;
+ } else {
+#ifdef DEBUG_TCAPSRT
+ dbg(23,"Bug in Clist ");
+#endif
+ }
+ /* Break when list end is reached */
+ if(p_tcaphash_contcall->next_contcall == NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(23,"End of Clist ");
+#endif
+ break;
+ }
+ p_tcaphash_contcall = p_tcaphash_contcall->next_contcall;
+ } while (p_tcaphash_contcall != NULL) ;
+ } else {
+#ifdef DEBUG_TCAPSRT
+ dbg(23,"Not in Chash ");
+#endif
+ }
+ return NULL;
+}
+
+static struct tcaphash_endcall_t * find_tcaphash_end(struct tcaphash_end_info_key_t * p_tcaphash_end_key,
+ packet_info *pinfo,
+ gboolean isEnd)
+{
+ struct tcaphash_endcall_t * p_tcaphash_endcall = NULL;
+ p_tcaphash_endcall = (struct tcaphash_endcall_t *)g_hash_table_lookup(tcaphash_end, p_tcaphash_end_key);
+
+ if(p_tcaphash_endcall) {
+ do {
+ if ( p_tcaphash_endcall->context ) {
+ if ( ( isEnd &&
+ (p_tcaphash_endcall->context->last_frame?pinfo->fd->num == p_tcaphash_endcall->context->last_frame:1)
+ )
+ ||
+ ( !isEnd &&
+ pinfo->fd->num >= p_tcaphash_endcall->context->first_frame &&
+ (p_tcaphash_endcall->context->last_frame?pinfo->fd->num <= p_tcaphash_endcall->context->last_frame:1)
+ )
+ ) {
+ /* We have a dialogue, with this key, opened before this request */
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"E%d ", p_tcaphash_endcall->context->session_id);
+#endif
+ return p_tcaphash_endcall;
+ break;
+ } else {
+#ifdef DEBUG_TCAPSRT
+ dbg(23,"Bug in Elist ");
+#endif
+ }
+ }
+ /* Break when list end is reached */
+ if(p_tcaphash_endcall->next_endcall == NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(23,"End of Elist ");
+#endif
+ break;
+ }
+ p_tcaphash_endcall = p_tcaphash_endcall->next_endcall;
+ } while (p_tcaphash_endcall != NULL) ;
+ } else {
+#ifdef DEBUG_TCAPSRT
+ dbg(23,"Not in Ehash ");
+#endif
+ }
+ return NULL;
+}
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_context_t * new_tcaphash_context(struct tcaphash_context_key_t * p_tcaphash_context_key,
+ packet_info *pinfo)
+{
+ struct tcaphash_context_key_t * p_new_tcaphash_context_key;
+ struct tcaphash_context_t * p_new_tcaphash_context = NULL;
+
+ /* Register the transaction in the hash table
+ with the tcap transaction Id as Main Key
+ Once created, this entry will be updated later */
+
+ p_new_tcaphash_context_key = se_alloc(sizeof(struct tcaphash_context_key_t));
+ p_new_tcaphash_context_key->session_id = p_tcaphash_context_key->session_id;
+
+ p_new_tcaphash_context = se_alloc0(sizeof(struct tcaphash_context_t));
+ p_new_tcaphash_context->key = p_new_tcaphash_context_key;
+ p_new_tcaphash_context->session_id = p_tcaphash_context_key->session_id;
+ p_new_tcaphash_context->first_frame = pinfo->fd->num;
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"S%d ", p_new_tcaphash_context->session_id);
+#endif
+ /* store it */
+ g_hash_table_insert(tcaphash_context, p_new_tcaphash_context_key, p_new_tcaphash_context);
+ return p_new_tcaphash_context;
+}
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_begincall_t * new_tcaphash_begin(struct tcaphash_begin_info_key_t * p_tcaphash_begin_key,
+ struct tcaphash_context_t * p_tcaphash_context,
+ packet_info *pinfo)
+{
+ struct tcaphash_begin_info_key_t * p_new_tcaphash_begin_key;
+ struct tcaphash_begincall_t * p_new_tcaphash_begincall = NULL;
+
+ /* Register the transaction in the hash table
+ with the tcap transaction Id as Main Key
+ Once created, this entry will be updated later */
+
+ p_new_tcaphash_begin_key = se_alloc(sizeof(struct tcaphash_begin_info_key_t));
+ p_new_tcaphash_begin_key->hashKey = p_tcaphash_begin_key->hashKey;
+ p_new_tcaphash_begin_key->tid = p_tcaphash_begin_key->tid;
+ p_new_tcaphash_begin_key->opc_hash = p_tcaphash_begin_key->opc_hash;
+ p_new_tcaphash_begin_key->dpc_hash = p_tcaphash_begin_key->dpc_hash;
+
+ p_new_tcaphash_begincall = se_alloc0(sizeof(struct tcaphash_begincall_t));
+ p_new_tcaphash_begincall->beginkey=p_new_tcaphash_begin_key;
+ p_new_tcaphash_begincall->context=p_tcaphash_context;
+ p_tcaphash_context->begincall=p_new_tcaphash_begincall;
+ p_new_tcaphash_begincall->father=TRUE;
+ p_new_tcaphash_begincall->next_begincall=NULL;
+ p_new_tcaphash_begincall->previous_begincall=NULL;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"B%d ", p_new_tcaphash_begincall->context->session_id);
+#endif
+ /* store it */
+ g_hash_table_insert(tcaphash_begin, p_new_tcaphash_begin_key, p_new_tcaphash_begincall);
+ return p_new_tcaphash_begincall;
+}
+
+
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_contcall_t * new_tcaphash_cont(struct tcaphash_cont_info_key_t * p_tcaphash_cont_key,
+ struct tcaphash_context_t * p_tcaphash_context,
+ packet_info *pinfo)
+{
+ struct tcaphash_cont_info_key_t * p_new_tcaphash_cont_key;
+ struct tcaphash_contcall_t * p_new_tcaphash_contcall = NULL;
+
+ /* Register the transaction in the hash table
+ with the tcap transaction Id as Main Key
+ Once created, this entry will be updated later */
+
+ p_new_tcaphash_cont_key = se_alloc(sizeof(struct tcaphash_cont_info_key_t));
+ p_new_tcaphash_cont_key->hashKey = p_tcaphash_cont_key->hashKey;
+ p_new_tcaphash_cont_key->src_tid = p_tcaphash_cont_key->src_tid;
+ p_new_tcaphash_cont_key->dst_tid = p_tcaphash_cont_key->dst_tid;
+ p_new_tcaphash_cont_key->opc_hash = p_tcaphash_cont_key->opc_hash;
+ p_new_tcaphash_cont_key->dpc_hash = p_tcaphash_cont_key->dpc_hash;
+
+ p_new_tcaphash_contcall = se_alloc0(sizeof(struct tcaphash_contcall_t));
+ p_new_tcaphash_contcall->contkey=p_new_tcaphash_cont_key;
+ p_new_tcaphash_contcall->context=p_tcaphash_context;
+ p_tcaphash_context->contcall=p_new_tcaphash_contcall;
+ p_new_tcaphash_contcall->father=TRUE;
+ p_new_tcaphash_contcall->next_contcall=NULL;
+ p_new_tcaphash_contcall->previous_contcall=NULL;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"C%d ", p_new_tcaphash_contcall->context->session_id);
+#endif
+ /* store it */
+ g_hash_table_insert(tcaphash_cont, p_new_tcaphash_cont_key, p_new_tcaphash_contcall);
+ return p_new_tcaphash_contcall;
+}
+
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_endcall_t * new_tcaphash_end(struct tcaphash_end_info_key_t * p_tcaphash_end_key,
+ struct tcaphash_context_t * p_tcaphash_context,
+ packet_info *pinfo)
+{
+ struct tcaphash_end_info_key_t * p_new_tcaphash_end_key;
+ struct tcaphash_endcall_t * p_new_tcaphash_endcall = NULL;
+
+ /* Register the transaction in the hash table
+ with the tcap transaction Id as Main Key
+ Once created, this entry will be updated later */
+
+ p_new_tcaphash_end_key = se_alloc(sizeof(struct tcaphash_end_info_key_t));
+ p_new_tcaphash_end_key->hashKey = p_tcaphash_end_key->hashKey;
+ p_new_tcaphash_end_key->tid = p_tcaphash_end_key->tid;
+ p_new_tcaphash_end_key->opc_hash = p_tcaphash_end_key->opc_hash;
+ p_new_tcaphash_end_key->dpc_hash = p_tcaphash_end_key->dpc_hash;
+
+ p_new_tcaphash_endcall = se_alloc0(sizeof(struct tcaphash_endcall_t));
+ p_new_tcaphash_endcall->endkey=p_new_tcaphash_end_key;
+ p_new_tcaphash_endcall->context=p_tcaphash_context;
+ p_tcaphash_context->endcall=p_new_tcaphash_endcall;
+ p_new_tcaphash_endcall->father=TRUE;
+ p_new_tcaphash_endcall->next_endcall=NULL;
+ p_new_tcaphash_endcall->previous_endcall=NULL;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"E%d ", p_new_tcaphash_endcall->context->session_id);
+#endif
+ /* store it */
+ g_hash_table_insert(tcaphash_end, p_new_tcaphash_end_key, p_new_tcaphash_endcall);
+ return p_new_tcaphash_endcall;
+}
+
+
+
+static struct tcaphash_contcall_t *
+create_tcaphash_cont(struct tcaphash_cont_info_key_t * p_tcaphash_cont_key,
+ struct tcaphash_context_t * p_tcaphash_context,
+ packet_info *pinfo)
+{
+ struct tcaphash_contcall_t * p_tcaphash_contcall1 = NULL;
+ struct tcaphash_contcall_t * p_tcaphash_contcall = NULL;
+
+ p_tcaphash_contcall1 = (struct tcaphash_contcall_t *)
+ g_hash_table_lookup(tcaphash_cont, p_tcaphash_cont_key);
+
+ if (p_tcaphash_contcall1) {
+ /* Walk through list of transaction with identical keys */
+ /* go the the end to insert new record */
+ do {
+ if (!p_tcaphash_contcall1->next_contcall) {
+ p_tcaphash_contcall=append_tcaphash_contcall(p_tcaphash_contcall1,
+ p_tcaphash_context,
+ pinfo);
+ break;
+ }
+ p_tcaphash_contcall1 = p_tcaphash_contcall1->next_contcall;
+ } while (p_tcaphash_contcall1 != NULL );
+ } else {
+ p_tcaphash_contcall = new_tcaphash_cont(p_tcaphash_cont_key,
+ p_tcaphash_context,
+ pinfo);
+ }
+ return p_tcaphash_contcall;
+}
+
+
+static struct tcaphash_endcall_t *
+create_tcaphash_end(struct tcaphash_end_info_key_t * p_tcaphash_end_key,
+ struct tcaphash_context_t * p_tcaphash_context,
+ packet_info *pinfo)
+{
+ struct tcaphash_endcall_t * p_tcaphash_endcall1 = NULL;
+ struct tcaphash_endcall_t * p_tcaphash_endcall = NULL;
+
+ p_tcaphash_endcall1 = (struct tcaphash_endcall_t *)
+ g_hash_table_lookup(tcaphash_end, p_tcaphash_end_key);
+
+ if (p_tcaphash_endcall1) {
+ /* Walk through list of transaction with identical keys */
+ /* go the the end to insert new record */
+ do {
+ if (!p_tcaphash_endcall1->next_endcall) {
+ p_tcaphash_endcall=append_tcaphash_endcall(p_tcaphash_endcall1,
+ p_tcaphash_context,
+ pinfo);
+ break;
+ }
+ p_tcaphash_endcall1 = p_tcaphash_endcall1->next_endcall;
+ } while (p_tcaphash_endcall1 != NULL );
+ } else {
+ p_tcaphash_endcall = new_tcaphash_end(p_tcaphash_end_key,
+ p_tcaphash_context,
+ pinfo);
+ }
+ return p_tcaphash_endcall;
+}
+
+
+/*
+ * Routine called when the TAP is initialized.
+ * so hash table are (re)created
+ */
+void tcapsrt_init_routine(void)
+{
+
+ /* free hash-tables and mem_chunks for SRT */
+ if (tcaphash_context != NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(16,"Destroy hash_context ");
+#endif
+ g_hash_table_destroy(tcaphash_context);
+ }
+
+ if (tcaphash_begin != NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(16,"Destroy hash_begin ");
+#endif
+ g_hash_table_destroy(tcaphash_begin);
+ }
+
+ if (tcaphash_cont != NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(16,"Destroy hash_cont ");
+#endif
+ g_hash_table_destroy(tcaphash_cont);
+ }
+
+ if (tcaphash_end != NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(16,"Destroy hash_end ");
+#endif
+ g_hash_table_destroy(tcaphash_end);
+ }
+
+#ifdef DEBUG_TCAPSRT
+ dbg(16,"Create hash ");
+#endif
+ /* create new hash-tables and mem_chunks for SRT */
+ tcaphash_context = g_hash_table_new(tcaphash_context_calchash, tcaphash_context_equal);
+ tcaphash_begin = g_hash_table_new(tcaphash_begin_calchash, tcaphash_begin_equal);
+ tcaphash_cont = g_hash_table_new(tcaphash_cont_calchash, tcaphash_cont_equal);
+ tcaphash_end = g_hash_table_new(tcaphash_end_calchash, tcaphash_end_equal);
+
+ /* Reset the session counter */
+ tcapsrt_global_SessionId=1;
+
+ /* Display of SRT only if Persistent Stat */
+ gtcap_DisplaySRT=gtcap_PersistentSRT || gtcap_HandleSRT&gtcap_StatSRT;
+}
+
+/*
+ * Service Responsee Time analyze
+ * Called just after dissector call
+ */
+struct tcaphash_context_t * tcapsrt_call_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct tcapsrt_info_t * p_tcapsrt_info)
+{
+ struct tcaphash_context_t * tcap_context=NULL;
+
+ switch (p_tcapsrt_info->ope) {
+
+ case TC_BEGIN: /*InitialDP*/
+#ifdef DEBUG_TCAPSRT
+ dbg(1,"TC_BEGIN ");
+#endif
+ tcap_context=tcaphash_begin_matching(tvb, pinfo, tree, p_tcapsrt_info);
+ break;
+
+ case TC_CONT:
+#ifdef DEBUG_TCAPSRT
+ dbg(1,"TC_CONT ");
+#endif
+ tcap_context=tcaphash_cont_matching(tvb, pinfo, tree, p_tcapsrt_info);
+ break;
+
+ case TC_ABORT:
+#ifdef DEBUG_TCAPSRT
+ dbg(1,"TC_ABORT ");
+#endif
+ tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
+ break;
+
+ case TC_END:
+#ifdef DEBUG_TCAPSRT
+ dbg(1,"TC_END ");
+#endif
+ tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
+ break;
+
+ default:
+#ifdef DEBUG_TCAPSRT
+ dbg(1,"Unknow %d ", p_tcapsrt_info->ope);
+#endif
+ break;
+ } /* switch tcapop */
+#ifdef DEBUG_TCAPSRT
+ if (tcap_context)
+ dbg(1,"session %d ", tcap_context->session_id);
+#endif
+ return tcap_context;
+}
+
+
+/*
+ * Create the record identifiying the TCAP transaction
+ * When the identifier for the transaction is reused, check
+ * the following criteria before to append a new record:
+ * - a timeout corresponding to a message retransmission is detected,
+ * - a message hast been lost
+ * - or the previous transaction has been be closed
+ */
+static struct tcaphash_context_t *
+tcaphash_begin_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct tcapsrt_info_t * p_tcapsrt_info)
+{
+ struct tcaphash_context_t * p_tcaphash_context=NULL;
+ struct tcaphash_context_key_t tcaphash_context_key;
+ struct tcaphash_begincall_t * p_tcaphash_begincall, * p_new_tcaphash_begincall;
+ struct tcaphash_begin_info_key_t tcaphash_begin_key;
+ proto_item *ti;
+
+ /* prepare the key data */
+ tcaphash_begin_key.tid = p_tcapsrt_info->src_tid;
+ tcaphash_begin_key.opc_hash = mtp3_pc_hash( ((address *)(&pinfo->src))->data);
+ tcaphash_begin_key.dpc_hash = mtp3_pc_hash( ((address *)(&pinfo->dst))->data);
+ tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
+
+ /* look up the request */
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"\n Hbegin #%d ", pinfo->fd->num);
+ dbg(11,"key %lx ",tcaphash_begin_key.hashKey);
+ dbg(51,"PC %s %s ",address_to_str(&pinfo->src), address_to_str(&pinfo->dst));
+ dbg(51,"Tid %lx ",tcaphash_begin_key.tid);
+#endif
+ p_tcaphash_begincall = (struct tcaphash_begincall_t *)
+ g_hash_table_lookup(tcaphash_begin, &tcaphash_begin_key);
+
+ if (p_tcaphash_begincall) {
+ /* Walk through list of transaction with identical keys */
+ do {
+ /* Check if the request with this reqSeqNum has been seen, with the same Message Type */
+ if (pinfo->fd->num == p_tcaphash_begincall->context->first_frame) {
+ /* We have seen this request before -> do nothing */
+#ifdef DEBUG_TCAPSRT
+ dbg(22,"Already seen ");
+#endif
+ p_tcaphash_context=p_tcaphash_begincall->context;
+ break;
+ }
+ /* If the last record for Tcap transaction with identifier has been reached */
+ if (!p_tcaphash_begincall->next_begincall) {
+ /* check if we have to create a new record or not */
+ /* if last request has been responded (response number in known)
+ and this request appears after last response (has bigger frame number)
+ and last request occured after the timeout for repetition,
+ or
+ if last request hasn't been responded (so number unknown)
+ and this request appears after last request (has bigger frame number)
+ and this request occured after the timeout for message lost */
+ if ( ( p_tcaphash_begincall->context->last_frame != 0
+ && pinfo->fd->num > p_tcaphash_begincall->context->first_frame
+ && (guint) pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_begincall->context->begin_time.secs + gtcap_RepetitionTimeout)
+ ) ||
+ ( p_tcaphash_begincall->context->last_frame == 0
+ && pinfo->fd->num > p_tcaphash_begincall->context->first_frame
+ && (guint)pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_begincall->context->begin_time.secs + gtcap_LostTimeout)
+ )
+ )
+ {
+ /* we decide that we have a new request */
+ /* Append new record to the list */
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"(timeout) Append key %lx ",tcaphash_begin_key.hashKey);
+ dbg(12,"Frame %d rsp %d ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
+#endif
+ tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+ p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+ p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
+ p_tcaphash_context,
+ pinfo);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"Update key %lx ",tcaphash_begin_key.hashKey);
+#endif
+ update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
+ p_tcaphash_begincall=p_new_tcaphash_begincall;
+ } else {
+
+ /* If the Tid is reused for a closed Transaction */
+ /* Or if we received an InitialDP for a non closed Transaction */
+ if ( p_tcaphash_begincall->context->closed) {
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"(closed) Append key %lu ",tcaphash_begin_key.hashKey);
+ dbg(12,"Frame %d rsp %d ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
+#endif
+ tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+ p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+ p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
+ p_tcaphash_context,
+ pinfo);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"Update key %lu ",tcaphash_begin_key.hashKey);
+#endif
+ update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
+ p_tcaphash_begincall=p_new_tcaphash_begincall;
+
+ } else {
+ /* No, so it's a duplicate request.Mark it as such. */
+#ifdef DEBUG_TCAPSRT
+ dbg(21,"Display_duplicate ");
+#endif
+ if (gtcap_DisplaySRT)
+ proto_tree_add_uint_hidden(tree, hf_tcapsrt_Duplicate, tvb, 0,0, p_tcapsrt_info->src_tid);
+ p_tcaphash_context=p_tcaphash_begincall->context;
+ } /* test with Timeout */
+ } /* closed */
+ break;
+ } /* Next call is NULL */
+ p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
+ } while (p_tcaphash_begincall != NULL );
+ /*
+ * New TCAP context
+ */
+ } else { /* p_tcaphash_begincall has not been found */
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"New key %lx ",tcaphash_begin_key.hashKey);
+#endif
+
+ tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+ p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+ p_tcaphash_begincall = new_tcaphash_begin(&tcaphash_begin_key, p_tcaphash_context, pinfo);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(11,"Update key %lx ",tcaphash_begin_key.hashKey);
+ dbg(11,"Frame reqlink #%d ", pinfo->fd->num);
+#endif
+ update_tcaphash_begincall(p_tcaphash_begincall, pinfo);
+ }
+
+ /* display tcap session, if available */
+ if ( gtcap_DisplaySRT &&
+ p_tcaphash_context &&
+ p_tcaphash_context->session_id)
+ proto_tree_add_uint(tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+
+ /* add link to response frame, if available */
+ if( gtcap_DisplaySRT &&
+ p_tcaphash_begincall->context->last_frame != 0){
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"Display_frameRsplink %d ",p_tcaphash_begincall->context->last_frame);
+#endif
+ ti = proto_tree_add_uint_format(tree, hf_tcapsrt_BeginSession, tvb, 0, 0,
+ p_tcaphash_begincall->context->last_frame,
+ "End of session in frame %u",
+ p_tcaphash_begincall->context->last_frame);
+ PROTO_ITEM_SET_GENERATED(ti);
+ }
+ return p_tcaphash_context;
+}
+
+
+/*
+ * Register the request, and try to find the response
+ *
+ */
+static struct tcaphash_context_t *
+tcaphash_cont_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct tcapsrt_info_t * p_tcapsrt_info)
+{
+ struct tcaphash_context_t * p_tcaphash_context=NULL;
+ struct tcaphash_contcall_t * p_tcaphash_contcall;
+ struct tcaphash_cont_info_key_t tcaphash_cont_key;
+ proto_item *ti;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"\n Hcont #%d ", pinfo->fd->num);
+#endif
+
+ /* look only for matching request, if matching conversation is available. */
+ tcaphash_cont_key.src_tid = p_tcapsrt_info->src_tid;
+ tcaphash_cont_key.dst_tid = p_tcapsrt_info->dst_tid;
+ tcaphash_cont_key.opc_hash=mtp3_pc_hash( ((address*)(&pinfo->src))->data);
+ tcaphash_cont_key.dpc_hash=mtp3_pc_hash( ((address*)(&pinfo->dst))->data);
+ tcaphash_cont_key.hashKey=tcaphash_cont_calchash(&tcaphash_cont_key);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(11,"Ckey %lx ", tcaphash_cont_key.hashKey);
+ dbg(51,"PC %s %s ",address_to_str(&pinfo->src), address_to_str(&pinfo->dst));
+ dbg(51,"Tid %lx %lx ",tcaphash_cont_key.src_tid, tcaphash_cont_key.dst_tid);
+#endif
+ p_tcaphash_contcall = find_tcaphash_cont(&tcaphash_cont_key, pinfo);
+ if(p_tcaphash_contcall) {
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"CFound ");
+#endif
+ p_tcaphash_context=p_tcaphash_contcall->context;
+ } else { /* Not found */
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"CnotFound ");
+#endif
+ struct tcaphash_begin_info_key_t tcaphash_begin_key;
+ struct tcaphash_begincall_t * p_tcaphash_begincall;
+
+ struct tcaphash_end_info_key_t tcaphash_end_key;
+ struct tcaphash_endcall_t * p_tcaphash_endcall;
+
+ tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
+ tcaphash_begin_key.opc_hash=mtp3_pc_hash( ((address*)(&pinfo->src))->data);
+ tcaphash_begin_key.dpc_hash=mtp3_pc_hash( ((address*)(&pinfo->dst))->data);
+ tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
+ dbg(51,"PC %s %s ",address_to_str(&pinfo->src), address_to_str(&pinfo->dst));
+ dbg(51,"Tid %lx ",tcaphash_begin_key.tid);
+#endif
+ p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
+ if(p_tcaphash_begincall &&
+ !p_tcaphash_begincall->context->contcall ) {
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"BFound ");
+#endif
+ p_tcaphash_context=p_tcaphash_begincall->context;
+ p_tcaphash_context->responded=TRUE;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"New Ckey %lx ",tcaphash_cont_key.hashKey);
+#endif
+ p_tcaphash_contcall = create_tcaphash_cont(&tcaphash_cont_key,
+ p_tcaphash_begincall->context,
+ pinfo);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(11,"Update Ckey %lx ",tcaphash_begin_key.hashKey);
+ dbg(11,"Frame reqlink #%d ", pinfo->fd->num);
+#endif
+ tcaphash_end_key.tid = p_tcapsrt_info->src_tid;
+ tcaphash_end_key.opc_hash=mtp3_pc_hash( ((address*)(&pinfo->src))->data);
+ tcaphash_end_key.dpc_hash=mtp3_pc_hash( ((address*)(&pinfo->dst))->data);
+ tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"New Ekey %lx ",tcaphash_end_key.hashKey);
+#endif
+ p_tcaphash_endcall = create_tcaphash_end(&tcaphash_end_key,
+ p_tcaphash_begincall->context,
+ pinfo);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(11,"Update Ekey %lx ",tcaphash_end_key.hashKey);
+ dbg(11,"Frame reqlink #%d ", pinfo->fd->num);
+#endif
+ } else { /* Begin not found */
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"BnotFound ");
+#endif
+ } /* begin found */
+ } /* cont found */
+ /* display tcap session, if available */
+ if (gtcap_DisplaySRT &&
+ p_tcaphash_context &&
+ p_tcaphash_context->session_id)
+ proto_tree_add_uint(tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+
+ return p_tcaphash_context;
+}
+
+
+
+/*
+ *
+ *
+ */
+static struct tcaphash_context_t *
+tcaphash_end_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct tcapsrt_info_t * p_tcapsrt_info)
+{
+ struct tcaphash_context_t * p_tcaphash_context=NULL;
+
+ struct tcaphash_end_info_key_t tcaphash_end_key;
+ struct tcaphash_endcall_t * p_tcaphash_endcall=NULL;
+
+ struct tcaphash_begin_info_key_t tcaphash_begin_key;
+ struct tcaphash_begincall_t * p_tcaphash_begincall=NULL;
+ proto_item *ti;
+ nstime_t delta;
+
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"\n Hend #%d ", pinfo->fd->num);
+#endif
+ /* look only for matching request, if matching conversation is available. */
+ tcaphash_end_key.tid = p_tcapsrt_info->dst_tid;
+ tcaphash_end_key.opc_hash = mtp3_pc_hash( ((address*)(&pinfo->src))->data);
+ tcaphash_end_key.dpc_hash = mtp3_pc_hash( ((address*)(&pinfo->dst))->data);
+ tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(11,"Ekey %lx ",tcaphash_end_key.hashKey);
+ dbg(11,"PC %s %s ",address_to_str(&pinfo->src), address_to_str(&pinfo->dst));
+ dbg(51,"Tid %lx ",tcaphash_end_key.tid);
+#endif
+ p_tcaphash_endcall = find_tcaphash_end(&tcaphash_end_key, pinfo,TRUE);
+
+ if(!p_tcaphash_endcall) {
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"EnotFound ");
+#endif
+ tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
+ tcaphash_begin_key.opc_hash=mtp3_pc_hash( ((address*)(&pinfo->src))->data);
+ tcaphash_begin_key.dpc_hash=mtp3_pc_hash( ((address*)(&pinfo->dst))->data);
+ tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
+ dbg(51,"PC %s %s ",address_to_str(&pinfo->src), address_to_str(&pinfo->dst));
+ dbg(51,"Tid %lx ",tcaphash_begin_key.tid);
+#endif
+ p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
+ }
+
+ if (p_tcaphash_endcall) {
+ /* Use the TC_BEGIN Destination reference */
+ p_tcaphash_context=p_tcaphash_endcall->context;
+ } else if (p_tcaphash_begincall) {
+ /* Use the TC_BEGIN Source reference */
+ p_tcaphash_context=p_tcaphash_begincall->context;
+ }
+
+ if (p_tcaphash_context) {
+
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
+#endif
+ if (gtcap_DisplaySRT)
+ proto_tree_add_uint(tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
+#endif
+ /* Indicate the frame to which this is a reply. */
+ if (gtcap_DisplaySRT) {
+ ti = proto_tree_add_uint_format(tree, hf_tcapsrt_EndSession, tvb, 0, 0,
+ p_tcaphash_context->first_frame,
+ "Begin of session in frame %u",
+ p_tcaphash_context->first_frame);
+ PROTO_ITEM_SET_GENERATED(ti);
+ /* Calculate Service Response Time */
+ nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
+
+ /* display Service Response Time and make it filterable */
+ ti = proto_tree_add_time(tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
+ PROTO_ITEM_SET_GENERATED(ti);
+ }
+ /* Close the context and remove it */
+ tcapsrt_close(p_tcaphash_context,pinfo);
+
+ } /* context present */
+ return p_tcaphash_context;
+}
+
+/*
+ * Initialize the Message Info used by the main dissector
+ * Data are linked to a TCAP transaction
+ */
+struct tcapsrt_info_t * tcapsrt_razinfo(void)
+{
+ struct tcapsrt_info_t * p_tcapsrt_info ;
+
+ /* Global buffer for packet extraction */
+ tcapsrt_global_current++;
+ if(tcapsrt_global_current==MAX_TCAP_INSTANCE){
+ tcapsrt_global_current=0;
+ }
+
+ p_tcapsrt_info=&tcapsrt_global_info[tcapsrt_global_current];
+ memset(p_tcapsrt_info,0,sizeof(struct tcapsrt_info_t));
+
+ return p_tcapsrt_info;
+}
+
+void tcapsrt_close(struct tcaphash_context_t * p_tcaphash_context,
+ packet_info * pinfo _U_)
+{
+#ifdef DEBUG_TCAPSRT
+ dbg(60,"Force close ");
+#endif
+ if (p_tcaphash_context) {
+ p_tcaphash_context->responded=TRUE;
+ p_tcaphash_context->last_frame = pinfo->fd->num;
+ p_tcaphash_context->end_time = pinfo->fd->abs_ts;
+ p_tcaphash_context->closed=TRUE;
+
+ /* If the endkey is present */
+ if ( p_tcaphash_context->endcall
+ && !gtcap_PersistentSRT ) {
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"remove Ehash ");
+#endif
+ g_hash_table_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
+ }
+
+ /* If the contkey is present */
+ if ( p_tcaphash_context->contcall
+ && !gtcap_PersistentSRT) {
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"remove Chash ");
+#endif
+ g_hash_table_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
+ }
+
+ /* If the beginkey is present */
+ if (p_tcaphash_context->begincall->next_begincall) {
+ if (p_tcaphash_context->begincall->previous_begincall ) {
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"deplace Bhash ");
+#endif
+ p_tcaphash_context->begincall->previous_begincall->next_begincall
+ = p_tcaphash_context->begincall->next_begincall;
+ p_tcaphash_context->begincall->next_begincall->previous_begincall
+ = p_tcaphash_context->begincall->previous_begincall;
+ } else {
+ /* cannot remove the father */
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"father Bhash ");
+#endif
+ }
+ } else if (!gtcap_PersistentSRT) {
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"remove Bhash ");
+#endif
+ g_hash_table_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"remove context ");
+#endif
+ g_hash_table_remove(tcaphash_context, p_tcaphash_context->key);
+
+ } /* begincall without chained string */
+ } else { /* no context */
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"No context to remove ");
+#endif
+ }
+}
diff --git a/epan/tcap-persistentdata.h b/epan/tcap-persistentdata.h
new file mode 100644
index 0000000000..f929271184
--- /dev/null
+++ b/epan/tcap-persistentdata.h
@@ -0,0 +1,127 @@
+/*
+ * tcap-persistentdata.h
+ * Definitions for lists and hash tables used in wireshark's tcap dissector
+ * for calculation of delays in tcap-transactions
+ * Copyright 2006 Florent Drouin (based on h225-persistentdata from Lars Roland)
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __tcapsrt_HASH__
+#define __tcapsrt_HASH__
+
+#include "epan/packet.h"
+#include "epan/conversation.h"
+#include "epan/dissectors/packet-tcap.h"
+
+#define LENGTH_OID 16
+struct tcaphash_context_t {
+ struct tcaphash_context_key_t * key;
+ guint32 session_id;
+ guint32 first_frame;
+ guint32 last_frame;
+ nstime_t begin_time; /* time of arrival of TC_BEGIN */
+ nstime_t end_time; /* time of closing message */
+ gboolean responded; /* true, if request has been responded */
+ gboolean closed;
+ gboolean upper_dissector;
+ gboolean oid_present;
+ gchar oid[LENGTH_OID+1];
+ dissector_handle_t subdissector_handle;
+ void (* callback) (tvbuff_t *,packet_info *, proto_tree *, struct tcaphash_context_t *);
+ struct tcaphash_begincall_t * begincall;
+ struct tcaphash_contcall_t * contcall;
+ struct tcaphash_endcall_t * endcall;
+};
+
+struct tcaphash_begincall_t {
+ struct tcaphash_begin_info_key_t * beginkey;
+ struct tcaphash_context_t * context;
+ gboolean father;
+ struct tcaphash_begincall_t * next_begincall;
+ struct tcaphash_begincall_t * previous_begincall;
+};
+
+struct tcaphash_contcall_t {
+ struct tcaphash_cont_info_key_t * contkey;
+ struct tcaphash_context_t * context;
+ gboolean father;
+ struct tcaphash_contcall_t * next_contcall;
+ struct tcaphash_contcall_t * previous_contcall;
+};
+
+struct tcaphash_endcall_t {
+ struct tcaphash_end_info_key_t * endkey;
+ struct tcaphash_context_t * context;
+ gboolean father;
+ struct tcaphash_endcall_t * next_endcall;
+ struct tcaphash_endcall_t * previous_endcall;
+};
+
+/* The Key for the hash table is the TCAP origine transaction identifier
+ of the TC_BEGIN containing the InitialDP */
+
+struct tcaphash_context_key_t {
+ guint32 session_id;
+};
+
+struct tcaphash_begin_info_key_t {
+ guint32 hashKey;
+ guint32 tid;
+ guint32 opc_hash;
+ guint32 dpc_hash;
+};
+
+struct tcaphash_cont_info_key_t {
+ guint32 hashKey;
+ guint32 src_tid;
+ guint32 dst_tid;
+ guint32 opc_hash;
+ guint32 dpc_hash;
+};
+
+struct tcaphash_end_info_key_t {
+ guint32 hashKey;
+ guint32 tid;
+ guint32 opc_hash;
+ guint32 dpc_hash;
+};
+
+
+/* List of infos to store for the analyse */
+struct tcapsrt_info_t {
+ guint32 tcap_session_id;
+ guint32 src_tid;
+ guint32 dst_tid;
+ guint8 ope;
+};
+
+void tcapsrt_init_routine(void);
+
+struct tcapsrt_info_t * tcapsrt_razinfo(void);
+
+void tcapsrt_close(struct tcaphash_context_t * p_tcaphash_context,
+ packet_info * pinfo _U_);
+
+struct tcaphash_context_t * tcapsrt_call_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct tcapsrt_info_t * p_tcap_info);
+
+#endif /* __tcapsrt_HASH__*/