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
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 #include <epan/emem.h>
35 #include "epan/packet.h"
36 #include "epan/conversation.h"
38 #include "epan/camel-persistentdata.h"
39 #include "epan/dissectors/packet-tcap.h"
40 #include "epan/dissectors/packet-mtp3.h"
42 const value_string camelSRTtype_naming[]= {
43 { CAMELSRT_SESSION, "TCAP_Session" },
44 { CAMELSRT_VOICE_INITIALDP, "InialDP/Continue" },
45 { CAMELSRT_VOICE_ACR1, "Slice1_ACR/ACH" },
46 { CAMELSRT_VOICE_ACR2, "Slice2_ACR/ACH" },
47 { CAMELSRT_VOICE_ACR3, "Slice3_ACR/ACH" },
48 { CAMELSRT_VOICE_DISC, "EvtRepBSCM/Release" },
49 { CAMELSRT_SMS_INITIALDP, "InitialDP/ContinueSMS" },
50 { CAMELSRT_GPRS_INITIALDP, "InitialDP/ContinueGPRS" },
51 { CAMELSRT_GPRS_REPORT, "EvtRepGPRS/ContinueGPRS" },
55 static gint camelsrt_call_equal(gconstpointer k1, gconstpointer k2);
56 static guint camelsrt_call_hash(gconstpointer k);
57 static struct camelsrt_call_t * find_camelsrt_call(struct camelsrt_call_info_key_t * p_camelsrt_call_key,
59 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,
64 guint msg_category _U_);
66 static void camelsrt_begin_call_matching(tvbuff_t *tvb,
67 packet_info * pinfo _U_,
69 struct camelsrt_info_t * p_camelsrt_info);
71 static void camelsrt_request_call_matching(tvbuff_t *tvb,
72 packet_info * pinfo _U_,
74 struct camelsrt_info_t * p_camelsrt_info,
77 static void camelsrt_report_call_matching(tvbuff_t *tvb,
78 packet_info * pinfo _U_,
80 struct camelsrt_info_t * p_camelsrt_info,
83 static void camelsrt_close_call_matching(tvbuff_t *tvb,
84 packet_info * pinfo _U_,
86 struct camelsrt_info_t * p_camelsrt_info);
88 static void camelsrt_display_DeltaTime(proto_tree *tree,
93 static void raz_camelsrt_call (struct camelsrt_call_t * p_camelsrt_call);
95 void camelsrt_tcap_matching(tvbuff_t *tvb,
96 packet_info * pinfo _U_,
98 struct tcaphash_context_t * tcap_context);
100 /* When several Camel components are received in a single TCAP message,
101 we have to use several buffers for the stored parameters
102 because else this data are erased during TAP dissector call */
103 #define MAX_CAMEL_INSTANCE 10
104 int camelsrt_global_current=0;
105 struct camelsrt_info_t camelsrt_global_info[MAX_CAMEL_INSTANCE];
107 /* Configuration parameters to enable or disable the Service Response Time */
108 extern gboolean gcamel_HandleSRT;
109 gboolean gcamel_PersistentSRT=FALSE;
110 gboolean gcamel_DisplaySRT=FALSE;
111 gboolean gcamel_StatSRT=FALSE;
113 extern int camel_tap;
115 extern int hf_camelsrt_SessionId;
116 extern int hf_camelsrt_RequestNumber;
117 extern int hf_camelsrt_Duplicate;
118 extern int hf_camelsrt_RequestFrame;
119 extern int hf_camelsrt_ResponseFrame;
120 extern int hf_camelsrt_DeltaTime;
121 extern int hf_camelsrt_SessionTime;
122 extern int hf_camelsrt_DeltaTime31;
123 extern int hf_camelsrt_DeltaTime75;
124 extern int hf_camelsrt_DeltaTime65;
125 extern int hf_camelsrt_DeltaTime22;
126 extern int hf_camelsrt_DeltaTime35;
127 extern int hf_camelsrt_DeltaTime80;
129 /* Global hash tables*/
130 static GHashTable *srt_calls = NULL;
131 guint32 camelsrt_global_SessionId=1;
137 #undef DEBUG_CAMELSRT
138 /* #define DEBUG_CAMELSRT */
140 #ifdef DEBUG_CAMELSRT
143 static unsigned debug_level = 99;
145 static void dbg(unsigned level, char* fmt, ...) {
148 if (level > debug_level) return;
150 vfprintf(stderr, fmt, ap);
156 * Functions needed for Hash-Table
160 static gint camelsrt_call_equal(gconstpointer k1, gconstpointer k2)
162 const struct camelsrt_call_info_key_t * key1 = (const struct camelsrt_call_info_key_t *) k1;
163 const struct camelsrt_call_info_key_t * key2 = (const struct camelsrt_call_info_key_t *) k2;
165 return (key1->SessionIdKey == key2->SessionIdKey) ;
168 /* calculate a hash key */
169 static guint camelsrt_call_hash(gconstpointer k)
171 const struct camelsrt_call_info_key_t * key = (const struct camelsrt_call_info_key_t *) k;
172 return key->SessionIdKey;
176 * Find the dialog by Key and Time
178 static struct camelsrt_call_t * find_camelsrt_call(struct camelsrt_call_info_key_t * p_camelsrt_call_key,
181 struct camelsrt_call_t * p_camelsrt_call = NULL;
182 p_camelsrt_call = (struct camelsrt_call_t *)g_hash_table_lookup(srt_calls, p_camelsrt_call_key);
184 if(p_camelsrt_call) {
185 #ifdef DEBUG_CAMELSRT
186 dbg(10,"D%d ", p_camelsrt_call->session_id);
189 #ifdef DEBUG_CAMELSRT
190 dbg(23,"Not in hash ");
194 return p_camelsrt_call;
198 * New record to create, to identify a new transaction
200 static struct camelsrt_call_t * new_camelsrt_call(struct camelsrt_call_info_key_t * p_camelsrt_call_key,
204 struct camelsrt_call_info_key_t * p_new_camelsrt_call_key;
205 struct camelsrt_call_t * p_new_camelsrt_call = NULL;
207 /* Register the transaction in the hash table
208 with the tcap transaction Id as main Key
209 Once created, this entry will be updated later */
211 p_new_camelsrt_call_key = se_alloc(sizeof(struct camelsrt_call_info_key_t));
212 p_new_camelsrt_call_key->SessionIdKey = p_camelsrt_call_key->SessionIdKey;
213 p_new_camelsrt_call = se_alloc(sizeof(struct camelsrt_call_t));
214 raz_camelsrt_call(p_new_camelsrt_call);
215 p_new_camelsrt_call->session_id = camelsrt_global_SessionId++;
216 #ifdef DEBUG_CAMELSRT
217 dbg(10,"D%d ", p_new_camelsrt_call->session_id);
220 g_hash_table_insert(srt_calls, p_new_camelsrt_call_key, p_new_camelsrt_call);
221 return p_new_camelsrt_call;
225 * Update a record with the data of the Request
227 static void update_camelsrt_call(struct camelsrt_call_t * p_camelsrt_call,
229 guint msg_category _U_)
231 p_camelsrt_call->category[msg_category].req_num = pinfo->fd->num;
232 p_camelsrt_call->category[msg_category].rsp_num = 0;
233 p_camelsrt_call->category[msg_category].responded = FALSE;
234 p_camelsrt_call->category[msg_category].req_time = pinfo->fd->abs_ts;
239 * Routine called when the TAP is initialized.
240 * so hash table are (re)created
242 void camelsrt_init_routine(void)
245 /* free hash-tables and mem_chunks for SRT */
246 if (srt_calls != NULL) {
247 #ifdef DEBUG_CAMELSRT
248 dbg(16,"Destroy hash ");
250 g_hash_table_destroy(srt_calls);
253 /* create new hash-tables and mem_chunks for SRT */
254 srt_calls = g_hash_table_new(camelsrt_call_hash, camelsrt_call_equal);
255 #ifdef DEBUG_CAMELSRT
256 dbg(16,"Create hash ");
258 /* Reset the session counter */
259 camelsrt_global_SessionId=1;
261 /* The Display of SRT is enable
262 * 1) For wireshark only if Persistent Stat is enable
263 * 2) For Tshark, if the SRT handling is enable
265 gcamel_DisplaySRT=gcamel_PersistentSRT || gcamel_HandleSRT&gcamel_StatSRT;
269 * Service Response Time analyze, called just after the camel dissector
270 * According to the camel operation, we
271 * - open/close a context for the camel session
272 * - look for a request, or look for the corresponding response
274 void camelsrt_call_matching(tvbuff_t *tvb,
275 packet_info * pinfo _U_,
277 struct camelsrt_info_t * p_camelsrt_info)
280 #ifdef DEBUG_CAMELSRT
281 dbg(10,"tcap_session #%d ", p_camelsrt_info->tcap_session_id);
284 switch (p_camelsrt_info->opcode) {
286 case 0: /*InitialDP*/
287 camelsrt_begin_call_matching(tvb, pinfo, tree, p_camelsrt_info);
288 camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
289 CAMELSRT_VOICE_INITIALDP);
291 case 60: /*InitialDPSMS*/
292 camelsrt_begin_call_matching(tvb, pinfo, tree, p_camelsrt_info);
293 camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
294 CAMELSRT_SMS_INITIALDP);
296 case 78: /*InitialDPGPRS*/
297 camelsrt_begin_call_matching(tvb, pinfo, tree, p_camelsrt_info);
298 camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
299 CAMELSRT_GPRS_INITIALDP);
302 case 23: /*RequestReportBCSMEvent*/
305 case 63: /*RequestReportSMSEvent*/
308 case 81: /*RequestReportGPRSEvent*/
311 case 24: /*EventReportBCSMEvent*/
312 camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
313 CAMELSRT_VOICE_DISC );
316 case 64: /*EventReportSMS*/
317 /* Session has been explicity closed without TC_END */
318 camelsrt_close_call_matching(tvb, pinfo, tree, p_camelsrt_info);
319 tcapsrt_close(p_camelsrt_info->tcap_context, pinfo);
322 case 80: /*EventReportGPRS*/
323 camelsrt_begin_call_matching(tvb, pinfo, tree, p_camelsrt_info);
324 camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
325 CAMELSRT_GPRS_REPORT);
328 case 35: /*ApplyCharging*/
329 camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
330 CAMELSRT_VOICE_ACR1 );
333 case 71: /*ApplyChargingGPRS*/
336 case 36: /*ApplyChargingReport*/
337 camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
338 CAMELSRT_VOICE_ACR1 );
341 case 72: /*ApplyChargingReportGPRS*/
344 case 31: /*Continue*/
345 camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
346 CAMELSRT_VOICE_INITIALDP);
348 case 65: /*ContinueSMS*/
349 camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
350 CAMELSRT_SMS_INITIALDP);
352 case 75: /*ContinueGPRS*/
353 camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
354 CAMELSRT_GPRS_INITIALDP);
355 camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
356 CAMELSRT_GPRS_REPORT);
359 case 22: /*ReleaseCall*/
360 camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
361 CAMELSRT_VOICE_DISC);
362 /* Session has been closed by Network */
363 camelsrt_close_call_matching(tvb, pinfo, tree, p_camelsrt_info);
366 case 66: /*ReleaseSMS*/
367 /* Session has been closed by Network */
368 camelsrt_close_call_matching(tvb, pinfo, tree, p_camelsrt_info);
369 tcapsrt_close(p_camelsrt_info->tcap_context,pinfo);
372 case 79: /*ReleaseGPRS*/
373 /* Session has been closed by Network */
374 camelsrt_close_call_matching(tvb, pinfo, tree, p_camelsrt_info);
376 } /* switch opcode */
380 * Callback function for the TCAP dissector
381 * This callback function is used to inform the camel layer, that the session
382 * has been Closed or Aborted by a TCAP message without Camel component
383 * So, we can close the context for camel session, and update the stats.
385 void camelsrt_tcap_matching(tvbuff_t *tvb,
386 packet_info * pinfo _U_,
388 struct tcaphash_context_t * p_tcap_context)
390 struct camelsrt_info_t * p_camelsrt_info;
392 #ifdef DEBUG_CAMELSRT
393 dbg(11,"Camel_CallBack ");
395 p_camelsrt_info=camelsrt_razinfo();
397 p_camelsrt_info->tcap_context=p_tcap_context;
398 if (p_tcap_context) {
399 #ifdef DEBUG_CAMELSRT
400 dbg(11,"Close TCAP ");
402 p_camelsrt_info->tcap_session_id = p_tcap_context->session_id;
403 camelsrt_close_call_matching(tvb, pinfo, tree, p_camelsrt_info);
404 tap_queue_packet(camel_tap, pinfo, p_camelsrt_info);
410 * Create the record identifiying the Camel session
411 * As the Tcap session id given by the TCAP dissector is uniq, it will be
414 static void camelsrt_begin_call_matching(tvbuff_t *tvb,
415 packet_info * pinfo _U_,
417 struct camelsrt_info_t * p_camelsrt_info)
419 struct camelsrt_call_t * p_camelsrt_call;
420 struct camelsrt_call_info_key_t camelsrt_call_key;
422 p_camelsrt_info->bool_msginfo[CAMELSRT_SESSION]=TRUE;
424 /* prepare the key data */
425 camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
427 /* look up the request */
428 #ifdef DEBUG_CAMELSRT
429 dbg(10,"\n Session begin #%d\n", pinfo->fd->num);
430 dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
432 p_camelsrt_call = (struct camelsrt_call_t *)g_hash_table_lookup(srt_calls, &camelsrt_call_key);
433 if (p_camelsrt_call) {
434 /* We have seen this request before -> do nothing */
435 #ifdef DEBUG_CAMELSRT
436 dbg(22,"Already seen ");
438 } else { /* p_camelsrt_call has not been found */
439 #ifdef DEBUG_CAMELSRT
440 dbg(10,"New key %lu ",camelsrt_call_key.SessionIdKey);
442 p_camelsrt_call = new_camelsrt_call(&camelsrt_call_key, pinfo);
443 p_camelsrt_call->tcap_context=p_camelsrt_info->tcap_context;
444 update_camelsrt_call(p_camelsrt_call, pinfo,CAMELSRT_SESSION);
446 #ifdef DEBUG_CAMELSRT
447 dbg(11,"Update Callback ");
449 p_camelsrt_call->tcap_context->callback=camelsrt_tcap_matching;
454 * Register the request, and try to find the response
457 static void camelsrt_request_call_matching(tvbuff_t *tvb,
458 packet_info * pinfo _U_,
460 struct camelsrt_info_t * p_camelsrt_info,
463 struct camelsrt_call_t * p_camelsrt_call;
464 struct camelsrt_call_info_key_t camelsrt_call_key;
467 #ifdef DEBUG_CAMELSRT
468 dbg(10,"\n %s #%d\n", val_to_str(srt_type, camelSRTtype_naming, "Unk"),pinfo->fd->num);
471 /* look only for matching request, if matching conversation is available. */
472 camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
474 #ifdef DEBUG_CAMELSRT
475 dbg(11,"Search key %lu ", camelsrt_call_key.SessionIdKey);
477 p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key, pinfo);
478 if(p_camelsrt_call) {
479 #ifdef DEBUG_CAMELSRT
482 if (gcamel_DisplaySRT)
483 proto_tree_add_uint(tree, hf_camelsrt_SessionId, tvb, 0,0, p_camelsrt_call->session_id);
486 /* Hmm.. As there are several slices ApplyChargingReport/ApplyCharging
487 * we will prepare the measurement for 3 slices with 3 categories */
488 if (srt_type==CAMELSRT_VOICE_ACR1) {
489 if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num == 0) {
490 srt_type=CAMELSRT_VOICE_ACR1;
491 } else if ( (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num == 0)
492 && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0)
493 && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num < pinfo->fd->num) ) {
494 srt_type=CAMELSRT_VOICE_ACR2;
495 } else if ( (p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num == 0)
496 && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num != 0)
497 && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num < pinfo->fd->num) ) {
498 srt_type=CAMELSRT_VOICE_ACR3;
499 } else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0
500 && p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num > pinfo->fd->num) {
501 srt_type=CAMELSRT_VOICE_ACR1;
502 } else if ( p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num != 0
503 && p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num > pinfo->fd->num) {
504 srt_type=CAMELSRT_VOICE_ACR2;
505 } else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0
506 && p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].rsp_num > pinfo->fd->num) {
507 srt_type=CAMELSRT_VOICE_ACR3;
509 #ifdef DEBUG_CAMELSRT
510 dbg(70,"Request ACR %u ",srt_type);
511 dbg(70,"ACR1 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num);
512 dbg(70,"ACR2 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num);
513 dbg(70,"ACR3 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].rsp_num);
516 p_camelsrt_info->bool_msginfo[srt_type]=TRUE;
519 if (p_camelsrt_call->category[srt_type].req_num == 0) {
520 /* We have not yet seen a request to that call, so this must be the first request
521 remember its frame number. */
522 #ifdef DEBUG_CAMELSRT
523 dbg(5,"Set reqlink #%d ", pinfo->fd->num);
525 update_camelsrt_call(p_camelsrt_call, pinfo, srt_type);
527 /* We have seen a request to this call - but was it *this* request? */
528 if (p_camelsrt_call->category[srt_type].req_num != pinfo->fd->num) {
530 if (srt_type!=CAMELSRT_VOICE_DISC) {
531 /* No, so it's a duplicate resquest. Mark it as such. */
532 #ifdef DEBUG_CAMELSRT
533 dbg(21,"Display_duplicate with req %d ", p_camelsrt_call->category[srt_type].req_num);
535 p_camelsrt_info->msginfo[srt_type].is_duplicate = TRUE;
536 if (gcamel_DisplaySRT)
537 proto_tree_add_uint_hidden(tree, hf_camelsrt_Duplicate, tvb, 0,0, 77);
540 /* Ignore duplicate frame */
541 if (pinfo->fd->num > p_camelsrt_call->category[srt_type].req_num) {
542 p_camelsrt_call->category[srt_type].req_num = pinfo->fd->num;
543 #ifdef DEBUG_CAMELSRT
544 dbg(5,"DISC Set reqlink #%d ", pinfo->fd->num);
546 update_camelsrt_call(p_camelsrt_call, pinfo, srt_type);
547 } /* greater frame */
549 } /* req_num already seen */
552 /* add link to response frame, if available */
553 if ( gcamel_DisplaySRT &&
554 (p_camelsrt_call->category[srt_type].rsp_num != 0) &&
555 (p_camelsrt_call->category[srt_type].req_num != 0) &&
556 (p_camelsrt_call->category[srt_type].req_num == pinfo->fd->num) ) {
557 #ifdef DEBUG_CAMELSRT
558 dbg(20,"Display_framersplink %d ",p_camelsrt_call->category[srt_type].rsp_num);
560 ti = proto_tree_add_uint_format(tree, hf_camelsrt_RequestFrame, tvb, 0, 0,
561 p_camelsrt_call->category[srt_type].rsp_num,
562 "Linked response %s in frame %u",
563 val_to_str(srt_type, camelSRTtype_naming, "Unk"),
564 p_camelsrt_call->category[srt_type].rsp_num);
565 PROTO_ITEM_SET_GENERATED(ti);
567 }/* call reference */
572 * Check if the received message is a response to a previous request
573 * registered is the camel session context.
575 static void camelsrt_report_call_matching(tvbuff_t *tvb,
576 packet_info * pinfo _U_,
578 struct camelsrt_info_t * p_camelsrt_info,
581 struct camelsrt_call_t * p_camelsrt_call;
582 struct camelsrt_call_info_key_t camelsrt_call_key;
586 #ifdef DEBUG_CAMELSRT
587 dbg(10,"\n %s #%d\n", val_to_str(srt_type, camelSRTtype_naming, "Unk"),pinfo->fd->num);
589 camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
590 /* look only for matching request, if matching conversation is available. */
592 #ifdef DEBUG_CAMELSRT
593 dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
595 p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key, pinfo);
596 if(p_camelsrt_call) {
597 #ifdef DEBUG_CAMELSRT
598 dbg(12,"Found, req=%d ",p_camelsrt_call->category[srt_type].req_num);
600 if ( gcamel_DisplaySRT )
601 proto_tree_add_uint(tree, hf_camelsrt_SessionId, tvb, 0,0, p_camelsrt_call->session_id);
603 if (srt_type==CAMELSRT_VOICE_ACR1) {
604 if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num != 0
605 && p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num < pinfo->fd->num) {
606 srt_type=CAMELSRT_VOICE_ACR1;
607 } else if ( p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num != 0
608 && p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num < pinfo->fd->num) {
609 srt_type=CAMELSRT_VOICE_ACR2;
610 } else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num != 0
611 && p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num < pinfo->fd->num) {
612 srt_type=CAMELSRT_VOICE_ACR1;
614 #ifdef DEBUG_CAMELSRT
615 dbg(70,"Report ACR %u ",srt_type);
618 p_camelsrt_info->bool_msginfo[srt_type]=TRUE;
620 if (p_camelsrt_call->category[srt_type].rsp_num == 0) {
621 if ( (p_camelsrt_call->category[srt_type].req_num != 0)
622 && (pinfo->fd->num > p_camelsrt_call->category[srt_type].req_num) ){
623 /* We have not yet seen a response to that call, so this must be the first response;
624 remember its frame number only if response comes after request */
625 #ifdef DEBUG_CAMELSRT
626 dbg(14,"Set reslink #%d req %d ",pinfo->fd->num, p_camelsrt_call->category[srt_type].req_num);
628 p_camelsrt_call->category[srt_type].rsp_num = pinfo->fd->num;
631 #ifdef DEBUG_CAMELSRT
632 dbg(2,"badreslink #%d req %u ",pinfo->fd->num, p_camelsrt_call->category[srt_type].req_num);
635 } else { /* rsp_num != 0 */
636 /* We have seen a response to this call - but was it *this* response? */
637 if (p_camelsrt_call->category[srt_type].rsp_num != pinfo->fd->num) {
638 /* No, so it's a duplicate response. Mark it as such. */
639 #ifdef DEBUG_CAMELSRT
640 dbg(21,"Display_duplicate rsp=%d ", p_camelsrt_call->category[srt_type].rsp_num);
642 p_camelsrt_info->msginfo[srt_type].is_duplicate = TRUE;
643 if ( gcamel_DisplaySRT )
644 proto_tree_add_uint_hidden(tree, hf_camelsrt_Duplicate, tvb, 0,0, 77);
648 if ( (p_camelsrt_call->category[srt_type].req_num != 0) &&
649 (p_camelsrt_call->category[srt_type].rsp_num != 0) &&
650 (p_camelsrt_call->category[srt_type].rsp_num == pinfo->fd->num) ) {
652 p_camelsrt_call->category[srt_type].responded = TRUE;
653 p_camelsrt_info->msginfo[srt_type].request_available = TRUE;
654 #ifdef DEBUG_CAMELSRT
655 dbg(20,"Display_frameReqlink %d ",p_camelsrt_call->category[srt_type].req_num);
657 /* Indicate the frame to which this is a reply. */
658 if ( gcamel_DisplaySRT ) {
659 ti = proto_tree_add_uint_format(tree, hf_camelsrt_ResponseFrame, tvb, 0, 0,
660 p_camelsrt_call->category[srt_type].req_num,
661 "Linked request %s in frame %u",
662 val_to_str(srt_type, camelSRTtype_naming, "Unk"),
663 p_camelsrt_call->category[srt_type].req_num);
664 PROTO_ITEM_SET_GENERATED(ti);
666 /* Calculate Service Response Time */
667 nstime_delta(&delta, &pinfo->fd->abs_ts, &p_camelsrt_call->category[srt_type].req_time);
669 p_camelsrt_info->msginfo[srt_type].is_delta_time = TRUE;
670 p_camelsrt_info->msginfo[srt_type].delta_time = delta; /* give it to tap */
671 p_camelsrt_info->msginfo[srt_type].req_time = p_camelsrt_call->category[srt_type].req_time;
673 /* display Service Response Time and make it filterable */
674 camelsrt_display_DeltaTime(tree, tvb, &delta, srt_type);
676 } /*req_num != 0 && not duplicate */
677 } /* call reference found */
681 * Update the Camel session info, and close the session.
682 * Then remove the associated context, if we do not have persistentSRT enable
684 static void camelsrt_close_call_matching(tvbuff_t *tvb,
685 packet_info * pinfo _U_,
687 struct camelsrt_info_t * p_camelsrt_info)
689 struct camelsrt_call_t * p_camelsrt_call;
690 struct camelsrt_call_info_key_t camelsrt_call_key;
693 p_camelsrt_info->bool_msginfo[CAMELSRT_SESSION]=TRUE;
694 #ifdef DEBUG_CAMELSRT
695 dbg(10,"\n Session end #%d\n", pinfo->fd->num);
697 /* look only for matching request, if matching conversation is available. */
698 camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
700 #ifdef DEBUG_CAMELSRT
701 dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
703 p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key, pinfo);
704 if(p_camelsrt_call) {
705 #ifdef DEBUG_CAMELSRT
708 /* Calculate Service Response Time */
709 nstime_delta(&delta, &pinfo->fd->abs_ts, &p_camelsrt_call->category[CAMELSRT_SESSION].req_time);
710 p_camelsrt_call->category[CAMELSRT_SESSION].responded = TRUE;
711 p_camelsrt_info->msginfo[CAMELSRT_SESSION].request_available = TRUE;
712 p_camelsrt_info->msginfo[CAMELSRT_SESSION].is_delta_time = TRUE;
713 p_camelsrt_info->msginfo[CAMELSRT_SESSION].delta_time = delta; /* give it to tap */
714 p_camelsrt_info->msginfo[CAMELSRT_SESSION].req_time = p_camelsrt_call->category[CAMELSRT_SESSION].req_time;
716 if ( !gcamel_PersistentSRT ) {
717 g_hash_table_remove(srt_calls, &camelsrt_call_key);
718 #ifdef DEBUG_CAMELSRT
719 dbg(20,"remove hash ");
722 #ifdef DEBUG_CAMELSRT
723 dbg(20,"keep hash ");
726 } /* call reference found */
730 * Display the delta time between two messages in a field corresponding
731 * to the category (hf_camelsrt_DeltaTimexx).
733 static void camelsrt_display_DeltaTime(proto_tree *tree,
740 if ( gcamel_DisplaySRT ) {
742 case CAMELSRT_VOICE_INITIALDP:
743 ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime31, tvb, 0, 0, value_ptr);
744 PROTO_ITEM_SET_GENERATED(ti);
747 case CAMELSRT_VOICE_ACR1:
748 case CAMELSRT_VOICE_ACR2:
749 case CAMELSRT_VOICE_ACR3:
750 ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime22, tvb, 0, 0, value_ptr);
751 PROTO_ITEM_SET_GENERATED(ti);
754 case CAMELSRT_VOICE_DISC:
755 ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime35, tvb, 0, 0, value_ptr);
756 PROTO_ITEM_SET_GENERATED(ti);
759 case CAMELSRT_GPRS_INITIALDP:
760 ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime75, tvb, 0, 0, value_ptr);
761 PROTO_ITEM_SET_GENERATED(ti);
764 case CAMELSRT_GPRS_REPORT:
765 ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime80, tvb, 0, 0, value_ptr);
766 PROTO_ITEM_SET_GENERATED(ti);
769 case CAMELSRT_SMS_INITIALDP:
770 ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime65, tvb, 0, 0, value_ptr);
771 PROTO_ITEM_SET_GENERATED(ti);
781 * Initialize the Message Info used by the main dissector
782 * Data are linked to a TCAP transaction
784 struct camelsrt_info_t * camelsrt_razinfo(void)
786 struct camelsrt_info_t * p_camelsrt_info ;
788 /* Global buffer for packet extraction */
789 camelsrt_global_current++;
790 if(camelsrt_global_current==MAX_CAMEL_INSTANCE){
791 camelsrt_global_current=0;
794 p_camelsrt_info=&camelsrt_global_info[camelsrt_global_current];
795 memset(p_camelsrt_info,0,sizeof(struct camelsrt_info_t));
797 p_camelsrt_info->opcode=255;
799 return p_camelsrt_info;
803 * Initialize the data per call for the Service Response Time Statistics
804 * Data are linked to a Camel operation in a TCAP transaction
806 static void raz_camelsrt_call (struct camelsrt_call_t * p_camelsrt_call)
808 memset(p_camelsrt_call,0,sizeof(struct camelsrt_call_t));