diff options
author | Michael Mann <mmann78@netscape.net> | 2013-12-30 22:07:38 +0000 |
---|---|---|
committer | Michael Mann <mmann78@netscape.net> | 2013-12-30 22:07:38 +0000 |
commit | 58346b632786cebda787c8519b2d3e70207ab6b5 (patch) | |
tree | 40afe325045aa3de70f202f91d7c2d08b8214d69 /asn1/camel | |
parent | 94387fdcbd451cf0762ed898a5e63fbf85f3904c (diff) | |
download | wireshark-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.c | 740 | ||||
-rw-r--r-- | asn1/camel/packet-camel-template.h | 99 |
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 */ |