summaryrefslogtreecommitdiff
path: root/asn1/camel
diff options
context:
space:
mode:
authorMichael Mann <mmann78@netscape.net>2013-12-30 22:07:38 +0000
committerMichael Mann <mmann78@netscape.net>2013-12-30 22:07:38 +0000
commit58346b632786cebda787c8519b2d3e70207ab6b5 (patch)
tree40afe325045aa3de70f202f91d7c2d08b8214d69 /asn1/camel
parent94387fdcbd451cf0762ed898a5e63fbf85f3904c (diff)
downloadwireshark-58346b632786cebda787c8519b2d3e70207ab6b5.tar.gz
Move tcap and camel "persistent data" functionality to the dissectors themselves instead of being part of epan directory.
svn path=/trunk/; revision=54499
Diffstat (limited to 'asn1/camel')
-rw-r--r--asn1/camel/packet-camel-template.c740
-rw-r--r--asn1/camel/packet-camel-template.h99
2 files changed, 820 insertions, 19 deletions
diff --git a/asn1/camel/packet-camel-template.c b/asn1/camel/packet-camel-template.c
index 9acc33ce0c..ad7e9eacd6 100644
--- a/asn1/camel/packet-camel-template.c
+++ b/asn1/camel/packet-camel-template.c
@@ -55,8 +55,6 @@
#include "packet-gsm_a_common.h"
#include "packet-inap.h"
#include "packet-tcap.h"
-#include <epan/camel-persistentdata.h>
-#include <epan/tcap-persistentdata.h>
#define PNAME "Camel"
#define PSNAME "CAMEL"
@@ -70,6 +68,14 @@ int camel_tap = -1;
static guint32 opcode=0;
static guint32 errorCode=0;
static guint32 camel_ver = 0;
+
+/* When several Camel 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_CAMEL_INSTANCE 10
+static int camelsrt_global_current=0;
+static struct camelsrt_info_t camelsrt_global_info[MAX_CAMEL_INSTANCE];
+
/* ROSE context */
static rose_ctx_t camel_rose_ctx;
@@ -91,20 +97,20 @@ static int hf_camel_CAMEL_SCIBillingChargingCharacteristics = -1;
static int hf_camel_CAMEL_SCIGPRSBillingChargingCharacteristics = -1;
static int hf_camel_CAMEL_CallResult = -1;
-/* Used by camel-persistentdata.c */
-int hf_camelsrt_SessionId=-1;
-int hf_camelsrt_RequestNumber=-1;
-int hf_camelsrt_Duplicate=-1;
-int hf_camelsrt_RequestFrame=-1;
-int hf_camelsrt_ResponseFrame=-1;
-int hf_camelsrt_DeltaTime=-1;
-int hf_camelsrt_SessionTime=-1;
-int hf_camelsrt_DeltaTime31=-1;
-int hf_camelsrt_DeltaTime75=-1;
-int hf_camelsrt_DeltaTime65=-1;
-int hf_camelsrt_DeltaTime22=-1;
-int hf_camelsrt_DeltaTime35=-1;
-int hf_camelsrt_DeltaTime80=-1;
+/* Used by persistent data */
+static int hf_camelsrt_SessionId=-1;
+static int hf_camelsrt_RequestNumber=-1;
+static int hf_camelsrt_Duplicate=-1;
+static int hf_camelsrt_RequestFrame=-1;
+static int hf_camelsrt_ResponseFrame=-1;
+static int hf_camelsrt_DeltaTime=-1;
+static int hf_camelsrt_SessionTime=-1;
+static int hf_camelsrt_DeltaTime31=-1;
+static int hf_camelsrt_DeltaTime75=-1;
+static int hf_camelsrt_DeltaTime65=-1;
+static int hf_camelsrt_DeltaTime22=-1;
+static int hf_camelsrt_DeltaTime35=-1;
+static int hf_camelsrt_DeltaTime80=-1;
#include "packet-camel-hf.c"
@@ -118,9 +124,10 @@ static int dissect_camel_CAMEL_AChBillingChargingCharacteristics(gboolean implic
static int dissect_camel_CAMEL_AChBillingChargingCharacteristicsV2(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
static int dissect_camel_CAMEL_CallResult(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
-gboolean gcamel_HandleSRT=FALSE;
-extern gboolean gcamel_PersistentSRT;
-extern gboolean gcamel_DisplaySRT;
+static gboolean gcamel_HandleSRT=FALSE;
+static gboolean gcamel_PersistentSRT=FALSE;
+static gboolean gcamel_DisplaySRT=FALSE;
+static gboolean gcamel_StatSRT=FALSE;
/* Initialize the subtree pointers */
static gint ett_camel = -1;
@@ -155,6 +162,10 @@ static guint8 PDPTypeNumber;
const char *camel_obj_id = NULL;
gboolean is_ExtensionField =FALSE;
+/* Global hash tables*/
+static GHashTable *srt_calls = NULL;
+static guint32 camelsrt_global_SessionId=1;
+
static int camel_opcode_type;
#define CAMEL_OPCODE_INVOKE 1
#define CAMEL_OPCODE_RETURN_RESULT 2
@@ -169,6 +180,19 @@ static const value_string camel_Component_vals[] = {
{ 0, NULL }
};
+const value_string camelSRTtype_naming[]= {
+ { CAMELSRT_SESSION, "TCAP_Session" },
+ { CAMELSRT_VOICE_INITIALDP, "InialDP/Continue" },
+ { CAMELSRT_VOICE_ACR1, "Slice1_ACR/ACH" },
+ { CAMELSRT_VOICE_ACR2, "Slice2_ACR/ACH" },
+ { CAMELSRT_VOICE_ACR3, "Slice3_ACR/ACH" },
+ { CAMELSRT_VOICE_DISC, "EvtRepBSCM/Release" },
+ { CAMELSRT_SMS_INITIALDP, "InitialDP/ContinueSMS" },
+ { CAMELSRT_GPRS_INITIALDP, "InitialDP/ContinueGPRS" },
+ { CAMELSRT_GPRS_REPORT, "EvtRepGPRS/ContinueGPRS" },
+ { 0,NULL}
+};
+
#if 0
static const true_false_string camel_extension_value = {
"No Extension",
@@ -281,6 +305,28 @@ static const value_string camel_ectTreatmentIndicator_values[] = {
#include "packet-camel-table.c"
+/*
+ * DEBUG fonctions
+ */
+
+#undef DEBUG_CAMELSRT
+/* #define DEBUG_CAMELSRT */
+
+#ifdef DEBUG_CAMELSRT
+#include <stdio.h>
+#include <stdarg.h>
+static guint debug_level = 99;
+
+static void dbg(guint level, char *fmt, ...) {
+ va_list ap;
+
+ if (level > debug_level) return;
+ va_start(ap,fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+#endif
+
static char camel_number_to_char(int number)
{
if (number < 10)
@@ -330,6 +376,662 @@ static int dissect_camel_InitialDPArgExtensionV2(gboolean implicit_tag _U_, tvbu
#include "packet-camel-table2.c"
+/*
+ * Functions needed for Hash-Table
+ */
+
+/* compare 2 keys */
+static gint
+camelsrt_call_equal(gconstpointer k1, gconstpointer k2)
+{
+ const struct camelsrt_call_info_key_t *key1 = (const struct camelsrt_call_info_key_t *) k1;
+ const struct camelsrt_call_info_key_t *key2 = (const struct camelsrt_call_info_key_t *) k2;
+
+ return (key1->SessionIdKey == key2->SessionIdKey) ;
+}
+
+/* calculate a hash key */
+static guint
+camelsrt_call_hash(gconstpointer k)
+{
+ const struct camelsrt_call_info_key_t *key = (const struct camelsrt_call_info_key_t *) k;
+ return key->SessionIdKey;
+}
+
+/*
+ * Find the dialog by Key and Time
+ */
+static struct camelsrt_call_t *
+find_camelsrt_call(struct camelsrt_call_info_key_t *p_camelsrt_call_key)
+{
+ struct camelsrt_call_t *p_camelsrt_call = NULL;
+ p_camelsrt_call = (struct camelsrt_call_t *)g_hash_table_lookup(srt_calls, p_camelsrt_call_key);
+
+#ifdef DEBUG_CAMELSRT
+ if(p_camelsrt_call) {
+ dbg(10,"D%d ", p_camelsrt_call->session_id);
+ } else {
+ dbg(23,"Not in hash ");
+ }
+#endif
+
+ return p_camelsrt_call;
+}
+
+/*
+ * Initialize the data per call for the Service Response Time Statistics
+ * Data are linked to a Camel operation in a TCAP transaction
+ */
+static void
+raz_camelsrt_call (struct camelsrt_call_t *p_camelsrt_call)
+{
+ memset(p_camelsrt_call,0,sizeof(struct camelsrt_call_t));
+}
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct camelsrt_call_t *
+new_camelsrt_call(struct camelsrt_call_info_key_t *p_camelsrt_call_key)
+{
+ struct camelsrt_call_info_key_t *p_new_camelsrt_call_key;
+ struct camelsrt_call_t *p_new_camelsrt_call = 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_camelsrt_call_key = se_new(struct camelsrt_call_info_key_t);
+ p_new_camelsrt_call_key->SessionIdKey = p_camelsrt_call_key->SessionIdKey;
+ p_new_camelsrt_call = se_new(struct camelsrt_call_t);
+ raz_camelsrt_call(p_new_camelsrt_call);
+ p_new_camelsrt_call->session_id = camelsrt_global_SessionId++;
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"D%d ", p_new_camelsrt_call->session_id);
+#endif
+ /* store it */
+ g_hash_table_insert(srt_calls, p_new_camelsrt_call_key, p_new_camelsrt_call);
+ return p_new_camelsrt_call;
+}
+
+/*
+ * Routine called when the TAP is initialized.
+ * so hash table are (re)created
+ */
+void
+camelsrt_init_routine(void)
+{
+
+ /* free hash-table for SRT */
+ if (srt_calls != NULL) {
+#ifdef DEBUG_CAMELSRT
+ dbg(16,"Destroy hash ");
+#endif
+ g_hash_table_destroy(srt_calls);
+ }
+
+ /* create new hash-table for SRT */
+ srt_calls = g_hash_table_new(camelsrt_call_hash, camelsrt_call_equal);
+#ifdef DEBUG_CAMELSRT
+ dbg(16,"Create hash ");
+#endif
+ /* Reset the session counter */
+ camelsrt_global_SessionId=1;
+
+ /* The Display of SRT is enable
+ * 1) For wireshark only if Persistent Stat is enable
+ * 2) For Tshark, if the SRT handling is enable
+ */
+ gcamel_DisplaySRT=gcamel_PersistentSRT || gcamel_HandleSRT&gcamel_StatSRT;
+}
+
+
+/*
+ * Update a record with the data of the Request
+ */
+static void
+update_camelsrt_call(struct camelsrt_call_t *p_camelsrt_call, packet_info *pinfo,
+ guint msg_category)
+{
+ p_camelsrt_call->category[msg_category].req_num = pinfo->fd->num;
+ p_camelsrt_call->category[msg_category].rsp_num = 0;
+ p_camelsrt_call->category[msg_category].responded = FALSE;
+ p_camelsrt_call->category[msg_category].req_time = pinfo->fd->abs_ts;
+}
+
+/*
+ * Update the Camel session info, and close the session.
+ * Then remove the associated context, if we do not have persistentSRT enable
+ */
+static void
+camelsrt_close_call_matching(packet_info *pinfo,
+ struct camelsrt_info_t *p_camelsrt_info)
+{
+ struct camelsrt_call_t *p_camelsrt_call;
+ struct camelsrt_call_info_key_t camelsrt_call_key;
+ nstime_t delta;
+
+ p_camelsrt_info->bool_msginfo[CAMELSRT_SESSION]=TRUE;
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"\n Session end #%u\n", pinfo->fd->num);
+#endif
+ /* look only for matching request, if matching conversation is available. */
+ camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
+
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
+#endif
+ p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key);
+ if(p_camelsrt_call) {
+#ifdef DEBUG_CAMELSRT
+ dbg(12,"Found ");
+#endif
+ /* Calculate Service Response Time */
+ nstime_delta(&delta, &pinfo->fd->abs_ts, &p_camelsrt_call->category[CAMELSRT_SESSION].req_time);
+ p_camelsrt_call->category[CAMELSRT_SESSION].responded = TRUE;
+ p_camelsrt_info->msginfo[CAMELSRT_SESSION].request_available = TRUE;
+ p_camelsrt_info->msginfo[CAMELSRT_SESSION].is_delta_time = TRUE;
+ p_camelsrt_info->msginfo[CAMELSRT_SESSION].delta_time = delta; /* give it to tap */
+ p_camelsrt_info->msginfo[CAMELSRT_SESSION].req_time = p_camelsrt_call->category[CAMELSRT_SESSION].req_time;
+
+ if ( !gcamel_PersistentSRT ) {
+ g_hash_table_remove(srt_calls, &camelsrt_call_key);
+#ifdef DEBUG_CAMELSRT
+ dbg(20,"remove hash ");
+#endif
+ } else {
+#ifdef DEBUG_CAMELSRT
+ dbg(20,"keep hash ");
+#endif
+ }
+ } /* call reference found */
+}
+
+/*
+ * Callback function for the TCAP dissector
+ * This callback function is used to inform the camel layer, that the session
+ * has been Closed or Aborted by a TCAP message without Camel component
+ * So, we can close the context for camel session, and update the stats.
+ */
+static void
+camelsrt_tcap_matching(tvbuff_t *tvb _U_, packet_info *pinfo,
+ proto_tree *tree _U_,
+ struct tcaphash_context_t *p_tcap_context)
+{
+ struct camelsrt_info_t *p_camelsrt_info;
+
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Camel_CallBack ");
+#endif
+ p_camelsrt_info=camelsrt_razinfo();
+
+ p_camelsrt_info->tcap_context=p_tcap_context;
+ if (p_tcap_context) {
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Close TCAP ");
+#endif
+ p_camelsrt_info->tcap_session_id = p_tcap_context->session_id;
+ camelsrt_close_call_matching(pinfo, p_camelsrt_info);
+ tap_queue_packet(camel_tap, pinfo, p_camelsrt_info);
+ }
+}
+
+/*
+ * Create the record identifiying the Camel session
+ * As the Tcap session id given by the TCAP dissector is uniq, it will be
+ * used as main key.
+ */
+static void
+camelsrt_begin_call_matching(packet_info *pinfo,
+ struct camelsrt_info_t *p_camelsrt_info)
+{
+ struct camelsrt_call_t *p_camelsrt_call;
+ struct camelsrt_call_info_key_t camelsrt_call_key;
+
+ p_camelsrt_info->bool_msginfo[CAMELSRT_SESSION]=TRUE;
+
+ /* prepare the key data */
+ camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
+
+ /* look up the request */
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"\n Session begin #%u\n", pinfo->fd->num);
+ dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
+#endif
+ p_camelsrt_call = (struct camelsrt_call_t *)g_hash_table_lookup(srt_calls, &camelsrt_call_key);
+ if (p_camelsrt_call) {
+ /* We have seen this request before -> do nothing */
+#ifdef DEBUG_CAMELSRT
+ dbg(22,"Already seen ");
+#endif
+ } else { /* p_camelsrt_call has not been found */
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"New key %lu ",camelsrt_call_key.SessionIdKey);
+#endif
+ p_camelsrt_call = new_camelsrt_call(&camelsrt_call_key);
+ p_camelsrt_call->tcap_context=(struct tcaphash_context_t *)p_camelsrt_info->tcap_context;
+ update_camelsrt_call(p_camelsrt_call, pinfo,CAMELSRT_SESSION);
+
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Update Callback ");
+#endif
+ p_camelsrt_call->tcap_context->callback=camelsrt_tcap_matching;
+ }
+}
+
+/*
+ * Register the request, and try to find the response
+ *
+ */
+static void
+camelsrt_request_call_matching(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree,
+ struct camelsrt_info_t *p_camelsrt_info,
+ guint srt_type )
+{
+ struct camelsrt_call_t *p_camelsrt_call;
+ struct camelsrt_call_info_key_t camelsrt_call_key;
+ proto_item *ti, *hidden_item;
+
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"\n %s #%u\n", val_to_str_const(srt_type, camelSRTtype_naming, "Unk"),pinfo->fd->num);
+#endif
+
+ /* look only for matching request, if matching conversation is available. */
+ camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
+
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Search key %lu ", camelsrt_call_key.SessionIdKey);
+#endif
+ p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key);
+ if(p_camelsrt_call) {
+#ifdef DEBUG_CAMELSRT
+ dbg(12,"Found ");
+#endif
+ if (gcamel_DisplaySRT)
+ proto_tree_add_uint(tree, hf_camelsrt_SessionId, tvb, 0,0, p_camelsrt_call->session_id);
+
+
+ /* Hmm.. As there are several slices ApplyChargingReport/ApplyCharging
+ * we will prepare the measurement for 3 slices with 3 categories */
+ if (srt_type==CAMELSRT_VOICE_ACR1) {
+ if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num == 0) {
+ srt_type=CAMELSRT_VOICE_ACR1;
+ } else if ( (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num == 0)
+ && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0)
+ && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num < pinfo->fd->num) ) {
+ srt_type=CAMELSRT_VOICE_ACR2;
+ } else if ( (p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num == 0)
+ && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num != 0)
+ && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num < pinfo->fd->num) ) {
+ srt_type=CAMELSRT_VOICE_ACR3;
+ } else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num > pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR1;
+ } else if ( p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num > pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR2;
+ } else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].rsp_num > pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR3;
+ }
+#ifdef DEBUG_CAMELSRT
+ dbg(70,"Request ACR %u ",srt_type);
+ dbg(70,"ACR1 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num);
+ dbg(70,"ACR2 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num);
+ dbg(70,"ACR3 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].rsp_num);
+#endif
+ } /* not ACR */
+ p_camelsrt_info->bool_msginfo[srt_type]=TRUE;
+
+
+ if (p_camelsrt_call->category[srt_type].req_num == 0) {
+ /* We have not yet seen a request to that call, so this must be the first request
+ remember its frame number. */
+#ifdef DEBUG_CAMELSRT
+ dbg(5,"Set reqlink #%u ", pinfo->fd->num);
+#endif
+ update_camelsrt_call(p_camelsrt_call, pinfo, srt_type);
+ } else {
+ /* We have seen a request to this call - but was it *this* request? */
+ if (p_camelsrt_call->category[srt_type].req_num != pinfo->fd->num) {
+
+ if (srt_type!=CAMELSRT_VOICE_DISC) {
+ /* No, so it's a duplicate resquest. Mark it as such. */
+#ifdef DEBUG_CAMELSRT
+ dbg(21,"Display_duplicate with req %d ", p_camelsrt_call->category[srt_type].req_num);
+#endif
+ p_camelsrt_info->msginfo[srt_type].is_duplicate = TRUE;
+ if (gcamel_DisplaySRT){
+ hidden_item = proto_tree_add_uint(tree, hf_camelsrt_Duplicate, tvb, 0,0, 77);
+ PROTO_ITEM_SET_HIDDEN(hidden_item);
+ }
+
+ } else {
+ /* Ignore duplicate frame */
+ if (pinfo->fd->num > p_camelsrt_call->category[srt_type].req_num) {
+ p_camelsrt_call->category[srt_type].req_num = pinfo->fd->num;
+#ifdef DEBUG_CAMELSRT
+ dbg(5,"DISC Set reqlink #%u ", pinfo->fd->num);
+#endif
+ update_camelsrt_call(p_camelsrt_call, pinfo, srt_type);
+ } /* greater frame */
+ } /* DISC */
+ } /* req_num already seen */
+ } /* req_num != 0 */
+
+ /* add link to response frame, if available */
+ if ( gcamel_DisplaySRT &&
+ (p_camelsrt_call->category[srt_type].rsp_num != 0) &&
+ (p_camelsrt_call->category[srt_type].req_num != 0) &&
+ (p_camelsrt_call->category[srt_type].req_num == pinfo->fd->num) ) {
+#ifdef DEBUG_CAMELSRT
+ dbg(20,"Display_framersplink %d ",p_camelsrt_call->category[srt_type].rsp_num);
+#endif
+ ti = proto_tree_add_uint_format(tree, hf_camelsrt_RequestFrame, tvb, 0, 0,
+ p_camelsrt_call->category[srt_type].rsp_num,
+ "Linked response %s in frame %u",
+ val_to_str_const(srt_type, camelSRTtype_naming, "Unk"),
+ p_camelsrt_call->category[srt_type].rsp_num);
+ PROTO_ITEM_SET_GENERATED(ti);
+ } /* frame valid */
+ } /* call reference */
+}
+
+/*
+ * Display the delta time between two messages in a field corresponding
+ * to the category (hf_camelsrt_DeltaTimexx).
+ */
+static void
+camelsrt_display_DeltaTime(proto_tree *tree, tvbuff_t *tvb, nstime_t *value_ptr,
+ guint category)
+{
+ proto_item *ti;
+
+ if ( gcamel_DisplaySRT ) {
+ switch(category) {
+ case CAMELSRT_VOICE_INITIALDP:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime31, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ case CAMELSRT_VOICE_ACR1:
+ case CAMELSRT_VOICE_ACR2:
+ case CAMELSRT_VOICE_ACR3:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime22, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ case CAMELSRT_VOICE_DISC:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime35, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ case CAMELSRT_GPRS_INITIALDP:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime75, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ case CAMELSRT_GPRS_REPORT:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime80, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ case CAMELSRT_SMS_INITIALDP:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime65, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+/*
+ * Check if the received message is a response to a previous request
+ * registered is the camel session context.
+ */
+static void
+camelsrt_report_call_matching(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree,
+ struct camelsrt_info_t *p_camelsrt_info,
+ guint srt_type)
+{
+ struct camelsrt_call_t *p_camelsrt_call;
+ struct camelsrt_call_info_key_t camelsrt_call_key;
+ nstime_t delta;
+ proto_item *ti, *hidden_item;
+
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"\n %s #%u\n", val_to_str_const(srt_type, camelSRTtype_naming, "Unk"),pinfo->fd->num);
+#endif
+ camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
+ /* look only for matching request, if matching conversation is available. */
+
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
+#endif
+ p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key);
+ if(p_camelsrt_call) {
+#ifdef DEBUG_CAMELSRT
+ dbg(12,"Found, req=%d ",p_camelsrt_call->category[srt_type].req_num);
+#endif
+ if ( gcamel_DisplaySRT )
+ proto_tree_add_uint(tree, hf_camelsrt_SessionId, tvb, 0,0, p_camelsrt_call->session_id);
+
+ if (srt_type==CAMELSRT_VOICE_ACR1) {
+ if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num < pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR1;
+ } else if ( p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num < pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR2;
+ } else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num < pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR1;
+ }
+#ifdef DEBUG_CAMELSRT
+ dbg(70,"Report ACR %u ",srt_type);
+#endif
+ } /* not ACR */
+ p_camelsrt_info->bool_msginfo[srt_type]=TRUE;
+
+ if (p_camelsrt_call->category[srt_type].rsp_num == 0) {
+ if ( (p_camelsrt_call->category[srt_type].req_num != 0)
+ && (pinfo->fd->num > p_camelsrt_call->category[srt_type].req_num) ){
+ /* We have not yet seen a response to that call, so this must be the first response;
+ remember its frame number only if response comes after request */
+#ifdef DEBUG_CAMELSRT
+ dbg(14,"Set reslink #%d req %u ",pinfo->fd->num, p_camelsrt_call->category[srt_type].req_num);
+#endif
+ p_camelsrt_call->category[srt_type].rsp_num = pinfo->fd->num;
+
+ } else {
+#ifdef DEBUG_CAMELSRT
+ dbg(2,"badreslink #%u req %u ",pinfo->fd->num, p_camelsrt_call->category[srt_type].req_num);
+#endif
+ } /* req_num != 0 */
+ } else { /* rsp_num != 0 */
+ /* We have seen a response to this call - but was it *this* response? */
+ if (p_camelsrt_call->category[srt_type].rsp_num != pinfo->fd->num) {
+ /* No, so it's a duplicate response. Mark it as such. */
+#ifdef DEBUG_CAMELSRT
+ dbg(21,"Display_duplicate rsp=%d ", p_camelsrt_call->category[srt_type].rsp_num);
+#endif
+ p_camelsrt_info->msginfo[srt_type].is_duplicate = TRUE;
+ if ( gcamel_DisplaySRT ){
+ hidden_item = proto_tree_add_uint(tree, hf_camelsrt_Duplicate, tvb, 0,0, 77);
+ PROTO_ITEM_SET_HIDDEN(hidden_item);
+ }
+ }
+ } /* rsp_num != 0 */
+
+ if ( (p_camelsrt_call->category[srt_type].req_num != 0) &&
+ (p_camelsrt_call->category[srt_type].rsp_num != 0) &&
+ (p_camelsrt_call->category[srt_type].rsp_num == pinfo->fd->num) ) {
+
+ p_camelsrt_call->category[srt_type].responded = TRUE;
+ p_camelsrt_info->msginfo[srt_type].request_available = TRUE;
+#ifdef DEBUG_CAMELSRT
+ dbg(20,"Display_frameReqlink %d ",p_camelsrt_call->category[srt_type].req_num);
+#endif
+ /* Indicate the frame to which this is a reply. */
+ if ( gcamel_DisplaySRT ) {
+ ti = proto_tree_add_uint_format(tree, hf_camelsrt_ResponseFrame, tvb, 0, 0,
+ p_camelsrt_call->category[srt_type].req_num,
+ "Linked request %s in frame %u",
+ val_to_str_const(srt_type, camelSRTtype_naming, "Unk"),
+ p_camelsrt_call->category[srt_type].req_num);
+ PROTO_ITEM_SET_GENERATED(ti);
+ }
+ /* Calculate Service Response Time */
+ nstime_delta(&delta, &pinfo->fd->abs_ts, &p_camelsrt_call->category[srt_type].req_time);
+
+ p_camelsrt_info->msginfo[srt_type].is_delta_time = TRUE;
+ p_camelsrt_info->msginfo[srt_type].delta_time = delta; /* give it to tap */
+ p_camelsrt_info->msginfo[srt_type].req_time = p_camelsrt_call->category[srt_type].req_time;
+
+ /* display Service Response Time and make it filterable */
+ camelsrt_display_DeltaTime(tree, tvb, &delta, srt_type);
+
+ } /*req_num != 0 && not duplicate */
+ } /* call reference found */
+}
+
+/*
+ * Service Response Time analyze, called just after the camel dissector
+ * According to the camel operation, we
+ * - open/close a context for the camel session
+ * - look for a request, or look for the corresponding response
+ */
+void
+camelsrt_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct camelsrt_info_t *p_camelsrt_info)
+{
+
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"tcap_session #%d ", p_camelsrt_info->tcap_session_id);
+#endif
+
+ switch (p_camelsrt_info->opcode) {
+
+ case 0: /*InitialDP*/
+ camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_INITIALDP);
+ break;
+ case 60: /*InitialDPSMS*/
+ camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_SMS_INITIALDP);
+ break;
+ case 78: /*InitialDPGPRS*/
+ camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_GPRS_INITIALDP);
+ break;
+
+ case 23: /*RequestReportBCSMEvent*/
+ break;
+
+ case 63: /*RequestReportSMSEvent*/
+ break;
+
+ case 81: /*RequestReportGPRSEvent*/
+ break;
+
+ case 24: /*EventReportBCSMEvent*/
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_DISC );
+ break;
+
+ case 64: /*EventReportSMS*/
+ /* Session has been explicity closed without TC_END */
+ camelsrt_close_call_matching(pinfo, p_camelsrt_info);
+ tcapsrt_close((struct tcaphash_context_t *)p_camelsrt_info->tcap_context, pinfo);
+ break;
+
+ case 80: /*EventReportGPRS*/
+ camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_GPRS_REPORT);
+ break;
+
+ case 35: /*ApplyCharging*/
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_ACR1 );
+ break;
+
+ case 71: /*ApplyChargingGPRS*/
+ break;
+
+ case 36: /*ApplyChargingReport*/
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_ACR1 );
+ break;
+
+ case 72: /*ApplyChargingReportGPRS*/
+ break;
+
+ case 31: /*Continue*/
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_INITIALDP);
+ break;
+ case 65: /*ContinueSMS*/
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_SMS_INITIALDP);
+ break;
+ case 75: /*ContinueGPRS*/
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_GPRS_INITIALDP);
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_GPRS_REPORT);
+ break;
+
+ case 22: /*ReleaseCall*/
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_DISC);
+ /* Session has been closed by Network */
+ camelsrt_close_call_matching(pinfo, p_camelsrt_info);
+ break;
+
+ case 66: /*ReleaseSMS*/
+ /* Session has been closed by Network */
+ camelsrt_close_call_matching(pinfo, p_camelsrt_info);
+ tcapsrt_close((struct tcaphash_context_t *)p_camelsrt_info->tcap_context,pinfo);
+ break;
+
+ case 79: /*ReleaseGPRS*/
+ /* Session has been closed by Network */
+ camelsrt_close_call_matching(pinfo, p_camelsrt_info);
+ break;
+ } /* switch opcode */
+}
+
+/*
+ * Initialize the Message Info used by the main dissector
+ * Data are linked to a TCAP transaction
+ */
+struct camelsrt_info_t *
+camelsrt_razinfo(void)
+{
+ struct camelsrt_info_t *p_camelsrt_info ;
+
+ /* Global buffer for packet extraction */
+ camelsrt_global_current++;
+ if(camelsrt_global_current==MAX_CAMEL_INSTANCE){
+ camelsrt_global_current=0;
+ }
+
+ p_camelsrt_info=&camelsrt_global_info[camelsrt_global_current];
+ memset(p_camelsrt_info,0,sizeof(struct camelsrt_info_t));
+
+ p_camelsrt_info->opcode=255;
+
+ return p_camelsrt_info;
+}
+
static guint8 camel_pdu_type = 0;
static guint8 camel_pdu_size = 0;
diff --git a/asn1/camel/packet-camel-template.h b/asn1/camel/packet-camel-template.h
index 5dd326b82e..ee40de3f55 100644
--- a/asn1/camel/packet-camel-template.h
+++ b/asn1/camel/packet-camel-template.h
@@ -46,4 +46,103 @@ void proto_register_camel(void);
WS_DLL_PUBLIC const value_string camel_opr_code_strings[];
/* #include "packet-camel-exp.h"*/
+/** @file
+*/
+#define NB_CAMELSRT_CATEGORY 9+1 /**< Number of type of message */
+/* for example TC_BEGIN with InitalDP, and TC_CONT with RequestReportBCSMEvent
+ is a category, we want to measure the delay between the two messages */
+
+#define CAMELSRT_SESSION 1
+
+#define CAMELSRT_VOICE_INITIALDP 2
+#define CAMELSRT_VOICE_ACR1 3
+#define CAMELSRT_VOICE_ACR2 4
+#define CAMELSRT_VOICE_ACR3 5
+#define CAMELSRT_VOICE_DISC 6
+
+#define CAMELSRT_GPRS_INITIALDP 7
+#define CAMELSRT_GPRS_REPORT 8
+
+#define CAMELSRT_SMS_INITIALDP 9
+
+WS_DLL_PUBLIC const value_string camelSRTtype_naming[];
+
+/** If we have a request message and its response,
+ (eg: ApplyCharging, ApplyChargingReport)
+ the frames numbers are stored in this structure */
+
+struct camelsrt_category_t {
+ guint32 req_num; /**< frame number request seen */
+ guint32 rsp_num; /**< frame number response seen */
+ nstime_t req_time; /**< arrival time of request */
+ gboolean responded; /**< true, if request has been responded */
+};
+
+/** List of stored parameters for a Camel dialogue
+ All this parameters are linked to the hash table key below (use of Tid)
+ In case of same Tid reused, the Camel parameters are chained.
+ The right dialogue will be identified with the arrival time of the InitialDP */
+
+struct camelsrt_call_t {
+ guint32 session_id; /**< Identify the session, with an internal number */
+ struct tcaphash_context_t * tcap_context;
+ struct camelsrt_category_t category[NB_CAMELSRT_CATEGORY];
+};
+
+
+/** The Key for the hash table is the TCAP origine transaction identifier
+ of the TC_BEGIN containing the InitialDP */
+
+struct camelsrt_call_info_key_t {
+ guint32 SessionIdKey;
+};
+
+/** Info for a couple of messages (or category)
+ The request must be available, not duplicated,
+ and once the corresponding response received,
+ we can deduce the Delta Time between Request/response */
+
+struct camelsrt_msginfo_t {
+ gboolean request_available;
+ gboolean is_duplicate;
+ gboolean is_delta_time;
+ nstime_t req_time;
+ nstime_t delta_time;
+};
+
+/** List of infos to store for the analyse */
+
+struct camelsrt_info_t {
+ guint32 tcap_session_id;
+ void * tcap_context;
+ guint8 opcode; /**< operation code of message received */
+ guint8 bool_msginfo[NB_CAMELSRT_CATEGORY]; /**< category for the received message */
+ struct camelsrt_msginfo_t msginfo[NB_CAMELSRT_CATEGORY];
+};
+
+/**
+ * Routine called when the TAP is initialized.
+ * so hash table are (re)created
+ */
+void camelsrt_init_routine(void);
+
+/**
+ * Initialize the Message Info used by the main dissector
+ * Data are linked to a TCAP transaction
+ */
+struct camelsrt_info_t * camelsrt_razinfo(void);
+
+/**
+ * Service Response Time analyze, called just after the camel dissector
+ * According to the camel operation, we
+ * - open/close a context for the camel session
+ * - look for a request, or look for the corresponding response
+ */
+void camelsrt_call_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct camelsrt_info_t * p_camel_info);
+
+WS_DLL_PUBLIC gboolean gcamel_StatSRT;
+
#endif /* PACKET_camel_H */