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 /epan/dissectors/packet-camel.c | |
parent | 94387fdcbd451cf0762ed898a5e63fbf85f3904c (diff) |
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 'epan/dissectors/packet-camel.c')
-rw-r--r-- | epan/dissectors/packet-camel.c | 758 |
1 files changed, 730 insertions, 28 deletions
diff --git a/epan/dissectors/packet-camel.c b/epan/dissectors/packet-camel.c index bca870f7fb..a08c6b36d0 100644 --- a/epan/dissectors/packet-camel.c +++ b/epan/dissectors/packet-camel.c @@ -63,8 +63,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" @@ -78,6 +76,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; @@ -99,20 +105,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; /*--- Included file: packet-camel-hf.c ---*/ @@ -603,7 +609,7 @@ static int hf_camel_present = -1; /* INTEGER */ static int hf_camel_InvokeId_present = -1; /* InvokeId_present */ /*--- End of included file: packet-camel-hf.c ---*/ -#line 110 "../../asn1/camel/packet-camel-template.c" +#line 116 "../../asn1/camel/packet-camel-template.c" static struct camelsrt_info_t * gp_camelsrt_info; @@ -615,9 +621,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; @@ -830,7 +837,7 @@ static gint ett_camel_T_problem = -1; static gint ett_camel_InvokeId = -1; /*--- End of included file: packet-camel-ett.c ---*/ -#line 138 "../../asn1/camel/packet-camel-template.c" +#line 145 "../../asn1/camel/packet-camel-template.c" static expert_field ei_camel_unknown_invokeData = EI_INIT; static expert_field ei_camel_unknown_returnResultData = EI_INIT; @@ -851,6 +858,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 @@ -865,6 +876,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", @@ -1158,7 +1182,7 @@ static const value_string camel_ectTreatmentIndicator_values[] = { #define noInvokeId NULL /*--- End of included file: packet-camel-val.h ---*/ -#line 281 "../../asn1/camel/packet-camel-template.c" +#line 305 "../../asn1/camel/packet-camel-template.c" /*--- Included file: packet-camel-table.c ---*/ @@ -1248,7 +1272,29 @@ static const value_string camel_err_code_string_vals[] = { /*--- End of included file: packet-camel-table.c ---*/ -#line 283 "../../asn1/camel/packet-camel-template.c" +#line 307 "../../asn1/camel/packet-camel-template.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) { @@ -7011,7 +7057,7 @@ static void dissect_CAP_U_ABORT_REASON_PDU(tvbuff_t *tvb _U_, packet_info *pinfo /*--- End of included file: packet-camel-fn.c ---*/ -#line 330 "../../asn1/camel/packet-camel-template.c" +#line 376 "../../asn1/camel/packet-camel-template.c" /*--- Included file: packet-camel-table2.c ---*/ @@ -7218,7 +7264,663 @@ static int dissect_returnErrorData(proto_tree *tree, tvbuff_t *tvb, int offset,a /*--- End of included file: packet-camel-table2.c ---*/ -#line 332 "../../asn1/camel/packet-camel-template.c" +#line 378 "../../asn1/camel/packet-camel-template.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; @@ -7417,7 +8119,7 @@ void proto_reg_handoff_camel(void) { /*--- End of included file: packet-camel-dis-tab.c ---*/ -#line 523 "../../asn1/camel/packet-camel-template.c" +#line 1225 "../../asn1/camel/packet-camel-template.c" } else { range_foreach(ssn_range, range_delete_callback); g_free(ssn_range); @@ -9531,7 +10233,7 @@ void proto_register_camel(void) { "InvokeId_present", HFILL }}, /*--- End of included file: packet-camel-hfarr.c ---*/ -#line 696 "../../asn1/camel/packet-camel-template.c" +#line 1398 "../../asn1/camel/packet-camel-template.c" }; /* List of subtrees */ @@ -9746,7 +10448,7 @@ void proto_register_camel(void) { &ett_camel_InvokeId, /*--- End of included file: packet-camel-ettarr.c ---*/ -#line 712 "../../asn1/camel/packet-camel-template.c" +#line 1414 "../../asn1/camel/packet-camel-template.c" }; static ei_register_info ei[] = { |