2 * camel-persistentdata.c
3 * Source for lists and hash tables used in wireshark's camel dissector
4 * for calculation of delays in camel calls
5 * Copyright 2006 Florent Drouin
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 #include <epan/emem.h>
37 #include "epan/packet.h"
39 #include <epan/asn1.h>
40 #include "epan/camel-persistentdata.h"
41 #include "epan/dissectors/packet-tcap.h"
42 #include "epan/dissectors/packet-mtp3.h"
44 const value_string camelSRTtype_naming[]= {
45 { CAMELSRT_SESSION, "TCAP_Session" },
46 { CAMELSRT_VOICE_INITIALDP, "InialDP/Continue" },
47 { CAMELSRT_VOICE_ACR1, "Slice1_ACR/ACH" },
48 { CAMELSRT_VOICE_ACR2, "Slice2_ACR/ACH" },
49 { CAMELSRT_VOICE_ACR3, "Slice3_ACR/ACH" },
50 { CAMELSRT_VOICE_DISC, "EvtRepBSCM/Release" },
51 { CAMELSRT_SMS_INITIALDP, "InitialDP/ContinueSMS" },
52 { CAMELSRT_GPRS_INITIALDP, "InitialDP/ContinueGPRS" },
53 { CAMELSRT_GPRS_REPORT, "EvtRepGPRS/ContinueGPRS" },
57 static gint camelsrt_call_equal(gconstpointer k1, gconstpointer k2);
58 static guint camelsrt_call_hash(gconstpointer k);
59 static struct camelsrt_call_t *find_camelsrt_call(struct camelsrt_call_info_key_t *p_camelsrt_call_key);
60 static struct camelsrt_call_t *new_camelsrt_call(struct camelsrt_call_info_key_t *p_camelsrt_call_key);
62 static void update_camelsrt_call(struct camelsrt_call_t *p_camelsrt_call,
63 packet_info *pinfo, guint msg_category);
65 static void camelsrt_begin_call_matching(packet_info *pinfo,
66 struct camelsrt_info_t *p_camelsrt_info);
68 static void camelsrt_request_call_matching(tvbuff_t *tvb, packet_info *pinfo,
70 struct camelsrt_info_t *p_camelsrt_info,
73 static void camelsrt_report_call_matching(tvbuff_t *tvb, packet_info *pinfo,
75 struct camelsrt_info_t *p_camelsrt_info,
78 static void camelsrt_close_call_matching(packet_info *pinfo,
79 struct camelsrt_info_t *p_camelsrt_info);
81 static void camelsrt_display_DeltaTime(proto_tree *tree, tvbuff_t *tvb,
82 nstime_t *value_ptr, guint category);
84 static void raz_camelsrt_call (struct camelsrt_call_t *p_camelsrt_call);
86 void camelsrt_tcap_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
87 struct tcaphash_context_t *tcap_context);
89 /* When several Camel components are received in a single TCAP message,
90 we have to use several buffers for the stored parameters
91 because else this data are erased during TAP dissector call */
92 #define MAX_CAMEL_INSTANCE 10
93 int camelsrt_global_current=0;
94 struct camelsrt_info_t camelsrt_global_info[MAX_CAMEL_INSTANCE];
96 /* Configuration parameters to enable or disable the Service Response Time */
97 extern gboolean gcamel_HandleSRT;
98 gboolean gcamel_PersistentSRT=FALSE;
99 gboolean gcamel_DisplaySRT=FALSE;
100 gboolean gcamel_StatSRT=FALSE;
102 extern int camel_tap;
104 extern int hf_camelsrt_SessionId;
105 extern int hf_camelsrt_RequestNumber;
106 extern int hf_camelsrt_Duplicate;
107 extern int hf_camelsrt_RequestFrame;
108 extern int hf_camelsrt_ResponseFrame;
109 extern int hf_camelsrt_DeltaTime;
110 extern int hf_camelsrt_SessionTime;
111 extern int hf_camelsrt_DeltaTime31;
112 extern int hf_camelsrt_DeltaTime75;
113 extern int hf_camelsrt_DeltaTime65;
114 extern int hf_camelsrt_DeltaTime22;
115 extern int hf_camelsrt_DeltaTime35;
116 extern int hf_camelsrt_DeltaTime80;
118 /* Global hash tables*/
119 static GHashTable *srt_calls = NULL;
120 guint32 camelsrt_global_SessionId=1;
126 #undef DEBUG_CAMELSRT
127 /* #define DEBUG_CAMELSRT */
129 #ifdef DEBUG_CAMELSRT
132 static unsigned debug_level = 99;
134 static void dbg(unsigned level, char *fmt, ...) {
137 if (level > debug_level) return;
139 vfprintf(stderr, fmt, ap);
145 * Functions needed for Hash-Table
150 camelsrt_call_equal(gconstpointer k1, gconstpointer k2)
152 const struct camelsrt_call_info_key_t *key1 = (const struct camelsrt_call_info_key_t *) k1;
153 const struct camelsrt_call_info_key_t *key2 = (const struct camelsrt_call_info_key_t *) k2;
155 return (key1->SessionIdKey == key2->SessionIdKey) ;
158 /* calculate a hash key */
160 camelsrt_call_hash(gconstpointer k)
162 const struct camelsrt_call_info_key_t *key = (const struct camelsrt_call_info_key_t *) k;
163 return key->SessionIdKey;
167 * Find the dialog by Key and Time
169 static struct camelsrt_call_t *
170 find_camelsrt_call(struct camelsrt_call_info_key_t *p_camelsrt_call_key)
172 struct camelsrt_call_t *p_camelsrt_call = NULL;
173 p_camelsrt_call = (struct camelsrt_call_t *)g_hash_table_lookup(srt_calls, p_camelsrt_call_key);
175 if(p_camelsrt_call) {
176 #ifdef DEBUG_CAMELSRT
177 dbg(10,"D%d ", p_camelsrt_call->session_id);
180 #ifdef DEBUG_CAMELSRT
181 dbg(23,"Not in hash ");
185 return p_camelsrt_call;
189 * New record to create, to identify a new transaction
191 static struct camelsrt_call_t *
192 new_camelsrt_call(struct camelsrt_call_info_key_t *p_camelsrt_call_key)
194 struct camelsrt_call_info_key_t *p_new_camelsrt_call_key;
195 struct camelsrt_call_t *p_new_camelsrt_call = NULL;
197 /* Register the transaction in the hash table
198 with the tcap transaction Id as main Key
199 Once created, this entry will be updated later */
201 p_new_camelsrt_call_key = se_alloc(sizeof(struct camelsrt_call_info_key_t));
202 p_new_camelsrt_call_key->SessionIdKey = p_camelsrt_call_key->SessionIdKey;
203 p_new_camelsrt_call = se_alloc(sizeof(struct camelsrt_call_t));
204 raz_camelsrt_call(p_new_camelsrt_call);
205 p_new_camelsrt_call->session_id = camelsrt_global_SessionId++;
206 #ifdef DEBUG_CAMELSRT
207 dbg(10,"D%d ", p_new_camelsrt_call->session_id);
210 g_hash_table_insert(srt_calls, p_new_camelsrt_call_key, p_new_camelsrt_call);
211 return p_new_camelsrt_call;
215 * Update a record with the data of the Request
218 update_camelsrt_call(struct camelsrt_call_t *p_camelsrt_call, packet_info *pinfo,
221 p_camelsrt_call->category[msg_category].req_num = pinfo->fd->num;
222 p_camelsrt_call->category[msg_category].rsp_num = 0;
223 p_camelsrt_call->category[msg_category].responded = FALSE;
224 p_camelsrt_call->category[msg_category].req_time = pinfo->fd->abs_ts;
229 * Routine called when the TAP is initialized.
230 * so hash table are (re)created
233 camelsrt_init_routine(void)
236 /* free hash-tables and mem_chunks for SRT */
237 if (srt_calls != NULL) {
238 #ifdef DEBUG_CAMELSRT
239 dbg(16,"Destroy hash ");
241 g_hash_table_destroy(srt_calls);
244 /* create new hash-tables and mem_chunks for SRT */
245 srt_calls = g_hash_table_new(camelsrt_call_hash, camelsrt_call_equal);
246 #ifdef DEBUG_CAMELSRT
247 dbg(16,"Create hash ");
249 /* Reset the session counter */
250 camelsrt_global_SessionId=1;
252 /* The Display of SRT is enable
253 * 1) For wireshark only if Persistent Stat is enable
254 * 2) For Tshark, if the SRT handling is enable
256 gcamel_DisplaySRT=gcamel_PersistentSRT || gcamel_HandleSRT&gcamel_StatSRT;
260 * Service Response Time analyze, called just after the camel dissector
261 * According to the camel operation, we
262 * - open/close a context for the camel session
263 * - look for a request, or look for the corresponding response
266 camelsrt_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
267 struct camelsrt_info_t *p_camelsrt_info)
270 #ifdef DEBUG_CAMELSRT
271 dbg(10,"tcap_session #%d ", p_camelsrt_info->tcap_session_id);
274 switch (p_camelsrt_info->opcode) {
276 case 0: /*InitialDP*/
277 camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
278 camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
279 CAMELSRT_VOICE_INITIALDP);
281 case 60: /*InitialDPSMS*/
282 camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
283 camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
284 CAMELSRT_SMS_INITIALDP);
286 case 78: /*InitialDPGPRS*/
287 camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
288 camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
289 CAMELSRT_GPRS_INITIALDP);
292 case 23: /*RequestReportBCSMEvent*/
295 case 63: /*RequestReportSMSEvent*/
298 case 81: /*RequestReportGPRSEvent*/
301 case 24: /*EventReportBCSMEvent*/
302 camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
303 CAMELSRT_VOICE_DISC );
306 case 64: /*EventReportSMS*/
307 /* Session has been explicity closed without TC_END */
308 camelsrt_close_call_matching(pinfo, p_camelsrt_info);
309 tcapsrt_close(p_camelsrt_info->tcap_context, pinfo);
312 case 80: /*EventReportGPRS*/
313 camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
314 camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
315 CAMELSRT_GPRS_REPORT);
318 case 35: /*ApplyCharging*/
319 camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
320 CAMELSRT_VOICE_ACR1 );
323 case 71: /*ApplyChargingGPRS*/
326 case 36: /*ApplyChargingReport*/
327 camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
328 CAMELSRT_VOICE_ACR1 );
331 case 72: /*ApplyChargingReportGPRS*/
334 case 31: /*Continue*/
335 camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
336 CAMELSRT_VOICE_INITIALDP);
338 case 65: /*ContinueSMS*/
339 camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
340 CAMELSRT_SMS_INITIALDP);
342 case 75: /*ContinueGPRS*/
343 camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
344 CAMELSRT_GPRS_INITIALDP);
345 camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
346 CAMELSRT_GPRS_REPORT);
349 case 22: /*ReleaseCall*/
350 camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
351 CAMELSRT_VOICE_DISC);
352 /* Session has been closed by Network */
353 camelsrt_close_call_matching(pinfo, p_camelsrt_info);
356 case 66: /*ReleaseSMS*/
357 /* Session has been closed by Network */
358 camelsrt_close_call_matching(pinfo, p_camelsrt_info);
359 tcapsrt_close(p_camelsrt_info->tcap_context,pinfo);
362 case 79: /*ReleaseGPRS*/
363 /* Session has been closed by Network */
364 camelsrt_close_call_matching(pinfo, p_camelsrt_info);
366 } /* switch opcode */
370 * Callback function for the TCAP dissector
371 * This callback function is used to inform the camel layer, that the session
372 * has been Closed or Aborted by a TCAP message without Camel component
373 * So, we can close the context for camel session, and update the stats.
376 camelsrt_tcap_matching(tvbuff_t *tvb _U_, packet_info *pinfo,
377 proto_tree *tree _U_,
378 struct tcaphash_context_t *p_tcap_context)
380 struct camelsrt_info_t *p_camelsrt_info;
382 #ifdef DEBUG_CAMELSRT
383 dbg(11,"Camel_CallBack ");
385 p_camelsrt_info=camelsrt_razinfo();
387 p_camelsrt_info->tcap_context=p_tcap_context;
388 if (p_tcap_context) {
389 #ifdef DEBUG_CAMELSRT
390 dbg(11,"Close TCAP ");
392 p_camelsrt_info->tcap_session_id = p_tcap_context->session_id;
393 camelsrt_close_call_matching(pinfo, p_camelsrt_info);
394 tap_queue_packet(camel_tap, pinfo, p_camelsrt_info);
400 * Create the record identifiying the Camel session
401 * As the Tcap session id given by the TCAP dissector is uniq, it will be
405 camelsrt_begin_call_matching(packet_info *pinfo,
406 struct camelsrt_info_t *p_camelsrt_info)
408 struct camelsrt_call_t *p_camelsrt_call;
409 struct camelsrt_call_info_key_t camelsrt_call_key;
411 p_camelsrt_info->bool_msginfo[CAMELSRT_SESSION]=TRUE;
413 /* prepare the key data */
414 camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
416 /* look up the request */
417 #ifdef DEBUG_CAMELSRT
418 dbg(10,"\n Session begin #%u\n", pinfo->fd->num);
419 dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
421 p_camelsrt_call = (struct camelsrt_call_t *)g_hash_table_lookup(srt_calls, &camelsrt_call_key);
422 if (p_camelsrt_call) {
423 /* We have seen this request before -> do nothing */
424 #ifdef DEBUG_CAMELSRT
425 dbg(22,"Already seen ");
427 } else { /* p_camelsrt_call has not been found */
428 #ifdef DEBUG_CAMELSRT
429 dbg(10,"New key %lu ",camelsrt_call_key.SessionIdKey);
431 p_camelsrt_call = new_camelsrt_call(&camelsrt_call_key);
432 p_camelsrt_call->tcap_context=p_camelsrt_info->tcap_context;
433 update_camelsrt_call(p_camelsrt_call, pinfo,CAMELSRT_SESSION);
435 #ifdef DEBUG_CAMELSRT
436 dbg(11,"Update Callback ");
438 p_camelsrt_call->tcap_context->callback=camelsrt_tcap_matching;
443 * Register the request, and try to find the response
447 camelsrt_request_call_matching(tvbuff_t *tvb, packet_info *pinfo,
449 struct camelsrt_info_t *p_camelsrt_info,
452 struct camelsrt_call_t *p_camelsrt_call;
453 struct camelsrt_call_info_key_t camelsrt_call_key;
454 proto_item *ti, *hidden_item;
456 #ifdef DEBUG_CAMELSRT
457 dbg(10,"\n %s #%u\n", val_to_str(srt_type, camelSRTtype_naming, "Unk"),pinfo->fd->num);
460 /* look only for matching request, if matching conversation is available. */
461 camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
463 #ifdef DEBUG_CAMELSRT
464 dbg(11,"Search key %lu ", camelsrt_call_key.SessionIdKey);
466 p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key);
467 if(p_camelsrt_call) {
468 #ifdef DEBUG_CAMELSRT
471 if (gcamel_DisplaySRT)
472 proto_tree_add_uint(tree, hf_camelsrt_SessionId, tvb, 0,0, p_camelsrt_call->session_id);
475 /* Hmm.. As there are several slices ApplyChargingReport/ApplyCharging
476 * we will prepare the measurement for 3 slices with 3 categories */
477 if (srt_type==CAMELSRT_VOICE_ACR1) {
478 if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num == 0) {
479 srt_type=CAMELSRT_VOICE_ACR1;
480 } else if ( (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num == 0)
481 && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0)
482 && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num < pinfo->fd->num) ) {
483 srt_type=CAMELSRT_VOICE_ACR2;
484 } else if ( (p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num == 0)
485 && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num != 0)
486 && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num < pinfo->fd->num) ) {
487 srt_type=CAMELSRT_VOICE_ACR3;
488 } else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0
489 && p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num > pinfo->fd->num) {
490 srt_type=CAMELSRT_VOICE_ACR1;
491 } else if ( p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num != 0
492 && p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num > pinfo->fd->num) {
493 srt_type=CAMELSRT_VOICE_ACR2;
494 } else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0
495 && p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].rsp_num > pinfo->fd->num) {
496 srt_type=CAMELSRT_VOICE_ACR3;
498 #ifdef DEBUG_CAMELSRT
499 dbg(70,"Request ACR %u ",srt_type);
500 dbg(70,"ACR1 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num);
501 dbg(70,"ACR2 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num);
502 dbg(70,"ACR3 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].rsp_num);
505 p_camelsrt_info->bool_msginfo[srt_type]=TRUE;
508 if (p_camelsrt_call->category[srt_type].req_num == 0) {
509 /* We have not yet seen a request to that call, so this must be the first request
510 remember its frame number. */
511 #ifdef DEBUG_CAMELSRT
512 dbg(5,"Set reqlink #%u ", pinfo->fd->num);
514 update_camelsrt_call(p_camelsrt_call, pinfo, srt_type);
516 /* We have seen a request to this call - but was it *this* request? */
517 if (p_camelsrt_call->category[srt_type].req_num != pinfo->fd->num) {
519 if (srt_type!=CAMELSRT_VOICE_DISC) {
520 /* No, so it's a duplicate resquest. Mark it as such. */
521 #ifdef DEBUG_CAMELSRT
522 dbg(21,"Display_duplicate with req %d ", p_camelsrt_call->category[srt_type].req_num);
524 p_camelsrt_info->msginfo[srt_type].is_duplicate = TRUE;
525 if (gcamel_DisplaySRT){
526 hidden_item = proto_tree_add_uint(tree, hf_camelsrt_Duplicate, tvb, 0,0, 77);
527 PROTO_ITEM_SET_HIDDEN(hidden_item);
531 /* Ignore duplicate frame */
532 if (pinfo->fd->num > p_camelsrt_call->category[srt_type].req_num) {
533 p_camelsrt_call->category[srt_type].req_num = pinfo->fd->num;
534 #ifdef DEBUG_CAMELSRT
535 dbg(5,"DISC Set reqlink #%u ", pinfo->fd->num);
537 update_camelsrt_call(p_camelsrt_call, pinfo, srt_type);
538 } /* greater frame */
540 } /* req_num already seen */
543 /* add link to response frame, if available */
544 if ( gcamel_DisplaySRT &&
545 (p_camelsrt_call->category[srt_type].rsp_num != 0) &&
546 (p_camelsrt_call->category[srt_type].req_num != 0) &&
547 (p_camelsrt_call->category[srt_type].req_num == pinfo->fd->num) ) {
548 #ifdef DEBUG_CAMELSRT
549 dbg(20,"Display_framersplink %d ",p_camelsrt_call->category[srt_type].rsp_num);
551 ti = proto_tree_add_uint_format(tree, hf_camelsrt_RequestFrame, tvb, 0, 0,
552 p_camelsrt_call->category[srt_type].rsp_num,
553 "Linked response %s in frame %u",
554 val_to_str(srt_type, camelSRTtype_naming, "Unk"),
555 p_camelsrt_call->category[srt_type].rsp_num);
556 PROTO_ITEM_SET_GENERATED(ti);
558 } /* call reference */
563 * Check if the received message is a response to a previous request
564 * registered is the camel session context.
567 camelsrt_report_call_matching(tvbuff_t *tvb, packet_info *pinfo,
569 struct camelsrt_info_t *p_camelsrt_info,
572 struct camelsrt_call_t *p_camelsrt_call;
573 struct camelsrt_call_info_key_t camelsrt_call_key;
575 proto_item *ti, *hidden_item;
577 #ifdef DEBUG_CAMELSRT
578 dbg(10,"\n %s #%u\n", val_to_str(srt_type, camelSRTtype_naming, "Unk"),pinfo->fd->num);
580 camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
581 /* look only for matching request, if matching conversation is available. */
583 #ifdef DEBUG_CAMELSRT
584 dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
586 p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key);
587 if(p_camelsrt_call) {
588 #ifdef DEBUG_CAMELSRT
589 dbg(12,"Found, req=%d ",p_camelsrt_call->category[srt_type].req_num);
591 if ( gcamel_DisplaySRT )
592 proto_tree_add_uint(tree, hf_camelsrt_SessionId, tvb, 0,0, p_camelsrt_call->session_id);
594 if (srt_type==CAMELSRT_VOICE_ACR1) {
595 if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num != 0
596 && p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num < pinfo->fd->num) {
597 srt_type=CAMELSRT_VOICE_ACR1;
598 } else if ( p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num != 0
599 && p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num < pinfo->fd->num) {
600 srt_type=CAMELSRT_VOICE_ACR2;
601 } else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num != 0
602 && p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num < pinfo->fd->num) {
603 srt_type=CAMELSRT_VOICE_ACR1;
605 #ifdef DEBUG_CAMELSRT
606 dbg(70,"Report ACR %u ",srt_type);
609 p_camelsrt_info->bool_msginfo[srt_type]=TRUE;
611 if (p_camelsrt_call->category[srt_type].rsp_num == 0) {
612 if ( (p_camelsrt_call->category[srt_type].req_num != 0)
613 && (pinfo->fd->num > p_camelsrt_call->category[srt_type].req_num) ){
614 /* We have not yet seen a response to that call, so this must be the first response;
615 remember its frame number only if response comes after request */
616 #ifdef DEBUG_CAMELSRT
617 dbg(14,"Set reslink #%d req %u ",pinfo->fd->num, p_camelsrt_call->category[srt_type].req_num);
619 p_camelsrt_call->category[srt_type].rsp_num = pinfo->fd->num;
622 #ifdef DEBUG_CAMELSRT
623 dbg(2,"badreslink #%u req %u ",pinfo->fd->num, p_camelsrt_call->category[srt_type].req_num);
626 } else { /* rsp_num != 0 */
627 /* We have seen a response to this call - but was it *this* response? */
628 if (p_camelsrt_call->category[srt_type].rsp_num != pinfo->fd->num) {
629 /* No, so it's a duplicate response. Mark it as such. */
630 #ifdef DEBUG_CAMELSRT
631 dbg(21,"Display_duplicate rsp=%d ", p_camelsrt_call->category[srt_type].rsp_num);
633 p_camelsrt_info->msginfo[srt_type].is_duplicate = TRUE;
634 if ( gcamel_DisplaySRT ){
635 hidden_item = proto_tree_add_uint(tree, hf_camelsrt_Duplicate, tvb, 0,0, 77);
636 PROTO_ITEM_SET_HIDDEN(hidden_item);
641 if ( (p_camelsrt_call->category[srt_type].req_num != 0) &&
642 (p_camelsrt_call->category[srt_type].rsp_num != 0) &&
643 (p_camelsrt_call->category[srt_type].rsp_num == pinfo->fd->num) ) {
645 p_camelsrt_call->category[srt_type].responded = TRUE;
646 p_camelsrt_info->msginfo[srt_type].request_available = TRUE;
647 #ifdef DEBUG_CAMELSRT
648 dbg(20,"Display_frameReqlink %d ",p_camelsrt_call->category[srt_type].req_num);
650 /* Indicate the frame to which this is a reply. */
651 if ( gcamel_DisplaySRT ) {
652 ti = proto_tree_add_uint_format(tree, hf_camelsrt_ResponseFrame, tvb, 0, 0,
653 p_camelsrt_call->category[srt_type].req_num,
654 "Linked request %s in frame %u",
655 val_to_str(srt_type, camelSRTtype_naming, "Unk"),
656 p_camelsrt_call->category[srt_type].req_num);
657 PROTO_ITEM_SET_GENERATED(ti);
659 /* Calculate Service Response Time */
660 nstime_delta(&delta, &pinfo->fd->abs_ts, &p_camelsrt_call->category[srt_type].req_time);
662 p_camelsrt_info->msginfo[srt_type].is_delta_time = TRUE;
663 p_camelsrt_info->msginfo[srt_type].delta_time = delta; /* give it to tap */
664 p_camelsrt_info->msginfo[srt_type].req_time = p_camelsrt_call->category[srt_type].req_time;
666 /* display Service Response Time and make it filterable */
667 camelsrt_display_DeltaTime(tree, tvb, &delta, srt_type);
669 } /*req_num != 0 && not duplicate */
670 } /* call reference found */
674 * Update the Camel session info, and close the session.
675 * Then remove the associated context, if we do not have persistentSRT enable
678 camelsrt_close_call_matching(packet_info *pinfo,
679 struct camelsrt_info_t *p_camelsrt_info)
681 struct camelsrt_call_t *p_camelsrt_call;
682 struct camelsrt_call_info_key_t camelsrt_call_key;
685 p_camelsrt_info->bool_msginfo[CAMELSRT_SESSION]=TRUE;
686 #ifdef DEBUG_CAMELSRT
687 dbg(10,"\n Session end #%u\n", pinfo->fd->num);
689 /* look only for matching request, if matching conversation is available. */
690 camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
692 #ifdef DEBUG_CAMELSRT
693 dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
695 p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key);
696 if(p_camelsrt_call) {
697 #ifdef DEBUG_CAMELSRT
700 /* Calculate Service Response Time */
701 nstime_delta(&delta, &pinfo->fd->abs_ts, &p_camelsrt_call->category[CAMELSRT_SESSION].req_time);
702 p_camelsrt_call->category[CAMELSRT_SESSION].responded = TRUE;
703 p_camelsrt_info->msginfo[CAMELSRT_SESSION].request_available = TRUE;
704 p_camelsrt_info->msginfo[CAMELSRT_SESSION].is_delta_time = TRUE;
705 p_camelsrt_info->msginfo[CAMELSRT_SESSION].delta_time = delta; /* give it to tap */
706 p_camelsrt_info->msginfo[CAMELSRT_SESSION].req_time = p_camelsrt_call->category[CAMELSRT_SESSION].req_time;
708 if ( !gcamel_PersistentSRT ) {
709 g_hash_table_remove(srt_calls, &camelsrt_call_key);
710 #ifdef DEBUG_CAMELSRT
711 dbg(20,"remove hash ");
714 #ifdef DEBUG_CAMELSRT
715 dbg(20,"keep hash ");
718 } /* call reference found */
722 * Display the delta time between two messages in a field corresponding
723 * to the category (hf_camelsrt_DeltaTimexx).
726 camelsrt_display_DeltaTime(proto_tree *tree, tvbuff_t *tvb, nstime_t *value_ptr,
731 if ( gcamel_DisplaySRT ) {
733 case CAMELSRT_VOICE_INITIALDP:
734 ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime31, tvb, 0, 0, value_ptr);
735 PROTO_ITEM_SET_GENERATED(ti);
738 case CAMELSRT_VOICE_ACR1:
739 case CAMELSRT_VOICE_ACR2:
740 case CAMELSRT_VOICE_ACR3:
741 ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime22, tvb, 0, 0, value_ptr);
742 PROTO_ITEM_SET_GENERATED(ti);
745 case CAMELSRT_VOICE_DISC:
746 ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime35, tvb, 0, 0, value_ptr);
747 PROTO_ITEM_SET_GENERATED(ti);
750 case CAMELSRT_GPRS_INITIALDP:
751 ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime75, tvb, 0, 0, value_ptr);
752 PROTO_ITEM_SET_GENERATED(ti);
755 case CAMELSRT_GPRS_REPORT:
756 ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime80, tvb, 0, 0, value_ptr);
757 PROTO_ITEM_SET_GENERATED(ti);
760 case CAMELSRT_SMS_INITIALDP:
761 ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime65, tvb, 0, 0, value_ptr);
762 PROTO_ITEM_SET_GENERATED(ti);
772 * Initialize the Message Info used by the main dissector
773 * Data are linked to a TCAP transaction
775 struct camelsrt_info_t *
776 camelsrt_razinfo(void)
778 struct camelsrt_info_t *p_camelsrt_info ;
780 /* Global buffer for packet extraction */
781 camelsrt_global_current++;
782 if(camelsrt_global_current==MAX_CAMEL_INSTANCE){
783 camelsrt_global_current=0;
786 p_camelsrt_info=&camelsrt_global_info[camelsrt_global_current];
787 memset(p_camelsrt_info,0,sizeof(struct camelsrt_info_t));
789 p_camelsrt_info->opcode=255;
791 return p_camelsrt_info;
795 * Initialize the data per call for the Service Response Time Statistics
796 * Data are linked to a Camel operation in a TCAP transaction
799 raz_camelsrt_call (struct camelsrt_call_t *p_camelsrt_call)
801 memset(p_camelsrt_call,0,sizeof(struct camelsrt_call_t));