Move tcap and camel "persistent data" functionality to the dissectors themselves instead of being part of epan directory.

svn path=/trunk/; revision=54499
This commit is contained in:
Michael Mann 2013-12-30 22:07:38 +00:00
parent 94387fdcbd
commit 58346b6327
20 changed files with 5620 additions and 3144 deletions

View File

@ -38,7 +38,6 @@
#include "packet-ber.h"
#include "packet-tcap.h"
#include "packet-ansi_tcap.h"
#include <epan/tcap-persistentdata.h>
#define PNAME "ANSI Transaction Capabilities Application Part"
#define PSNAME "ANSI_TCAP"
@ -89,6 +88,13 @@ extern gboolean gtcap_PersistentSRT;
extern guint gtcap_RepetitionTimeout;
extern guint gtcap_LostTimeout;
/* 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];
static dissector_table_t ber_oid_dissector_table=NULL;
static const char * cur_oid;
static const char * tcapext_oid;

View File

@ -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;

View File

@ -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 */

File diff suppressed because it is too large Load Diff

View File

@ -70,6 +70,147 @@ struct tcap_private_t {
gchar *TransactionID_str;
};
/** @file
* lists and hash tables used in wireshark's tcap dissector
* for calculation of delays in tcap-calls
*/
#define LENGTH_OID 23
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];
gboolean subdissector_present;
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_ansicall_t * ansicall;
};
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;
};
struct tcaphash_ansicall_t {
struct tcaphash_ansi_info_key_t * ansikey;
struct tcaphash_context_t * context;
gboolean father;
struct tcaphash_ansicall_t * next_ansicall;
struct tcaphash_ansicall_t * previous_ansicall;
};
/** 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;
};
struct tcaphash_ansi_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;
};
/**
* Routine called when the TAP is initialized.
* so hash table are (re)created
*/
void tcapsrt_init_routine(void);
/**
* Initialize the Message Info used by the main dissector
* Data are linked to a TCAP transaction
*/
struct tcapsrt_info_t * tcapsrt_razinfo(void);
void tcapsrt_close(struct tcaphash_context_t * p_tcaphash_context,
packet_info * pinfo _U_);
/**
* Service Response Time analyze
* Called just after dissector call
* Associate a TCAP context to a tcap session and display session related infomations
* like the first frame, the last, the session duration,
* and a uniq session identifier for the filtering
*
* For ETSI tcap, the TCAP context can be reached through three keys
* - a key (BEGIN) identifying the session according to the tcap source identifier
* - a key (CONT) identifying the established session (src_id and dst_id)
* - a key (END) identifying the session according to the tcap destination identifier
*
* For ANSI tcap, the TCAP context is reached through a uniq key
* - a key (ANSI) identifying the session according to the tcap identifier
*/
struct tcaphash_context_t * tcapsrt_call_matching(tvbuff_t *tvb,
packet_info * pinfo _U_,
proto_tree *tree,
struct tcapsrt_info_t * p_tcap_info);
WS_DLL_PUBLIC gboolean gtcap_StatSRT;
extern gint tcap_standard;
extern const value_string tcap_component_type_str[];

View File

@ -1476,7 +1476,6 @@ set(LIBWIRESHARK_FILES
app_mem_usage.c
asn1.c
atalk-utils.c
camel-persistentdata.c
charsets.c
circuit.c
column.c
@ -1534,7 +1533,6 @@ set(LIBWIRESHARK_FILES
stream.c
t35.c
tap.c
tcap-persistentdata.c
timestamp.c
timestats.c
tfs.c

View File

@ -32,7 +32,6 @@ LIBWIRESHARK_SRC = \
app_mem_usage.c \
asn1.c \
atalk-utils.c \
camel-persistentdata.c \
charsets.c \
circuit.c \
column.c \
@ -89,7 +88,6 @@ LIBWIRESHARK_SRC = \
stream.c \
t35.c \
tap.c \
tcap-persistentdata.c \
timestamp.c \
timestats.c \
tfs.c \
@ -158,7 +156,6 @@ LIBWIRESHARK_INCLUDES = \
atalk-utils.h \
ax25_pids.h \
bridged_pids.h \
camel-persistentdata.h \
charsets.h \
chdlctypes.h \
circuit.h \
@ -246,7 +243,6 @@ LIBWIRESHARK_INCLUDES = \
t35.h \
tap.h \
tap-voip.h \
tcap-persistentdata.h \
timestamp.h \
timestats.h \
tfs.h \

View File

@ -1,798 +0,0 @@
/*
* camel-persistentdata.c
* Source for lists and hash tables used in wireshark's camel dissector
* for calculation of delays in camel calls
* Copyright 2006 Florent Drouin
*
* $Id$
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include <glib.h>
#include <stdio.h>
#include <string.h>
#include <epan/emem.h>
#include <epan/packet.h>
#include <epan/tap.h>
#include <epan/asn1.h>
#include <epan/camel-persistentdata.h>
#include <epan/dissectors/packet-tcap.h>
#include <epan/dissectors/packet-mtp3.h>
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}
};
static gint camelsrt_call_equal(gconstpointer k1, gconstpointer k2);
static guint camelsrt_call_hash(gconstpointer k);
static struct camelsrt_call_t *find_camelsrt_call(struct camelsrt_call_info_key_t *p_camelsrt_call_key);
static struct camelsrt_call_t *new_camelsrt_call(struct camelsrt_call_info_key_t *p_camelsrt_call_key);
static void update_camelsrt_call(struct camelsrt_call_t *p_camelsrt_call,
packet_info *pinfo, guint msg_category);
static void camelsrt_begin_call_matching(packet_info *pinfo,
struct camelsrt_info_t *p_camelsrt_info);
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);
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);
static void camelsrt_close_call_matching(packet_info *pinfo,
struct camelsrt_info_t *p_camelsrt_info);
static void camelsrt_display_DeltaTime(proto_tree *tree, tvbuff_t *tvb,
nstime_t *value_ptr, guint category);
static void raz_camelsrt_call (struct camelsrt_call_t *p_camelsrt_call);
void camelsrt_tcap_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
struct tcaphash_context_t *tcap_context);
/* 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
int camelsrt_global_current=0;
struct camelsrt_info_t camelsrt_global_info[MAX_CAMEL_INSTANCE];
/* Configuration parameters to enable or disable the Service Response Time */
extern gboolean gcamel_HandleSRT;
gboolean gcamel_PersistentSRT=FALSE;
gboolean gcamel_DisplaySRT=FALSE;
gboolean gcamel_StatSRT=FALSE;
extern int camel_tap;
extern int hf_camelsrt_SessionId;
extern int hf_camelsrt_RequestNumber;
extern int hf_camelsrt_Duplicate;
extern int hf_camelsrt_RequestFrame;
extern int hf_camelsrt_ResponseFrame;
extern int hf_camelsrt_DeltaTime;
extern int hf_camelsrt_SessionTime;
extern int hf_camelsrt_DeltaTime31;
extern int hf_camelsrt_DeltaTime75;
extern int hf_camelsrt_DeltaTime65;
extern int hf_camelsrt_DeltaTime22;
extern int hf_camelsrt_DeltaTime35;
extern int hf_camelsrt_DeltaTime80;
/* Global hash tables*/
static GHashTable *srt_calls = NULL;
guint32 camelsrt_global_SessionId=1;
/*
* 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
/*
* 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;
}
/*
* 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;
}
/*
* 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;
}
/*
* 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;
}
/*
* 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 */
}
/*
* 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.
*/
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 */
}
/*
* 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 */
}
/*
* 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 */
}
/*
* 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;
}
}
}
/*
* 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;
}
/*
* 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));
}

View File

@ -1,144 +0,0 @@
/*
* camel-persistentdata.h
* Definitions for lists and hash tables used in wireshark's camel dissector
* for calculation of delays in camel-transactions
* Copyright 2006 Florent Drouin
*
* $Id$
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __CAMEL_PERSISTENTDATA_H__
#define __CAMEL_PERSISTENTDATA_H__
#include <epan/packet.h>
#include <epan/conversation.h>
#include <epan/dissectors/packet-camel.h>
#include <epan/tcap-persistentdata.h>
#include "ws_symbol_export.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/** @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;
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* camel-persistentdata.h */

View File

@ -46,7 +46,6 @@
#include "packet-ber.h"
#include "packet-tcap.h"
#include "packet-ansi_tcap.h"
#include <epan/tcap-persistentdata.h>
#define PNAME "ANSI Transaction Capabilities Application Part"
#define PSNAME "ANSI_TCAP"
@ -126,7 +125,7 @@ static int hf_ansi_tcap_paramSequence = -1; /* T_paramSequence */
static int hf_ansi_tcap_paramSet = -1; /* T_paramSet */
/*--- End of included file: packet-ansi_tcap-hf.c ---*/
#line 66 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
#line 65 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
/* Initialize the subtree pointers */
static gint ett_tcap = -1;
@ -172,7 +171,7 @@ static gint ett_ansi_tcap_T_paramSequence = -1;
static gint ett_ansi_tcap_T_paramSet = -1;
/*--- End of included file: packet-ansi_tcap-ett.c ---*/
#line 85 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
#line 84 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
#define MAX_SSN 254
@ -1395,7 +1394,7 @@ dissect_ansi_tcap_PackageType(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int
/*--- End of included file: packet-ansi_tcap-fn.c ---*/
#line 353 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
#line 352 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
@ -1740,7 +1739,7 @@ proto_register_ansi_tcap(void)
NULL, HFILL }},
/*--- End of included file: packet-ansi_tcap-hfarr.c ---*/
#line 489 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
#line 488 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
};
/* Setup protocol subtree array */
@ -1778,7 +1777,7 @@ proto_register_ansi_tcap(void)
&ett_ansi_tcap_T_paramSet,
/*--- End of included file: packet-ansi_tcap-ettarr.c ---*/
#line 500 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
#line 499 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
};
static const enum_val_t ansi_tcap_response_matching_type_values[] = {

View File

@ -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[] = {

View File

@ -54,4 +54,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 */

File diff suppressed because it is too large Load Diff

View File

@ -78,6 +78,147 @@ struct tcap_private_t {
gchar *TransactionID_str;
};
/** @file
* lists and hash tables used in wireshark's tcap dissector
* for calculation of delays in tcap-calls
*/
#define LENGTH_OID 23
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];
gboolean subdissector_present;
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_ansicall_t * ansicall;
};
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;
};
struct tcaphash_ansicall_t {
struct tcaphash_ansi_info_key_t * ansikey;
struct tcaphash_context_t * context;
gboolean father;
struct tcaphash_ansicall_t * next_ansicall;
struct tcaphash_ansicall_t * previous_ansicall;
};
/** 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;
};
struct tcaphash_ansi_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;
};
/**
* Routine called when the TAP is initialized.
* so hash table are (re)created
*/
void tcapsrt_init_routine(void);
/**
* Initialize the Message Info used by the main dissector
* Data are linked to a TCAP transaction
*/
struct tcapsrt_info_t * tcapsrt_razinfo(void);
void tcapsrt_close(struct tcaphash_context_t * p_tcaphash_context,
packet_info * pinfo _U_);
/**
* Service Response Time analyze
* Called just after dissector call
* Associate a TCAP context to a tcap session and display session related infomations
* like the first frame, the last, the session duration,
* and a uniq session identifier for the filtering
*
* For ETSI tcap, the TCAP context can be reached through three keys
* - a key (BEGIN) identifying the session according to the tcap source identifier
* - a key (CONT) identifying the established session (src_id and dst_id)
* - a key (END) identifying the session according to the tcap destination identifier
*
* For ANSI tcap, the TCAP context is reached through a uniq key
* - a key (ANSI) identifying the session according to the tcap identifier
*/
struct tcaphash_context_t * tcapsrt_call_matching(tvbuff_t *tvb,
packet_info * pinfo _U_,
proto_tree *tree,
struct tcapsrt_info_t * p_tcap_info);
WS_DLL_PUBLIC gboolean gtcap_StatSRT;
extern gint tcap_standard;
extern const value_string tcap_component_type_str[];
@ -104,6 +245,6 @@ int dissect_tcap_UniDialoguePDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, in
int dissect_tcap_DialoguePDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
/*--- End of included file: packet-tcap-exp.h ---*/
#line 91 "../../asn1/tcap/packet-tcap-template.h"
#line 232 "../../asn1/tcap/packet-tcap-template.h"
#endif /* PACKET_tcap_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,177 +0,0 @@
/*
* 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
*
* $Id$
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __tcapsrt_HASH__
#define __tcapsrt_HASH__
#include <epan/packet.h>
#include <epan/conversation.h>
#include <epan/dissectors/packet-tcap.h>
#include "ws_symbol_export.h"
/** @file
* lists and hash tables used in wireshark's tcap dissector
* for calculation of delays in tcap-calls
*/
#define LENGTH_OID 23
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];
gboolean subdissector_present;
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_ansicall_t * ansicall;
};
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;
};
struct tcaphash_ansicall_t {
struct tcaphash_ansi_info_key_t * ansikey;
struct tcaphash_context_t * context;
gboolean father;
struct tcaphash_ansicall_t * next_ansicall;
struct tcaphash_ansicall_t * previous_ansicall;
};
/** 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;
};
struct tcaphash_ansi_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;
};
/**
* Routine called when the TAP is initialized.
* so hash table are (re)created
*/
void tcapsrt_init_routine(void);
/**
* Initialize the Message Info used by the main dissector
* Data are linked to a TCAP transaction
*/
struct tcapsrt_info_t * tcapsrt_razinfo(void);
void tcapsrt_close(struct tcaphash_context_t * p_tcaphash_context,
packet_info * pinfo _U_);
/**
* Service Response Time analyze
* Called just after dissector call
* Associate a TCAP context to a tcap session and display session related infomations
* like the first frame, the last, the session duration,
* and a uniq session identifier for the filtering
*
* For ETSI tcap, the TCAP context can be reached through three keys
* - a key (BEGIN) identifying the session according to the tcap source identifier
* - a key (CONT) identifying the established session (src_id and dst_id)
* - a key (END) identifying the session according to the tcap destination identifier
*
* For ANSI tcap, the TCAP context is reached through a uniq key
* - a key (ANSI) identifying the session according to the tcap identifier
*/
struct tcaphash_context_t * tcapsrt_call_matching(tvbuff_t *tvb,
packet_info * pinfo _U_,
proto_tree *tree,
struct tcapsrt_info_t * p_tcap_info);
WS_DLL_PUBLIC gboolean gtcap_StatSRT;
#endif /* __tcapsrt_HASH__*/

View File

@ -37,7 +37,7 @@
#include "epan/value_string.h"
#include "epan/stat_cmd_args.h"
#include "epan/asn1.h"
#include "epan/camel-persistentdata.h"
#include "epan/dissectors/packet-camel.h"
void register_tap_listener_camelcounter(void);

View File

@ -35,7 +35,7 @@
#include "epan/value_string.h"
#include "epan/asn1.h"
#include "epan/dissectors/packet-camel.h"
#include "epan/camel-persistentdata.h"
#include "epan/dissectors/packet-tcap.h"
#include "epan/timestats.h"
#include "epan/stat_cmd_args.h"

View File

@ -35,7 +35,7 @@
#include <epan/tap.h>
#include <epan/packet.h>
#include <epan/asn1.h>
#include <epan/camel-persistentdata.h>
#include <epan/dissectors/packet-camel.h>
#include "../stat_menu.h"

View File

@ -34,7 +34,7 @@
#include <epan/tap.h>
#include <epan/packet.h>
#include <epan/asn1.h>
#include <epan/camel-persistentdata.h>
#include <epan/dissectors/packet-camel.h>
#include "../file.h"
#include "../stat_menu.h"