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), T38 and Graph Support
14 * By Alejandro Vaquero, alejandro.vaquero@verso.com
15 * Copyright 2005, Verso Technologies Inc.
17 * Wireshark - Network traffic analyzer
18 * By Gerald Combs <gerald@wireshark.org>
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"
50 #include <epan/dissectors/packet-sip.h>
51 #include <epan/dissectors/packet-mtp3.h>
52 #include <epan/dissectors/packet-isup.h>
53 #include <epan/dissectors/packet-h225.h>
54 #include <epan/dissectors/packet-h245.h>
55 #include <epan/dissectors/packet-q931.h>
56 #include <epan/dissectors/packet-sdp.h>
57 #include <plugins/mgcp/packet-mgcp.h>
58 #include <epan/dissectors/packet-actrace.h>
59 #include <epan/dissectors/packet-rtp.h>
60 #include <epan/dissectors/packet-rtp-events.h>
61 #include <epan/dissectors/packet-t38.h>
62 #include <epan/conversation.h>
63 #include <epan/rtp_pt.h>
65 #include "alert_box.h"
66 #include "simple_dialog.h"
68 const char *voip_call_state_name[7]={
78 /* defines whether we can consider the call active */
79 const char *voip_protocol_name[7]={
99 graph_str labels[H245_MAX];
102 static h245_labels_t h245_labels;
104 /****************************************************************************/
105 /* the one and only global voip_calls_tapinfo_t structure */
106 static voip_calls_tapinfo_t the_tapinfo_struct =
107 {0, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
109 /* the one and only global voip_rtp_tapinfo_t structure */
110 static voip_rtp_tapinfo_t the_tapinfo_rtp_struct =
113 /****************************************************************************/
114 /* when there is a [re]reading of packet's */
115 void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
117 voip_calls_info_t *strinfo;
118 sip_calls_info_t *tmp_sipinfo;
119 h323_calls_info_t *tmp_h323info;
120 h245_address_t *h245_add;
122 graph_analysis_item_t *graph_item;
127 /* free the data items first */
128 list = g_list_first(tapinfo->strinfo_list);
131 strinfo = list->data;
132 g_free(strinfo->from_identity);
133 g_free(strinfo->to_identity);
134 g_free((void *)(strinfo->initial_speaker.data));
135 if (strinfo->protocol == VOIP_SIP){
136 tmp_sipinfo = strinfo->prot_info;
137 g_free(tmp_sipinfo->call_identifier);
139 if (strinfo->protocol == VOIP_H323){
140 tmp_h323info = strinfo->prot_info;
141 g_free(tmp_h323info->guid);
142 /* free the H245 list address */
143 list2 = g_list_first(tmp_h323info->h245_list);
146 h245_add=list2->data;
147 g_free((void *)h245_add->h245_address.data);
149 list2 = g_list_next(list2);
151 g_list_free(tmp_h323info->h245_list);
152 tmp_h323info->h245_list = NULL;
154 g_free(strinfo->prot_info);
157 list = g_list_next(list);
159 g_list_free(tapinfo->strinfo_list);
160 tapinfo->strinfo_list = NULL;
162 tapinfo->npackets = 0;
163 tapinfo->start_packets = 0;
164 tapinfo->completed_calls = 0;
165 tapinfo->rejected_calls = 0;
167 /* free the graph data items first */
168 list = g_list_first(tapinfo->graph_analysis->list);
171 graph_item = list->data;
172 g_free(graph_item->frame_label);
173 g_free(graph_item->comment);
174 g_free((void *)graph_item->src_addr.data);
175 g_free((void *)graph_item->dst_addr.data);
177 list = g_list_next(list);
179 g_list_free(tapinfo->graph_analysis->list);
180 tapinfo->graph_analysis->nconv = 0;
181 tapinfo->graph_analysis->list = NULL;
183 ++(tapinfo->launch_count);
188 /****************************************************************************/
189 void graph_analysis_data_init(void){
190 the_tapinfo_struct.graph_analysis = g_malloc(sizeof(graph_analysis_info_t));
191 the_tapinfo_struct.graph_analysis->nconv = 0;
192 the_tapinfo_struct.graph_analysis->list = NULL;
196 /****************************************************************************/
197 /* Add a new item into the graph */
198 static 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, guint16 line_style)
200 graph_analysis_item_t *gai;
202 gai = g_malloc(sizeof(graph_analysis_item_t));
203 gai->frame_num = pinfo->fd->num;
204 gai->time= nstime_to_sec(&pinfo->fd->rel_ts);
205 COPY_ADDRESS(&(gai->src_addr),src_addr);
206 COPY_ADDRESS(&(gai->dst_addr),dst_addr);
208 gai->port_src=pinfo->srcport;
209 gai->port_dst=pinfo->destport;
210 if (frame_label != NULL)
211 gai->frame_label = g_strdup(frame_label);
213 gai->frame_label = g_strdup("");
216 gai->comment = g_strdup(comment);
218 gai->comment = g_strdup("");
219 gai->conv_num=call_num;
220 gai->line_style=line_style;
223 tapinfo->graph_analysis->list = g_list_append(tapinfo->graph_analysis->list, gai);
229 /****************************************************************************/
230 /* Append str to frame_label and comment in a graph item */
231 /* return 0 if the frame_num is not in the graph list */
232 static int append_to_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
234 graph_analysis_item_t *gai;
236 gchar *tmp_str = NULL;
237 gchar *tmp_str2 = NULL;
239 list = g_list_first(tapinfo->graph_analysis->list);
243 if (gai->frame_num == frame_num){
244 tmp_str = gai->frame_label;
245 tmp_str2 = gai->comment;
247 if (new_frame_label != NULL){
248 gai->frame_label = g_strdup_printf("%s %s", gai->frame_label, new_frame_label);
253 if (new_comment != NULL){
254 gai->comment = g_strdup_printf("%s %s", gai->comment, new_comment);
259 list = g_list_next (list);
261 if (tmp_str == NULL) return 0; /* it is not in the list */
266 /****************************************************************************/
267 /* Change the frame_label and comment in a graph item if not NULL*/
268 /* return 0 if the frame_num is not in the graph list */
269 static int change_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
271 graph_analysis_item_t *gai;
273 gchar *tmp_str = NULL;
274 gchar *tmp_str2 = NULL;
276 list = g_list_first(tapinfo->graph_analysis->list);
280 if (gai->frame_num == frame_num){
281 tmp_str = gai->frame_label;
282 tmp_str2 = gai->comment;
284 if (new_frame_label != NULL){
285 gai->frame_label = g_strdup(new_frame_label);
289 if (new_comment != NULL){
290 gai->comment = g_strdup(new_comment);
295 list = g_list_next (list);
297 if (tmp_str == NULL) return 0; /* it is not in the list */
302 /****************************************************************************/
303 /* Change all the graph items with call_num to new_call_num */
304 static guint change_call_num_graph(voip_calls_tapinfo_t *tapinfo _U_, guint16 call_num, guint16 new_call_num)
306 graph_analysis_item_t *gai;
311 list = g_list_first(tapinfo->graph_analysis->list);
315 if (gai->conv_num == call_num){
316 gai->conv_num = new_call_num;
319 list = g_list_next (list);
321 return items_changed;
327 /****************************************************************************/
328 /* Insert the item in the graph list */
329 void insert_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, guint16 line_style, double time, guint32 frame_num)
331 graph_analysis_item_t *gai, *new_gai;
336 new_gai = g_malloc(sizeof(graph_analysis_item_t));
337 new_gai->frame_num = frame_num;
339 COPY_ADDRESS(&(new_gai->src_addr),src_addr);
340 COPY_ADDRESS(&(new_gai->dst_addr),dst_addr);
342 new_gai->port_src=pinfo->srcport;
343 new_gai->port_dst=pinfo->destport;
344 if (frame_label != NULL)
345 new_gai->frame_label = g_strdup(frame_label);
347 new_gai->frame_label = g_strdup("");
350 new_gai->comment = g_strdup(comment);
352 new_gai->comment = g_strdup("");
353 new_gai->conv_num=call_num;
354 new_gai->line_style=line_style;
355 new_gai->display=FALSE;
359 list = g_list_first(tapinfo->graph_analysis->list);
363 if (gai->frame_num > frame_num){
364 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item_num);
368 list = g_list_next (list);
372 if ( !inserted) tapinfo->graph_analysis->list = g_list_append(tapinfo->graph_analysis->list, new_gai);
375 /****************************************************************************/
376 /* ***************************TAP for RTP Events*****************************/
377 /****************************************************************************/
379 static guint32 rtp_evt_frame_num = 0;
380 static guint8 rtp_evt = 0;
381 static gboolean rtp_evt_end = FALSE;
382 /*static guint32 rtp_evt_setup_frame_num = 0;*/
384 /****************************************************************************/
385 /* whenever a rtp event packet is seen by the tap listener */
387 rtp_event_packet(void *ptr _U_, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *rtp_event_info)
389 const struct _rtp_event_info *pi = rtp_event_info;
391 /* do not consider RTP events packets without a setup frame */
392 if (pi->info_setup_frame_num == 0){
396 rtp_evt_frame_num = pinfo->fd->num;
397 rtp_evt = pi->info_rtp_evt;
398 rtp_evt_end = pi->info_end;
403 /****************************************************************************/
404 static gboolean have_rtp_event_tap_listener=FALSE;
407 rtp_event_init_tap(void)
409 GString *error_string;
412 if(have_rtp_event_tap_listener==FALSE)
414 error_string = register_tap_listener("rtpevent", &(the_tapinfo_rtp_struct.rtp_event_dummy),
421 if (error_string != NULL) {
422 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
424 g_string_free(error_string, TRUE);
427 have_rtp_event_tap_listener=TRUE;
431 /****************************************************************************/
434 remove_tap_listener_rtp_event(void)
436 protect_thread_critical_region();
437 remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_event_dummy));
438 unprotect_thread_critical_region();
440 have_rtp_event_tap_listener=FALSE;
443 /****************************************************************************/
444 /* ***************************TAP for RTP **********************************/
445 /****************************************************************************/
447 /****************************************************************************/
448 /* when there is a [re]reading of RTP packet's */
449 static void voip_rtp_reset(void *ptr _U_)
451 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
453 /* free the data items first */
454 list = g_list_first(tapinfo->list);
458 list = g_list_next(list);
460 g_list_free(tapinfo->list);
461 tapinfo->list = NULL;
462 tapinfo->nstreams = 0;
466 /****************************************************************************/
467 /* whenever a RTP packet is seen by the tap listener */
469 RTP_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *RTPinfo)
471 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
472 voip_rtp_stream_info_t *tmp_listinfo;
473 voip_rtp_stream_info_t *strinfo = NULL;
475 struct _rtp_conversation_info *p_conv_data = NULL;
477 const struct _rtp_info *pi = RTPinfo;
479 /* do not consider RTP packets without a setup frame */
480 if (pi->info_setup_frame_num == 0){
484 /* check wether we already have a RTP stream with this setup frame and ssrc in the list */
485 list = g_list_first(tapinfo->list);
488 tmp_listinfo=list->data;
489 if ( (tmp_listinfo->setup_frame_number == pi->info_setup_frame_num)
490 && (tmp_listinfo->ssrc == pi->info_sync_src) && (tmp_listinfo->end_stream == FALSE)){
491 /* if the payload type has changed, we mark the stream as finished to create a new one
492 this is to show multiple payload changes in the Graph for example for DTMF RFC2833 */
493 if ( tmp_listinfo->pt != pi->info_payload_type ) {
494 tmp_listinfo->end_stream = TRUE;
496 strinfo = (voip_rtp_stream_info_t*)(list->data);
500 list = g_list_next (list);
503 /* if this is a duplicated RTP Event End, just return */
504 if ((rtp_evt_frame_num == pinfo->fd->num) && !strinfo && (rtp_evt_end == TRUE)) {
508 /* not in the list? then create a new entry */
510 strinfo = g_malloc(sizeof(voip_rtp_stream_info_t));
511 COPY_ADDRESS(&(strinfo->src_addr), &(pinfo->src));
512 strinfo->src_port = pinfo->srcport;
513 COPY_ADDRESS(&(strinfo->dest_addr), &(pinfo->dst));
514 strinfo->dest_port = pinfo->destport;
515 strinfo->ssrc = pi->info_sync_src;
516 strinfo->end_stream = FALSE;
517 strinfo->pt = pi->info_payload_type;
518 strinfo->pt_str = NULL;
519 /* if it is dynamic payload, let use the conv data to see if it is defined */
520 if ( (strinfo->pt>95) && (strinfo->pt<128) ) {
521 /* Use existing packet info if available */
522 p_conv_data = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name("rtp"));
524 strinfo->pt_str = g_strdup(g_hash_table_lookup(p_conv_data->rtp_dyn_payload, &strinfo->pt));
526 if (!strinfo->pt_str) strinfo->pt_str = g_strdup(val_to_str(strinfo->pt, rtp_payload_type_short_vals, "%u"));
527 strinfo->npackets = 0;
528 strinfo->first_frame_num = pinfo->fd->num;
529 strinfo->start_rel_sec = pinfo->fd->rel_ts.secs;
530 strinfo->start_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
531 strinfo->setup_frame_number = pi->info_setup_frame_num;
532 strinfo->rtp_event = -1;
533 tapinfo->list = g_list_append(tapinfo->list, strinfo);
537 /* Add the info to the existing RTP stream */
539 strinfo->stop_rel_sec = pinfo->fd->rel_ts.secs;
540 strinfo->stop_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
542 /* process RTP Event */
543 if (rtp_evt_frame_num == pinfo->fd->num) {
544 strinfo->rtp_event = rtp_evt;
545 if (rtp_evt_end == TRUE) {
546 strinfo->end_stream = TRUE;
551 the_tapinfo_struct.redraw = TRUE;
556 /****************************************************************************/
557 /* whenever a redraw in the RTP tap listener */
558 static void RTP_packet_draw(void *prs _U_)
560 voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
561 GList* rtp_streams_list;
562 voip_rtp_stream_info_t *rtp_listinfo;
563 GList* voip_calls_graph_list;
565 graph_analysis_item_t *gai;
566 graph_analysis_item_t *new_gai;
570 /* add each rtp stream to the graph */
571 rtp_streams_list = g_list_first(rtp_tapinfo->list);
572 while (rtp_streams_list)
574 rtp_listinfo = rtp_streams_list->data;
576 /* using the setup frame number of the RTP stream, we get the call number that it belongs */
577 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
578 while (voip_calls_graph_list)
580 gai = voip_calls_graph_list->data;
581 conv_num = gai->conv_num;
582 /* if we get the setup frame number, then get the time position to graph the RTP arrow */
583 if (rtp_listinfo->setup_frame_number == gai->frame_num){
584 /* look again from the begining because there are cases where the Setup frame is after the RTP */
585 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
587 while(voip_calls_graph_list){
588 gai = voip_calls_graph_list->data;
589 /* if RTP was already in the Graph, just update the comment information */
590 if (rtp_listinfo->first_frame_num == gai->frame_num){
591 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
592 g_free(gai->comment);
593 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);
595 /* add the RTP item to the graph if was not there*/
596 } else if (rtp_listinfo->first_frame_num<gai->frame_num){
597 new_gai = g_malloc(sizeof(graph_analysis_item_t));
598 new_gai->frame_num = rtp_listinfo->first_frame_num;
599 new_gai->time = (double)rtp_listinfo->start_rel_sec + (double)rtp_listinfo->start_rel_usec/1000000;
600 COPY_ADDRESS(&(new_gai->src_addr),&(rtp_listinfo->src_addr));
601 COPY_ADDRESS(&(new_gai->dst_addr),&(rtp_listinfo->dest_addr));
602 new_gai->port_src = rtp_listinfo->src_port;
603 new_gai->port_dst = rtp_listinfo->dest_port;
604 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
605 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"));
606 g_free(rtp_listinfo->pt_str);
607 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);
608 new_gai->conv_num = conv_num;
609 new_gai->display=FALSE;
610 new_gai->line_style = 2; /* the arrow line will be 2 pixels width */
611 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item);
615 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
620 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
622 rtp_streams_list = g_list_next(rtp_streams_list);
626 static gboolean have_RTP_tap_listener=FALSE;
627 /****************************************************************************/
631 GString *error_string;
633 if(have_RTP_tap_listener==FALSE)
635 /* don't register tap listener, if we have it already */
636 error_string = register_tap_listener("rtp", &(the_tapinfo_rtp_struct.rtp_dummy), NULL,
641 if (error_string != NULL) {
642 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
644 g_string_free(error_string, TRUE);
647 have_RTP_tap_listener=TRUE;
651 /****************************************************************************/
653 remove_tap_listener_rtp(void)
655 protect_thread_critical_region();
656 remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_dummy));
657 unprotect_thread_critical_region();
659 have_RTP_tap_listener=FALSE;
662 /****************************************************************************/
663 /******************************TAP for T38 **********************************/
664 /****************************************************************************/
666 /****************************************************************************/
667 /* whenever a T38 packet is seen by the tap listener */
669 T38_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *T38info)
671 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
673 voip_calls_info_t *strinfo = NULL;
674 voip_calls_info_t *tmp_listinfo;
675 GList* voip_calls_graph_list;
677 gchar *frame_label = NULL;
678 gchar *comment = NULL;
679 graph_analysis_item_t *tmp_gai, *gai = NULL;
680 guint16 line_style = 2;
684 const t38_packet_info *pi = T38info;
686 if (pi->setup_frame_number != 0) {
687 /* using the setup frame number of the T38 packet, we get the call number that it belongs */
688 voip_calls_graph_list = g_list_first(tapinfo->graph_analysis->list);
689 while (voip_calls_graph_list)
691 tmp_gai = voip_calls_graph_list->data;
692 if (pi->setup_frame_number == tmp_gai->frame_num){
696 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
698 if (gai) conv_num = (int) gai->conv_num;
701 /* if setup_frame_number in the t38 packet is 0, it means it was not set using an SDP or H245 sesion, which means we don't
702 * have the associated Voip calls. It probably means the the packet was decoded using the deafult t38 port, or using "Decode as.."
703 * in this case we create a "voip" call that only have t38 media (no signaling)
704 * OR if we have not found the Setup message in the graph.
706 if ( (pi->setup_frame_number == 0) || (gai == NULL) ){
707 /* check wether we already have a call with these parameters in the list */
708 list = g_list_first(tapinfo->strinfo_list);
711 tmp_listinfo=list->data;
712 if (tmp_listinfo->protocol == MEDIA_T38){
713 strinfo = (voip_calls_info_t*)(list->data);
716 list = g_list_next (list);
719 /* not in the list? then create a new entry */
721 strinfo = g_malloc(sizeof(voip_calls_info_t));
722 strinfo->call_active_state = VOIP_ACTIVE;
723 strinfo->call_state = VOIP_UNKNOWN;
724 strinfo->from_identity=g_strdup("T38 Media only");
725 strinfo->to_identity=g_strdup("T38 Media only");
726 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
727 strinfo->first_frame_num=pinfo->fd->num;
728 strinfo->selected=FALSE;
729 strinfo->start_sec=pinfo->fd->rel_ts.secs;
730 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
731 strinfo->protocol=MEDIA_T38;
732 strinfo->prot_info=NULL;
733 strinfo->npackets = 0;
734 strinfo->call_num = tapinfo->ncalls++;
735 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
737 ++(strinfo->npackets);
738 /* increment the packets counter of all calls */
739 ++(tapinfo->npackets);
741 conv_num = (int) strinfo->call_num;
744 /* at this point we should have found the call num for this t38 packets belong */
745 if (conv_num == -1) {
749 /* add the item to the graph list */
750 if (pi->type_msg == 0) { /* 0=t30-indicator */
751 frame_label = g_strdup(val_to_str(pi->t30ind_value, t30_indicator_vals, "Ukn (0x%02X)") );
752 comment = g_strdup_printf("t38:t30 Ind:%s",val_to_str(pi->t30ind_value, t30_indicator_vals, "Ukn (0x%02X)") );
754 } else if (pi->type_msg == 1) { /* 1=data */
755 switch(pi->Data_Field_field_type_value){
756 case 0: /* hdlc-data */
758 case 2: /* hdlc-fcs-OK */
759 case 4: /* hdlc-fcs-OK-sig-end */
760 frame_label = g_strdup_printf("%s %s", val_to_str(pi->t30_Facsimile_Control & 0x7F, t30_facsimile_control_field_vals_short, "Ukn (0x%02X)"), pi->desc);
761 comment = g_strdup_printf("t38:%s:HDLC:%s",val_to_str(pi->data_value, t30_data_vals, "Ukn (0x%02X)"), val_to_str(pi->t30_Facsimile_Control & 0x7F, t30_facsimile_control_field_vals, "Ukn (0x%02X)"));
763 case 3: /* hdlc-fcs-BAD */
764 case 5: /* hdlc-fcs-BAD-sig-end */
765 frame_label = g_strdup(pi->Data_Field_field_type_value == 3 ? "fcs-BAD" : "fcs-BAD-sig-end");
766 comment = g_strdup_printf("WARNING: received t38:%s:HDLC:%s", val_to_str(pi->data_value, t30_data_vals, "Ukn (0x%02X)"), pi->Data_Field_field_type_value == 3 ? "fcs-BAD" : "fcs-BAD-sig-end");
768 case 7: /* t4-non-ecm-sig-end */
769 duration = nstime_to_sec(&pinfo->fd->rel_ts) - pi->time_first_t4_data;
770 frame_label = g_strdup_printf("t4-non-ecm-data:%s",val_to_str(pi->data_value, t30_data_vals, "Ukn (0x%02X)") );
771 comment = g_strdup_printf("t38:t4-non-ecm-data:%s Duration: %.2fs %s",val_to_str(pi->data_value, t30_data_vals, "Ukn (0x%02X)"), duration, pi->desc_comment );
772 insert_to_graph(tapinfo, pinfo, frame_label, comment, (guint16)conv_num, &(pinfo->src), &(pinfo->dst), line_style, pi->time_first_t4_data, pi->frame_num_first_t4_data);
777 if (frame_label && !(pi->Data_Field_field_type_value == 7 && pi->type_msg == 1)) {
778 add_to_graph(tapinfo, pinfo, frame_label, comment, (guint16)conv_num, &(pinfo->src), &(pinfo->dst), line_style);
784 tapinfo->redraw = TRUE;
786 return 1; /* refresh output */
789 static gboolean have_T38_tap_listener=FALSE;
790 /****************************************************************************/
794 GString *error_string;
796 if(have_T38_tap_listener==FALSE)
798 /* don't register tap listener, if we have it already */
799 error_string = register_tap_listener("t38", &(the_tapinfo_struct.t38_dummy), NULL,
800 voip_calls_dlg_reset,
804 if (error_string != NULL) {
805 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
807 g_string_free(error_string, TRUE);
810 have_T38_tap_listener=TRUE;
814 /****************************************************************************/
816 remove_tap_listener_t38(void)
818 protect_thread_critical_region();
819 remove_tap_listener(&(the_tapinfo_struct.t38_dummy));
820 unprotect_thread_critical_region();
822 have_T38_tap_listener=FALSE;
826 /****************************************************************************/
827 static gchar *sdp_summary = NULL;
828 static guint32 sdp_frame_num = 0;
830 /****************************************************************************/
831 /* ***************************TAP for SIP **********************************/
832 /****************************************************************************/
834 /****************************************************************************/
835 /* whenever a SIP packet is seen by the tap listener */
837 SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SIPinfo)
839 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
840 /* we just take note of the ISUP data here; when we receive the MTP3 part everything will
841 be compared with existing calls */
843 voip_calls_info_t *tmp_listinfo;
844 voip_calls_info_t *strinfo = NULL;
845 sip_calls_info_t *tmp_sipinfo = NULL;
847 address tmp_src, tmp_dst;
848 gchar *frame_label = NULL;
849 gchar *comment = NULL;
851 const sip_info_value_t *pi = SIPinfo;
853 /* do not consider packets without call_id */
854 if (pi->tap_call_id ==NULL){
858 /* check wether we already have a call with these parameters in the list */
859 list = g_list_first(tapinfo->strinfo_list);
862 tmp_listinfo=list->data;
863 if (tmp_listinfo->protocol == VOIP_SIP){
864 tmp_sipinfo = tmp_listinfo->prot_info;
865 if (strcmp(tmp_sipinfo->call_identifier,pi->tap_call_id)==0){
866 strinfo = (voip_calls_info_t*)(list->data);
870 list = g_list_next (list);
873 /* not in the list? then create a new entry if the message is INVITE -i.e. if this session is a call*/
874 if ((strinfo==NULL) &&(pi->request_method!=NULL)){
875 if (strcmp(pi->request_method,"INVITE")==0){
876 strinfo = g_malloc(sizeof(voip_calls_info_t));
877 strinfo->call_active_state = VOIP_ACTIVE;
878 strinfo->call_state = VOIP_CALL_SETUP;
879 strinfo->from_identity=g_strdup(pi->tap_from_addr);
880 strinfo->to_identity=g_strdup(pi->tap_to_addr);
881 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
882 strinfo->first_frame_num=pinfo->fd->num;
883 strinfo->selected=FALSE;
884 strinfo->start_sec=pinfo->fd->rel_ts.secs;
885 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
886 strinfo->protocol=VOIP_SIP;
887 strinfo->prot_info=g_malloc(sizeof(sip_calls_info_t));
888 tmp_sipinfo=strinfo->prot_info;
889 tmp_sipinfo->call_identifier=strdup(pi->tap_call_id);
890 tmp_sipinfo->sip_state=SIP_INVITE_SENT;
891 tmp_sipinfo->invite_cseq=pi->tap_cseq_number;
892 strinfo->npackets = 0;
893 strinfo->call_num = tapinfo->ncalls++;
894 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
900 /* let's analyze the call state */
902 COPY_ADDRESS(&(tmp_src), &(pinfo->src));
903 COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
905 if (pi->request_method == NULL){
906 frame_label = g_strdup_printf("%d %s", pi->response_code, pi->reason_phrase );
907 comment = g_strdup_printf("SIP Status");
909 if ((tmp_sipinfo && pi->tap_cseq_number == tmp_sipinfo->invite_cseq)&&(ADDRESSES_EQUAL(&tmp_dst,&(strinfo->initial_speaker)))){
910 if ((pi->response_code > 199) && (pi->response_code<300) && (tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
911 tmp_sipinfo->sip_state = SIP_200_REC;
913 else if ((pi->response_code>299)&&(tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
914 strinfo->call_state = VOIP_REJECTED;
915 tapinfo->rejected_calls++;
921 frame_label = g_strdup(pi->request_method);
923 if ((strcmp(pi->request_method,"INVITE")==0)&&(ADDRESSES_EQUAL(&tmp_src,&(strinfo->initial_speaker)))){
924 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
925 strinfo->call_state = VOIP_CALL_SETUP;
926 comment = g_strdup_printf("SIP From: %s To:%s", strinfo->from_identity, strinfo->to_identity);
928 else if ((strcmp(pi->request_method,"ACK")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
929 &&(ADDRESSES_EQUAL(&tmp_src,&(strinfo->initial_speaker)))&&(tmp_sipinfo->sip_state==SIP_200_REC)
930 &&(strinfo->call_state == VOIP_CALL_SETUP)){
931 strinfo->call_state = VOIP_IN_CALL;
932 comment = g_strdup_printf("SIP Request");
934 else if (strcmp(pi->request_method,"BYE")==0){
935 strinfo->call_state = VOIP_COMPLETED;
936 tapinfo->completed_calls++;
937 comment = g_strdup_printf("SIP Request");
939 else if ((strcmp(pi->request_method,"CANCEL")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
940 &&(ADDRESSES_EQUAL(&tmp_src,&(strinfo->initial_speaker)))&&(strinfo->call_state==VOIP_CALL_SETUP)){
941 strinfo->call_state = VOIP_CANCELLED;
942 tmp_sipinfo->sip_state = SIP_CANCEL_SENT;
943 comment = g_strdup_printf("SIP Request");
945 comment = g_strdup_printf("SIP Request");
949 strinfo->stop_sec=pinfo->fd->rel_ts.secs;
950 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
951 strinfo->last_frame_num=pinfo->fd->num;
952 ++(strinfo->npackets);
953 /* increment the packets counter of all calls */
954 ++(tapinfo->npackets);
956 /* add to the graph */
957 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
960 g_free((void *)tmp_src.data);
961 g_free((void *)tmp_dst.data);
963 /* add SDP info if apply */
964 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
965 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
971 tapinfo->redraw = TRUE;
973 return 1; /* refresh output */
977 /****************************************************************************/
978 voip_calls_tapinfo_t* voip_calls_get_info(void)
980 return &the_tapinfo_struct;
984 /****************************************************************************/
986 /****************************************************************************/
987 static gboolean have_SIP_tap_listener=FALSE;
988 /****************************************************************************/
990 sip_calls_init_tap(void)
992 GString *error_string;
994 if(have_SIP_tap_listener==FALSE)
996 /* don't register tap listener, if we have it already */
997 error_string = register_tap_listener("sip", &(the_tapinfo_struct.sip_dummy), NULL,
998 voip_calls_dlg_reset,
1002 if (error_string != NULL) {
1003 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1005 g_string_free(error_string, TRUE);
1008 have_SIP_tap_listener=TRUE;
1012 /****************************************************************************/
1014 remove_tap_listener_sip_calls(void)
1016 protect_thread_critical_region();
1017 remove_tap_listener(&(the_tapinfo_struct.sip_dummy));
1018 unprotect_thread_critical_region();
1020 have_SIP_tap_listener=FALSE;
1023 /****************************************************************************/
1024 /* ***************************TAP for ISUP **********************************/
1025 /****************************************************************************/
1027 static guint32 mtp3_opc, mtp3_dpc;
1028 static guint8 mtp3_ni;
1029 static guint32 mtp3_frame_num;
1032 /****************************************************************************/
1033 /* whenever a isup_ packet is seen by the tap listener */
1035 isup_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *isup_info _U_)
1037 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1038 voip_calls_info_t *tmp_listinfo;
1039 voip_calls_info_t *strinfo = NULL;
1040 isup_calls_info_t *tmp_isupinfo;
1041 gboolean found = FALSE;
1042 gboolean forward = FALSE;
1043 gboolean right_pair;
1045 gchar *frame_label = NULL;
1046 gchar *comment = NULL;
1049 /*voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct; unused */
1050 const isup_tap_rec_t *pi = isup_info;
1053 /* check if the lower layer is MTP matching the frame number */
1054 if (mtp3_frame_num != pinfo->fd->num) return 0;
1056 /* check wether we already have a call with these parameters in the list */
1057 list = g_list_first(tapinfo->strinfo_list);
1061 tmp_listinfo=list->data;
1062 if ((tmp_listinfo->protocol == VOIP_ISUP)&&(tmp_listinfo->call_active_state==VOIP_ACTIVE)){
1063 tmp_isupinfo = tmp_listinfo->prot_info;
1064 if ((tmp_isupinfo->cic == pinfo->circuit_id)&&(tmp_isupinfo->ni == mtp3_ni)) {
1065 if ((tmp_isupinfo->opc == mtp3_opc)&&(tmp_isupinfo->dpc == mtp3_dpc)){
1068 else if ((tmp_isupinfo->dpc == mtp3_opc)&&(tmp_isupinfo->opc == mtp3_dpc)){
1075 /* if there is an IAM for a call that is not in setup state, that means the previous call in the same
1076 cic is no longer active */
1077 if (tmp_listinfo->call_state == VOIP_CALL_SETUP){
1080 else if (pi->message_type != 1){
1084 tmp_listinfo->call_active_state=VOIP_INACTIVE;
1088 strinfo = (voip_calls_info_t*)(list->data);
1093 list = g_list_next (list);
1096 /* not in the list? then create a new entry if the message is IAM
1097 -i.e. if this session is a call*/
1100 if ((strinfo==NULL) &&(pi->message_type==1)){
1102 strinfo = g_malloc(sizeof(voip_calls_info_t));
1103 strinfo->call_active_state = VOIP_ACTIVE;
1104 strinfo->call_state = VOIP_UNKNOWN;
1105 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
1106 strinfo->selected=FALSE;
1107 strinfo->first_frame_num=pinfo->fd->num;
1108 strinfo->start_sec=pinfo->fd->rel_ts.secs;
1109 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1110 strinfo->protocol=VOIP_ISUP;
1111 if (pi->calling_number!=NULL){
1112 strinfo->from_identity=g_strdup(pi->calling_number);
1114 if (pi->called_number!=NULL){
1115 strinfo->to_identity=g_strdup(pi->called_number);
1117 strinfo->prot_info=g_malloc(sizeof(isup_calls_info_t));
1118 tmp_isupinfo=strinfo->prot_info;
1119 tmp_isupinfo->opc = mtp3_opc;
1120 tmp_isupinfo->dpc = mtp3_dpc;
1121 tmp_isupinfo->ni = mtp3_ni;
1122 tmp_isupinfo->cic = pinfo->circuit_id;
1123 strinfo->npackets = 0;
1124 strinfo->call_num = tapinfo->ncalls++;
1125 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
1129 strinfo->stop_sec=pinfo->fd->rel_ts.secs;
1130 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1131 strinfo->last_frame_num=pinfo->fd->num;
1132 ++(strinfo->npackets);
1134 /* Let's analyze the call state */
1137 for (i=0;(isup_message_type_value[i].strptr!=NULL)&& (isup_message_type_value[i].value!=pi->message_type);i++);
1139 if (isup_message_type_value[i].value==pi->message_type){
1140 frame_label = g_strdup(isup_message_type_value_acro[i].strptr);
1143 frame_label = g_strdup_printf("Unknown");
1146 if (strinfo->npackets == 1){ /* this is the first packet, that must be an IAM */
1147 if ((pi->calling_number!=NULL)&&(pi->called_number !=NULL)){
1148 comment = g_strdup_printf("Call from %s to %s",
1149 pi->calling_number, pi->called_number);
1152 else if (strinfo->npackets == 2){ /* in the second packet we show the SPs */
1154 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
1156 mtp3_ni, mtp3_dpc, pinfo->circuit_id);
1160 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
1162 mtp3_ni, mtp3_opc, pinfo->circuit_id);
1167 switch(pi->message_type){
1169 strinfo->call_state=VOIP_CALL_SETUP;
1171 case 7: /* CONNECT */
1172 case 9: /* ANSWER */
1173 strinfo->call_state=VOIP_IN_CALL;
1175 case 12: /* RELEASE */
1176 if (strinfo->call_state==VOIP_CALL_SETUP){
1178 strinfo->call_state=VOIP_CANCELLED;
1181 strinfo->call_state=VOIP_REJECTED;
1182 tapinfo->rejected_calls++;
1185 else if (strinfo->call_state == VOIP_IN_CALL){
1186 strinfo->call_state = VOIP_COMPLETED;
1187 tapinfo->completed_calls++;
1189 for (i=0;(q931_cause_code_vals[i].strptr!=NULL)&& (q931_cause_code_vals[i].value!=pi->cause_value);i++);
1190 if (q931_cause_code_vals[i].value==pi->cause_value){
1191 comment = g_strdup_printf("Cause %i - %s",pi->cause_value, q931_cause_code_vals[i].strptr);
1194 comment = g_strdup_printf("Cause %i",pi->cause_value);
1199 /* increment the packets counter of all calls */
1200 ++(tapinfo->npackets);
1202 /* add to the graph */
1203 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1205 g_free(frame_label);
1208 tapinfo->redraw = TRUE;
1210 return 1; /* refresh output */
1213 /****************************************************************************/
1215 static gboolean have_isup_tap_listener=FALSE;
1218 isup_calls_init_tap(void)
1220 GString *error_string;
1223 if(have_isup_tap_listener==FALSE)
1225 error_string = register_tap_listener("isup", &(the_tapinfo_struct.isup_dummy),
1227 voip_calls_dlg_reset,
1232 if (error_string != NULL) {
1233 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1235 g_string_free(error_string, TRUE);
1238 have_isup_tap_listener=TRUE;
1242 /****************************************************************************/
1245 remove_tap_listener_isup_calls(void)
1247 protect_thread_critical_region();
1248 remove_tap_listener(&(the_tapinfo_struct.isup_dummy));
1249 unprotect_thread_critical_region();
1251 have_isup_tap_listener=FALSE;
1255 /****************************************************************************/
1256 /* ***************************TAP for MTP3 **********************************/
1257 /****************************************************************************/
1260 /****************************************************************************/
1261 /* whenever a mtp3_ packet is seen by the tap listener */
1263 mtp3_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *mtp3_info _U_)
1265 const mtp3_tap_rec_t *pi = mtp3_info;
1267 /* keep the data in memory to use when the ISUP information arrives */
1269 mtp3_opc = pi->addr_opc.pc;
1270 mtp3_dpc = pi->addr_dpc.pc;
1271 mtp3_ni = pi->addr_opc.ni;
1272 mtp3_frame_num = pinfo->fd->num;
1277 /****************************************************************************/
1279 static gboolean have_mtp3_tap_listener=FALSE;
1282 mtp3_calls_init_tap(void)
1284 GString *error_string;
1287 if(have_mtp3_tap_listener==FALSE)
1289 error_string = register_tap_listener("mtp3", &(the_tapinfo_struct.mtp3_dummy),
1291 voip_calls_dlg_reset,
1296 if (error_string != NULL) {
1297 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1299 g_string_free(error_string, TRUE);
1302 have_mtp3_tap_listener=TRUE;
1306 /****************************************************************************/
1309 remove_tap_listener_mtp3_calls(void)
1311 protect_thread_critical_region();
1312 remove_tap_listener(&(the_tapinfo_struct.mtp3_dummy));
1313 unprotect_thread_critical_region();
1315 have_mtp3_tap_listener=FALSE;
1318 /****************************************************************************/
1319 /* ***************************TAP for Q931 **********************************/
1320 /****************************************************************************/
1321 void h245_add_to_graph(guint32 new_frame_num);
1322 static const e_guid_t guid_allzero = {0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };
1323 /* defines specific H323 data */
1325 static gchar *q931_calling_number;
1326 static gchar *q931_called_number;
1327 static guint8 q931_cause_value;
1328 static gint32 q931_crv;
1329 static guint32 q931_frame_num;
1331 static guint32 h225_frame_num = 0;
1332 static guint16 h225_call_num = 0;
1333 static h225_cs_type h225_cstype = H225_OTHER;
1334 static gboolean h225_is_faststart;
1336 static guint32 actrace_frame_num = 0;
1337 static gint32 actrace_trunk = 0;
1338 static gint32 actrace_direction = 0;
1341 /****************************************************************************/
1342 /* whenever a q931_ packet is seen by the tap listener */
1344 q931_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *q931_info _U_)
1347 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1348 h323_calls_info_t *tmp_h323info,*tmp2_h323info;
1349 actrace_isdn_calls_info_t *tmp_actrace_isdn_info;
1350 voip_calls_info_t *tmp_listinfo;
1351 voip_calls_info_t *strinfo = NULL;
1352 h245_address_t *h245_add = NULL;
1355 const q931_packet_info *pi = q931_info;
1357 /* free previously allocated q931_calling/ed_number */
1358 g_free(q931_calling_number);
1359 g_free(q931_called_number);
1361 if (pi->calling_number!=NULL)
1362 q931_calling_number = g_strdup(pi->calling_number);
1364 q931_calling_number = g_strdup("");
1366 if (pi->called_number!=NULL)
1367 q931_called_number = g_strdup(pi->called_number);
1369 q931_called_number = g_strdup("");
1370 q931_cause_value = pi->cause_value;
1371 q931_frame_num = pinfo->fd->num;
1375 /* add staff to H323 calls */
1376 if (h225_frame_num == q931_frame_num) {
1377 tmp_h323info = NULL;
1378 list = g_list_first(tapinfo->strinfo_list);
1381 tmp_listinfo=list->data;
1382 if ( (tmp_listinfo->protocol == VOIP_H323) && (tmp_listinfo->call_num == h225_call_num) ){
1383 tmp_h323info = tmp_listinfo->prot_info;
1384 strinfo = (voip_calls_info_t*)(list->data);
1386 /* Add the CRV to the h323 call */
1387 if (tmp_h323info->q931_crv == -1) {
1388 tmp_h323info->q931_crv = q931_crv;
1389 } else if (tmp_h323info->q931_crv != q931_crv) {
1390 tmp_h323info->q931_crv2 = q931_crv;
1394 list = g_list_next (list);
1397 if (strinfo != NULL) {
1399 if (h225_cstype == H225_SETUP) {
1400 /* set te calling and called number from the Q931 packet */
1401 if (q931_calling_number != NULL){
1402 g_free(strinfo->from_identity);
1403 strinfo->from_identity=g_strdup(q931_calling_number);
1405 if (q931_called_number != NULL){
1406 g_free(strinfo->to_identity);
1407 strinfo->to_identity=g_strdup(q931_called_number);
1410 /* check if there is an LRQ/LCF that match this Setup */
1411 /* TODO: we are just checking the DialedNumer in LRQ/LCF agains the Setup
1412 we should also check if the h225 signaling IP and port match the destination
1413 Setup ip and port */
1414 list = g_list_first(tapinfo->strinfo_list);
1417 tmp_listinfo=list->data;
1418 if (tmp_listinfo->protocol == VOIP_H323){
1419 tmp2_h323info = tmp_listinfo->prot_info;
1421 /* check if the called number match a LRQ/LCF */
1422 if ( (strcmp(strinfo->to_identity, tmp_listinfo->to_identity)==0)
1423 && (memcmp(&tmp2_h323info->guid, &guid_allzero, GUID_LEN) == 0) ){
1424 /* change the call graph to the LRQ/LCF to belong to this call */
1425 strinfo->npackets += change_call_num_graph(tapinfo, tmp_listinfo->call_num, strinfo->call_num);
1427 /* remove this LRQ/LCF call entry because we have found the Setup that match them */
1428 g_free(tmp_listinfo->from_identity);
1429 g_free(tmp_listinfo->to_identity);
1430 g_free(tmp2_h323info->guid);
1432 list2 = g_list_first(tmp2_h323info->h245_list);
1435 h245_add=list2->data;
1436 g_free((void *)h245_add->h245_address.data);
1437 g_free(list2->data);
1438 list2 = g_list_next(list2);
1440 g_list_free(tmp_h323info->h245_list);
1441 tmp_h323info->h245_list = NULL;
1442 g_free(tmp_listinfo->prot_info);
1443 tapinfo->strinfo_list = g_list_remove(tapinfo->strinfo_list, tmp_listinfo);
1447 list = g_list_next (list);
1450 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"),
1451 (h225_is_faststart==TRUE?"on":"off"));
1452 } else if (h225_cstype == H225_RELEASE_COMPLET) {
1453 /* get the Q931 Release cause code */
1454 if (q931_cause_value != 0xFF){
1455 comment = g_strdup_printf("H225 Q931 Rel Cause (%i):%s", q931_cause_value, val_to_str(q931_cause_value, q931_cause_code_vals, "<unknown>"));
1456 } else { /* Cause not set */
1457 comment = g_strdup("H225 No Q931 Rel Cause");
1460 /* change the graph comment for this new one */
1461 if (comment != NULL) {
1462 change_frame_graph(tapinfo, h225_frame_num, NULL, comment);
1466 /* we reset the h225_frame_num to 0 because there could be empty h225 in the same frame
1467 as non empty h225 (e.g connect), so we don't have to be here twice */
1470 /* add staff to H245 */
1471 } else if (h245_labels.frame_num == q931_frame_num) {
1472 /* there are empty H225 frames that don't have guid (guaid=0) but they have h245 info,
1473 so the only way to match those frames is with the Q931 CRV number */
1474 list = g_list_first(tapinfo->strinfo_list);
1477 tmp_listinfo=list->data;
1478 if (tmp_listinfo->protocol == VOIP_H323){
1479 tmp_h323info = tmp_listinfo->prot_info;
1480 if ( ((tmp_h323info->q931_crv == q931_crv) || (tmp_h323info->q931_crv2 == q931_crv)) && (q931_crv!=-1)){
1482 comment = g_strdup("");
1484 /* if the frame number exists in graph, append to it*/
1485 if (!append_to_frame_graph(tapinfo, q931_frame_num, "", comment)) {
1486 /* if not exist, add to the graph */
1487 add_to_graph(tapinfo, pinfo, "", comment, tmp_listinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1488 ++(tmp_listinfo->npackets);
1489 /* increment the packets counter of all calls */
1490 ++(tapinfo->npackets);
1493 /* Add the H245 info if exists to the Graph */
1494 h245_add_to_graph(pinfo->fd->num);
1499 list = g_list_next (list);
1502 /* add staff to ACTRACE */
1503 } else if (actrace_frame_num == q931_frame_num) {
1505 gchar *comment = NULL;
1508 list = g_list_first(tapinfo->strinfo_list);
1511 tmp_listinfo=list->data;
1512 if ( tmp_listinfo->protocol == VOIP_AC_ISDN ){
1513 tmp_actrace_isdn_info = tmp_listinfo->prot_info;
1514 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
1515 if ( (tmp_actrace_isdn_info->crv == q931_crv) && (tmp_actrace_isdn_info->trunk == actrace_trunk) ) {
1516 strinfo = (voip_calls_info_t*)(list->data);
1520 list = g_list_next (list);
1523 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, g_strdup("PSTN"));
1525 /* if it is a new call, add it to the list */
1527 strinfo = g_malloc(sizeof(voip_calls_info_t));
1528 strinfo->call_active_state = VOIP_ACTIVE;
1529 strinfo->call_state = VOIP_CALL_SETUP;
1530 strinfo->from_identity=g_strdup(q931_calling_number);
1531 strinfo->to_identity=g_strdup(q931_called_number);
1532 COPY_ADDRESS(&(strinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
1533 strinfo->first_frame_num=pinfo->fd->num;
1534 strinfo->selected=FALSE;
1535 strinfo->start_sec=pinfo->fd->rel_ts.secs;
1536 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1537 strinfo->protocol=VOIP_AC_ISDN;
1538 strinfo->prot_info=g_malloc(sizeof(actrace_isdn_calls_info_t));
1539 tmp_actrace_isdn_info=strinfo->prot_info;
1540 tmp_actrace_isdn_info->crv=q931_crv;
1541 tmp_actrace_isdn_info->trunk=actrace_trunk;
1542 strinfo->npackets = 0;
1543 strinfo->call_num = tapinfo->ncalls++;
1544 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
1547 strinfo->stop_sec=pinfo->fd->rel_ts.secs;
1548 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1549 strinfo->last_frame_num=pinfo->fd->num;
1550 ++(strinfo->npackets);
1551 /* increment the packets counter of all calls */
1552 ++(tapinfo->npackets);
1554 switch(pi->message_type){
1556 comment = g_strdup_printf("AC_ISDN trunk:%u Calling: %s Called:%s", actrace_trunk, q931_calling_number, q931_called_number);
1557 strinfo->call_state=VOIP_CALL_SETUP;
1560 strinfo->call_state=VOIP_IN_CALL;
1562 case Q931_RELEASE_COMPLETE:
1564 case Q931_DISCONNECT:
1565 if (strinfo->call_state==VOIP_CALL_SETUP){
1566 if (ADDRESSES_EQUAL(&(strinfo->initial_speaker), actrace_direction?&pstn_add:&(pinfo->src) )){ /* forward direction */
1567 strinfo->call_state=VOIP_CANCELLED;
1570 strinfo->call_state=VOIP_REJECTED;
1571 tapinfo->rejected_calls++;
1573 } else if ( (strinfo->call_state!=VOIP_CANCELLED) && (strinfo->call_state!=VOIP_REJECTED) ){
1574 strinfo->call_state=VOIP_COMPLETED;
1575 tapinfo->completed_calls++;
1577 if (q931_cause_value != 0xFF){
1578 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>"));
1579 } else { /* Cause not set */
1580 comment = g_strdup("AC_ISDN No Q931 Rel Cause");
1586 comment = g_strdup_printf("AC_ISDN trunk:%u", actrace_trunk );
1588 add_to_graph(tapinfo, pinfo, val_to_str(pi->message_type, q931_message_type_vals, "<unknown>") , comment, strinfo->call_num,
1589 actrace_direction?&pstn_add:&(pinfo->src),
1590 actrace_direction?&(pinfo->src):&pstn_add,
1594 g_free((char *)pstn_add.data);
1597 tapinfo->redraw = TRUE;
1599 return 1; /* refresh output */
1602 /****************************************************************************/
1603 static gboolean have_q931_tap_listener=FALSE;
1606 q931_calls_init_tap(void)
1608 GString *error_string;
1611 if(have_q931_tap_listener==FALSE)
1613 error_string = register_tap_listener("q931", &(the_tapinfo_struct.q931_dummy),
1615 voip_calls_dlg_reset,
1620 if (error_string != NULL) {
1621 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1623 g_string_free(error_string, TRUE);
1626 have_q931_tap_listener=TRUE;
1630 /****************************************************************************/
1633 remove_tap_listener_q931_calls(void)
1635 protect_thread_critical_region();
1636 remove_tap_listener(&(the_tapinfo_struct.q931_dummy));
1637 unprotect_thread_critical_region();
1639 have_q931_tap_listener=FALSE;
1642 /****************************************************************************/
1643 /****************************TAP for H323 ***********************************/
1644 /****************************************************************************/
1646 static void add_h245_Address(h323_calls_info_t *h323info, h245_address_t *h245_address)
1648 h323info->h245_list = g_list_append(h323info->h245_list, h245_address);
1651 /****************************************************************************/
1652 /* whenever a H225 packet is seen by the tap listener */
1654 H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H225info)
1656 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1657 voip_calls_info_t *tmp_listinfo;
1658 voip_calls_info_t *strinfo = NULL;
1659 h323_calls_info_t *tmp_h323info = NULL;
1663 address tmp_src, tmp_dst;
1664 h245_address_t *h245_add = NULL;
1666 const h225_packet_info *pi = H225info;
1668 /* if not guid and RAS and not LRQ, LCF or LRJ return because did not belong to a call */
1669 /* OR, if not guid and is H225 return because doesn't belong to a call */
1670 if ((memcmp(&pi->guid, &guid_allzero, GUID_LEN) == 0))
1671 if ( ((pi->msg_type == H225_RAS) && ((pi->msg_tag < 18) || (pi->msg_tag > 20))) || (pi->msg_type != H225_RAS) )
1674 /* if it is RAS LCF or LRJ*/
1675 if ( (pi->msg_type == H225_RAS) && ((pi->msg_tag == 19) || (pi->msg_tag == 20))) {
1676 /* if the LCF/LRJ doesn't match to a LRQ, just return */
1677 if (!pi->request_available) return 0;
1679 /* check wether we already have a call with this request SeqNum */
1680 list = g_list_first(tapinfo->strinfo_list);
1683 tmp_listinfo=list->data;
1684 if (tmp_listinfo->protocol == VOIP_H323){
1685 tmp_h323info = tmp_listinfo->prot_info;
1686 if (tmp_h323info->requestSeqNum == pi->requestSeqNum) {
1687 strinfo = (voip_calls_info_t*)(list->data);
1691 list = g_list_next (list);
1694 /* check wether we already have a call with this guid in the list */
1695 list = g_list_first(tapinfo->strinfo_list);
1698 tmp_listinfo=list->data;
1699 if (tmp_listinfo->protocol == VOIP_H323){
1700 tmp_h323info = tmp_listinfo->prot_info;
1701 if ( (memcmp(&tmp_h323info->guid, &guid_allzero, GUID_LEN) != 0) && (memcmp(&tmp_h323info->guid, &pi->guid,GUID_LEN)==0) ){
1702 strinfo = (voip_calls_info_t*)(list->data);
1706 list = g_list_next (list);
1710 h225_cstype = pi->cs_type;
1711 h225_is_faststart = pi->is_faststart;
1713 /* not in the list? then create a new entry */
1714 if ((strinfo==NULL)){
1715 strinfo = g_malloc(sizeof(voip_calls_info_t));
1716 strinfo->call_active_state = VOIP_ACTIVE;
1717 strinfo->call_state = VOIP_UNKNOWN;
1718 strinfo->from_identity=g_strdup("");
1719 strinfo->to_identity=g_strdup("");
1720 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
1721 strinfo->selected=FALSE;
1722 strinfo->first_frame_num=pinfo->fd->num;
1723 strinfo->start_sec=pinfo->fd->rel_ts.secs;
1724 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1725 strinfo->protocol=VOIP_H323;
1726 strinfo->prot_info=g_malloc(sizeof(h323_calls_info_t));
1727 tmp_h323info = strinfo->prot_info;
1728 tmp_h323info->guid = g_memdup(&pi->guid, sizeof pi->guid);
1729 tmp_h323info->h225SetupAddr.type = AT_NONE;
1730 tmp_h323info->h225SetupAddr.len = 0;
1731 tmp_h323info->h245_list = NULL;
1732 tmp_h323info->is_faststart_Setup = FALSE;
1733 tmp_h323info->is_faststart_Proc = FALSE;
1734 tmp_h323info->is_h245Tunneling = FALSE;
1735 tmp_h323info->is_h245 = FALSE;
1736 tmp_h323info->q931_crv = -1;
1737 tmp_h323info->q931_crv2 = -1;
1738 tmp_h323info->requestSeqNum = 0;
1739 strinfo->call_num = tapinfo->ncalls++;
1740 strinfo->npackets = 0;
1742 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
1747 h225_frame_num = pinfo->fd->num;
1748 h225_call_num = strinfo->call_num;
1750 /* let's analyze the call state */
1752 COPY_ADDRESS(&(tmp_src),&(pinfo->src));
1753 COPY_ADDRESS(&(tmp_dst),&(pinfo->dst));
1755 strinfo->stop_sec=pinfo->fd->rel_ts.secs;
1756 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1757 strinfo->last_frame_num=pinfo->fd->num;
1758 ++(strinfo->npackets);
1759 /* increment the packets counter of all calls */
1760 ++(tapinfo->npackets);
1763 /* XXX: it is supposed to be initialized isn't it? */
1764 g_assert(tmp_h323info != NULL);
1766 /* change the status */
1767 if (pi->msg_type == H225_CS){
1769 /* this is still IPv4 only, because the dissector is */
1770 if (pi->is_h245 == TRUE){
1771 h245_add = g_malloc(sizeof (h245_address_t));
1772 h245_add->h245_address.type=AT_IPv4;
1773 h245_add->h245_address.len=4;
1774 h245_add->h245_address.data = g_malloc(sizeof(pi->h245_address));
1775 g_memmove((void *)(h245_add->h245_address.data), &(pi->h245_address), 4);
1776 h245_add->h245_port = pi->h245_port;
1777 add_h245_Address(tmp_h323info, h245_add);
1780 if (pi->cs_type != H225_RELEASE_COMPLET) tmp_h323info->is_h245Tunneling = pi->is_h245Tunneling;
1782 frame_label = g_strdup(pi->frame_label);
1784 switch(pi->cs_type){
1786 tmp_h323info->is_faststart_Setup = pi->is_faststart;
1788 /* Set the Setup address if it was not set */
1789 if (tmp_h323info->h225SetupAddr.type == AT_NONE)
1790 COPY_ADDRESS(&(tmp_h323info->h225SetupAddr), &(pinfo->src));
1791 strinfo->call_state=VOIP_CALL_SETUP;
1792 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1793 (pi->is_faststart==TRUE?"on":"off"));
1796 strinfo->call_state=VOIP_IN_CALL;
1797 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1798 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1799 (pi->is_faststart==TRUE?"on":"off"));
1801 case H225_RELEASE_COMPLET:
1802 COPY_ADDRESS(&tmp_src,&(pinfo->src));
1803 if (strinfo->call_state==VOIP_CALL_SETUP){
1804 if (ADDRESSES_EQUAL(&(tmp_h323info->h225SetupAddr),&tmp_src)){ /* forward direction */
1805 strinfo->call_state=VOIP_CANCELLED;
1808 strinfo->call_state=VOIP_REJECTED;
1809 tapinfo->rejected_calls++;
1812 strinfo->call_state=VOIP_COMPLETED;
1813 tapinfo->completed_calls++;
1815 comment = g_strdup("H225 No Q931 Rel Cause");
1819 case H225_CALL_PROCEDING:
1820 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1821 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1822 (pi->is_faststart==TRUE?"on":"off"));
1825 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1826 (pi->is_faststart==TRUE?"on":"off"));
1830 else if (pi->msg_type == H225_RAS){
1831 switch(pi->msg_tag){
1833 if (!pi->is_duplicate){
1834 g_free(strinfo->to_identity);
1835 strinfo->to_identity=g_strdup(pi->dialedDigits);
1836 tmp_h323info->requestSeqNum = pi->requestSeqNum;
1839 if (strlen(pi->dialedDigits))
1840 comment = g_strdup_printf("H225 RAS dialedDigits: %s", pi->dialedDigits);
1842 comment = g_strdup("H225 RAS");
1845 comment = g_strdup("H225 RAS");
1847 frame_label = g_strdup_printf("%s", val_to_str(pi->msg_tag, RasMessage_vals, "<unknown>"));
1849 frame_label = g_strdup("H225: Unknown");
1850 comment = g_strdup("");
1853 /* add to graph analysis */
1855 /* if the frame number exists in graph, append to it*/
1856 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, comment)) {
1857 /* if not exist, add to the graph */
1858 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1859 g_free((void *)tmp_src.data);
1860 g_free((void *)tmp_dst.data);
1863 /* Add the H245 info if exists to the Graph */
1864 h245_add_to_graph(pinfo->fd->num);
1866 g_free(frame_label);
1871 tapinfo->redraw = TRUE;
1873 return 1; /* refresh output */
1877 /****************************************************************************/
1879 /****************************************************************************/
1880 static gboolean have_H225_tap_listener=FALSE;
1881 /****************************************************************************/
1883 h225_calls_init_tap(void)
1885 GString *error_string;
1887 if(have_H225_tap_listener==FALSE)
1889 /* don't register tap listener, if we have it already */
1890 error_string = register_tap_listener("h225", &(the_tapinfo_struct.h225_dummy), NULL,
1891 voip_calls_dlg_reset,
1896 if (error_string != NULL) {
1897 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1899 g_string_free(error_string, TRUE);
1902 have_H225_tap_listener=TRUE;
1906 /****************************************************************************/
1908 remove_tap_listener_h225_calls(void)
1910 protect_thread_critical_region();
1911 remove_tap_listener(&(the_tapinfo_struct.h225_dummy));
1912 unprotect_thread_critical_region();
1914 have_H225_tap_listener=FALSE;
1917 /* Add the h245 label info to the graph */
1918 void h245_add_to_graph(guint32 new_frame_num)
1922 if (new_frame_num != h245_labels.frame_num) return;
1924 for (n=0; n<h245_labels.labels_count; n++) {
1925 append_to_frame_graph(&the_tapinfo_struct, new_frame_num, h245_labels.labels[n].frame_label, h245_labels.labels[n].comment);
1926 g_free(h245_labels.labels[n].frame_label);
1927 h245_labels.labels[n].frame_label = NULL;
1928 g_free(h245_labels.labels[n].comment);
1929 h245_labels.labels[n].comment = NULL;
1931 h245_labels.frame_num = 0;
1932 h245_labels.labels_count = 0;
1935 /* free the h245_labels if the frame number is different */
1936 static void h245_free_labels(guint32 new_frame_num)
1940 if (new_frame_num == h245_labels.frame_num) return;
1942 for (n=0; n<h245_labels.labels_count; n++) {
1943 g_free(h245_labels.labels[n].frame_label);
1944 h245_labels.labels[n].frame_label = NULL;
1945 g_free(h245_labels.labels[n].comment);
1946 h245_labels.labels[n].comment = NULL;
1948 h245_labels.frame_num = 0;
1949 h245_labels.labels_count = 0;
1952 /* add the frame_label and comment to h245_labels and free the actual one if it is different frame num */
1953 static void h245_add_label(guint32 new_frame_num, gchar *frame_label, gchar *comment)
1955 h245_free_labels(new_frame_num);
1957 h245_labels.frame_num = new_frame_num;
1958 h245_labels.labels[h245_labels.labels_count].frame_label = g_strdup(frame_label);
1959 h245_labels.labels[h245_labels.labels_count].comment = g_strdup(comment);
1961 if (h245_labels.labels_count < (H245_MAX-1))
1962 h245_labels.labels_count++;
1966 /****************************************************************************/
1967 /* whenever a H245dg packet is seen by the tap listener (when H245 tunneling is ON) */
1969 H245dgcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H245info)
1971 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1972 voip_calls_info_t *tmp_listinfo;
1973 voip_calls_info_t *strinfo = NULL;
1974 h323_calls_info_t *tmp_h323info;
1979 address tmp_src, tmp_dst;
1980 h245_address_t *h245_add = NULL;
1982 const h245_packet_info *pi = H245info;
1984 /* check if Tunneling is OFF and we have a call with this H245 add */
1985 list = g_list_first(tapinfo->strinfo_list);
1988 tmp_listinfo=list->data;
1989 if (tmp_listinfo->protocol == VOIP_H323){
1990 tmp_h323info = tmp_listinfo->prot_info;
1992 COPY_ADDRESS(&(tmp_src), &(pinfo->src));
1993 COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
1994 list2 = g_list_first(tmp_h323info->h245_list);
1997 h245_add=list2->data;
1998 if ( (ADDRESSES_EQUAL(&(h245_add->h245_address),&tmp_src) && (h245_add->h245_port == pinfo->srcport))
1999 || (ADDRESSES_EQUAL(&(h245_add->h245_address),&tmp_dst) && (h245_add->h245_port == pinfo->destport)) ){
2000 strinfo = (voip_calls_info_t*)(list->data);
2002 ++(strinfo->npackets);
2003 /* increment the packets counter of all calls */
2004 ++(tapinfo->npackets);
2008 list2 = g_list_next(list2);
2010 if (strinfo!=NULL) break;
2011 g_free((void *)tmp_src.data);
2012 g_free((void *)tmp_dst.data);
2014 list = g_list_next(list);
2017 /* Tunnel is OFF, and we matched the h245 add so we add it to graph */
2019 ++(strinfo->npackets);
2020 /* increment the packets counter of all calls */
2021 ++(tapinfo->npackets);
2022 frame_label = g_strdup(pi->frame_label);
2023 comment = g_strdup(pi->comment);
2024 /* if the frame number exists in graph, append to it*/
2025 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, frame_label, comment)) {
2026 /* if not exist, add to the graph */
2027 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2029 g_free(frame_label);
2032 /* Tunnel is ON, so we save the label info to use it into h225 or q931 tap. OR may be
2033 tunnel OFF but we did not matched the h245 add, in this case nobady will set this label
2034 since the frame_num will not match */
2036 h245_add_label(pinfo->fd->num, (gchar *) pi->frame_label, (gchar *) pi->comment);
2039 tapinfo->redraw = TRUE;
2041 return 1; /* refresh output */
2045 /****************************************************************************/
2047 /****************************************************************************/
2048 static gboolean have_H245dg_tap_listener=FALSE;
2049 /****************************************************************************/
2051 h245dg_calls_init_tap(void)
2053 GString *error_string;
2055 if(have_H245dg_tap_listener==FALSE)
2057 /* don't register tap listener, if we have it already */
2058 error_string = register_tap_listener("h245dg", &(the_tapinfo_struct.h245dg_dummy), NULL,
2059 voip_calls_dlg_reset,
2064 if (error_string != NULL) {
2065 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2067 g_string_free(error_string, TRUE);
2070 have_H245dg_tap_listener=TRUE;
2074 /****************************************************************************/
2076 remove_tap_listener_h245dg_calls(void)
2078 protect_thread_critical_region();
2079 remove_tap_listener(&(the_tapinfo_struct.h245dg_dummy));
2080 unprotect_thread_critical_region();
2082 have_H245dg_tap_listener=FALSE;
2085 /****************************************************************************/
2086 /****************************TAP for SDP PROTOCOL ***************************/
2087 /****************************************************************************/
2088 /* whenever a SDP packet is seen by the tap listener */
2090 SDPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SDPinfo)
2092 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2093 const sdp_packet_info *pi = SDPinfo;
2095 /* There are protocols like MGCP/SIP where the SDP is called before the tap for the
2096 MGCP/SIP packet, in those cases we assign the SPD summary to global lastSDPsummary
2099 g_free(sdp_summary);
2100 sdp_frame_num = pinfo->fd->num;
2101 /* Append to graph the SDP summary if the packet exists */
2102 sdp_summary = g_strdup_printf("SDP (%s)", pi->summary_str);
2103 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2105 tapinfo->redraw = TRUE;
2107 return 1; /* refresh output */
2111 /****************************************************************************/
2113 /****************************************************************************/
2114 static gboolean have_sdp_tap_listener=FALSE;
2115 /****************************************************************************/
2117 sdp_calls_init_tap(void)
2119 GString *error_string;
2121 if(have_sdp_tap_listener==FALSE)
2123 /* don't register tap listener, if we have it already */
2124 error_string = register_tap_listener("sdp", &(the_tapinfo_struct.sdp_dummy), NULL,
2125 voip_calls_dlg_reset,
2130 if (error_string != NULL) {
2131 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2133 g_string_free(error_string, TRUE);
2136 have_sdp_tap_listener=TRUE;
2140 /****************************************************************************/
2142 remove_tap_listener_sdp_calls(void)
2144 protect_thread_critical_region();
2145 remove_tap_listener(&(the_tapinfo_struct.sdp_dummy));
2146 unprotect_thread_critical_region();
2148 have_sdp_tap_listener=FALSE;
2153 /****************************************************************************/
2154 /* ***************************TAP for MGCP **********************************/
2155 /****************************************************************************/
2158 This function will look for a signal/event in the SignalReq/ObsEvent string
2159 and return true if it is found
2161 static gboolean isSignal(const gchar *signal, const gchar *signalStr)
2164 gchar **resultArray;
2166 /* if there is no signalStr, just return false */
2167 if (signalStr == NULL) return FALSE;
2169 /* if are both "blank" return true */
2170 if ( (*signal == '\0') && (*signalStr == '\0') ) return TRUE;
2172 /* look for signal in signalSre */
2173 resultArray = g_strsplit(signalStr, ",", 10);
2175 for (i = 0; resultArray[i]; i++) {
2176 g_strstrip(resultArray[i]);
2177 if (strcmp(resultArray[i], signal) == 0) return TRUE;
2180 g_strfreev(resultArray);
2186 This function will get the Caller ID info and replace the current string
2187 This is how it looks the caller Id: rg, ci(02/16/08/29, "3035550002","Ale Sipura 2")
2189 static void mgcpCallerID(gchar *signalStr, gchar **callerId)
2193 /* if there is no signalStr, just return false */
2194 if (signalStr == NULL) return;
2196 arrayStr = g_strsplit(signalStr, "\"", 10);
2198 if (arrayStr[0] == NULL) return;
2200 /* look for the ci signal */
2201 if (strstr(arrayStr[0], "ci(") && (arrayStr[1] != NULL) ) {
2202 /* free the previous "From" field of the call, and assign the new */
2204 *callerId = g_strdup(arrayStr[1]);
2206 g_strfreev(arrayStr);
2213 This function will get the Dialed Digits and replace the current string
2214 This is how it looks the dialed digits 5,5,5,0,0,0,2,#,*
2216 static void mgcpDialedDigits(gchar *signalStr, gchar **dialedDigits)
2219 gchar resultStr[50];
2222 /* if there is no signalStr, just return false */
2223 if (signalStr == NULL) return;
2225 tmpStr = g_strdup(signalStr);
2227 for ( i = 0 ; tmpStr[i] ; i++) {
2228 switch (tmpStr[i]) {
2229 case '0' : case '1' : case '2' : case '3' : case '4' :
2230 case '5' : case '6' : case '7' : case '8' : case '9' :
2231 case '#' : case '*' :
2239 for (i = 0, j = 0; tmpStr[i] && i<50; i++) {
2240 if (tmpStr[i] != '?')
2241 resultStr[j++] = tmpStr[i];
2243 resultStr[j] = '\0';
2245 if (*resultStr == '\0') return;
2247 g_free(*dialedDigits);
2248 *dialedDigits = g_strdup(resultStr);
2256 /****************************************************************************/
2257 /* whenever a MGCP packet is seen by the tap listener */
2259 MGCPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *MGCPinfo)
2261 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2263 voip_calls_info_t *tmp_listinfo;
2264 voip_calls_info_t *strinfo = NULL;
2265 mgcp_calls_info_t *tmp_mgcpinfo = NULL;
2268 gchar *frame_label = NULL;
2269 gchar *comment = NULL;
2270 graph_analysis_item_t *gai;
2271 gboolean new = FALSE;
2272 gboolean fromEndpoint = FALSE; /* true for calls originated in Endpoints, false for calls from MGC */
2275 const mgcp_info_t *pi = MGCPinfo;
2278 if ((pi->mgcp_type == MGCP_REQUEST) && !pi->is_duplicate ){
2279 /* check wether we already have a call with this Endpoint and it is active*/
2280 list = g_list_first(tapinfo->strinfo_list);
2283 tmp_listinfo=list->data;
2284 if ((tmp_listinfo->protocol == VOIP_MGCP) && (tmp_listinfo->call_active_state == VOIP_ACTIVE)){
2285 tmp_mgcpinfo = tmp_listinfo->prot_info;
2286 if (pi->endpointId != NULL){
2287 if (g_strcasecmp(tmp_mgcpinfo->endpointId,pi->endpointId) == 0){
2289 check first if it is an ended call. We consider an ended call after 1sec we don't
2290 get a packet in this Endpoint and the call has been released
2292 diff_time = nstime_to_sec(&pinfo->fd->rel_ts) - tmp_listinfo->stop_sec + (double)tmp_listinfo->stop_usec/1000000;
2293 if ( ((tmp_listinfo->call_state == VOIP_CANCELLED) || (tmp_listinfo->call_state == VOIP_COMPLETED) || (tmp_listinfo->call_state == VOIP_REJECTED)) && (diff_time > 1) ){
2294 tmp_listinfo->call_active_state = VOIP_INACTIVE;
2296 strinfo = (voip_calls_info_t*)(list->data);
2302 list = g_list_next (list);
2305 /* there is no call with this Endpoint, lets see if this a new call or not */
2306 if (strinfo == NULL){
2307 if ( (strcmp(pi->code, "NTFY") == 0) && isSignal("hd", pi->observedEvents) ){ /* off hook transition */
2308 /* this is a new call from the Endpoint */
2309 fromEndpoint = TRUE;
2311 } else if (strcmp(pi->code, "CRCX") == 0){
2312 /* this is a new call from the MGC */
2313 fromEndpoint = FALSE;
2318 } else if ( ((pi->mgcp_type == MGCP_RESPONSE) && pi->request_available) ||
2319 ((pi->mgcp_type == MGCP_REQUEST) && pi->is_duplicate) ) {
2320 /* if it is a response OR if it is a duplicated Request, lets look in the Graph if thre is a request that match */
2321 listGraph = g_list_first(tapinfo->graph_analysis->list);
2324 gai = listGraph->data;
2325 if (gai->frame_num == pi->req_num){
2326 /* there is a request that match, so look the associated call with this call_num */
2327 list = g_list_first(tapinfo->strinfo_list);
2330 tmp_listinfo=list->data;
2331 if (tmp_listinfo->protocol == VOIP_MGCP){
2332 if (tmp_listinfo->call_num == gai->conv_num){
2333 tmp_mgcpinfo = tmp_listinfo->prot_info;
2334 strinfo = (voip_calls_info_t*)(list->data);
2338 list = g_list_next (list);
2340 if (strinfo != NULL) break;
2342 listGraph = g_list_next(listGraph);
2344 /* if there is not a matching request, just return */
2345 if (strinfo == NULL) return 0;
2348 /* not in the list? then create a new entry */
2350 strinfo = g_malloc(sizeof(voip_calls_info_t));
2351 strinfo->call_active_state = VOIP_ACTIVE;
2352 strinfo->call_state = VOIP_CALL_SETUP;
2354 strinfo->from_identity=g_strdup(pi->endpointId);
2355 strinfo->to_identity=g_strdup("");
2357 strinfo->from_identity=g_strdup("");
2358 strinfo->to_identity=g_strdup(pi->endpointId);
2360 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
2361 strinfo->first_frame_num=pinfo->fd->num;
2362 strinfo->selected=FALSE;
2363 strinfo->start_sec=pinfo->fd->rel_ts.secs;
2364 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
2365 strinfo->protocol=VOIP_MGCP;
2366 strinfo->prot_info=g_malloc(sizeof(mgcp_calls_info_t));
2367 tmp_mgcpinfo=strinfo->prot_info;
2368 tmp_mgcpinfo->endpointId = g_strdup(pi->endpointId);
2369 tmp_mgcpinfo->fromEndpoint = fromEndpoint;
2370 strinfo->npackets = 0;
2371 strinfo->call_num = tapinfo->ncalls++;
2372 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
2375 g_assert(tmp_mgcpinfo != NULL);
2377 /* change call state and add to graph */
2378 switch (pi->mgcp_type)
2381 if ( (strcmp(pi->code, "NTFY") == 0) && (pi->observedEvents != NULL) ){
2382 frame_label = g_strdup_printf("%s ObsEvt:%s",pi->code, pi->observedEvents);
2384 if (tmp_mgcpinfo->fromEndpoint){
2385 /* use the Dialed digits to fill the "To" for the call, but use the first NTFY */
2386 if (strinfo->to_identity[0] == '\0') mgcpDialedDigits(pi->observedEvents, &(strinfo->to_identity));
2388 /* from MGC and the user picked up, the call is connected */
2389 } else if (isSignal("hd", pi->observedEvents))
2390 strinfo->call_state=VOIP_IN_CALL;
2392 /* hung up signal */
2393 if (isSignal("hu", pi->observedEvents)) {
2394 if ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state == VOIP_RINGING)){
2395 strinfo->call_state = VOIP_CANCELLED;
2397 strinfo->call_state = VOIP_COMPLETED;
2401 } else if (strcmp(pi->code, "RQNT") == 0) {
2402 /* for calls from Endpoint: if there is a "no signal" RQNT and the call was RINGING, we assume this is the CONNECT */
2403 if ( tmp_mgcpinfo->fromEndpoint && isSignal("", pi->signalReq) && (strinfo->call_state == VOIP_RINGING) ) {
2404 strinfo->call_state = VOIP_IN_CALL;
2407 /* if there is ringback or ring tone, change state to ringing */
2408 if ( isSignal("rg", pi->signalReq) || isSignal("rt", pi->signalReq) ) {
2409 strinfo->call_state = VOIP_RINGING;
2412 /* if there is a Busy or ReorderTone, and the call was Ringing or Setup the call is Rejected */
2413 if ( (isSignal("ro", pi->signalReq) || isSignal("bz", pi->signalReq)) && ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state = VOIP_RINGING)) ) {
2414 strinfo->call_state = VOIP_REJECTED;
2417 if (pi->signalReq != NULL)
2418 frame_label = g_strdup_printf("%s%sSigReq:%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"", pi->signalReq);
2420 frame_label = g_strdup_printf("%s%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"");
2422 /* use the CallerID info to fill the "From" for the call */
2423 if (!tmp_mgcpinfo->fromEndpoint) mgcpCallerID(pi->signalReq, &(strinfo->from_identity));
2425 } else if (strcmp(pi->code, "DLCX") == 0) {
2427 if there is a DLCX in a call To an Endpoint and the call was not connected, we use
2428 the DLCX as the end of the call
2430 if (!tmp_mgcpinfo->fromEndpoint){
2431 if ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state == VOIP_RINGING)){
2432 strinfo->call_state = VOIP_CANCELLED;
2437 if (frame_label == NULL) frame_label = g_strdup_printf("%s",pi->code);
2440 frame_label = g_strdup_printf("%d (%s)",pi->rspcode, pi->code);
2443 /* XXX what to do? */
2448 comment = g_strdup_printf("MGCP %s %s%s", tmp_mgcpinfo->endpointId, (pi->mgcp_type == MGCP_REQUEST)?"Request":"Response", pi->is_duplicate?" Duplicate":"");
2450 strinfo->stop_sec=pinfo->fd->rel_ts.secs;
2451 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
2452 strinfo->last_frame_num=pinfo->fd->num;
2453 ++(strinfo->npackets);
2454 /* increment the packets counter of all calls */
2455 ++(tapinfo->npackets);
2457 /* add to the graph */
2458 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2460 g_free(frame_label);
2462 /* add SDP info if apply */
2463 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
2464 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2465 g_free(sdp_summary);
2469 tapinfo->redraw = TRUE;
2471 return 1; /* refresh output */
2475 /****************************************************************************/
2477 /****************************************************************************/
2478 static gboolean have_MGCP_tap_listener=FALSE;
2479 /****************************************************************************/
2481 mgcp_calls_init_tap(void)
2483 GString *error_string;
2485 if(have_MGCP_tap_listener==FALSE)
2487 /* don't register tap listener, if we have it already */
2488 /* we send an empty filter, to force a non null "tree" in the mgcp dissector */
2489 error_string = register_tap_listener("mgcp", &(the_tapinfo_struct.mgcp_dummy), strdup(""),
2490 voip_calls_dlg_reset,
2494 if (error_string != NULL) {
2495 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2497 g_string_free(error_string, TRUE);
2500 have_MGCP_tap_listener=TRUE;
2504 /****************************************************************************/
2506 remove_tap_listener_mgcp_calls(void)
2508 protect_thread_critical_region();
2509 remove_tap_listener(&(the_tapinfo_struct.mgcp_dummy));
2510 unprotect_thread_critical_region();
2512 have_MGCP_tap_listener=FALSE;
2516 /****************************************************************************/
2517 /****************************TAP for ACTRACE (AudioCodes trace)**************/
2518 /****************************************************************************/
2520 /* whenever a ACTRACE packet is seen by the tap listener */
2522 ACTRACEcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *ACTRACEinfo)
2524 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2525 const actrace_info_t *pi = ACTRACEinfo;
2527 actrace_cas_calls_info_t *tmp_actrace_cas_info;
2528 voip_calls_info_t *tmp_listinfo;
2529 voip_calls_info_t *strinfo = NULL;
2532 actrace_frame_num = pinfo->fd->num;
2533 actrace_trunk = pi->trunk;
2534 actrace_direction = pi->direction;
2536 if (pi->type == 1){ /* is CAS protocol */
2538 gchar *comment = NULL;
2541 list = g_list_first(tapinfo->strinfo_list);
2544 tmp_listinfo=list->data;
2545 if ( tmp_listinfo->protocol == VOIP_AC_CAS ){
2546 tmp_actrace_cas_info = tmp_listinfo->prot_info;
2547 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
2548 if ( (tmp_actrace_cas_info->bchannel == pi->cas_bchannel) && (tmp_actrace_cas_info->trunk == actrace_trunk) ) {
2549 strinfo = (voip_calls_info_t*)(list->data);
2553 list = g_list_next (list);
2556 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, g_strdup("PSTN"));
2558 /* if it is a new call, add it to the list */
2560 strinfo = g_malloc(sizeof(voip_calls_info_t));
2561 strinfo->call_active_state = VOIP_ACTIVE;
2562 strinfo->call_state = VOIP_CALL_SETUP;
2563 strinfo->from_identity=g_strdup("N/A");
2564 strinfo->to_identity=g_strdup("N/A");
2565 COPY_ADDRESS(&(strinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
2566 strinfo->first_frame_num=pinfo->fd->num;
2567 strinfo->selected=FALSE;
2568 strinfo->start_sec=pinfo->fd->rel_ts.secs;
2569 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
2570 strinfo->protocol=VOIP_AC_CAS;
2571 strinfo->prot_info=g_malloc(sizeof(actrace_cas_calls_info_t));
2572 tmp_actrace_cas_info=strinfo->prot_info;
2573 tmp_actrace_cas_info->bchannel=pi->cas_bchannel;
2574 tmp_actrace_cas_info->trunk=actrace_trunk;
2575 strinfo->npackets = 0;
2576 strinfo->call_num = tapinfo->ncalls++;
2577 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
2580 strinfo->stop_sec=pinfo->fd->rel_ts.secs;
2581 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
2582 strinfo->last_frame_num=pinfo->fd->num;
2583 ++(strinfo->npackets);
2584 /* increment the packets counter of all calls */
2585 ++(tapinfo->npackets);
2588 comment = g_strdup_printf("AC_CAS trunk:%u", actrace_trunk );
2590 add_to_graph(tapinfo, pinfo, pi->cas_frame_label , comment, strinfo->call_num,
2591 actrace_direction?&pstn_add:&(pinfo->src),
2592 actrace_direction?&(pinfo->src):&pstn_add,
2596 g_free((char *)pstn_add.data);
2599 tapinfo->redraw = TRUE;
2601 return 1; /* refresh output */
2605 /****************************************************************************/
2607 /****************************************************************************/
2608 static gboolean have_actrace_tap_listener=FALSE;
2609 /****************************************************************************/
2611 actrace_calls_init_tap(void)
2613 GString *error_string;
2615 if(have_actrace_tap_listener==FALSE)
2617 /* don't register tap listener, if we have it already */
2618 error_string = register_tap_listener("actrace", &(the_tapinfo_struct.actrace_dummy), NULL,
2619 voip_calls_dlg_reset,
2620 ACTRACEcalls_packet,
2624 if (error_string != NULL) {
2625 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2627 g_string_free(error_string, TRUE);
2630 have_actrace_tap_listener=TRUE;
2634 /****************************************************************************/
2636 remove_tap_listener_actrace_calls(void)
2638 protect_thread_critical_region();
2639 remove_tap_listener(&(the_tapinfo_struct.actrace_dummy));
2640 unprotect_thread_critical_region();
2642 have_actrace_tap_listener=FALSE;
2645 /****************************************************************************/
2646 /* ***************************TAP for OTHER PROTOCOL **********************************/
2647 /****************************************************************************/
2649 /****************************************************************************/
2650 /* whenever a prot_ packet is seen by the tap listener */
2653 prot_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info _U_)
2655 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2657 strinfo->stop_sec=pinfo->fd->rel_secs;
2658 strinfo->stop_usec=pinfo->fd->rel_usecs;
2659 strinfo->last_frame_num=pinfo->fd->num;
2660 ++(strinfo->npackets);
2661 ++(tapinfo->npackets);
2664 tapinfo->redraw = TRUE;
2669 /****************************************************************************/
2671 static gboolean have_prot__tap_listener=FALSE;
2674 prot_calls_init_tap(void)
2676 GString *error_string;
2678 if(have_prot__tap_listener==FALSE)
2680 error_string = register_tap_listener("prot_", &(the_tapinfo_struct.prot__dummy),
2682 voip_calls_dlg_reset,
2687 if (error_string != NULL) {
2688 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2690 g_string_free(error_string, TRUE);
2693 have_prot__tap_listener=TRUE;
2697 /****************************************************************************/
2700 remove_tap_listener_prot__calls(void)
2702 protect_thread_critical_region();
2703 remove_tap_listener(&(the_tapinfo_struct.prot__dummy));
2704 unprotect_thread_critical_region();
2706 have_prot__tap_listener=FALSE;