HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / camel-persistentdata.c
blob7f269a40cd2d3a9fec02aa43d6084507f051e05f
1 /*
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 * $Id$
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.
28 #include "config.h"
30 #include <glib.h>
31 #include <stdio.h>
32 #include <string.h>
34 #include <epan/emem.h>
35 #include <epan/packet.h>
36 #include <epan/tap.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" },
52 { 0,NULL}
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,
67 proto_tree *tree,
68 struct camelsrt_info_t *p_camelsrt_info,
69 guint srt_type);
71 static void camelsrt_report_call_matching(tvbuff_t *tvb, packet_info *pinfo,
72 proto_tree *tree,
73 struct camelsrt_info_t *p_camelsrt_info,
74 guint srt_type);
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;
121 * DEBUG fonctions
124 #undef DEBUG_CAMELSRT
125 /* #define DEBUG_CAMELSRT */
127 #ifdef DEBUG_CAMELSRT
128 #include <stdio.h>
129 #include <stdarg.h>
130 static guint debug_level = 99;
132 static void dbg(guint level, char *fmt, ...) {
133 va_list ap;
135 if (level > debug_level) return;
136 va_start(ap,fmt);
137 vfprintf(stderr, fmt, ap);
138 va_end(ap);
140 #endif
143 * Functions needed for Hash-Table
146 /* compare 2 keys */
147 static gint
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 */
157 static guint
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);
176 } else {
177 dbg(23,"Not in hash ");
179 #endif
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);
204 #endif
205 /* store it */
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
213 static void
214 update_camelsrt_call(struct camelsrt_call_t *p_camelsrt_call, packet_info *pinfo,
215 guint msg_category)
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
228 void
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 ");
236 #endif
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 ");
244 #endif
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
261 void
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);
268 #endif
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);
276 break;
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);
281 break;
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);
286 break;
288 case 23: /*RequestReportBCSMEvent*/
289 break;
291 case 63: /*RequestReportSMSEvent*/
292 break;
294 case 81: /*RequestReportGPRSEvent*/
295 break;
297 case 24: /*EventReportBCSMEvent*/
298 camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
299 CAMELSRT_VOICE_DISC );
300 break;
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);
306 break;
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);
312 break;
314 case 35: /*ApplyCharging*/
315 camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
316 CAMELSRT_VOICE_ACR1 );
317 break;
319 case 71: /*ApplyChargingGPRS*/
320 break;
322 case 36: /*ApplyChargingReport*/
323 camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
324 CAMELSRT_VOICE_ACR1 );
325 break;
327 case 72: /*ApplyChargingReportGPRS*/
328 break;
330 case 31: /*Continue*/
331 camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
332 CAMELSRT_VOICE_INITIALDP);
333 break;
334 case 65: /*ContinueSMS*/
335 camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
336 CAMELSRT_SMS_INITIALDP);
337 break;
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);
343 break;
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);
350 break;
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);
356 break;
358 case 79: /*ReleaseGPRS*/
359 /* Session has been closed by Network */
360 camelsrt_close_call_matching(pinfo, p_camelsrt_info);
361 break;
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.
371 void
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 ");
380 #endif
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 ");
387 #endif
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
398 * used as main key.
400 static void
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);
416 #endif
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 ");
422 #endif
423 } else { /* p_camelsrt_call has not been found */
424 #ifdef DEBUG_CAMELSRT
425 dbg(10,"New key %lu ",camelsrt_call_key.SessionIdKey);
426 #endif
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 ");
433 #endif
434 p_camelsrt_call->tcap_context->callback=camelsrt_tcap_matching;
439 * Register the request, and try to find the response
442 static void
443 camelsrt_request_call_matching(tvbuff_t *tvb, packet_info *pinfo,
444 proto_tree *tree,
445 struct camelsrt_info_t *p_camelsrt_info,
446 guint srt_type )
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);
454 #endif
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);
461 #endif
462 p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key);
463 if(p_camelsrt_call) {
464 #ifdef DEBUG_CAMELSRT
465 dbg(12,"Found ");
466 #endif
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);
499 #endif
500 } /* not ACR */
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);
509 #endif
510 update_camelsrt_call(p_camelsrt_call, pinfo, srt_type);
511 } else {
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);
519 #endif
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);
526 } else {
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);
532 #endif
533 update_camelsrt_call(p_camelsrt_call, pinfo, srt_type);
534 } /* greater frame */
535 } /* DISC */
536 } /* req_num already seen */
537 } /* req_num != 0 */
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);
546 #endif
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);
553 } /* frame valid */
554 } /* call reference */
559 * Check if the received message is a response to a previous request
560 * registered is the camel session context.
562 static void
563 camelsrt_report_call_matching(tvbuff_t *tvb, packet_info *pinfo,
564 proto_tree *tree,
565 struct camelsrt_info_t *p_camelsrt_info,
566 guint srt_type)
568 struct camelsrt_call_t *p_camelsrt_call;
569 struct camelsrt_call_info_key_t camelsrt_call_key;
570 nstime_t delta;
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);
575 #endif
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);
581 #endif
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);
586 #endif
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);
603 #endif
604 } /* not ACR */
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);
614 #endif
615 p_camelsrt_call->category[srt_type].rsp_num = pinfo->fd->num;
617 } else {
618 #ifdef DEBUG_CAMELSRT
619 dbg(2,"badreslink #%u req %u ",pinfo->fd->num, p_camelsrt_call->category[srt_type].req_num);
620 #endif
621 } /* req_num != 0 */
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);
628 #endif
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);
635 } /* rsp_num != 0 */
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);
645 #endif
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
673 static void
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;
679 nstime_t delta;
681 p_camelsrt_info->bool_msginfo[CAMELSRT_SESSION]=TRUE;
682 #ifdef DEBUG_CAMELSRT
683 dbg(10,"\n Session end #%u\n", pinfo->fd->num);
684 #endif
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);
690 #endif
691 p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key);
692 if(p_camelsrt_call) {
693 #ifdef DEBUG_CAMELSRT
694 dbg(12,"Found ");
695 #endif
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 ");
708 #endif
709 } else {
710 #ifdef DEBUG_CAMELSRT
711 dbg(20,"keep hash ");
712 #endif
714 } /* call reference found */
718 * Display the delta time between two messages in a field corresponding
719 * to the category (hf_camelsrt_DeltaTimexx).
721 static void
722 camelsrt_display_DeltaTime(proto_tree *tree, tvbuff_t *tvb, nstime_t *value_ptr,
723 guint category)
725 proto_item *ti;
727 if ( gcamel_DisplaySRT ) {
728 switch(category) {
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);
732 break;
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);
739 break;
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);
744 break;
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);
749 break;
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);
754 break;
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);
759 break;
761 default:
762 break;
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
794 static void
795 raz_camelsrt_call (struct camelsrt_call_t *p_camelsrt_call)
797 memset(p_camelsrt_call,0,sizeof(struct camelsrt_call_t));