2 * VoIP calls summary addition for ethereal
6 * Copyright 2004, Ericsson, Spain
7 * By Francisco Alcoba <francisco.alcoba@ericsson.com>
9 * based on h323_calls.c
10 * Copyright 2004, Iskratel, Ltd, Kranj
11 * By Miha Jemec <m.jemec@iskratel.si>
13 * H323, RTP, RTP Event, MGCP, AudioCodes (ISDN PRI and CAS) and Graph Support
14 * By Alejandro Vaquero, alejandro.vaquero@verso.com
15 * Copyright 2005, Verso Technologies Inc.
17 * Ethereal - Network traffic analyzer
18 * By Gerald Combs <gerald@ethereal.com>
19 * Copyright 1998 Gerald Combs
21 * This program is free software; you can redistribute it and/or
22 * modify it under the terms of the GNU General Public License
23 * as published by the Free Software Foundation; either version 2
24 * of the License, or (at your option) any later version.
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
42 #include "graph_analysis.h"
43 #include "voip_calls.h"
44 #include "voip_calls_dlg.h"
49 #include <epan/dissectors/packet-sip.h>
50 #include <epan/dissectors/packet-mtp3.h>
51 #include <epan/dissectors/packet-isup.h>
52 #include <epan/dissectors/packet-h225.h>
53 #include <epan/dissectors/packet-h245.h>
54 #include <epan/dissectors/packet-q931.h>
55 #include <epan/dissectors/packet-sdp.h>
56 #include <plugins/mgcp/packet-mgcp.h>
57 #include <epan/dissectors/packet-actrace.h>
58 #include <epan/dissectors/packet-rtp.h>
59 #include <epan/dissectors/packet-rtp-events.h>
60 #include <epan/conversation.h>
63 #include "alert_box.h"
64 #include "simple_dialog.h"
66 const char *voip_call_state_name[7]={
76 /* defines whether we can consider the call active */
77 const char *voip_protocol_name[6]={
87 const gchar *frame_label;
96 graph_str labels[H245_MAX];
99 static h245_labels_t h245_labels;
101 /****************************************************************************/
102 /* the one and only global voip_calls_tapinfo_t structure */
103 static voip_calls_tapinfo_t the_tapinfo_struct =
104 {0, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
106 /* the one and only global voip_rtp_tapinfo_t structure */
107 static voip_rtp_tapinfo_t the_tapinfo_rtp_struct =
110 /****************************************************************************/
111 /* when there is a [re]reading of packet's */
112 void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
114 voip_calls_info_t *strinfo;
115 sip_calls_info_t *tmp_sipinfo;
116 h323_calls_info_t *tmp_h323info;
117 h245_address_t *h245_add;
119 graph_analysis_item_t *graph_item;
124 /* free the data items first */
125 list = g_list_first(tapinfo->strinfo_list);
128 strinfo = list->data;
129 g_free(strinfo->from_identity);
130 g_free(strinfo->to_identity);
131 g_free((void *)(strinfo->initial_speaker.data));
132 if (strinfo->protocol == VOIP_SIP){
133 tmp_sipinfo = strinfo->prot_info;
134 g_free(tmp_sipinfo->call_identifier);
136 if (strinfo->protocol == VOIP_H323){
137 tmp_h323info = strinfo->prot_info;
138 g_free(tmp_h323info->guid);
139 /* free the H245 list address */
140 list2 = g_list_first(tmp_h323info->h245_list);
143 h245_add=list2->data;
144 g_free((void *)h245_add->h245_address.data);
146 list2 = g_list_next(list2);
148 g_list_free(tmp_h323info->h245_list);
149 tmp_h323info->h245_list = NULL;
151 g_free(strinfo->prot_info);
154 list = g_list_next(list);
156 g_list_free(tapinfo->strinfo_list);
157 tapinfo->strinfo_list = NULL;
159 tapinfo->npackets = 0;
160 tapinfo->start_packets = 0;
161 tapinfo->completed_calls = 0;
162 tapinfo->rejected_calls = 0;
164 /* free the graph data items first */
165 list = g_list_first(tapinfo->graph_analysis->list);
168 graph_item = list->data;
169 g_free(graph_item->frame_label);
170 g_free(graph_item->comment);
172 list = g_list_next(list);
174 g_list_free(tapinfo->graph_analysis->list);
175 tapinfo->graph_analysis->nconv = 0;
176 tapinfo->graph_analysis->list = NULL;
178 ++(tapinfo->launch_count);
183 /****************************************************************************/
184 void graph_analysis_data_init(void){
185 the_tapinfo_struct.graph_analysis = g_malloc(sizeof(graph_analysis_info_t));
186 the_tapinfo_struct.graph_analysis->nconv = 0;
187 the_tapinfo_struct.graph_analysis->list = NULL;
191 /****************************************************************************/
192 /* Add a new item into the graph */
193 int add_to_graph(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, const gchar *frame_label, gchar *comment, guint16 call_num, address *src_addr, address *dst_addr)
195 graph_analysis_item_t *gai;
197 gai = g_malloc(sizeof(graph_analysis_item_t));
198 gai->frame_num = pinfo->fd->num;
199 gai->time= (double)pinfo->fd->rel_secs + (double) pinfo->fd->rel_usecs/1000000;
200 COPY_ADDRESS(&(gai->src_addr),src_addr);
201 COPY_ADDRESS(&(gai->dst_addr),dst_addr);
203 gai->port_src=pinfo->srcport;
204 gai->port_dst=pinfo->destport;
205 if (frame_label != NULL)
206 gai->frame_label = g_strdup(frame_label);
208 gai->frame_label = g_strdup("");
211 gai->comment = g_strdup(comment);
213 gai->comment = g_strdup("");
214 gai->conv_num=call_num;
218 tapinfo->graph_analysis->list = g_list_append(tapinfo->graph_analysis->list, gai);
224 /****************************************************************************/
225 /* Append str to frame_label and comment in a graph item */
226 /* return 0 if the frame_num is not in the graph list */
227 int append_to_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
229 graph_analysis_item_t *gai;
231 gchar *tmp_str = NULL;
232 gchar *tmp_str2 = NULL;
234 list = g_list_first(tapinfo->graph_analysis->list);
238 if (gai->frame_num == frame_num){
239 tmp_str = gai->frame_label;
240 tmp_str2 = gai->comment;
242 if (new_frame_label != NULL){
243 gai->frame_label = g_strdup_printf("%s %s", gai->frame_label, new_frame_label);
248 if (new_comment != NULL){
249 gai->comment = g_strdup_printf("%s %s", gai->comment, new_comment);
254 list = g_list_next (list);
256 if (tmp_str == NULL) return 0; /* it is not in the list */
261 /****************************************************************************/
262 /* Change the frame_label and comment in a graph item if not NULL*/
263 /* return 0 if the frame_num is not in the graph list */
264 int change_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
266 graph_analysis_item_t *gai;
268 gchar *tmp_str = NULL;
269 gchar *tmp_str2 = NULL;
271 list = g_list_first(tapinfo->graph_analysis->list);
275 if (gai->frame_num == frame_num){
276 tmp_str = gai->frame_label;
277 tmp_str2 = gai->comment;
279 if (new_frame_label != NULL){
280 gai->frame_label = g_strdup(new_frame_label);
284 if (new_comment != NULL){
285 gai->comment = g_strdup(new_comment);
290 list = g_list_next (list);
292 if (tmp_str == NULL) return 0; /* it is not in the list */
297 /****************************************************************************/
298 /* Change all the graph items with call_num to new_call_num */
299 guint change_call_num_graph(voip_calls_tapinfo_t *tapinfo _U_, guint16 call_num, guint16 new_call_num)
301 graph_analysis_item_t *gai;
306 list = g_list_first(tapinfo->graph_analysis->list);
310 if (gai->conv_num == call_num){
311 gai->conv_num = new_call_num;
314 list = g_list_next (list);
316 return items_changed;
319 /* XXX just copied from gtk/rpc_stat.c */
320 void protect_thread_critical_region(void);
321 void unprotect_thread_critical_region(void);
323 /****************************************************************************/
324 /* ***************************TAP for RTP Events*****************************/
325 /****************************************************************************/
327 /****************************************************************************/
328 /* whenever a rtp event packet is seen by the tap listener */
330 rtp_event_packet(void *ptr _U_, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *rtp_event_info)
332 const struct _rtp_event_info *pi = rtp_event_info;
333 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
334 voip_rtp_stream_info_t *tmp_listinfo;
335 voip_rtp_stream_info_t *strinfo = NULL;
338 /* do not consider RTP events packets without a setup frame */
339 if (pi->info_setup_frame_num == 0){
343 /* check wether we already have a RTP stream with this setup frame in the list */
344 list = g_list_first(tapinfo->list);
347 tmp_listinfo=list->data;
348 if ( (tmp_listinfo->setup_frame_number == pi->info_setup_frame_num)
349 && (tmp_listinfo->end_stream == FALSE) && (tmp_listinfo->rtp_event == -1)){
350 strinfo = (voip_rtp_stream_info_t*)(list->data);
351 strinfo->rtp_event = pi->info_rtp_evt;
354 list = g_list_next (list);
361 /****************************************************************************/
362 static gboolean have_rtp_event_tap_listener=FALSE;
365 rtp_event_init_tap(void)
367 GString *error_string;
370 if(have_rtp_event_tap_listener==FALSE)
372 error_string = register_tap_listener("rtpevent", &(the_tapinfo_rtp_struct.rtp_event_dummy),
379 if (error_string != NULL) {
380 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
382 g_string_free(error_string, TRUE);
385 have_rtp_event_tap_listener=TRUE;
389 /****************************************************************************/
392 remove_tap_listener_rtp_event(void)
394 protect_thread_critical_region();
395 remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_event_dummy));
396 unprotect_thread_critical_region();
398 have_rtp_event_tap_listener=FALSE;
401 /****************************************************************************/
402 /* ***************************TAP for RTP **********************************/
403 /****************************************************************************/
405 /****************************************************************************/
406 /* when there is a [re]reading of RTP packet's */
407 void voip_rtp_reset(void *ptr _U_)
409 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
411 /* free the data items first */
412 list = g_list_first(tapinfo->list);
416 list = g_list_next(list);
418 g_list_free(tapinfo->list);
419 tapinfo->list = NULL;
420 tapinfo->nstreams = 0;
424 /****************************************************************************/
425 /* whenever a RTP packet is seen by the tap listener */
427 RTP_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *RTPinfo)
429 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
430 voip_rtp_stream_info_t *tmp_listinfo;
431 voip_rtp_stream_info_t *strinfo = NULL;
433 struct _rtp_conversation_info *p_conv_data = NULL;
435 const struct _rtp_info *pi = RTPinfo;
437 /* do not consider RTP packets without a setup frame */
438 if (pi->info_setup_frame_num == 0){
442 /* check wether we already have a RTP stream with this setup frame and ssrc in the list */
443 list = g_list_first(tapinfo->list);
446 tmp_listinfo=list->data;
447 if ( (tmp_listinfo->setup_frame_number == pi->info_setup_frame_num)
448 && (tmp_listinfo->ssrc == pi->info_sync_src) && (tmp_listinfo->end_stream == FALSE)){
449 /* if the payload type has changed, we mark the stream as finished to create a new one
450 this is to show multiple payload changes in the Graph for example for DTMF RFC2833 */
451 if ( tmp_listinfo->pt != pi->info_payload_type )
452 tmp_listinfo->end_stream = TRUE;
454 strinfo = (voip_rtp_stream_info_t*)(list->data);
458 list = g_list_next (list);
461 /* not in the list? then create a new entry */
463 strinfo = g_malloc(sizeof(voip_rtp_stream_info_t));
464 COPY_ADDRESS(&(strinfo->src_addr), &(pinfo->src));
465 strinfo->src_port = pinfo->srcport;
466 COPY_ADDRESS(&(strinfo->dest_addr), &(pinfo->dst));
467 strinfo->dest_port = pinfo->destport;
468 strinfo->ssrc = pi->info_sync_src;
469 strinfo->end_stream = FALSE;
470 strinfo->pt = pi->info_payload_type;
471 strinfo->pt_str = NULL;
472 /* if it is dynamic payload, let use the conv data to see if it is defined */
473 if ( (strinfo->pt>95) && (strinfo->pt<128) ) {
474 /* Use existing packet info if available */
475 p_conv_data = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name("rtp"));
477 strinfo->pt_str = g_strdup(g_hash_table_lookup(p_conv_data->rtp_dyn_payload, &strinfo->pt));
479 if (!strinfo->pt_str) strinfo->pt_str = g_strdup(val_to_str(strinfo->pt, rtp_payload_type_short_vals, "%u"));
480 strinfo->npackets = 0;
481 strinfo->first_frame_num = pinfo->fd->num;
482 strinfo->start_rel_sec = pinfo->fd->rel_secs;
483 strinfo->start_rel_usec = pinfo->fd->rel_usecs;
484 strinfo->setup_frame_number = pi->info_setup_frame_num;
485 strinfo->rtp_event = -1;
486 tapinfo->list = g_list_append(tapinfo->list, strinfo);
490 /* Add the info to the existing RTP stream */
492 strinfo->stop_rel_sec = pinfo->fd->rel_secs;
493 strinfo->stop_rel_usec = pinfo->fd->rel_usecs;
496 the_tapinfo_struct.redraw = TRUE;
501 /****************************************************************************/
502 /* whenever a redraw in the RTP tap listener */
503 void RTP_packet_draw(void *prs _U_)
505 voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
506 GList* rtp_streams_list;
507 voip_rtp_stream_info_t *rtp_listinfo;
508 GList* voip_calls_graph_list;
510 graph_analysis_item_t *gai;
511 graph_analysis_item_t *new_gai;
515 /* add each rtp stream to the graph */
516 rtp_streams_list = g_list_first(rtp_tapinfo->list);
517 while (rtp_streams_list)
519 rtp_listinfo = rtp_streams_list->data;
521 /* using the setup frame number of the RTP stream, we get the call number that it belongs */
522 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
524 while (voip_calls_graph_list)
526 gai = voip_calls_graph_list->data;
527 conv_num = gai->conv_num;
528 /* if we get the setup frame number, then get the time position to graph the RTP arrow */
529 if (rtp_listinfo->setup_frame_number == gai->frame_num){
530 while(voip_calls_graph_list){
531 gai = voip_calls_graph_list->data;
532 /* if RTP was already in the Graph, just update the comment information */
533 if (rtp_listinfo->first_frame_num == gai->frame_num){
534 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
535 g_free(gai->comment);
536 gai->comment = g_strdup_printf("RTP Num packets:%d Duration:%d.%03ds ssrc:%d", rtp_listinfo->npackets, duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
538 /* add the RTP item to the graph if was not there*/
539 } else if (rtp_listinfo->first_frame_num<gai->frame_num){
540 new_gai = g_malloc(sizeof(graph_analysis_item_t));
541 new_gai->frame_num = rtp_listinfo->first_frame_num;
542 new_gai->time = (double)rtp_listinfo->start_rel_sec + (double)rtp_listinfo->start_rel_usec/1000000;
543 COPY_ADDRESS(&(new_gai->src_addr),&(rtp_listinfo->src_addr));
544 COPY_ADDRESS(&(new_gai->dst_addr),&(rtp_listinfo->dest_addr));
545 new_gai->port_src = rtp_listinfo->src_port;
546 new_gai->port_dst = rtp_listinfo->dest_port;
547 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
548 new_gai->frame_label = g_strdup_printf("RTP (%s) %s", rtp_listinfo->pt_str, (rtp_listinfo->rtp_event == -1)?"":val_to_str(rtp_listinfo->rtp_event, rtp_event_type_values, "Uknown RTP Event"));
549 g_free(rtp_listinfo->pt_str);
550 new_gai->comment = g_strdup_printf("RTP Num packets:%d Duration:%d.%03ds ssrc:%d", rtp_listinfo->npackets, duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
551 new_gai->conv_num = conv_num;
552 new_gai->display=FALSE;
553 new_gai->line_style = 2; /* the arrow line will be 2 pixels width */
554 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item);
558 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
563 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
566 rtp_streams_list = g_list_next(rtp_streams_list);
570 static gboolean have_RTP_tap_listener=FALSE;
571 /****************************************************************************/
575 GString *error_string;
577 if(have_RTP_tap_listener==FALSE)
579 /* don't register tap listener, if we have it already */
580 error_string = register_tap_listener("rtp", &(the_tapinfo_rtp_struct.rtp_dummy), NULL,
585 if (error_string != NULL) {
586 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
588 g_string_free(error_string, TRUE);
591 have_RTP_tap_listener=TRUE;
595 /****************************************************************************/
597 remove_tap_listener_rtp(void)
599 protect_thread_critical_region();
600 remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_dummy));
601 unprotect_thread_critical_region();
603 have_RTP_tap_listener=FALSE;
606 /****************************************************************************/
607 static gchar *sdp_summary = NULL;
608 static guint32 sdp_frame_num = 0;
610 /****************************************************************************/
611 /* ***************************TAP for SIP **********************************/
612 /****************************************************************************/
614 /****************************************************************************/
615 /* whenever a SIP packet is seen by the tap listener */
617 SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SIPinfo)
619 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
620 /* we just take note of the ISUP data here; when we receive the MTP3 part everything will
621 be compared with existing calls */
623 voip_calls_info_t *tmp_listinfo;
624 voip_calls_info_t *strinfo = NULL;
625 sip_calls_info_t *tmp_sipinfo = NULL;
627 address tmp_src, tmp_dst;
628 gchar *frame_label = NULL;
629 gchar *comment = NULL;
631 const sip_info_value_t *pi = SIPinfo;
633 /* do not consider packets without call_id */
634 if (pi->tap_call_id ==NULL){
638 /* check wether we already have a call with these parameters in the list */
639 list = g_list_first(tapinfo->strinfo_list);
642 tmp_listinfo=list->data;
643 if (tmp_listinfo->protocol == VOIP_SIP){
644 tmp_sipinfo = tmp_listinfo->prot_info;
645 if (strcmp(tmp_sipinfo->call_identifier,pi->tap_call_id)==0){
646 strinfo = (voip_calls_info_t*)(list->data);
650 list = g_list_next (list);
653 /* not in the list? then create a new entry if the message is INVITE -i.e. if this session is a call*/
654 if ((strinfo==NULL) &&(pi->request_method!=NULL)){
655 if (strcmp(pi->request_method,"INVITE")==0){
656 strinfo = g_malloc(sizeof(voip_calls_info_t));
657 strinfo->call_active_state = VOIP_ACTIVE;
658 strinfo->call_state = VOIP_CALL_SETUP;
659 strinfo->from_identity=g_strdup(pi->tap_from_addr);
660 strinfo->to_identity=g_strdup(pi->tap_to_addr);
661 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
662 strinfo->first_frame_num=pinfo->fd->num;
663 strinfo->selected=FALSE;
664 strinfo->start_sec=pinfo->fd->rel_secs;
665 strinfo->start_usec=pinfo->fd->rel_usecs;
666 strinfo->protocol=VOIP_SIP;
667 strinfo->prot_info=g_malloc(sizeof(sip_calls_info_t));
668 tmp_sipinfo=strinfo->prot_info;
669 tmp_sipinfo->call_identifier=strdup(pi->tap_call_id);
670 tmp_sipinfo->sip_state=SIP_INVITE_SENT;
671 tmp_sipinfo->invite_cseq=pi->tap_cseq_number;
672 strinfo->npackets = 0;
673 strinfo->call_num = tapinfo->ncalls++;
674 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
680 /* let's analyze the call state */
682 COPY_ADDRESS(&(tmp_src), &(pinfo->src));
683 COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
685 if (pi->request_method == NULL){
686 frame_label = g_strdup_printf("%d %s", pi->response_code, pi->reason_phrase );
687 comment = g_strdup_printf("SIP Status");
689 if ((tmp_sipinfo && pi->tap_cseq_number == tmp_sipinfo->invite_cseq)&&(ADDRESSES_EQUAL(&tmp_dst,&(strinfo->initial_speaker)))){
690 if ((pi->response_code > 199) && (pi->response_code<300) && (tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
691 tmp_sipinfo->sip_state = SIP_200_REC;
693 else if ((pi->response_code>299)&&(tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
694 strinfo->call_state = VOIP_REJECTED;
695 tapinfo->rejected_calls++;
701 frame_label = g_strdup(pi->request_method);
703 if ((strcmp(pi->request_method,"INVITE")==0)&&(ADDRESSES_EQUAL(&tmp_src,&(strinfo->initial_speaker)))){
704 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
705 strinfo->call_state = VOIP_CALL_SETUP;
706 comment = g_strdup_printf("SIP From: %s To:%s", strinfo->from_identity, strinfo->to_identity);
708 else if ((strcmp(pi->request_method,"ACK")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
709 &&(ADDRESSES_EQUAL(&tmp_src,&(strinfo->initial_speaker)))&&(tmp_sipinfo->sip_state==SIP_200_REC)
710 &&(strinfo->call_state == VOIP_CALL_SETUP)){
711 strinfo->call_state = VOIP_IN_CALL;
712 comment = g_strdup_printf("SIP Request");
714 else if (strcmp(pi->request_method,"BYE")==0){
715 strinfo->call_state = VOIP_COMPLETED;
716 tapinfo->completed_calls++;
717 comment = g_strdup_printf("SIP Request");
719 else if ((strcmp(pi->request_method,"CANCEL")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
720 &&(ADDRESSES_EQUAL(&tmp_src,&(strinfo->initial_speaker)))&&(strinfo->call_state==VOIP_CALL_SETUP)){
721 strinfo->call_state = VOIP_CANCELLED;
722 tmp_sipinfo->sip_state = SIP_CANCEL_SENT;
723 comment = g_strdup_printf("SIP Request");
725 comment = g_strdup_printf("SIP Request");
729 strinfo->stop_sec=pinfo->fd->rel_secs;
730 strinfo->stop_usec=pinfo->fd->rel_usecs;
731 strinfo->last_frame_num=pinfo->fd->num;
732 ++(strinfo->npackets);
733 /* increment the packets counter of all calls */
734 ++(tapinfo->npackets);
736 /* add to the graph */
737 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst));
740 g_free((void *)tmp_src.data);
741 g_free((void *)tmp_dst.data);
743 /* add SDP info if apply */
744 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
745 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
751 tapinfo->redraw = TRUE;
753 return 1; /* refresh output */
757 /****************************************************************************/
758 voip_calls_tapinfo_t* voip_calls_get_info(void)
760 return &the_tapinfo_struct;
764 /****************************************************************************/
766 /****************************************************************************/
767 static gboolean have_SIP_tap_listener=FALSE;
768 /****************************************************************************/
770 sip_calls_init_tap(void)
772 GString *error_string;
774 if(have_SIP_tap_listener==FALSE)
776 /* don't register tap listener, if we have it already */
777 error_string = register_tap_listener("sip", &(the_tapinfo_struct.sip_dummy), NULL,
778 voip_calls_dlg_reset,
782 if (error_string != NULL) {
783 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
785 g_string_free(error_string, TRUE);
788 have_SIP_tap_listener=TRUE;
794 /* XXX just copied from gtk/rpc_stat.c */
795 void protect_thread_critical_region(void);
796 void unprotect_thread_critical_region(void);
798 /****************************************************************************/
800 remove_tap_listener_sip_calls(void)
802 protect_thread_critical_region();
803 remove_tap_listener(&(the_tapinfo_struct.sip_dummy));
804 unprotect_thread_critical_region();
806 have_SIP_tap_listener=FALSE;
809 /****************************************************************************/
810 /* ***************************TAP for ISUP **********************************/
811 /****************************************************************************/
813 static guint32 mtp3_opc, mtp3_dpc;
814 static guint8 mtp3_ni;
815 static guint32 mtp3_frame_num;
818 /****************************************************************************/
819 /* whenever a isup_ packet is seen by the tap listener */
821 isup_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *isup_info _U_)
823 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
824 voip_calls_info_t *tmp_listinfo;
825 voip_calls_info_t *strinfo = NULL;
826 isup_calls_info_t *tmp_isupinfo;
827 gboolean found = FALSE;
828 gboolean forward = FALSE;
831 gchar *frame_label = NULL;
832 gchar *comment = NULL;
835 /*voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct; unused */
836 const isup_tap_rec_t *pi = isup_info;
839 /* check if the lower layer is MTP matching the frame number */
840 if (mtp3_frame_num != pinfo->fd->num) return 0;
842 /* check wether we already have a call with these parameters in the list */
843 list = g_list_first(tapinfo->strinfo_list);
847 tmp_listinfo=list->data;
848 if ((tmp_listinfo->protocol == VOIP_ISUP)&&(tmp_listinfo->call_active_state==VOIP_ACTIVE)){
849 tmp_isupinfo = tmp_listinfo->prot_info;
850 if ((tmp_isupinfo->cic == pinfo->circuit_id)&&(tmp_isupinfo->ni == mtp3_ni)) {
851 if ((tmp_isupinfo->opc == mtp3_opc)&&(tmp_isupinfo->dpc == mtp3_dpc)){
854 else if ((tmp_isupinfo->dpc == mtp3_opc)&&(tmp_isupinfo->opc == mtp3_dpc)){
861 /* if there is an IAM for a call that is not in setup state, that means the previous call in the same
862 cic is no longer active */
863 if (tmp_listinfo->call_state == VOIP_CALL_SETUP){
866 else if (pi->message_type != 1){
870 tmp_listinfo->call_active_state=VOIP_INACTIVE;
874 strinfo = (voip_calls_info_t*)(list->data);
879 list = g_list_next (list);
882 /* not in the list? then create a new entry if the message is IAM
883 -i.e. if this session is a call*/
886 if ((strinfo==NULL) &&(pi->message_type==1)){
888 strinfo = g_malloc(sizeof(voip_calls_info_t));
889 strinfo->call_active_state = VOIP_ACTIVE;
890 strinfo->call_state = VOIP_UNKNOWN;
891 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
892 strinfo->selected=FALSE;
893 strinfo->first_frame_num=pinfo->fd->num;
894 strinfo->start_sec=pinfo->fd->rel_secs;
895 strinfo->start_usec=pinfo->fd->rel_usecs;
896 strinfo->protocol=VOIP_ISUP;
897 if (pi->calling_number!=NULL){
898 strinfo->from_identity=g_strdup(pi->calling_number);
900 if (pi->called_number!=NULL){
901 strinfo->to_identity=g_strdup(pi->called_number);
903 strinfo->prot_info=g_malloc(sizeof(isup_calls_info_t));
904 tmp_isupinfo=strinfo->prot_info;
905 tmp_isupinfo->opc = mtp3_opc;
906 tmp_isupinfo->dpc = mtp3_dpc;
907 tmp_isupinfo->ni = mtp3_ni;
908 tmp_isupinfo->cic = pinfo->circuit_id;
909 strinfo->npackets = 0;
910 strinfo->call_num = tapinfo->ncalls++;
911 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
915 strinfo->stop_sec=pinfo->fd->rel_secs;
916 strinfo->stop_usec=pinfo->fd->rel_usecs;
917 strinfo->last_frame_num=pinfo->fd->num;
918 ++(strinfo->npackets);
920 /* Let's analyze the call state */
923 for (i=0;(isup_message_type_value[i].strptr!=NULL)&& (isup_message_type_value[i].value!=pi->message_type);i++);
925 if (isup_message_type_value[i].value==pi->message_type){
926 frame_label = g_strdup(isup_message_type_value_acro[i].strptr);
929 frame_label = g_strdup_printf("Unknown");
932 if (strinfo->npackets == 1){ /* this is the first packet, that must be an IAM */
933 if ((pi->calling_number!=NULL)&&(pi->called_number !=NULL)){
934 comment = g_strdup_printf("Call from %s to %s",
935 pi->calling_number, pi->called_number);
938 else if (strinfo->npackets == 2){ /* in the second packet we show the SPs */
940 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
942 mtp3_ni, mtp3_dpc, pinfo->circuit_id);
946 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
948 mtp3_ni, mtp3_opc, pinfo->circuit_id);
953 switch(pi->message_type){
955 strinfo->call_state=VOIP_CALL_SETUP;
957 case 7: /* CONNECT */
959 strinfo->call_state=VOIP_IN_CALL;
961 case 12: /* RELEASE */
962 if (strinfo->call_state==VOIP_CALL_SETUP){
964 strinfo->call_state=VOIP_CANCELLED;
967 strinfo->call_state=VOIP_REJECTED;
968 tapinfo->rejected_calls++;
971 else if (strinfo->call_state == VOIP_IN_CALL){
972 strinfo->call_state = VOIP_COMPLETED;
973 tapinfo->completed_calls++;
975 for (i=0;(q931_cause_code_vals[i].strptr!=NULL)&& (q931_cause_code_vals[i].value!=pi->cause_value);i++);
976 if (q931_cause_code_vals[i].value==pi->cause_value){
977 comment = g_strdup_printf("Cause %i - %s",pi->cause_value, q931_cause_code_vals[i].strptr);
980 comment = g_strdup_printf("Cause %i",pi->cause_value);
985 /* increment the packets counter of all calls */
986 ++(tapinfo->npackets);
988 /* add to the graph */
989 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst));
994 tapinfo->redraw = TRUE;
996 return 1; /* refresh output */
999 /****************************************************************************/
1001 static gboolean have_isup_tap_listener=FALSE;
1004 isup_calls_init_tap(void)
1006 GString *error_string;
1009 if(have_isup_tap_listener==FALSE)
1011 error_string = register_tap_listener("isup", &(the_tapinfo_struct.isup_dummy),
1013 voip_calls_dlg_reset,
1018 if (error_string != NULL) {
1019 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1021 g_string_free(error_string, TRUE);
1024 have_isup_tap_listener=TRUE;
1028 /****************************************************************************/
1031 remove_tap_listener_isup_calls(void)
1033 protect_thread_critical_region();
1034 remove_tap_listener(&(the_tapinfo_struct.isup_dummy));
1035 unprotect_thread_critical_region();
1037 have_isup_tap_listener=FALSE;
1041 /****************************************************************************/
1042 /* ***************************TAP for MTP3 **********************************/
1043 /****************************************************************************/
1046 /****************************************************************************/
1047 /* whenever a mtp3_ packet is seen by the tap listener */
1049 mtp3_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *mtp3_info _U_)
1051 const mtp3_tap_rec_t *pi = mtp3_info;
1053 /* keep the data in memory to use when the ISUP information arrives */
1055 mtp3_opc = pi->addr_opc.pc;
1056 mtp3_dpc = pi->addr_dpc.pc;
1057 mtp3_ni = pi->addr_opc.ni;
1058 mtp3_frame_num = pinfo->fd->num;
1063 /****************************************************************************/
1065 static gboolean have_mtp3_tap_listener=FALSE;
1068 mtp3_calls_init_tap(void)
1070 GString *error_string;
1073 if(have_mtp3_tap_listener==FALSE)
1075 error_string = register_tap_listener("mtp3", &(the_tapinfo_struct.mtp3_dummy),
1077 voip_calls_dlg_reset,
1082 if (error_string != NULL) {
1083 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1085 g_string_free(error_string, TRUE);
1088 have_mtp3_tap_listener=TRUE;
1092 /****************************************************************************/
1095 remove_tap_listener_mtp3_calls(void)
1097 protect_thread_critical_region();
1098 remove_tap_listener(&(the_tapinfo_struct.mtp3_dummy));
1099 unprotect_thread_critical_region();
1101 have_mtp3_tap_listener=FALSE;
1104 /****************************************************************************/
1105 /* ***************************TAP for Q931 **********************************/
1106 /****************************************************************************/
1107 void h245_add_to_graph(guint32 new_frame_num);
1109 static const guint8 guid_allzero[GUID_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1110 /* defines specific H323 data */
1112 static gchar *q931_calling_number;
1113 static gchar *q931_called_number;
1114 static guint8 q931_cause_value;
1115 static gint32 q931_crv;
1116 static guint32 q931_frame_num;
1118 static guint32 h225_frame_num = 0;
1119 static guint16 h225_call_num = 0;
1120 static h225_cs_type h225_cstype = H225_OTHER;
1121 static gboolean h225_is_faststart;
1123 static guint32 actrace_frame_num = 0;
1124 static gint32 actrace_trunk = 0;
1125 static gint32 actrace_direction = 0;
1128 /****************************************************************************/
1129 /* whenever a q931_ packet is seen by the tap listener */
1131 q931_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *q931_info _U_)
1134 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1135 h323_calls_info_t *tmp_h323info,*tmp2_h323info;
1136 actrace_isdn_calls_info_t *tmp_actrace_isdn_info;
1137 voip_calls_info_t *tmp_listinfo;
1138 voip_calls_info_t *strinfo = NULL;
1139 h245_address_t *h245_add = NULL;
1142 const q931_packet_info *pi = q931_info;
1144 /* free previously allocated q931_calling/ed_number */
1145 g_free(q931_calling_number);
1146 g_free(q931_called_number);
1148 if (pi->calling_number!=NULL)
1149 q931_calling_number = g_strdup(pi->calling_number);
1151 q931_calling_number = g_strdup("");
1153 if (pi->called_number!=NULL)
1154 q931_called_number = g_strdup(pi->called_number);
1156 q931_called_number = g_strdup("");
1157 q931_cause_value = pi->cause_value;
1158 q931_frame_num = pinfo->fd->num;
1162 /* add staff to H323 calls */
1163 if (h225_frame_num == q931_frame_num) {
1164 tmp_h323info = NULL;
1165 list = g_list_first(tapinfo->strinfo_list);
1168 tmp_listinfo=list->data;
1169 if ( (tmp_listinfo->protocol == VOIP_H323) && (tmp_listinfo->call_num == h225_call_num) ){
1170 tmp_h323info = tmp_listinfo->prot_info;
1171 strinfo = (voip_calls_info_t*)(list->data);
1173 /* Add the CRV to the h323 call */
1174 if (tmp_h323info->q931_crv == -1) {
1175 tmp_h323info->q931_crv = q931_crv;
1176 } else if (tmp_h323info->q931_crv != q931_crv) {
1177 tmp_h323info->q931_crv2 = q931_crv;
1181 list = g_list_next (list);
1184 if (strinfo != NULL) {
1186 if (h225_cstype == H225_SETUP) {
1187 /* set te calling and called number from the Q931 packet */
1188 if (q931_calling_number != NULL){
1189 g_free(strinfo->from_identity);
1190 strinfo->from_identity=g_strdup(q931_calling_number);
1192 if (q931_called_number != NULL){
1193 g_free(strinfo->to_identity);
1194 strinfo->to_identity=g_strdup(q931_called_number);
1197 /* check if there is an LRQ/LCF that match this Setup */
1198 /* TODO: we are just checking the DialedNumer in LRQ/LCF agains the Setup
1199 we should also check if the h225 signaling IP and port match the destination
1200 Setup ip and port */
1201 list = g_list_first(tapinfo->strinfo_list);
1204 tmp_listinfo=list->data;
1205 if (tmp_listinfo->protocol == VOIP_H323){
1206 tmp2_h323info = tmp_listinfo->prot_info;
1208 /* check if the called number match a LRQ/LCF */
1209 if ( (strcmp(strinfo->to_identity, tmp_listinfo->to_identity)==0)
1210 && (memcmp(tmp2_h323info->guid, guid_allzero, GUID_LEN) == 0) ){
1211 /* change the call graph to the LRQ/LCF to belong to this call */
1212 strinfo->npackets += change_call_num_graph(tapinfo, tmp_listinfo->call_num, strinfo->call_num);
1214 /* remove this LRQ/LCF call entry because we have found the Setup that match them */
1215 g_free(tmp_listinfo->from_identity);
1216 g_free(tmp_listinfo->to_identity);
1217 g_free(tmp2_h323info->guid);
1219 list2 = g_list_first(tmp2_h323info->h245_list);
1222 h245_add=list2->data;
1223 g_free((void *)h245_add->h245_address.data);
1224 g_free(list2->data);
1225 list2 = g_list_next(list2);
1227 g_list_free(tmp_h323info->h245_list);
1228 tmp_h323info->h245_list = NULL;
1229 g_free(tmp_listinfo->prot_info);
1230 tapinfo->strinfo_list = g_list_remove(tapinfo->strinfo_list, tmp_listinfo);
1234 list = g_list_next (list);
1237 comment = g_strdup_printf("H225 From: %s To:%s TunnH245:%s FS:%s", strinfo->from_identity, strinfo->to_identity, (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1238 (h225_is_faststart==TRUE?"on":"off"));
1239 } else if (h225_cstype == H225_RELEASE_COMPLET) {
1240 /* get the Q931 Release cause code */
1241 if (q931_cause_value != 0xFF){
1242 comment = g_strdup_printf("H225 Q931 Rel Cause (%i):%s", q931_cause_value, val_to_str(q931_cause_value, q931_cause_code_vals, "<unknown>"));
1243 } else { /* Cause not set */
1244 comment = g_strdup("H225 No Q931 Rel Cause");
1247 /* change the graph comment for this new one */
1248 if (comment != NULL) {
1249 change_frame_graph(tapinfo, h225_frame_num, NULL, comment);
1253 /* we reset the h225_frame_num to 0 because there could be empty h225 in the same frame
1254 as non empty h225 (e.g connect), so we don't have to be here twice */
1257 /* add staff to H245 */
1258 } else if (h245_labels.frame_num == q931_frame_num) {
1259 /* there are empty H225 frames that don't have guid (guaid=0) but they have h245 info,
1260 so the only way to match those frames is with the Q931 CRV number */
1261 list = g_list_first(tapinfo->strinfo_list);
1264 tmp_listinfo=list->data;
1265 if (tmp_listinfo->protocol == VOIP_H323){
1266 tmp_h323info = tmp_listinfo->prot_info;
1267 if ( ((tmp_h323info->q931_crv == q931_crv) || (tmp_h323info->q931_crv2 == q931_crv)) && (q931_crv!=-1)){
1269 comment = g_strdup("");
1271 /* if the frame number exists in graph, append to it*/
1272 if (!append_to_frame_graph(tapinfo, q931_frame_num, "", comment)) {
1273 /* if not exist, add to the graph */
1274 add_to_graph(tapinfo, pinfo, "", comment, tmp_listinfo->call_num, &(pinfo->src), &(pinfo->dst));
1275 ++(tmp_listinfo->npackets);
1276 /* increment the packets counter of all calls */
1277 ++(tapinfo->npackets);
1280 /* Add the H245 info if exists to the Graph */
1281 h245_add_to_graph(pinfo->fd->num);
1286 list = g_list_next (list);
1289 /* add staff to ACTRACE */
1290 } else if (actrace_frame_num == q931_frame_num) {
1292 gchar *comment = NULL;
1295 list = g_list_first(tapinfo->strinfo_list);
1298 tmp_listinfo=list->data;
1299 if ( tmp_listinfo->protocol == VOIP_AC_ISDN ){
1300 tmp_actrace_isdn_info = tmp_listinfo->prot_info;
1301 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
1302 if ( (tmp_actrace_isdn_info->crv == q931_crv) && (tmp_actrace_isdn_info->trunk == actrace_trunk) ) {
1303 strinfo = (voip_calls_info_t*)(list->data);
1307 list = g_list_next (list);
1310 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, g_strdup("PSTN"));
1312 /* if it is a new call, add it to the list */
1314 strinfo = g_malloc(sizeof(voip_calls_info_t));
1315 strinfo->call_active_state = VOIP_ACTIVE;
1316 strinfo->call_state = VOIP_CALL_SETUP;
1317 strinfo->from_identity=g_strdup(q931_calling_number);
1318 strinfo->to_identity=g_strdup(q931_called_number);
1319 COPY_ADDRESS(&(strinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
1320 strinfo->first_frame_num=pinfo->fd->num;
1321 strinfo->selected=FALSE;
1322 strinfo->start_sec=pinfo->fd->rel_secs;
1323 strinfo->start_usec=pinfo->fd->rel_usecs;
1324 strinfo->protocol=VOIP_AC_ISDN;
1325 strinfo->prot_info=g_malloc(sizeof(actrace_isdn_calls_info_t));
1326 tmp_actrace_isdn_info=strinfo->prot_info;
1327 tmp_actrace_isdn_info->crv=q931_crv;
1328 tmp_actrace_isdn_info->trunk=actrace_trunk;
1329 strinfo->npackets = 0;
1330 strinfo->call_num = tapinfo->ncalls++;
1331 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
1334 strinfo->stop_sec=pinfo->fd->rel_secs;
1335 strinfo->stop_usec=pinfo->fd->rel_usecs;
1336 strinfo->last_frame_num=pinfo->fd->num;
1337 ++(strinfo->npackets);
1338 /* increment the packets counter of all calls */
1339 ++(tapinfo->npackets);
1341 switch(pi->message_type){
1343 comment = g_strdup_printf("AC_ISDN trunk:%u Calling: %s Called:%s", actrace_trunk, q931_calling_number, q931_called_number);
1344 strinfo->call_state=VOIP_CALL_SETUP;
1347 strinfo->call_state=VOIP_IN_CALL;
1349 case Q931_RELEASE_COMPLETE:
1351 case Q931_DISCONNECT:
1352 if (strinfo->call_state==VOIP_CALL_SETUP){
1353 if (ADDRESSES_EQUAL(&(strinfo->initial_speaker), actrace_direction?&pstn_add:&(pinfo->src) )){ /* forward direction */
1354 strinfo->call_state=VOIP_CANCELLED;
1357 strinfo->call_state=VOIP_REJECTED;
1358 tapinfo->rejected_calls++;
1360 } else if ( (strinfo->call_state!=VOIP_CANCELLED) && (strinfo->call_state!=VOIP_REJECTED) ){
1361 strinfo->call_state=VOIP_COMPLETED;
1362 tapinfo->completed_calls++;
1364 if (q931_cause_value != 0xFF){
1365 comment = g_strdup_printf("AC_ISDN trunk:%u Q931 Rel Cause (%i):%s", actrace_trunk, q931_cause_value, val_to_str(q931_cause_value, q931_cause_code_vals, "<unknown>"));
1366 } else { /* Cause not set */
1367 comment = g_strdup("AC_ISDN No Q931 Rel Cause");
1373 comment = g_strdup_printf("AC_ISDN trunk:%u", actrace_trunk );
1375 add_to_graph(tapinfo, pinfo, val_to_str(pi->message_type, q931_message_type_vals, "<unknown>") , comment, strinfo->call_num,
1376 actrace_direction?&pstn_add:&(pinfo->src),
1377 actrace_direction?&(pinfo->src):&pstn_add);
1380 g_free((char *)pstn_add.data);
1383 tapinfo->redraw = TRUE;
1385 return 1; /* refresh output */
1388 /****************************************************************************/
1389 static gboolean have_q931_tap_listener=FALSE;
1392 q931_calls_init_tap(void)
1394 GString *error_string;
1397 if(have_q931_tap_listener==FALSE)
1399 error_string = register_tap_listener("q931", &(the_tapinfo_struct.q931_dummy),
1401 voip_calls_dlg_reset,
1406 if (error_string != NULL) {
1407 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1409 g_string_free(error_string, TRUE);
1412 have_q931_tap_listener=TRUE;
1416 /****************************************************************************/
1419 remove_tap_listener_q931_calls(void)
1421 protect_thread_critical_region();
1422 remove_tap_listener(&(the_tapinfo_struct.q931_dummy));
1423 unprotect_thread_critical_region();
1425 have_q931_tap_listener=FALSE;
1428 /****************************************************************************/
1429 /****************************TAP for H323 ***********************************/
1430 /****************************************************************************/
1432 void add_h245_Address(h323_calls_info_t *h323info, h245_address_t *h245_address)
1434 h323info->h245_list = g_list_append(h323info->h245_list, h245_address);
1437 /****************************************************************************/
1438 /* whenever a H225 packet is seen by the tap listener */
1440 H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H225info)
1442 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1443 voip_calls_info_t *tmp_listinfo;
1444 voip_calls_info_t *strinfo = NULL;
1445 h323_calls_info_t *tmp_h323info = NULL;
1449 address tmp_src, tmp_dst;
1450 h245_address_t *h245_add = NULL;
1452 const h225_packet_info *pi = H225info;
1454 /* if not guid and RAS and not LRQ, LCF or LRJ return because did not belong to a call */
1455 /* OR, if not guid and is H225 return because doesn't belong to a call */
1456 if ((memcmp(pi->guid, guid_allzero, GUID_LEN) == 0))
1457 if ( ((pi->msg_type == H225_RAS) && ((pi->msg_tag < 18) || (pi->msg_tag > 20))) || (pi->msg_type != H225_RAS) )
1460 /* if it is RAS LCF or LRJ*/
1461 if ( (pi->msg_type == H225_RAS) && ((pi->msg_tag == 19) || (pi->msg_tag == 20))) {
1462 /* if the LCF/LRJ doesn't match to a LRQ, just return */
1463 if (!pi->request_available) return 0;
1465 /* check wether we already have a call with this request SeqNum */
1466 list = g_list_first(tapinfo->strinfo_list);
1469 tmp_listinfo=list->data;
1470 if (tmp_listinfo->protocol == VOIP_H323){
1471 tmp_h323info = tmp_listinfo->prot_info;
1472 if (tmp_h323info->requestSeqNum == pi->requestSeqNum) {
1473 strinfo = (voip_calls_info_t*)(list->data);
1477 list = g_list_next (list);
1480 /* check wether we already have a call with this guid in the list */
1481 list = g_list_first(tapinfo->strinfo_list);
1484 tmp_listinfo=list->data;
1485 if (tmp_listinfo->protocol == VOIP_H323){
1486 tmp_h323info = tmp_listinfo->prot_info;
1487 if ( (memcmp(tmp_h323info->guid, guid_allzero, GUID_LEN) != 0) && (memcmp(tmp_h323info->guid, pi->guid,GUID_LEN)==0) ){
1488 strinfo = (voip_calls_info_t*)(list->data);
1492 list = g_list_next (list);
1496 h225_cstype = pi->cs_type;
1497 h225_is_faststart = pi->is_faststart;
1499 /* not in the list? then create a new entry */
1500 if ((strinfo==NULL)){
1501 strinfo = g_malloc(sizeof(voip_calls_info_t));
1502 strinfo->call_active_state = VOIP_ACTIVE;
1503 strinfo->call_state = VOIP_UNKNOWN;
1504 strinfo->from_identity=g_strdup("");
1505 strinfo->to_identity=g_strdup("");
1506 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
1507 strinfo->selected=FALSE;
1508 strinfo->first_frame_num=pinfo->fd->num;
1509 strinfo->start_sec=pinfo->fd->rel_secs;
1510 strinfo->start_usec=pinfo->fd->rel_usecs;
1511 strinfo->protocol=VOIP_H323;
1512 strinfo->prot_info=g_malloc(sizeof(h323_calls_info_t));
1513 tmp_h323info = strinfo->prot_info;
1514 tmp_h323info->guid = (guint8 *) g_memdup(pi->guid,GUID_LEN);
1515 tmp_h323info->h225SetupAddr.type = AT_NONE;
1516 tmp_h323info->h225SetupAddr.len = 0;
1517 tmp_h323info->h245_list = NULL;
1518 tmp_h323info->is_faststart_Setup = FALSE;
1519 tmp_h323info->is_faststart_Proc = FALSE;
1520 tmp_h323info->is_h245Tunneling = FALSE;
1521 tmp_h323info->is_h245 = FALSE;
1522 tmp_h323info->q931_crv = -1;
1523 tmp_h323info->q931_crv2 = -1;
1524 tmp_h323info->requestSeqNum = 0;
1525 strinfo->call_num = tapinfo->ncalls++;
1526 strinfo->npackets = 0;
1528 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
1533 h225_frame_num = pinfo->fd->num;
1534 h225_call_num = strinfo->call_num;
1536 /* let's analyze the call state */
1538 COPY_ADDRESS(&(tmp_src),&(pinfo->src));
1539 COPY_ADDRESS(&(tmp_dst),&(pinfo->dst));
1541 strinfo->stop_sec=pinfo->fd->rel_secs;
1542 strinfo->stop_usec=pinfo->fd->rel_usecs;
1543 strinfo->last_frame_num=pinfo->fd->num;
1544 ++(strinfo->npackets);
1545 /* increment the packets counter of all calls */
1546 ++(tapinfo->npackets);
1549 /* XXX: it is supposed to be initialized isn't it? */
1550 g_assert(tmp_h323info != NULL);
1552 /* change the status */
1553 if (pi->msg_type == H225_CS){
1555 /* this is still IPv4 only, because the dissector is */
1556 if (pi->is_h245 == TRUE){
1557 h245_add = g_malloc(sizeof (h245_address_t));
1558 h245_add->h245_address.type=AT_IPv4;
1559 h245_add->h245_address.len=4;
1560 h245_add->h245_address.data = g_malloc(sizeof(pi->h245_address));
1561 g_memmove((void *)(h245_add->h245_address.data), &(pi->h245_address), 4);
1562 h245_add->h245_port = pi->h245_port;
1563 add_h245_Address(tmp_h323info, h245_add);
1566 if (pi->cs_type != H225_RELEASE_COMPLET) tmp_h323info->is_h245Tunneling = pi->is_h245Tunneling;
1568 frame_label = g_strdup(pi->frame_label);
1570 switch(pi->cs_type){
1572 tmp_h323info->is_faststart_Setup = pi->is_faststart;
1574 /* Set the Setup address if it was not set */
1575 if (tmp_h323info->h225SetupAddr.type == AT_NONE)
1576 COPY_ADDRESS(&(tmp_h323info->h225SetupAddr), &(pinfo->src));
1577 strinfo->call_state=VOIP_CALL_SETUP;
1578 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1579 (pi->is_faststart==TRUE?"on":"off"));
1582 strinfo->call_state=VOIP_IN_CALL;
1583 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1584 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1585 (pi->is_faststart==TRUE?"on":"off"));
1587 case H225_RELEASE_COMPLET:
1588 COPY_ADDRESS(&tmp_src,&(pinfo->src));
1589 if (strinfo->call_state==VOIP_CALL_SETUP){
1590 if (ADDRESSES_EQUAL(&(tmp_h323info->h225SetupAddr),&tmp_src)){ /* forward direction */
1591 strinfo->call_state=VOIP_CANCELLED;
1594 strinfo->call_state=VOIP_REJECTED;
1595 tapinfo->rejected_calls++;
1598 strinfo->call_state=VOIP_COMPLETED;
1599 tapinfo->completed_calls++;
1601 comment = g_strdup("H225 No Q931 Rel Cause");
1605 case H225_CALL_PROCEDING:
1606 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1607 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1608 (pi->is_faststart==TRUE?"on":"off"));
1611 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1612 (pi->is_faststart==TRUE?"on":"off"));
1616 else if (pi->msg_type == H225_RAS){
1617 switch(pi->msg_tag){
1619 if (!pi->is_duplicate){
1620 g_free(strinfo->to_identity);
1621 strinfo->to_identity=g_strdup(pi->dialedDigits);
1622 tmp_h323info->requestSeqNum = pi->requestSeqNum;
1625 if (strlen(pi->dialedDigits))
1626 comment = g_strdup_printf("H225 RAS dialedDigits: %s", pi->dialedDigits);
1628 comment = g_strdup("H225 RAS");
1631 comment = g_strdup("H225 RAS");
1633 frame_label = g_strdup_printf("%s", val_to_str(pi->msg_tag, RasMessage_vals, "<unknown>"));
1635 frame_label = g_strdup("H225: Unknown");
1636 comment = g_strdup("");
1639 /* add to graph analysis */
1641 /* if the frame number exists in graph, append to it*/
1642 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, comment)) {
1643 /* if not exist, add to the graph */
1644 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst));
1645 g_free((void *)tmp_src.data);
1646 g_free((void *)tmp_dst.data);
1649 /* Add the H245 info if exists to the Graph */
1650 h245_add_to_graph(pinfo->fd->num);
1652 g_free(frame_label);
1657 tapinfo->redraw = TRUE;
1659 return 1; /* refresh output */
1663 /****************************************************************************/
1665 /****************************************************************************/
1666 static gboolean have_H225_tap_listener=FALSE;
1667 /****************************************************************************/
1669 h225_calls_init_tap(void)
1671 GString *error_string;
1673 if(have_H225_tap_listener==FALSE)
1675 /* don't register tap listener, if we have it already */
1676 error_string = register_tap_listener("h225", &(the_tapinfo_struct.h225_dummy), NULL,
1677 voip_calls_dlg_reset,
1682 if (error_string != NULL) {
1683 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1685 g_string_free(error_string, TRUE);
1688 have_H225_tap_listener=TRUE;
1694 /* XXX just copied from gtk/rpc_stat.c */
1695 void protect_thread_critical_region(void);
1696 void unprotect_thread_critical_region(void);
1698 /****************************************************************************/
1700 remove_tap_listener_h225_calls(void)
1702 protect_thread_critical_region();
1703 remove_tap_listener(&(the_tapinfo_struct.h225_dummy));
1704 unprotect_thread_critical_region();
1706 have_H225_tap_listener=FALSE;
1709 /* Add the h245 label info to the graph */
1710 void h245_add_to_graph(guint32 new_frame_num)
1714 if (new_frame_num != h245_labels.frame_num) return;
1716 for (n=0; n<h245_labels.labels_count; n++) {
1717 append_to_frame_graph(&the_tapinfo_struct, new_frame_num, h245_labels.labels[n].frame_label, h245_labels.labels[n].comment);
1718 g_free(h245_labels.labels[n].frame_label);
1719 h245_labels.labels[n].frame_label = NULL;
1720 g_free(h245_labels.labels[n].comment);
1721 h245_labels.labels[n].comment = NULL;
1723 h245_labels.frame_num = 0;
1724 h245_labels.labels_count = 0;
1727 /* free the h245_labels if the frame number is different */
1728 void h245_free_labels(guint32 new_frame_num)
1732 if (new_frame_num == h245_labels.frame_num) return;
1734 for (n=0; n<h245_labels.labels_count; n++) {
1735 g_free(h245_labels.labels[n].frame_label);
1736 h245_labels.labels[n].frame_label = NULL;
1737 g_free(h245_labels.labels[n].comment);
1738 h245_labels.labels[n].comment = NULL;
1740 h245_labels.frame_num = 0;
1741 h245_labels.labels_count = 0;
1744 /* add the frame_label and comment to h245_labels and free the actual one if it is different frame num */
1745 void h245_add_label(guint32 new_frame_num, gchar *frame_label, gchar *comment)
1747 h245_free_labels(new_frame_num);
1749 h245_labels.frame_num = new_frame_num;
1750 h245_labels.labels[h245_labels.labels_count].frame_label = g_strdup(frame_label);
1751 h245_labels.labels[h245_labels.labels_count].comment = g_strdup(comment);
1753 if (h245_labels.labels_count < (H245_MAX-1))
1754 h245_labels.labels_count++;
1758 /****************************************************************************/
1759 /* whenever a H245dg packet is seen by the tap listener (when H245 tunneling is ON) */
1761 H245dgcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H245info)
1763 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1764 voip_calls_info_t *tmp_listinfo;
1765 voip_calls_info_t *strinfo = NULL;
1766 h323_calls_info_t *tmp_h323info;
1771 address tmp_src, tmp_dst;
1772 h245_address_t *h245_add = NULL;
1774 const h245_packet_info *pi = H245info;
1776 /* check if Tunneling is OFF and we have a call with this H245 add */
1777 list = g_list_first(tapinfo->strinfo_list);
1780 tmp_listinfo=list->data;
1781 if (tmp_listinfo->protocol == VOIP_H323){
1782 tmp_h323info = tmp_listinfo->prot_info;
1784 COPY_ADDRESS(&(tmp_src), &(pinfo->src));
1785 COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
1786 list2 = g_list_first(tmp_h323info->h245_list);
1789 h245_add=list2->data;
1790 if ( (ADDRESSES_EQUAL(&(h245_add->h245_address),&tmp_src) && (h245_add->h245_port == pinfo->srcport))
1791 || (ADDRESSES_EQUAL(&(h245_add->h245_address),&tmp_dst) && (h245_add->h245_port == pinfo->destport)) ){
1792 strinfo = (voip_calls_info_t*)(list->data);
1794 ++(strinfo->npackets);
1795 /* increment the packets counter of all calls */
1796 ++(tapinfo->npackets);
1800 list2 = g_list_next(list2);
1802 if (strinfo!=NULL) break;
1803 g_free((void *)tmp_src.data);
1804 g_free((void *)tmp_dst.data);
1806 list = g_list_next(list);
1809 /* Tunnel is OFF, and we matched the h245 add so we add it to graph */
1811 ++(strinfo->npackets);
1812 /* increment the packets counter of all calls */
1813 ++(tapinfo->npackets);
1814 frame_label = g_strdup(pi->frame_label);
1815 comment = g_strdup(pi->comment);
1816 /* if the frame number exists in graph, append to it*/
1817 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, frame_label, comment)) {
1818 /* if not exist, add to the graph */
1819 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst));
1821 g_free(frame_label);
1824 /* Tunnel is ON, so we save the label info to use it into h225 or q931 tap. OR may be
1825 tunnel OFF but we did not matched the h245 add, in this case nobady will set this label
1826 since the frame_num will not match */
1828 h245_add_label(pinfo->fd->num, (gchar *) pi->frame_label, (gchar *) pi->comment);
1831 tapinfo->redraw = TRUE;
1833 return 1; /* refresh output */
1837 /****************************************************************************/
1839 /****************************************************************************/
1840 static gboolean have_H245dg_tap_listener=FALSE;
1841 /****************************************************************************/
1843 h245dg_calls_init_tap(void)
1845 GString *error_string;
1847 if(have_H245dg_tap_listener==FALSE)
1849 /* don't register tap listener, if we have it already */
1850 error_string = register_tap_listener("h245dg", &(the_tapinfo_struct.h245dg_dummy), NULL,
1851 voip_calls_dlg_reset,
1856 if (error_string != NULL) {
1857 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1859 g_string_free(error_string, TRUE);
1862 have_H245dg_tap_listener=TRUE;
1867 /* XXX just copied from gtk/rpc_stat.c */
1868 void protect_thread_critical_region(void);
1869 void unprotect_thread_critical_region(void);
1871 /****************************************************************************/
1873 remove_tap_listener_h245dg_calls(void)
1875 protect_thread_critical_region();
1876 remove_tap_listener(&(the_tapinfo_struct.h245dg_dummy));
1877 unprotect_thread_critical_region();
1879 have_H245dg_tap_listener=FALSE;
1882 /****************************************************************************/
1883 /****************************TAP for SDP PROTOCOL ***************************/
1884 /****************************************************************************/
1885 /* whenever a SDP packet is seen by the tap listener */
1887 SDPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SDPinfo)
1889 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1890 const sdp_packet_info *pi = SDPinfo;
1892 /* There are protocols like MGCP/SIP where the SDP is called before the tap for the
1893 MGCP/SIP packet, in those cases we assign the SPD summary to global lastSDPsummary
1896 g_free(sdp_summary);
1897 sdp_frame_num = pinfo->fd->num;
1898 /* Append to graph the SDP summary if the packet exists */
1899 sdp_summary = g_strdup_printf("SDP (%s)", pi->summary_str);
1900 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
1902 tapinfo->redraw = TRUE;
1904 return 1; /* refresh output */
1908 /****************************************************************************/
1910 /****************************************************************************/
1911 static gboolean have_sdp_tap_listener=FALSE;
1912 /****************************************************************************/
1914 sdp_calls_init_tap(void)
1916 GString *error_string;
1918 if(have_sdp_tap_listener==FALSE)
1920 /* don't register tap listener, if we have it already */
1921 error_string = register_tap_listener("sdp", &(the_tapinfo_struct.sdp_dummy), NULL,
1922 voip_calls_dlg_reset,
1927 if (error_string != NULL) {
1928 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1930 g_string_free(error_string, TRUE);
1933 have_sdp_tap_listener=TRUE;
1938 /* XXX just copied from gtk/rpc_stat.c */
1939 void protect_thread_critical_region(void);
1940 void unprotect_thread_critical_region(void);
1942 /****************************************************************************/
1944 remove_tap_listener_sdp_calls(void)
1946 protect_thread_critical_region();
1947 remove_tap_listener(&(the_tapinfo_struct.sdp_dummy));
1948 unprotect_thread_critical_region();
1950 have_sdp_tap_listener=FALSE;
1955 /****************************************************************************/
1956 /* ***************************TAP for MGCP **********************************/
1957 /****************************************************************************/
1960 This function will look for a signal/event in the SignalReq/ObsEvent string
1961 and return true if it is found
1963 gboolean isSignal(const gchar *signal, const gchar *signalStr)
1966 gchar **resultArray;
1968 /* if there is no signalStr, just return false */
1969 if (signalStr == NULL) return FALSE;
1971 /* if are both "blank" return true */
1972 if ( (*signal == '\0') && (*signalStr == '\0') ) return TRUE;
1974 /* look for signal in signalSre */
1975 resultArray = g_strsplit(signalStr, ",", 10);
1977 for (i = 0; resultArray[i]; i++) {
1978 g_strstrip(resultArray[i]);
1979 if (strcmp(resultArray[i], signal) == 0) return TRUE;
1982 g_strfreev(resultArray);
1988 This function will get the Caller ID info and replace the current string
1989 This is how it looks the caller Id: rg, ci(02/16/08/29, "3035550002","Ale Sipura 2")
1991 void mgcpCallerID(gchar *signalStr, gchar **callerId)
1995 /* if there is no signalStr, just return false */
1996 if (signalStr == NULL) return;
1998 arrayStr = g_strsplit(signalStr, "\"", 10);
2000 if (arrayStr[0] == NULL) return;
2002 /* look for the ci signal */
2003 if (strstr(arrayStr[0], "ci(") && (arrayStr[1] != NULL) ) {
2004 /* free the previous "From" field of the call, and assign the new */
2006 *callerId = g_strdup(arrayStr[1]);
2008 g_strfreev(arrayStr);
2015 This function will get the Dialed Digits and replace the current string
2016 This is how it looks the dialed digits 5,5,5,0,0,0,2,#,*
2018 void mgcpDialedDigits(gchar *signalStr, gchar **dialedDigits)
2021 gchar resultStr[50];
2024 /* if there is no signalStr, just return false */
2025 if (signalStr == NULL) return;
2027 tmpStr = g_strdup(signalStr);
2029 for ( i = 0 ; tmpStr[i] ; i++) {
2030 switch (tmpStr[i]) {
2031 case '0' : case '1' : case '2' : case '3' : case '4' :
2032 case '5' : case '6' : case '7' : case '8' : case '9' :
2033 case '#' : case '*' :
2041 for (i = 0, j = 0; tmpStr[i] && i<50; i++) {
2042 if (tmpStr[i] != '?')
2043 resultStr[j++] = tmpStr[i];
2045 resultStr[j] = '\0';
2047 if (*resultStr == '\0') return;
2049 g_free(*dialedDigits);
2050 *dialedDigits = g_strdup(resultStr);
2058 /****************************************************************************/
2059 /* whenever a MGCP packet is seen by the tap listener */
2061 MGCPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *MGCPinfo)
2063 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2065 voip_calls_info_t *tmp_listinfo;
2066 voip_calls_info_t *strinfo = NULL;
2067 mgcp_calls_info_t *tmp_mgcpinfo = NULL;
2070 gchar *frame_label = NULL;
2071 gchar *comment = NULL;
2072 graph_analysis_item_t *gai;
2073 gboolean new = FALSE;
2074 gboolean fromEndpoint = FALSE; /* true for calls originated in Endpoints, false for calls from MGC */
2077 const mgcp_info_t *pi = MGCPinfo;
2080 if ((pi->mgcp_type == MGCP_REQUEST) && !pi->is_duplicate ){
2081 /* check wether we already have a call with this Endpoint and it is active*/
2082 list = g_list_first(tapinfo->strinfo_list);
2085 tmp_listinfo=list->data;
2086 if ((tmp_listinfo->protocol == VOIP_MGCP) && (tmp_listinfo->call_active_state == VOIP_ACTIVE)){
2087 tmp_mgcpinfo = tmp_listinfo->prot_info;
2088 if (pi->endpointId != NULL){
2089 if (g_strcasecmp(tmp_mgcpinfo->endpointId,pi->endpointId) == 0){
2091 check first if it is an ended call. We consider an ended call after 1sec we don't
2092 get a packet in this Endpoint and the call has been released
2094 diff_time = (pinfo->fd->rel_secs + (double)pinfo->fd->rel_secs/1000000) - (tmp_listinfo->stop_sec + (double)tmp_listinfo->stop_usec/1000000);
2095 if ( ((tmp_listinfo->call_state == VOIP_CANCELLED) || (tmp_listinfo->call_state == VOIP_COMPLETED) || (tmp_listinfo->call_state == VOIP_REJECTED)) && (diff_time > 1) ){
2096 tmp_listinfo->call_active_state = VOIP_INACTIVE;
2098 strinfo = (voip_calls_info_t*)(list->data);
2104 list = g_list_next (list);
2107 /* there is no call with this Endpoint, lets see if this a new call or not */
2108 if (strinfo == NULL){
2109 if ( (strcmp(pi->code, "NTFY") == 0) && isSignal("hd", pi->observedEvents) ){ /* off hook transition */
2110 /* this is a new call from the Endpoint */
2111 fromEndpoint = TRUE;
2113 } else if (strcmp(pi->code, "CRCX") == 0){
2114 /* this is a new call from the MGC */
2115 fromEndpoint = FALSE;
2120 } else if ( ((pi->mgcp_type == MGCP_RESPONSE) && pi->request_available) ||
2121 ((pi->mgcp_type == MGCP_REQUEST) && pi->is_duplicate) ) {
2122 /* if it is a response OR if it is a duplicated Request, lets look in the Graph if thre is a request that match */
2123 listGraph = g_list_first(tapinfo->graph_analysis->list);
2126 gai = listGraph->data;
2127 if (gai->frame_num == pi->req_num){
2128 /* there is a request that match, so look the associated call with this call_num */
2129 list = g_list_first(tapinfo->strinfo_list);
2132 tmp_listinfo=list->data;
2133 if (tmp_listinfo->protocol == VOIP_MGCP){
2134 if (tmp_listinfo->call_num == gai->conv_num){
2135 tmp_mgcpinfo = tmp_listinfo->prot_info;
2136 strinfo = (voip_calls_info_t*)(list->data);
2140 list = g_list_next (list);
2142 if (strinfo != NULL) break;
2144 listGraph = g_list_next(listGraph);
2146 /* if there is not a matching request, just return */
2147 if (strinfo == NULL) return 0;
2150 /* not in the list? then create a new entry */
2152 strinfo = g_malloc(sizeof(voip_calls_info_t));
2153 strinfo->call_active_state = VOIP_ACTIVE;
2154 strinfo->call_state = VOIP_CALL_SETUP;
2156 strinfo->from_identity=g_strdup(pi->endpointId);
2157 strinfo->to_identity=g_strdup("");
2159 strinfo->from_identity=g_strdup("");
2160 strinfo->to_identity=g_strdup(pi->endpointId);
2162 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
2163 strinfo->first_frame_num=pinfo->fd->num;
2164 strinfo->selected=FALSE;
2165 strinfo->start_sec=pinfo->fd->rel_secs;
2166 strinfo->start_usec=pinfo->fd->rel_usecs;
2167 strinfo->protocol=VOIP_MGCP;
2168 strinfo->prot_info=g_malloc(sizeof(mgcp_calls_info_t));
2169 tmp_mgcpinfo=strinfo->prot_info;
2170 tmp_mgcpinfo->endpointId = g_strdup(pi->endpointId);
2171 tmp_mgcpinfo->fromEndpoint = fromEndpoint;
2172 strinfo->npackets = 0;
2173 strinfo->call_num = tapinfo->ncalls++;
2174 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
2177 g_assert(tmp_mgcpinfo != NULL);
2179 /* change call state and add to graph */
2180 switch (pi->mgcp_type)
2183 if ( (strcmp(pi->code, "NTFY") == 0) && (pi->observedEvents != NULL) ){
2184 frame_label = g_strdup_printf("%s ObsEvt:%s",pi->code, pi->observedEvents);
2186 if (tmp_mgcpinfo->fromEndpoint){
2187 /* use the Dialed digits to fill the "To" for the call */
2188 mgcpDialedDigits(pi->observedEvents, &(strinfo->to_identity));
2190 /* from MGC and the user picked up, the call is connected */
2191 } else if (isSignal("hd", pi->observedEvents))
2192 strinfo->call_state=VOIP_IN_CALL;
2194 /* hung up signal */
2195 if (isSignal("hu", pi->observedEvents)) {
2196 if ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state == VOIP_RINGING)){
2197 strinfo->call_state = VOIP_CANCELLED;
2199 strinfo->call_state = VOIP_COMPLETED;
2203 } else if (strcmp(pi->code, "RQNT") == 0) {
2204 /* for calls from Endpoint: if there is a "no signal" RQNT and the call was RINGING, we assume this is the CONNECT */
2205 if ( tmp_mgcpinfo->fromEndpoint && isSignal("", pi->signalReq) && (strinfo->call_state == VOIP_RINGING) ) {
2206 strinfo->call_state = VOIP_IN_CALL;
2209 /* if there is ringback or ring tone, change state to ringing */
2210 if ( isSignal("rg", pi->signalReq) || isSignal("rt", pi->signalReq) ) {
2211 strinfo->call_state = VOIP_RINGING;
2214 /* if there is a Busy or ReorderTone, and the call was Ringing or Setup the call is Rejected */
2215 if ( (isSignal("ro", pi->signalReq) || isSignal("bz", pi->signalReq)) && ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state = VOIP_RINGING)) ) {
2216 strinfo->call_state = VOIP_REJECTED;
2219 if (pi->signalReq != NULL)
2220 frame_label = g_strdup_printf("%s%sSigReq:%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"", pi->signalReq);
2222 frame_label = g_strdup_printf("%s%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"");
2224 /* use the CallerID info to fill the "From" for the call */
2225 if (!tmp_mgcpinfo->fromEndpoint) mgcpCallerID(pi->signalReq, &(strinfo->from_identity));
2227 } else if (strcmp(pi->code, "DLCX") == 0) {
2229 if there is a DLCX in a call To an Endpoint and the call was not connected, we use
2230 the DLCX as the end of the call
2232 if (!tmp_mgcpinfo->fromEndpoint){
2233 if ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state == VOIP_RINGING)){
2234 strinfo->call_state = VOIP_CANCELLED;
2239 if (frame_label == NULL) frame_label = g_strdup_printf("%s",pi->code);
2242 frame_label = g_strdup_printf("%d (%s)",pi->rspcode, pi->code);
2245 /* XXX what to do? */
2250 comment = g_strdup_printf("MGCP %s %s%s", tmp_mgcpinfo->endpointId, (pi->mgcp_type == MGCP_REQUEST)?"Request":"Response", pi->is_duplicate?" Duplicate":"");
2252 strinfo->stop_sec=pinfo->fd->rel_secs;
2253 strinfo->stop_usec=pinfo->fd->rel_usecs;
2254 strinfo->last_frame_num=pinfo->fd->num;
2255 ++(strinfo->npackets);
2256 /* increment the packets counter of all calls */
2257 ++(tapinfo->npackets);
2259 /* add to the graph */
2260 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst));
2262 g_free(frame_label);
2264 /* add SDP info if apply */
2265 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
2266 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2267 g_free(sdp_summary);
2271 tapinfo->redraw = TRUE;
2273 return 1; /* refresh output */
2277 /****************************************************************************/
2279 /****************************************************************************/
2280 static gboolean have_MGCP_tap_listener=FALSE;
2281 /****************************************************************************/
2283 mgcp_calls_init_tap(void)
2285 GString *error_string;
2287 if(have_MGCP_tap_listener==FALSE)
2289 /* don't register tap listener, if we have it already */
2290 /* we send an empty filter, to force a non null "tree" in the mgcp dissector */
2291 error_string = register_tap_listener("mgcp", &(the_tapinfo_struct.mgcp_dummy), strdup(""),
2292 voip_calls_dlg_reset,
2296 if (error_string != NULL) {
2297 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2299 g_string_free(error_string, TRUE);
2302 have_MGCP_tap_listener=TRUE;
2308 /* XXX just copied from gtk/rpc_stat.c */
2309 void protect_thread_critical_region(void);
2310 void unprotect_thread_critical_region(void);
2312 /****************************************************************************/
2314 remove_tap_listener_mgcp_calls(void)
2316 protect_thread_critical_region();
2317 remove_tap_listener(&(the_tapinfo_struct.mgcp_dummy));
2318 unprotect_thread_critical_region();
2320 have_MGCP_tap_listener=FALSE;
2324 /****************************************************************************/
2325 /****************************TAP for ACTRACE (AudioCodes trace)**************/
2326 /****************************************************************************/
2328 /* whenever a ACTRACE packet is seen by the tap listener */
2330 ACTRACEcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *ACTRACEinfo)
2332 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2333 const actrace_info_t *pi = ACTRACEinfo;
2335 actrace_cas_calls_info_t *tmp_actrace_cas_info;
2336 voip_calls_info_t *tmp_listinfo;
2337 voip_calls_info_t *strinfo = NULL;
2340 actrace_frame_num = pinfo->fd->num;
2341 actrace_trunk = pi->trunk;
2342 actrace_direction = pi->direction;
2344 if (pi->type == 1){ /* is CAS protocol */
2346 gchar *comment = NULL;
2349 list = g_list_first(tapinfo->strinfo_list);
2352 tmp_listinfo=list->data;
2353 if ( tmp_listinfo->protocol == VOIP_AC_CAS ){
2354 tmp_actrace_cas_info = tmp_listinfo->prot_info;
2355 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
2356 if ( (tmp_actrace_cas_info->bchannel == pi->cas_bchannel) && (tmp_actrace_cas_info->trunk == actrace_trunk) ) {
2357 strinfo = (voip_calls_info_t*)(list->data);
2361 list = g_list_next (list);
2364 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, g_strdup("PSTN"));
2366 /* if it is a new call, add it to the list */
2368 strinfo = g_malloc(sizeof(voip_calls_info_t));
2369 strinfo->call_active_state = VOIP_ACTIVE;
2370 strinfo->call_state = VOIP_CALL_SETUP;
2371 strinfo->from_identity=g_strdup("N/A");
2372 strinfo->to_identity=g_strdup("N/A");
2373 COPY_ADDRESS(&(strinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
2374 strinfo->first_frame_num=pinfo->fd->num;
2375 strinfo->selected=FALSE;
2376 strinfo->start_sec=pinfo->fd->rel_secs;
2377 strinfo->start_usec=pinfo->fd->rel_usecs;
2378 strinfo->protocol=VOIP_AC_CAS;
2379 strinfo->prot_info=g_malloc(sizeof(actrace_cas_calls_info_t));
2380 tmp_actrace_cas_info=strinfo->prot_info;
2381 tmp_actrace_cas_info->bchannel=pi->cas_bchannel;
2382 tmp_actrace_cas_info->trunk=actrace_trunk;
2383 strinfo->npackets = 0;
2384 strinfo->call_num = tapinfo->ncalls++;
2385 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
2388 strinfo->stop_sec=pinfo->fd->rel_secs;
2389 strinfo->stop_usec=pinfo->fd->rel_usecs;
2390 strinfo->last_frame_num=pinfo->fd->num;
2391 ++(strinfo->npackets);
2392 /* increment the packets counter of all calls */
2393 ++(tapinfo->npackets);
2396 comment = g_strdup_printf("AC_CAS trunk:%u", actrace_trunk );
2398 add_to_graph(tapinfo, pinfo, pi->cas_frame_label , comment, strinfo->call_num,
2399 actrace_direction?&pstn_add:&(pinfo->src),
2400 actrace_direction?&(pinfo->src):&pstn_add);
2403 g_free((char *)pstn_add.data);
2406 tapinfo->redraw = TRUE;
2408 return 1; /* refresh output */
2412 /****************************************************************************/
2414 /****************************************************************************/
2415 static gboolean have_actrace_tap_listener=FALSE;
2416 /****************************************************************************/
2418 actrace_calls_init_tap(void)
2420 GString *error_string;
2422 if(have_actrace_tap_listener==FALSE)
2424 /* don't register tap listener, if we have it already */
2425 error_string = register_tap_listener("actrace", &(the_tapinfo_struct.actrace_dummy), NULL,
2426 voip_calls_dlg_reset,
2427 ACTRACEcalls_packet,
2431 if (error_string != NULL) {
2432 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2434 g_string_free(error_string, TRUE);
2437 have_actrace_tap_listener=TRUE;
2442 /* XXX just copied from gtk/rpc_stat.c */
2443 void protect_thread_critical_region(void);
2444 void unprotect_thread_critical_region(void);
2446 /****************************************************************************/
2448 remove_tap_listener_actrace_calls(void)
2450 protect_thread_critical_region();
2451 remove_tap_listener(&(the_tapinfo_struct.actrace_dummy));
2452 unprotect_thread_critical_region();
2454 have_actrace_tap_listener=FALSE;
2457 /****************************************************************************/
2458 /* ***************************TAP for OTHER PROTOCOL **********************************/
2459 /****************************************************************************/
2461 /****************************************************************************/
2462 /* whenever a prot_ packet is seen by the tap listener */
2465 prot_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info _U_)
2467 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2469 strinfo->stop_sec=pinfo->fd->rel_secs;
2470 strinfo->stop_usec=pinfo->fd->rel_usecs;
2471 strinfo->last_frame_num=pinfo->fd->num;
2472 ++(strinfo->npackets);
2473 ++(tapinfo->npackets);
2476 tapinfo->redraw = TRUE;
2481 /****************************************************************************/
2483 static gboolean have_prot__tap_listener=FALSE;
2486 prot_calls_init_tap(void)
2488 GString *error_string;
2490 if(have_prot__tap_listener==FALSE)
2492 error_string = register_tap_listener("prot_", &(the_tapinfo_struct.prot__dummy),
2494 voip_calls_dlg_reset,
2499 if (error_string != NULL) {
2500 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2502 g_string_free(error_string, TRUE);
2505 have_prot__tap_listener=TRUE;
2509 /****************************************************************************/
2512 remove_tap_listener_prot__calls(void)
2514 protect_thread_critical_region();
2515 remove_tap_listener(&(the_tapinfo_struct.prot__dummy));
2516 unprotect_thread_critical_region();
2518 have_prot__tap_listener=FALSE;