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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
34 #include <epan/emem.h>
35 #include <epan/packet.h>
37 #include <epan/asn1.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
);
58 static struct camelsrt_call_t
*new_camelsrt_call(struct camelsrt_call_info_key_t
*p_camelsrt_call_key
);
60 static void update_camelsrt_call(struct camelsrt_call_t
*p_camelsrt_call
,
61 packet_info
*pinfo
, guint msg_category
);
63 static void camelsrt_begin_call_matching(packet_info
*pinfo
,
64 struct camelsrt_info_t
*p_camelsrt_info
);
66 static void camelsrt_request_call_matching(tvbuff_t
*tvb
, packet_info
*pinfo
,
68 struct camelsrt_info_t
*p_camelsrt_info
,
71 static void camelsrt_report_call_matching(tvbuff_t
*tvb
, packet_info
*pinfo
,
73 struct camelsrt_info_t
*p_camelsrt_info
,
76 static void camelsrt_close_call_matching(packet_info
*pinfo
,
77 struct camelsrt_info_t
*p_camelsrt_info
);
79 static void camelsrt_display_DeltaTime(proto_tree
*tree
, tvbuff_t
*tvb
,
80 nstime_t
*value_ptr
, guint category
);
82 static void raz_camelsrt_call (struct camelsrt_call_t
*p_camelsrt_call
);
84 void camelsrt_tcap_matching(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
85 struct tcaphash_context_t
*tcap_context
);
87 /* When several Camel components are received in a single TCAP message,
88 we have to use several buffers for the stored parameters
89 because else this data are erased during TAP dissector call */
90 #define MAX_CAMEL_INSTANCE 10
91 int camelsrt_global_current
=0;
92 struct camelsrt_info_t camelsrt_global_info
[MAX_CAMEL_INSTANCE
];
94 /* Configuration parameters to enable or disable the Service Response Time */
95 extern gboolean gcamel_HandleSRT
;
96 gboolean gcamel_PersistentSRT
=FALSE
;
97 gboolean gcamel_DisplaySRT
=FALSE
;
98 gboolean gcamel_StatSRT
=FALSE
;
100 extern int camel_tap
;
102 extern int hf_camelsrt_SessionId
;
103 extern int hf_camelsrt_RequestNumber
;
104 extern int hf_camelsrt_Duplicate
;
105 extern int hf_camelsrt_RequestFrame
;
106 extern int hf_camelsrt_ResponseFrame
;
107 extern int hf_camelsrt_DeltaTime
;
108 extern int hf_camelsrt_SessionTime
;
109 extern int hf_camelsrt_DeltaTime31
;
110 extern int hf_camelsrt_DeltaTime75
;
111 extern int hf_camelsrt_DeltaTime65
;
112 extern int hf_camelsrt_DeltaTime22
;
113 extern int hf_camelsrt_DeltaTime35
;
114 extern int hf_camelsrt_DeltaTime80
;
116 /* Global hash tables*/
117 static GHashTable
*srt_calls
= NULL
;
118 guint32 camelsrt_global_SessionId
=1;
124 #undef DEBUG_CAMELSRT
125 /* #define DEBUG_CAMELSRT */
127 #ifdef DEBUG_CAMELSRT
130 static guint debug_level
= 99;
132 static void dbg(guint level
, char *fmt
, ...) {
135 if (level
> debug_level
) return;
137 vfprintf(stderr
, fmt
, ap
);
143 * Functions needed for Hash-Table
148 camelsrt_call_equal(gconstpointer k1
, gconstpointer k2
)
150 const struct camelsrt_call_info_key_t
*key1
= (const struct camelsrt_call_info_key_t
*) k1
;
151 const struct camelsrt_call_info_key_t
*key2
= (const struct camelsrt_call_info_key_t
*) k2
;
153 return (key1
->SessionIdKey
== key2
->SessionIdKey
) ;
156 /* calculate a hash key */
158 camelsrt_call_hash(gconstpointer k
)
160 const struct camelsrt_call_info_key_t
*key
= (const struct camelsrt_call_info_key_t
*) k
;
161 return key
->SessionIdKey
;
165 * Find the dialog by Key and Time
167 static struct camelsrt_call_t
*
168 find_camelsrt_call(struct camelsrt_call_info_key_t
*p_camelsrt_call_key
)
170 struct camelsrt_call_t
*p_camelsrt_call
= NULL
;
171 p_camelsrt_call
= (struct camelsrt_call_t
*)g_hash_table_lookup(srt_calls
, p_camelsrt_call_key
);
173 #ifdef DEBUG_CAMELSRT
174 if(p_camelsrt_call
) {
175 dbg(10,"D%d ", p_camelsrt_call
->session_id
);
177 dbg(23,"Not in hash ");
181 return p_camelsrt_call
;
185 * New record to create, to identify a new transaction
187 static struct camelsrt_call_t
*
188 new_camelsrt_call(struct camelsrt_call_info_key_t
*p_camelsrt_call_key
)
190 struct camelsrt_call_info_key_t
*p_new_camelsrt_call_key
;
191 struct camelsrt_call_t
*p_new_camelsrt_call
= NULL
;
193 /* Register the transaction in the hash table
194 with the tcap transaction Id as main Key
195 Once created, this entry will be updated later */
197 p_new_camelsrt_call_key
= se_new(struct camelsrt_call_info_key_t
);
198 p_new_camelsrt_call_key
->SessionIdKey
= p_camelsrt_call_key
->SessionIdKey
;
199 p_new_camelsrt_call
= se_new(struct camelsrt_call_t
);
200 raz_camelsrt_call(p_new_camelsrt_call
);
201 p_new_camelsrt_call
->session_id
= camelsrt_global_SessionId
++;
202 #ifdef DEBUG_CAMELSRT
203 dbg(10,"D%d ", p_new_camelsrt_call
->session_id
);
206 g_hash_table_insert(srt_calls
, p_new_camelsrt_call_key
, p_new_camelsrt_call
);
207 return p_new_camelsrt_call
;
211 * Update a record with the data of the Request
214 update_camelsrt_call(struct camelsrt_call_t
*p_camelsrt_call
, packet_info
*pinfo
,
217 p_camelsrt_call
->category
[msg_category
].req_num
= pinfo
->fd
->num
;
218 p_camelsrt_call
->category
[msg_category
].rsp_num
= 0;
219 p_camelsrt_call
->category
[msg_category
].responded
= FALSE
;
220 p_camelsrt_call
->category
[msg_category
].req_time
= pinfo
->fd
->abs_ts
;
225 * Routine called when the TAP is initialized.
226 * so hash table are (re)created
229 camelsrt_init_routine(void)
232 /* free hash-table for SRT */
233 if (srt_calls
!= NULL
) {
234 #ifdef DEBUG_CAMELSRT
235 dbg(16,"Destroy hash ");
237 g_hash_table_destroy(srt_calls
);
240 /* create new hash-table for SRT */
241 srt_calls
= g_hash_table_new(camelsrt_call_hash
, camelsrt_call_equal
);
242 #ifdef DEBUG_CAMELSRT
243 dbg(16,"Create hash ");
245 /* Reset the session counter */
246 camelsrt_global_SessionId
=1;
248 /* The Display of SRT is enable
249 * 1) For wireshark only if Persistent Stat is enable
250 * 2) For Tshark, if the SRT handling is enable
252 gcamel_DisplaySRT
=gcamel_PersistentSRT
|| gcamel_HandleSRT
&gcamel_StatSRT
;
256 * Service Response Time analyze, called just after the camel dissector
257 * According to the camel operation, we
258 * - open/close a context for the camel session
259 * - look for a request, or look for the corresponding response
262 camelsrt_call_matching(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
263 struct camelsrt_info_t
*p_camelsrt_info
)
266 #ifdef DEBUG_CAMELSRT
267 dbg(10,"tcap_session #%d ", p_camelsrt_info
->tcap_session_id
);
270 switch (p_camelsrt_info
->opcode
) {
272 case 0: /*InitialDP*/
273 camelsrt_begin_call_matching(pinfo
, p_camelsrt_info
);
274 camelsrt_request_call_matching(tvb
, pinfo
, tree
, p_camelsrt_info
,
275 CAMELSRT_VOICE_INITIALDP
);
277 case 60: /*InitialDPSMS*/
278 camelsrt_begin_call_matching(pinfo
, p_camelsrt_info
);
279 camelsrt_request_call_matching(tvb
, pinfo
, tree
, p_camelsrt_info
,
280 CAMELSRT_SMS_INITIALDP
);
282 case 78: /*InitialDPGPRS*/
283 camelsrt_begin_call_matching(pinfo
, p_camelsrt_info
);
284 camelsrt_request_call_matching(tvb
, pinfo
, tree
, p_camelsrt_info
,
285 CAMELSRT_GPRS_INITIALDP
);
288 case 23: /*RequestReportBCSMEvent*/
291 case 63: /*RequestReportSMSEvent*/
294 case 81: /*RequestReportGPRSEvent*/
297 case 24: /*EventReportBCSMEvent*/
298 camelsrt_request_call_matching(tvb
, pinfo
, tree
, p_camelsrt_info
,
299 CAMELSRT_VOICE_DISC
);
302 case 64: /*EventReportSMS*/
303 /* Session has been explicity closed without TC_END */
304 camelsrt_close_call_matching(pinfo
, p_camelsrt_info
);
305 tcapsrt_close((struct tcaphash_context_t
*)p_camelsrt_info
->tcap_context
, pinfo
);
308 case 80: /*EventReportGPRS*/
309 camelsrt_begin_call_matching(pinfo
, p_camelsrt_info
);
310 camelsrt_request_call_matching(tvb
, pinfo
, tree
, p_camelsrt_info
,
311 CAMELSRT_GPRS_REPORT
);
314 case 35: /*ApplyCharging*/
315 camelsrt_report_call_matching(tvb
, pinfo
, tree
, p_camelsrt_info
,
316 CAMELSRT_VOICE_ACR1
);
319 case 71: /*ApplyChargingGPRS*/
322 case 36: /*ApplyChargingReport*/
323 camelsrt_request_call_matching(tvb
, pinfo
, tree
, p_camelsrt_info
,
324 CAMELSRT_VOICE_ACR1
);
327 case 72: /*ApplyChargingReportGPRS*/
330 case 31: /*Continue*/
331 camelsrt_report_call_matching(tvb
, pinfo
, tree
, p_camelsrt_info
,
332 CAMELSRT_VOICE_INITIALDP
);
334 case 65: /*ContinueSMS*/
335 camelsrt_report_call_matching(tvb
, pinfo
, tree
, p_camelsrt_info
,
336 CAMELSRT_SMS_INITIALDP
);
338 case 75: /*ContinueGPRS*/
339 camelsrt_report_call_matching(tvb
, pinfo
, tree
, p_camelsrt_info
,
340 CAMELSRT_GPRS_INITIALDP
);
341 camelsrt_report_call_matching(tvb
, pinfo
, tree
, p_camelsrt_info
,
342 CAMELSRT_GPRS_REPORT
);
345 case 22: /*ReleaseCall*/
346 camelsrt_report_call_matching(tvb
, pinfo
, tree
, p_camelsrt_info
,
347 CAMELSRT_VOICE_DISC
);
348 /* Session has been closed by Network */
349 camelsrt_close_call_matching(pinfo
, p_camelsrt_info
);
352 case 66: /*ReleaseSMS*/
353 /* Session has been closed by Network */
354 camelsrt_close_call_matching(pinfo
, p_camelsrt_info
);
355 tcapsrt_close((struct tcaphash_context_t
*)p_camelsrt_info
->tcap_context
,pinfo
);
358 case 79: /*ReleaseGPRS*/
359 /* Session has been closed by Network */
360 camelsrt_close_call_matching(pinfo
, p_camelsrt_info
);
362 } /* switch opcode */
366 * Callback function for the TCAP dissector
367 * This callback function is used to inform the camel layer, that the session
368 * has been Closed or Aborted by a TCAP message without Camel component
369 * So, we can close the context for camel session, and update the stats.
372 camelsrt_tcap_matching(tvbuff_t
*tvb _U_
, packet_info
*pinfo
,
373 proto_tree
*tree _U_
,
374 struct tcaphash_context_t
*p_tcap_context
)
376 struct camelsrt_info_t
*p_camelsrt_info
;
378 #ifdef DEBUG_CAMELSRT
379 dbg(11,"Camel_CallBack ");
381 p_camelsrt_info
=camelsrt_razinfo();
383 p_camelsrt_info
->tcap_context
=p_tcap_context
;
384 if (p_tcap_context
) {
385 #ifdef DEBUG_CAMELSRT
386 dbg(11,"Close TCAP ");
388 p_camelsrt_info
->tcap_session_id
= p_tcap_context
->session_id
;
389 camelsrt_close_call_matching(pinfo
, p_camelsrt_info
);
390 tap_queue_packet(camel_tap
, pinfo
, p_camelsrt_info
);
396 * Create the record identifiying the Camel session
397 * As the Tcap session id given by the TCAP dissector is uniq, it will be
401 camelsrt_begin_call_matching(packet_info
*pinfo
,
402 struct camelsrt_info_t
*p_camelsrt_info
)
404 struct camelsrt_call_t
*p_camelsrt_call
;
405 struct camelsrt_call_info_key_t camelsrt_call_key
;
407 p_camelsrt_info
->bool_msginfo
[CAMELSRT_SESSION
]=TRUE
;
409 /* prepare the key data */
410 camelsrt_call_key
.SessionIdKey
= p_camelsrt_info
->tcap_session_id
;
412 /* look up the request */
413 #ifdef DEBUG_CAMELSRT
414 dbg(10,"\n Session begin #%u\n", pinfo
->fd
->num
);
415 dbg(11,"Search key %lu ",camelsrt_call_key
.SessionIdKey
);
417 p_camelsrt_call
= (struct camelsrt_call_t
*)g_hash_table_lookup(srt_calls
, &camelsrt_call_key
);
418 if (p_camelsrt_call
) {
419 /* We have seen this request before -> do nothing */
420 #ifdef DEBUG_CAMELSRT
421 dbg(22,"Already seen ");
423 } else { /* p_camelsrt_call has not been found */
424 #ifdef DEBUG_CAMELSRT
425 dbg(10,"New key %lu ",camelsrt_call_key
.SessionIdKey
);
427 p_camelsrt_call
= new_camelsrt_call(&camelsrt_call_key
);
428 p_camelsrt_call
->tcap_context
=(struct tcaphash_context_t
*)p_camelsrt_info
->tcap_context
;
429 update_camelsrt_call(p_camelsrt_call
, pinfo
,CAMELSRT_SESSION
);
431 #ifdef DEBUG_CAMELSRT
432 dbg(11,"Update Callback ");
434 p_camelsrt_call
->tcap_context
->callback
=camelsrt_tcap_matching
;
439 * Register the request, and try to find the response
443 camelsrt_request_call_matching(tvbuff_t
*tvb
, packet_info
*pinfo
,
445 struct camelsrt_info_t
*p_camelsrt_info
,
448 struct camelsrt_call_t
*p_camelsrt_call
;
449 struct camelsrt_call_info_key_t camelsrt_call_key
;
450 proto_item
*ti
, *hidden_item
;
452 #ifdef DEBUG_CAMELSRT
453 dbg(10,"\n %s #%u\n", val_to_str_const(srt_type
, camelSRTtype_naming
, "Unk"),pinfo
->fd
->num
);
456 /* look only for matching request, if matching conversation is available. */
457 camelsrt_call_key
.SessionIdKey
= p_camelsrt_info
->tcap_session_id
;
459 #ifdef DEBUG_CAMELSRT
460 dbg(11,"Search key %lu ", camelsrt_call_key
.SessionIdKey
);
462 p_camelsrt_call
= find_camelsrt_call(&camelsrt_call_key
);
463 if(p_camelsrt_call
) {
464 #ifdef DEBUG_CAMELSRT
467 if (gcamel_DisplaySRT
)
468 proto_tree_add_uint(tree
, hf_camelsrt_SessionId
, tvb
, 0,0, p_camelsrt_call
->session_id
);
471 /* Hmm.. As there are several slices ApplyChargingReport/ApplyCharging
472 * we will prepare the measurement for 3 slices with 3 categories */
473 if (srt_type
==CAMELSRT_VOICE_ACR1
) {
474 if (p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR1
].req_num
== 0) {
475 srt_type
=CAMELSRT_VOICE_ACR1
;
476 } else if ( (p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR2
].req_num
== 0)
477 && (p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR1
].rsp_num
!= 0)
478 && (p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR1
].rsp_num
< pinfo
->fd
->num
) ) {
479 srt_type
=CAMELSRT_VOICE_ACR2
;
480 } else if ( (p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR3
].req_num
== 0)
481 && (p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR2
].rsp_num
!= 0)
482 && (p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR2
].rsp_num
< pinfo
->fd
->num
) ) {
483 srt_type
=CAMELSRT_VOICE_ACR3
;
484 } else if (p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR1
].rsp_num
!= 0
485 && p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR1
].rsp_num
> pinfo
->fd
->num
) {
486 srt_type
=CAMELSRT_VOICE_ACR1
;
487 } else if ( p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR2
].rsp_num
!= 0
488 && p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR2
].rsp_num
> pinfo
->fd
->num
) {
489 srt_type
=CAMELSRT_VOICE_ACR2
;
490 } else if (p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR1
].rsp_num
!= 0
491 && p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR3
].rsp_num
> pinfo
->fd
->num
) {
492 srt_type
=CAMELSRT_VOICE_ACR3
;
494 #ifdef DEBUG_CAMELSRT
495 dbg(70,"Request ACR %u ",srt_type
);
496 dbg(70,"ACR1 %u %u",p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR1
].req_num
, p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR1
].rsp_num
);
497 dbg(70,"ACR2 %u %u",p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR2
].req_num
, p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR2
].rsp_num
);
498 dbg(70,"ACR3 %u %u",p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR3
].req_num
, p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR3
].rsp_num
);
501 p_camelsrt_info
->bool_msginfo
[srt_type
]=TRUE
;
504 if (p_camelsrt_call
->category
[srt_type
].req_num
== 0) {
505 /* We have not yet seen a request to that call, so this must be the first request
506 remember its frame number. */
507 #ifdef DEBUG_CAMELSRT
508 dbg(5,"Set reqlink #%u ", pinfo
->fd
->num
);
510 update_camelsrt_call(p_camelsrt_call
, pinfo
, srt_type
);
512 /* We have seen a request to this call - but was it *this* request? */
513 if (p_camelsrt_call
->category
[srt_type
].req_num
!= pinfo
->fd
->num
) {
515 if (srt_type
!=CAMELSRT_VOICE_DISC
) {
516 /* No, so it's a duplicate resquest. Mark it as such. */
517 #ifdef DEBUG_CAMELSRT
518 dbg(21,"Display_duplicate with req %d ", p_camelsrt_call
->category
[srt_type
].req_num
);
520 p_camelsrt_info
->msginfo
[srt_type
].is_duplicate
= TRUE
;
521 if (gcamel_DisplaySRT
){
522 hidden_item
= proto_tree_add_uint(tree
, hf_camelsrt_Duplicate
, tvb
, 0,0, 77);
523 PROTO_ITEM_SET_HIDDEN(hidden_item
);
527 /* Ignore duplicate frame */
528 if (pinfo
->fd
->num
> p_camelsrt_call
->category
[srt_type
].req_num
) {
529 p_camelsrt_call
->category
[srt_type
].req_num
= pinfo
->fd
->num
;
530 #ifdef DEBUG_CAMELSRT
531 dbg(5,"DISC Set reqlink #%u ", pinfo
->fd
->num
);
533 update_camelsrt_call(p_camelsrt_call
, pinfo
, srt_type
);
534 } /* greater frame */
536 } /* req_num already seen */
539 /* add link to response frame, if available */
540 if ( gcamel_DisplaySRT
&&
541 (p_camelsrt_call
->category
[srt_type
].rsp_num
!= 0) &&
542 (p_camelsrt_call
->category
[srt_type
].req_num
!= 0) &&
543 (p_camelsrt_call
->category
[srt_type
].req_num
== pinfo
->fd
->num
) ) {
544 #ifdef DEBUG_CAMELSRT
545 dbg(20,"Display_framersplink %d ",p_camelsrt_call
->category
[srt_type
].rsp_num
);
547 ti
= proto_tree_add_uint_format(tree
, hf_camelsrt_RequestFrame
, tvb
, 0, 0,
548 p_camelsrt_call
->category
[srt_type
].rsp_num
,
549 "Linked response %s in frame %u",
550 val_to_str_const(srt_type
, camelSRTtype_naming
, "Unk"),
551 p_camelsrt_call
->category
[srt_type
].rsp_num
);
552 PROTO_ITEM_SET_GENERATED(ti
);
554 } /* call reference */
559 * Check if the received message is a response to a previous request
560 * registered is the camel session context.
563 camelsrt_report_call_matching(tvbuff_t
*tvb
, packet_info
*pinfo
,
565 struct camelsrt_info_t
*p_camelsrt_info
,
568 struct camelsrt_call_t
*p_camelsrt_call
;
569 struct camelsrt_call_info_key_t camelsrt_call_key
;
571 proto_item
*ti
, *hidden_item
;
573 #ifdef DEBUG_CAMELSRT
574 dbg(10,"\n %s #%u\n", val_to_str_const(srt_type
, camelSRTtype_naming
, "Unk"),pinfo
->fd
->num
);
576 camelsrt_call_key
.SessionIdKey
= p_camelsrt_info
->tcap_session_id
;
577 /* look only for matching request, if matching conversation is available. */
579 #ifdef DEBUG_CAMELSRT
580 dbg(11,"Search key %lu ",camelsrt_call_key
.SessionIdKey
);
582 p_camelsrt_call
= find_camelsrt_call(&camelsrt_call_key
);
583 if(p_camelsrt_call
) {
584 #ifdef DEBUG_CAMELSRT
585 dbg(12,"Found, req=%d ",p_camelsrt_call
->category
[srt_type
].req_num
);
587 if ( gcamel_DisplaySRT
)
588 proto_tree_add_uint(tree
, hf_camelsrt_SessionId
, tvb
, 0,0, p_camelsrt_call
->session_id
);
590 if (srt_type
==CAMELSRT_VOICE_ACR1
) {
591 if (p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR3
].req_num
!= 0
592 && p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR3
].req_num
< pinfo
->fd
->num
) {
593 srt_type
=CAMELSRT_VOICE_ACR1
;
594 } else if ( p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR2
].req_num
!= 0
595 && p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR2
].req_num
< pinfo
->fd
->num
) {
596 srt_type
=CAMELSRT_VOICE_ACR2
;
597 } else if (p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR1
].req_num
!= 0
598 && p_camelsrt_call
->category
[CAMELSRT_VOICE_ACR1
].req_num
< pinfo
->fd
->num
) {
599 srt_type
=CAMELSRT_VOICE_ACR1
;
601 #ifdef DEBUG_CAMELSRT
602 dbg(70,"Report ACR %u ",srt_type
);
605 p_camelsrt_info
->bool_msginfo
[srt_type
]=TRUE
;
607 if (p_camelsrt_call
->category
[srt_type
].rsp_num
== 0) {
608 if ( (p_camelsrt_call
->category
[srt_type
].req_num
!= 0)
609 && (pinfo
->fd
->num
> p_camelsrt_call
->category
[srt_type
].req_num
) ){
610 /* We have not yet seen a response to that call, so this must be the first response;
611 remember its frame number only if response comes after request */
612 #ifdef DEBUG_CAMELSRT
613 dbg(14,"Set reslink #%d req %u ",pinfo
->fd
->num
, p_camelsrt_call
->category
[srt_type
].req_num
);
615 p_camelsrt_call
->category
[srt_type
].rsp_num
= pinfo
->fd
->num
;
618 #ifdef DEBUG_CAMELSRT
619 dbg(2,"badreslink #%u req %u ",pinfo
->fd
->num
, p_camelsrt_call
->category
[srt_type
].req_num
);
622 } else { /* rsp_num != 0 */
623 /* We have seen a response to this call - but was it *this* response? */
624 if (p_camelsrt_call
->category
[srt_type
].rsp_num
!= pinfo
->fd
->num
) {
625 /* No, so it's a duplicate response. Mark it as such. */
626 #ifdef DEBUG_CAMELSRT
627 dbg(21,"Display_duplicate rsp=%d ", p_camelsrt_call
->category
[srt_type
].rsp_num
);
629 p_camelsrt_info
->msginfo
[srt_type
].is_duplicate
= TRUE
;
630 if ( gcamel_DisplaySRT
){
631 hidden_item
= proto_tree_add_uint(tree
, hf_camelsrt_Duplicate
, tvb
, 0,0, 77);
632 PROTO_ITEM_SET_HIDDEN(hidden_item
);
637 if ( (p_camelsrt_call
->category
[srt_type
].req_num
!= 0) &&
638 (p_camelsrt_call
->category
[srt_type
].rsp_num
!= 0) &&
639 (p_camelsrt_call
->category
[srt_type
].rsp_num
== pinfo
->fd
->num
) ) {
641 p_camelsrt_call
->category
[srt_type
].responded
= TRUE
;
642 p_camelsrt_info
->msginfo
[srt_type
].request_available
= TRUE
;
643 #ifdef DEBUG_CAMELSRT
644 dbg(20,"Display_frameReqlink %d ",p_camelsrt_call
->category
[srt_type
].req_num
);
646 /* Indicate the frame to which this is a reply. */
647 if ( gcamel_DisplaySRT
) {
648 ti
= proto_tree_add_uint_format(tree
, hf_camelsrt_ResponseFrame
, tvb
, 0, 0,
649 p_camelsrt_call
->category
[srt_type
].req_num
,
650 "Linked request %s in frame %u",
651 val_to_str_const(srt_type
, camelSRTtype_naming
, "Unk"),
652 p_camelsrt_call
->category
[srt_type
].req_num
);
653 PROTO_ITEM_SET_GENERATED(ti
);
655 /* Calculate Service Response Time */
656 nstime_delta(&delta
, &pinfo
->fd
->abs_ts
, &p_camelsrt_call
->category
[srt_type
].req_time
);
658 p_camelsrt_info
->msginfo
[srt_type
].is_delta_time
= TRUE
;
659 p_camelsrt_info
->msginfo
[srt_type
].delta_time
= delta
; /* give it to tap */
660 p_camelsrt_info
->msginfo
[srt_type
].req_time
= p_camelsrt_call
->category
[srt_type
].req_time
;
662 /* display Service Response Time and make it filterable */
663 camelsrt_display_DeltaTime(tree
, tvb
, &delta
, srt_type
);
665 } /*req_num != 0 && not duplicate */
666 } /* call reference found */
670 * Update the Camel session info, and close the session.
671 * Then remove the associated context, if we do not have persistentSRT enable
674 camelsrt_close_call_matching(packet_info
*pinfo
,
675 struct camelsrt_info_t
*p_camelsrt_info
)
677 struct camelsrt_call_t
*p_camelsrt_call
;
678 struct camelsrt_call_info_key_t camelsrt_call_key
;
681 p_camelsrt_info
->bool_msginfo
[CAMELSRT_SESSION
]=TRUE
;
682 #ifdef DEBUG_CAMELSRT
683 dbg(10,"\n Session end #%u\n", pinfo
->fd
->num
);
685 /* look only for matching request, if matching conversation is available. */
686 camelsrt_call_key
.SessionIdKey
= p_camelsrt_info
->tcap_session_id
;
688 #ifdef DEBUG_CAMELSRT
689 dbg(11,"Search key %lu ",camelsrt_call_key
.SessionIdKey
);
691 p_camelsrt_call
= find_camelsrt_call(&camelsrt_call_key
);
692 if(p_camelsrt_call
) {
693 #ifdef DEBUG_CAMELSRT
696 /* Calculate Service Response Time */
697 nstime_delta(&delta
, &pinfo
->fd
->abs_ts
, &p_camelsrt_call
->category
[CAMELSRT_SESSION
].req_time
);
698 p_camelsrt_call
->category
[CAMELSRT_SESSION
].responded
= TRUE
;
699 p_camelsrt_info
->msginfo
[CAMELSRT_SESSION
].request_available
= TRUE
;
700 p_camelsrt_info
->msginfo
[CAMELSRT_SESSION
].is_delta_time
= TRUE
;
701 p_camelsrt_info
->msginfo
[CAMELSRT_SESSION
].delta_time
= delta
; /* give it to tap */
702 p_camelsrt_info
->msginfo
[CAMELSRT_SESSION
].req_time
= p_camelsrt_call
->category
[CAMELSRT_SESSION
].req_time
;
704 if ( !gcamel_PersistentSRT
) {
705 g_hash_table_remove(srt_calls
, &camelsrt_call_key
);
706 #ifdef DEBUG_CAMELSRT
707 dbg(20,"remove hash ");
710 #ifdef DEBUG_CAMELSRT
711 dbg(20,"keep hash ");
714 } /* call reference found */
718 * Display the delta time between two messages in a field corresponding
719 * to the category (hf_camelsrt_DeltaTimexx).
722 camelsrt_display_DeltaTime(proto_tree
*tree
, tvbuff_t
*tvb
, nstime_t
*value_ptr
,
727 if ( gcamel_DisplaySRT
) {
729 case CAMELSRT_VOICE_INITIALDP
:
730 ti
= proto_tree_add_time(tree
, hf_camelsrt_DeltaTime31
, tvb
, 0, 0, value_ptr
);
731 PROTO_ITEM_SET_GENERATED(ti
);
734 case CAMELSRT_VOICE_ACR1
:
735 case CAMELSRT_VOICE_ACR2
:
736 case CAMELSRT_VOICE_ACR3
:
737 ti
= proto_tree_add_time(tree
, hf_camelsrt_DeltaTime22
, tvb
, 0, 0, value_ptr
);
738 PROTO_ITEM_SET_GENERATED(ti
);
741 case CAMELSRT_VOICE_DISC
:
742 ti
= proto_tree_add_time(tree
, hf_camelsrt_DeltaTime35
, tvb
, 0, 0, value_ptr
);
743 PROTO_ITEM_SET_GENERATED(ti
);
746 case CAMELSRT_GPRS_INITIALDP
:
747 ti
= proto_tree_add_time(tree
, hf_camelsrt_DeltaTime75
, tvb
, 0, 0, value_ptr
);
748 PROTO_ITEM_SET_GENERATED(ti
);
751 case CAMELSRT_GPRS_REPORT
:
752 ti
= proto_tree_add_time(tree
, hf_camelsrt_DeltaTime80
, tvb
, 0, 0, value_ptr
);
753 PROTO_ITEM_SET_GENERATED(ti
);
756 case CAMELSRT_SMS_INITIALDP
:
757 ti
= proto_tree_add_time(tree
, hf_camelsrt_DeltaTime65
, tvb
, 0, 0, value_ptr
);
758 PROTO_ITEM_SET_GENERATED(ti
);
768 * Initialize the Message Info used by the main dissector
769 * Data are linked to a TCAP transaction
771 struct camelsrt_info_t
*
772 camelsrt_razinfo(void)
774 struct camelsrt_info_t
*p_camelsrt_info
;
776 /* Global buffer for packet extraction */
777 camelsrt_global_current
++;
778 if(camelsrt_global_current
==MAX_CAMEL_INSTANCE
){
779 camelsrt_global_current
=0;
782 p_camelsrt_info
=&camelsrt_global_info
[camelsrt_global_current
];
783 memset(p_camelsrt_info
,0,sizeof(struct camelsrt_info_t
));
785 p_camelsrt_info
->opcode
=255;
787 return p_camelsrt_info
;
791 * Initialize the data per call for the Service Response Time Statistics
792 * Data are linked to a Camel operation in a TCAP transaction
795 raz_camelsrt_call (struct camelsrt_call_t
*p_camelsrt_call
)
797 memset(p_camelsrt_call
,0,sizeof(struct camelsrt_call_t
));