2 * VoIP calls summary addition for Wireshark
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 #ifdef HAVE_LIBPORTAUDIO
69 #if GTK_MAJOR_VERSION >= 2
70 #include "rtp_player.h"
71 #endif /* GTK_MAJOR_VERSION >= 2 */
72 #endif /* HAVE_LIBPORTAUDIO */
74 const char *voip_call_state_name[7]={
84 /* defines whether we can consider the call active */
85 const char *voip_protocol_name[7]={
105 graph_str labels[H245_MAX];
108 static h245_labels_t h245_labels;
110 /****************************************************************************/
111 /* the one and only global voip_calls_tapinfo_t structure */
112 static voip_calls_tapinfo_t the_tapinfo_struct =
113 {0, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
115 /* the one and only global voip_rtp_tapinfo_t structure */
116 static voip_rtp_tapinfo_t the_tapinfo_rtp_struct =
119 /****************************************************************************/
120 /* when there is a [re]reading of packet's */
121 void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
123 voip_calls_info_t *strinfo;
124 sip_calls_info_t *tmp_sipinfo;
125 h323_calls_info_t *tmp_h323info;
126 h245_address_t *h245_add;
128 graph_analysis_item_t *graph_item;
133 #ifdef HAVE_LIBPORTAUDIO
134 #if GTK_MAJOR_VERSION >= 2
135 /* reset the RTP player */
140 /* free the data items first */
141 list = g_list_first(tapinfo->strinfo_list);
144 strinfo = list->data;
145 g_free(strinfo->from_identity);
146 g_free(strinfo->to_identity);
147 g_free((void *)(strinfo->initial_speaker.data));
148 if (strinfo->protocol == VOIP_SIP){
149 tmp_sipinfo = strinfo->prot_info;
150 g_free(tmp_sipinfo->call_identifier);
152 if (strinfo->protocol == VOIP_H323){
153 tmp_h323info = strinfo->prot_info;
154 g_free(tmp_h323info->guid);
155 /* free the H245 list address */
156 list2 = g_list_first(tmp_h323info->h245_list);
159 h245_add=list2->data;
160 g_free((void *)h245_add->h245_address.data);
162 list2 = g_list_next(list2);
164 g_list_free(tmp_h323info->h245_list);
165 tmp_h323info->h245_list = NULL;
167 g_free(strinfo->prot_info);
170 list = g_list_next(list);
172 g_list_free(tapinfo->strinfo_list);
173 tapinfo->strinfo_list = NULL;
175 tapinfo->npackets = 0;
176 tapinfo->start_packets = 0;
177 tapinfo->completed_calls = 0;
178 tapinfo->rejected_calls = 0;
180 /* free the graph data items first */
181 list = g_list_first(tapinfo->graph_analysis->list);
184 graph_item = list->data;
185 g_free(graph_item->frame_label);
186 g_free(graph_item->comment);
187 g_free((void *)graph_item->src_addr.data);
188 g_free((void *)graph_item->dst_addr.data);
190 list = g_list_next(list);
192 g_list_free(tapinfo->graph_analysis->list);
193 tapinfo->graph_analysis->nconv = 0;
194 tapinfo->graph_analysis->list = NULL;
196 ++(tapinfo->launch_count);
201 /****************************************************************************/
202 void graph_analysis_data_init(void){
203 the_tapinfo_struct.graph_analysis = g_malloc(sizeof(graph_analysis_info_t));
204 the_tapinfo_struct.graph_analysis->nconv = 0;
205 the_tapinfo_struct.graph_analysis->list = NULL;
208 /****************************************************************************/
209 /* Add a new item into the graph */
210 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)
212 graph_analysis_item_t *gai;
214 gai = g_malloc(sizeof(graph_analysis_item_t));
215 gai->frame_num = pinfo->fd->num;
216 gai->time= nstime_to_sec(&pinfo->fd->rel_ts);
217 COPY_ADDRESS(&(gai->src_addr),src_addr);
218 COPY_ADDRESS(&(gai->dst_addr),dst_addr);
220 gai->port_src=pinfo->srcport;
221 gai->port_dst=pinfo->destport;
222 if (frame_label != NULL)
223 gai->frame_label = g_strdup(frame_label);
225 gai->frame_label = g_strdup("");
228 gai->comment = g_strdup(comment);
230 gai->comment = g_strdup("");
231 gai->conv_num=call_num;
232 gai->line_style=line_style;
235 tapinfo->graph_analysis->list = g_list_append(tapinfo->graph_analysis->list, gai);
241 /****************************************************************************/
242 /* Append str to frame_label and comment in a graph item */
243 /* return 0 if the frame_num is not in the graph list */
244 static int append_to_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
246 graph_analysis_item_t *gai;
248 gchar *tmp_str = NULL;
249 gchar *tmp_str2 = NULL;
251 list = g_list_first(tapinfo->graph_analysis->list);
255 if (gai->frame_num == frame_num){
256 tmp_str = gai->frame_label;
257 tmp_str2 = gai->comment;
259 if (new_frame_label != NULL){
260 gai->frame_label = g_strdup_printf("%s %s", gai->frame_label, new_frame_label);
265 if (new_comment != NULL){
266 gai->comment = g_strdup_printf("%s %s", gai->comment, new_comment);
271 list = g_list_next (list);
273 if (tmp_str == NULL) return 0; /* it is not in the list */
278 /****************************************************************************/
279 /* Change the frame_label and comment in a graph item if not NULL*/
280 /* return 0 if the frame_num is not in the graph list */
281 static int change_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
283 graph_analysis_item_t *gai;
285 gchar *tmp_str = NULL;
286 gchar *tmp_str2 = NULL;
288 list = g_list_first(tapinfo->graph_analysis->list);
292 if (gai->frame_num == frame_num){
293 tmp_str = gai->frame_label;
294 tmp_str2 = gai->comment;
296 if (new_frame_label != NULL){
297 gai->frame_label = g_strdup(new_frame_label);
301 if (new_comment != NULL){
302 gai->comment = g_strdup(new_comment);
307 list = g_list_next (list);
309 if (tmp_str == NULL) return 0; /* it is not in the list */
314 /****************************************************************************/
315 /* Change all the graph items with call_num to new_call_num */
316 static guint change_call_num_graph(voip_calls_tapinfo_t *tapinfo _U_, guint16 call_num, guint16 new_call_num)
318 graph_analysis_item_t *gai;
323 list = g_list_first(tapinfo->graph_analysis->list);
327 if (gai->conv_num == call_num){
328 gai->conv_num = new_call_num;
331 list = g_list_next (list);
333 return items_changed;
339 /****************************************************************************/
340 /* Insert the item in the graph list */
341 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)
343 graph_analysis_item_t *gai, *new_gai;
348 new_gai = g_malloc(sizeof(graph_analysis_item_t));
349 new_gai->frame_num = frame_num;
351 COPY_ADDRESS(&(new_gai->src_addr),src_addr);
352 COPY_ADDRESS(&(new_gai->dst_addr),dst_addr);
354 new_gai->port_src=pinfo->srcport;
355 new_gai->port_dst=pinfo->destport;
356 if (frame_label != NULL)
357 new_gai->frame_label = g_strdup(frame_label);
359 new_gai->frame_label = g_strdup("");
362 new_gai->comment = g_strdup(comment);
364 new_gai->comment = g_strdup("");
365 new_gai->conv_num=call_num;
366 new_gai->line_style=line_style;
367 new_gai->display=FALSE;
371 list = g_list_first(tapinfo->graph_analysis->list);
375 if (gai->frame_num > frame_num){
376 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item_num);
380 list = g_list_next (list);
384 if ( !inserted) tapinfo->graph_analysis->list = g_list_append(tapinfo->graph_analysis->list, new_gai);
387 /****************************************************************************/
388 /* ***************************TAP for RTP Events*****************************/
389 /****************************************************************************/
391 static guint32 rtp_evt_frame_num = 0;
392 static guint8 rtp_evt = 0;
393 static gboolean rtp_evt_end = FALSE;
394 /*static guint32 rtp_evt_setup_frame_num = 0;*/
396 /****************************************************************************/
397 /* whenever a rtp event packet is seen by the tap listener */
399 rtp_event_packet(void *ptr _U_, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *rtp_event_info)
401 const struct _rtp_event_info *pi = rtp_event_info;
403 /* do not consider RTP events packets without a setup frame */
404 if (pi->info_setup_frame_num == 0){
408 rtp_evt_frame_num = pinfo->fd->num;
409 rtp_evt = pi->info_rtp_evt;
410 rtp_evt_end = pi->info_end;
415 /****************************************************************************/
416 static gboolean have_rtp_event_tap_listener=FALSE;
419 rtp_event_init_tap(void)
421 GString *error_string;
424 if(have_rtp_event_tap_listener==FALSE)
426 error_string = register_tap_listener("rtpevent", &(the_tapinfo_rtp_struct.rtp_event_dummy),
433 if (error_string != NULL) {
434 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
436 g_string_free(error_string, TRUE);
439 have_rtp_event_tap_listener=TRUE;
443 /****************************************************************************/
446 remove_tap_listener_rtp_event(void)
448 protect_thread_critical_region();
449 remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_event_dummy));
450 unprotect_thread_critical_region();
452 have_rtp_event_tap_listener=FALSE;
455 /****************************************************************************/
456 /* ***************************TAP for RTP **********************************/
457 /****************************************************************************/
459 /****************************************************************************/
460 /* when there is a [re]reading of RTP packet's */
461 static void voip_rtp_reset(void *ptr _U_)
463 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
465 /* free the data items first */
466 list = g_list_first(tapinfo->list);
470 list = g_list_next(list);
472 g_list_free(tapinfo->list);
473 tapinfo->list = NULL;
474 tapinfo->nstreams = 0;
478 /****************************************************************************/
479 /* whenever a RTP packet is seen by the tap listener */
481 RTP_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void const *RTPinfo)
483 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
484 voip_rtp_stream_info_t *tmp_listinfo;
485 voip_rtp_stream_info_t *strinfo = NULL;
487 struct _rtp_conversation_info *p_conv_data = NULL;
489 const struct _rtp_info *pi = RTPinfo;
491 /* do not consider RTP packets without a setup frame */
492 if (pi->info_setup_frame_num == 0){
496 /* add this RTP for future listening using the RTP Player*/
497 #if GTK_MAJOR_VERSION >= 2
498 #ifdef HAVE_LIBPORTAUDIO
499 add_rtp_packet(pi, pinfo);
503 /* check wether we already have a RTP stream with this setup frame and ssrc in the list */
504 list = g_list_first(tapinfo->list);
507 tmp_listinfo=list->data;
508 if ( (tmp_listinfo->setup_frame_number == pi->info_setup_frame_num)
509 && (tmp_listinfo->ssrc == pi->info_sync_src) && (tmp_listinfo->end_stream == FALSE)){
510 /* if the payload type has changed, we mark the stream as finished to create a new one
511 this is to show multiple payload changes in the Graph for example for DTMF RFC2833 */
512 if ( tmp_listinfo->pt != pi->info_payload_type ) {
513 tmp_listinfo->end_stream = TRUE;
515 strinfo = (voip_rtp_stream_info_t*)(list->data);
519 list = g_list_next (list);
522 /* if this is a duplicated RTP Event End, just return */
523 if ((rtp_evt_frame_num == pinfo->fd->num) && !strinfo && (rtp_evt_end == TRUE)) {
527 /* not in the list? then create a new entry */
529 strinfo = g_malloc(sizeof(voip_rtp_stream_info_t));
530 COPY_ADDRESS(&(strinfo->src_addr), &(pinfo->src));
531 strinfo->src_port = pinfo->srcport;
532 COPY_ADDRESS(&(strinfo->dest_addr), &(pinfo->dst));
533 strinfo->dest_port = pinfo->destport;
534 strinfo->ssrc = pi->info_sync_src;
535 strinfo->end_stream = FALSE;
536 strinfo->pt = pi->info_payload_type;
537 strinfo->pt_str = NULL;
538 /* if it is dynamic payload, let use the conv data to see if it is defined */
539 if ( (strinfo->pt>95) && (strinfo->pt<128) ) {
540 /* Use existing packet info if available */
541 p_conv_data = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name("rtp"));
543 strinfo->pt_str = g_strdup(g_hash_table_lookup(p_conv_data->rtp_dyn_payload, &strinfo->pt));
545 if (!strinfo->pt_str) strinfo->pt_str = g_strdup(val_to_str(strinfo->pt, rtp_payload_type_short_vals, "%u"));
546 strinfo->npackets = 0;
547 strinfo->first_frame_num = pinfo->fd->num;
548 strinfo->start_rel_sec = pinfo->fd->rel_ts.secs;
549 strinfo->start_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
550 strinfo->setup_frame_number = pi->info_setup_frame_num;
551 strinfo->rtp_event = -1;
552 tapinfo->list = g_list_append(tapinfo->list, strinfo);
556 /* Add the info to the existing RTP stream */
558 strinfo->stop_rel_sec = pinfo->fd->rel_ts.secs;
559 strinfo->stop_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
561 /* process RTP Event */
562 if (rtp_evt_frame_num == pinfo->fd->num) {
563 strinfo->rtp_event = rtp_evt;
564 if (rtp_evt_end == TRUE) {
565 strinfo->end_stream = TRUE;
570 the_tapinfo_struct.redraw = TRUE;
575 /****************************************************************************/
576 /* whenever a redraw in the RTP tap listener */
577 static void RTP_packet_draw(void *prs _U_)
579 voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
580 GList* rtp_streams_list;
581 voip_rtp_stream_info_t *rtp_listinfo;
582 GList* voip_calls_graph_list;
584 graph_analysis_item_t *gai;
585 graph_analysis_item_t *new_gai;
589 /* add each rtp stream to the graph */
590 rtp_streams_list = g_list_first(rtp_tapinfo->list);
591 while (rtp_streams_list)
593 rtp_listinfo = rtp_streams_list->data;
595 /* using the setup frame number of the RTP stream, we get the call number that it belongs */
596 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
597 while (voip_calls_graph_list)
599 gai = voip_calls_graph_list->data;
600 conv_num = gai->conv_num;
601 /* if we get the setup frame number, then get the time position to graph the RTP arrow */
602 if (rtp_listinfo->setup_frame_number == gai->frame_num){
603 /* look again from the begining because there are cases where the Setup frame is after the RTP */
604 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
606 while(voip_calls_graph_list){
607 gai = voip_calls_graph_list->data;
608 /* if RTP was already in the Graph, just update the comment information */
609 if (rtp_listinfo->first_frame_num == gai->frame_num){
610 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
611 g_free(gai->comment);
612 gai->comment = g_strdup_printf("RTP Num packets:%u Duration:%u.%03us ssrc:%u", rtp_listinfo->npackets, duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
614 /* add the RTP item to the graph if was not there*/
615 } else if (rtp_listinfo->first_frame_num<gai->frame_num){
616 new_gai = g_malloc(sizeof(graph_analysis_item_t));
617 new_gai->frame_num = rtp_listinfo->first_frame_num;
618 new_gai->time = (double)rtp_listinfo->start_rel_sec + (double)rtp_listinfo->start_rel_usec/1000000;
619 COPY_ADDRESS(&(new_gai->src_addr),&(rtp_listinfo->src_addr));
620 COPY_ADDRESS(&(new_gai->dst_addr),&(rtp_listinfo->dest_addr));
621 new_gai->port_src = rtp_listinfo->src_port;
622 new_gai->port_dst = rtp_listinfo->dest_port;
623 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
624 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, "Unknown RTP Event"));
625 g_free(rtp_listinfo->pt_str);
626 new_gai->comment = g_strdup_printf("RTP Num packets:%u Duration:%u.%03us ssrc:%u", rtp_listinfo->npackets, duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
627 new_gai->conv_num = conv_num;
628 new_gai->display=FALSE;
629 new_gai->line_style = 2; /* the arrow line will be 2 pixels width */
630 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item);
634 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
639 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
641 rtp_streams_list = g_list_next(rtp_streams_list);
645 static gboolean have_RTP_tap_listener=FALSE;
646 /****************************************************************************/
650 GString *error_string;
652 if(have_RTP_tap_listener==FALSE)
654 /* don't register tap listener, if we have it already */
655 error_string = register_tap_listener("rtp", &(the_tapinfo_rtp_struct.rtp_dummy), NULL,
660 if (error_string != NULL) {
661 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
663 g_string_free(error_string, TRUE);
666 have_RTP_tap_listener=TRUE;
670 /****************************************************************************/
672 remove_tap_listener_rtp(void)
674 protect_thread_critical_region();
675 remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_dummy));
676 unprotect_thread_critical_region();
678 have_RTP_tap_listener=FALSE;
681 /* XXX just copied from gtk/rpc_stat.c */
682 void protect_thread_critical_region(void);
683 void unprotect_thread_critical_region(void);
685 /****************************************************************************/
686 /******************************TAP for T38 **********************************/
687 /****************************************************************************/
689 /****************************************************************************/
690 /* whenever a T38 packet is seen by the tap listener */
692 T38_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *T38info)
694 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
696 voip_calls_info_t *strinfo = NULL;
697 voip_calls_info_t *tmp_listinfo;
698 GList* voip_calls_graph_list;
700 gchar *frame_label = NULL;
701 gchar *comment = NULL;
702 graph_analysis_item_t *tmp_gai, *gai = NULL;
703 guint16 line_style = 2;
707 const t38_packet_info *pi = T38info;
709 if (pi->setup_frame_number != 0) {
710 /* using the setup frame number of the T38 packet, we get the call number that it belongs */
711 voip_calls_graph_list = g_list_first(tapinfo->graph_analysis->list);
712 while (voip_calls_graph_list)
714 tmp_gai = voip_calls_graph_list->data;
715 if (pi->setup_frame_number == tmp_gai->frame_num){
719 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
721 if (gai) conv_num = (int) gai->conv_num;
724 /* 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
725 * have the associated Voip calls. It probably means the the packet was decoded using the default t38 port, or using "Decode as.."
726 * in this case we create a "voip" call that only have t38 media (no signaling)
727 * OR if we have not found the Setup message in the graph.
729 if ( (pi->setup_frame_number == 0) || (gai == NULL) ){
730 /* check whether we already have a call with these parameters in the list */
731 list = g_list_first(tapinfo->strinfo_list);
734 tmp_listinfo=list->data;
735 if (tmp_listinfo->protocol == MEDIA_T38){
736 strinfo = (voip_calls_info_t*)(list->data);
739 list = g_list_next (list);
742 /* not in the list? then create a new entry */
744 strinfo = g_malloc(sizeof(voip_calls_info_t));
745 strinfo->call_active_state = VOIP_ACTIVE;
746 strinfo->call_state = VOIP_UNKNOWN;
747 strinfo->from_identity=g_strdup("T38 Media only");
748 strinfo->to_identity=g_strdup("T38 Media only");
749 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
750 strinfo->first_frame_num=pinfo->fd->num;
751 strinfo->selected=FALSE;
752 strinfo->start_sec=pinfo->fd->rel_ts.secs;
753 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
754 strinfo->protocol=MEDIA_T38;
755 strinfo->prot_info=NULL;
756 strinfo->npackets = 0;
757 strinfo->call_num = tapinfo->ncalls++;
758 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
760 ++(strinfo->npackets);
761 /* increment the packets counter of all calls */
762 ++(tapinfo->npackets);
764 conv_num = (int) strinfo->call_num;
767 /* at this point we should have found the call num for this t38 packets belong */
768 if (conv_num == -1) {
772 /* add the item to the graph list */
773 if (pi->type_msg == 0) { /* 0=t30-indicator */
774 frame_label = g_strdup(val_to_str(pi->t30ind_value, t30_indicator_vals, "Ukn (0x%02X)") );
775 comment = g_strdup_printf("t38:t30 Ind:%s",val_to_str(pi->t30ind_value, t30_indicator_vals, "Ukn (0x%02X)") );
777 } else if (pi->type_msg == 1) { /* 1=data */
778 switch(pi->Data_Field_field_type_value){
779 case 0: /* hdlc-data */
781 case 2: /* hdlc-fcs-OK */
782 case 4: /* hdlc-fcs-OK-sig-end */
783 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);
784 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)"));
786 case 3: /* hdlc-fcs-BAD */
787 case 5: /* hdlc-fcs-BAD-sig-end */
788 frame_label = g_strdup(pi->Data_Field_field_type_value == 3 ? "fcs-BAD" : "fcs-BAD-sig-end");
789 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");
791 case 7: /* t4-non-ecm-sig-end */
792 duration = nstime_to_sec(&pinfo->fd->rel_ts) - pi->time_first_t4_data;
793 frame_label = g_strdup_printf("t4-non-ecm-data:%s",val_to_str(pi->data_value, t30_data_vals, "Ukn (0x%02X)") );
794 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 );
795 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);
800 if (frame_label && !(pi->Data_Field_field_type_value == 7 && pi->type_msg == 1)) {
801 add_to_graph(tapinfo, pinfo, frame_label, comment, (guint16)conv_num, &(pinfo->src), &(pinfo->dst), line_style);
807 tapinfo->redraw = TRUE;
809 return 1; /* refresh output */
812 static gboolean have_T38_tap_listener=FALSE;
813 /****************************************************************************/
817 GString *error_string;
819 if(have_T38_tap_listener==FALSE)
821 /* don't register tap listener, if we have it already */
822 error_string = register_tap_listener("t38", &(the_tapinfo_struct.t38_dummy), NULL,
823 voip_calls_dlg_reset,
827 if (error_string != NULL) {
828 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
830 g_string_free(error_string, TRUE);
833 have_T38_tap_listener=TRUE;
837 /****************************************************************************/
839 remove_tap_listener_t38(void)
841 protect_thread_critical_region();
842 remove_tap_listener(&(the_tapinfo_struct.t38_dummy));
843 unprotect_thread_critical_region();
845 have_T38_tap_listener=FALSE;
849 /****************************************************************************/
850 static gchar *sdp_summary = NULL;
851 static guint32 sdp_frame_num = 0;
853 /****************************************************************************/
854 /* ***************************TAP for SIP **********************************/
855 /****************************************************************************/
857 /****************************************************************************/
858 /* whenever a SIP packet is seen by the tap listener */
860 SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SIPinfo)
862 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
863 /* we just take note of the ISUP data here; when we receive the MTP3 part everything will
864 be compared with existing calls */
866 voip_calls_info_t *tmp_listinfo;
867 voip_calls_info_t *strinfo = NULL;
868 sip_calls_info_t *tmp_sipinfo = NULL;
870 address tmp_src, tmp_dst;
871 gchar *frame_label = NULL;
872 gchar *comment = NULL;
874 const sip_info_value_t *pi = SIPinfo;
876 /* do not consider packets without call_id */
877 if (pi->tap_call_id ==NULL){
881 /* check whether we already have a call with these parameters in the list */
882 list = g_list_first(tapinfo->strinfo_list);
885 tmp_listinfo=list->data;
886 if (tmp_listinfo->protocol == VOIP_SIP){
887 tmp_sipinfo = tmp_listinfo->prot_info;
888 if (strcmp(tmp_sipinfo->call_identifier,pi->tap_call_id)==0){
889 strinfo = (voip_calls_info_t*)(list->data);
893 list = g_list_next (list);
896 /* not in the list? then create a new entry if the message is INVITE -i.e. if this session is a call*/
897 if ((strinfo==NULL) &&(pi->request_method!=NULL)){
898 if (strcmp(pi->request_method,"INVITE")==0){
899 strinfo = g_malloc(sizeof(voip_calls_info_t));
900 strinfo->call_active_state = VOIP_ACTIVE;
901 strinfo->call_state = VOIP_CALL_SETUP;
902 strinfo->from_identity=g_strdup(pi->tap_from_addr);
903 strinfo->to_identity=g_strdup(pi->tap_to_addr);
904 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
905 strinfo->first_frame_num=pinfo->fd->num;
906 strinfo->selected=FALSE;
907 strinfo->start_sec=pinfo->fd->rel_ts.secs;
908 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
909 strinfo->protocol=VOIP_SIP;
910 strinfo->prot_info=g_malloc(sizeof(sip_calls_info_t));
911 tmp_sipinfo=strinfo->prot_info;
912 tmp_sipinfo->call_identifier=strdup(pi->tap_call_id);
913 tmp_sipinfo->sip_state=SIP_INVITE_SENT;
914 tmp_sipinfo->invite_cseq=pi->tap_cseq_number;
915 strinfo->npackets = 0;
916 strinfo->call_num = tapinfo->ncalls++;
917 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
923 /* let's analyze the call state */
925 COPY_ADDRESS(&(tmp_src), &(pinfo->src));
926 COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
928 if (pi->request_method == NULL){
929 frame_label = g_strdup_printf("%u %s", pi->response_code, pi->reason_phrase );
930 comment = g_strdup_printf("SIP Status");
932 if ((tmp_sipinfo && pi->tap_cseq_number == tmp_sipinfo->invite_cseq)&&(ADDRESSES_EQUAL(&tmp_dst,&(strinfo->initial_speaker)))){
933 if ((pi->response_code > 199) && (pi->response_code<300) && (tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
934 tmp_sipinfo->sip_state = SIP_200_REC;
936 else if ((pi->response_code>299)&&(tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
937 strinfo->call_state = VOIP_REJECTED;
938 tapinfo->rejected_calls++;
944 frame_label = g_strdup(pi->request_method);
946 if ((strcmp(pi->request_method,"INVITE")==0)&&(ADDRESSES_EQUAL(&tmp_src,&(strinfo->initial_speaker)))){
947 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
948 strinfo->call_state = VOIP_CALL_SETUP;
949 comment = g_strdup_printf("SIP From: %s To:%s", strinfo->from_identity, strinfo->to_identity);
951 else if ((strcmp(pi->request_method,"ACK")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
952 &&(ADDRESSES_EQUAL(&tmp_src,&(strinfo->initial_speaker)))&&(tmp_sipinfo->sip_state==SIP_200_REC)
953 &&(strinfo->call_state == VOIP_CALL_SETUP)){
954 strinfo->call_state = VOIP_IN_CALL;
955 comment = g_strdup_printf("SIP Request");
957 else if (strcmp(pi->request_method,"BYE")==0){
958 strinfo->call_state = VOIP_COMPLETED;
959 tapinfo->completed_calls++;
960 comment = g_strdup_printf("SIP Request");
962 else if ((strcmp(pi->request_method,"CANCEL")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
963 &&(ADDRESSES_EQUAL(&tmp_src,&(strinfo->initial_speaker)))&&(strinfo->call_state==VOIP_CALL_SETUP)){
964 strinfo->call_state = VOIP_CANCELLED;
965 tmp_sipinfo->sip_state = SIP_CANCEL_SENT;
966 comment = g_strdup_printf("SIP Request");
968 comment = g_strdup_printf("SIP Request");
972 strinfo->stop_sec=pinfo->fd->rel_ts.secs;
973 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
974 strinfo->last_frame_num=pinfo->fd->num;
975 ++(strinfo->npackets);
976 /* increment the packets counter of all calls */
977 ++(tapinfo->npackets);
979 /* add to the graph */
980 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
983 g_free((void *)tmp_src.data);
984 g_free((void *)tmp_dst.data);
986 /* add SDP info if apply */
987 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
988 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
994 tapinfo->redraw = TRUE;
996 return 1; /* refresh output */
1000 /****************************************************************************/
1001 voip_calls_tapinfo_t* voip_calls_get_info(void)
1003 return &the_tapinfo_struct;
1007 /****************************************************************************/
1009 /****************************************************************************/
1010 static gboolean have_SIP_tap_listener=FALSE;
1011 /****************************************************************************/
1013 sip_calls_init_tap(void)
1015 GString *error_string;
1017 if(have_SIP_tap_listener==FALSE)
1019 /* don't register tap listener, if we have it already */
1020 error_string = register_tap_listener("sip", &(the_tapinfo_struct.sip_dummy), NULL,
1021 voip_calls_dlg_reset,
1025 if (error_string != NULL) {
1026 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1028 g_string_free(error_string, TRUE);
1031 have_SIP_tap_listener=TRUE;
1035 /****************************************************************************/
1037 remove_tap_listener_sip_calls(void)
1039 protect_thread_critical_region();
1040 remove_tap_listener(&(the_tapinfo_struct.sip_dummy));
1041 unprotect_thread_critical_region();
1043 have_SIP_tap_listener=FALSE;
1046 /****************************************************************************/
1047 /* ***************************TAP for ISUP **********************************/
1048 /****************************************************************************/
1050 static guint32 mtp3_opc, mtp3_dpc;
1051 static guint8 mtp3_ni;
1052 static guint32 mtp3_frame_num;
1055 /****************************************************************************/
1056 /* whenever a isup_ packet is seen by the tap listener */
1058 isup_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *isup_info _U_)
1060 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1061 voip_calls_info_t *tmp_listinfo;
1062 voip_calls_info_t *strinfo = NULL;
1063 isup_calls_info_t *tmp_isupinfo;
1064 gboolean found = FALSE;
1065 gboolean forward = FALSE;
1066 gboolean right_pair;
1068 gchar *frame_label = NULL;
1069 gchar *comment = NULL;
1072 /*voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct; unused */
1073 const isup_tap_rec_t *pi = isup_info;
1076 /* check if the lower layer is MTP matching the frame number */
1077 if (mtp3_frame_num != pinfo->fd->num) return 0;
1079 /* check whether we already have a call with these parameters in the list */
1080 list = g_list_first(tapinfo->strinfo_list);
1084 tmp_listinfo=list->data;
1085 if ((tmp_listinfo->protocol == VOIP_ISUP)&&(tmp_listinfo->call_active_state==VOIP_ACTIVE)){
1086 tmp_isupinfo = tmp_listinfo->prot_info;
1087 if ((tmp_isupinfo->cic == pinfo->circuit_id)&&(tmp_isupinfo->ni == mtp3_ni)) {
1088 if ((tmp_isupinfo->opc == mtp3_opc)&&(tmp_isupinfo->dpc == mtp3_dpc)){
1091 else if ((tmp_isupinfo->dpc == mtp3_opc)&&(tmp_isupinfo->opc == mtp3_dpc)){
1098 /* if there is an IAM for a call that is not in setup state, that means the previous call in the same
1099 cic is no longer active */
1100 if (tmp_listinfo->call_state == VOIP_CALL_SETUP){
1103 else if (pi->message_type != 1){
1107 tmp_listinfo->call_active_state=VOIP_INACTIVE;
1111 strinfo = (voip_calls_info_t*)(list->data);
1116 list = g_list_next (list);
1119 /* not in the list? then create a new entry if the message is IAM
1120 -i.e. if this session is a call*/
1123 if ((strinfo==NULL) &&(pi->message_type==1)){
1125 strinfo = g_malloc(sizeof(voip_calls_info_t));
1126 strinfo->call_active_state = VOIP_ACTIVE;
1127 strinfo->call_state = VOIP_UNKNOWN;
1128 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
1129 strinfo->selected=FALSE;
1130 strinfo->first_frame_num=pinfo->fd->num;
1131 strinfo->start_sec=pinfo->fd->rel_ts.secs;
1132 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1133 strinfo->protocol=VOIP_ISUP;
1134 if (pi->calling_number!=NULL){
1135 strinfo->from_identity=g_strdup(pi->calling_number);
1137 if (pi->called_number!=NULL){
1138 strinfo->to_identity=g_strdup(pi->called_number);
1140 strinfo->prot_info=g_malloc(sizeof(isup_calls_info_t));
1141 tmp_isupinfo=strinfo->prot_info;
1142 tmp_isupinfo->opc = mtp3_opc;
1143 tmp_isupinfo->dpc = mtp3_dpc;
1144 tmp_isupinfo->ni = mtp3_ni;
1145 tmp_isupinfo->cic = pinfo->circuit_id;
1146 strinfo->npackets = 0;
1147 strinfo->call_num = tapinfo->ncalls++;
1148 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
1152 strinfo->stop_sec=pinfo->fd->rel_ts.secs;
1153 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1154 strinfo->last_frame_num=pinfo->fd->num;
1155 ++(strinfo->npackets);
1157 /* Let's analyze the call state */
1160 for (i=0;(isup_message_type_value[i].strptr!=NULL)&& (isup_message_type_value[i].value!=pi->message_type);i++);
1162 if (isup_message_type_value[i].value==pi->message_type){
1163 frame_label = g_strdup(isup_message_type_value_acro[i].strptr);
1166 frame_label = g_strdup_printf("Unknown");
1169 if (strinfo->npackets == 1){ /* this is the first packet, that must be an IAM */
1170 if ((pi->calling_number!=NULL)&&(pi->called_number !=NULL)){
1171 comment = g_strdup_printf("Call from %s to %s",
1172 pi->calling_number, pi->called_number);
1175 else if (strinfo->npackets == 2){ /* in the second packet we show the SPs */
1177 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
1179 mtp3_ni, mtp3_dpc, pinfo->circuit_id);
1183 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
1185 mtp3_ni, mtp3_opc, pinfo->circuit_id);
1190 switch(pi->message_type){
1192 strinfo->call_state=VOIP_CALL_SETUP;
1194 case 7: /* CONNECT */
1195 case 9: /* ANSWER */
1196 strinfo->call_state=VOIP_IN_CALL;
1198 case 12: /* RELEASE */
1199 if (strinfo->call_state==VOIP_CALL_SETUP){
1201 strinfo->call_state=VOIP_CANCELLED;
1204 strinfo->call_state=VOIP_REJECTED;
1205 tapinfo->rejected_calls++;
1208 else if (strinfo->call_state == VOIP_IN_CALL){
1209 strinfo->call_state = VOIP_COMPLETED;
1210 tapinfo->completed_calls++;
1212 for (i=0;(q931_cause_code_vals[i].strptr!=NULL)&& (q931_cause_code_vals[i].value!=pi->cause_value);i++);
1213 if (q931_cause_code_vals[i].value==pi->cause_value){
1214 comment = g_strdup_printf("Cause %i - %s",pi->cause_value, q931_cause_code_vals[i].strptr);
1217 comment = g_strdup_printf("Cause %i",pi->cause_value);
1222 /* increment the packets counter of all calls */
1223 ++(tapinfo->npackets);
1225 /* add to the graph */
1226 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1228 g_free(frame_label);
1231 tapinfo->redraw = TRUE;
1233 return 1; /* refresh output */
1236 /****************************************************************************/
1238 static gboolean have_isup_tap_listener=FALSE;
1241 isup_calls_init_tap(void)
1243 GString *error_string;
1246 if(have_isup_tap_listener==FALSE)
1248 error_string = register_tap_listener("isup", &(the_tapinfo_struct.isup_dummy),
1250 voip_calls_dlg_reset,
1255 if (error_string != NULL) {
1256 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1258 g_string_free(error_string, TRUE);
1261 have_isup_tap_listener=TRUE;
1265 /****************************************************************************/
1268 remove_tap_listener_isup_calls(void)
1270 protect_thread_critical_region();
1271 remove_tap_listener(&(the_tapinfo_struct.isup_dummy));
1272 unprotect_thread_critical_region();
1274 have_isup_tap_listener=FALSE;
1278 /****************************************************************************/
1279 /* ***************************TAP for MTP3 **********************************/
1280 /****************************************************************************/
1283 /****************************************************************************/
1284 /* whenever a mtp3_ packet is seen by the tap listener */
1286 mtp3_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *mtp3_info _U_)
1288 const mtp3_tap_rec_t *pi = mtp3_info;
1290 /* keep the data in memory to use when the ISUP information arrives */
1292 mtp3_opc = pi->addr_opc.pc;
1293 mtp3_dpc = pi->addr_dpc.pc;
1294 mtp3_ni = pi->addr_opc.ni;
1295 mtp3_frame_num = pinfo->fd->num;
1300 /****************************************************************************/
1302 static gboolean have_mtp3_tap_listener=FALSE;
1305 mtp3_calls_init_tap(void)
1307 GString *error_string;
1310 if(have_mtp3_tap_listener==FALSE)
1312 error_string = register_tap_listener("mtp3", &(the_tapinfo_struct.mtp3_dummy),
1314 voip_calls_dlg_reset,
1319 if (error_string != NULL) {
1320 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1322 g_string_free(error_string, TRUE);
1325 have_mtp3_tap_listener=TRUE;
1329 /****************************************************************************/
1332 remove_tap_listener_mtp3_calls(void)
1334 protect_thread_critical_region();
1335 remove_tap_listener(&(the_tapinfo_struct.mtp3_dummy));
1336 unprotect_thread_critical_region();
1338 have_mtp3_tap_listener=FALSE;
1341 /****************************************************************************/
1342 /* ***************************TAP for Q931 **********************************/
1343 /****************************************************************************/
1344 void h245_add_to_graph(guint32 new_frame_num);
1345 static const e_guid_t guid_allzero = {0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };
1346 /* defines specific H323 data */
1348 static gchar *q931_calling_number;
1349 static gchar *q931_called_number;
1350 static guint8 q931_cause_value;
1351 static gint32 q931_crv;
1352 static guint32 q931_frame_num;
1354 static guint32 h225_frame_num = 0;
1355 static guint16 h225_call_num = 0;
1356 static h225_cs_type h225_cstype = H225_OTHER;
1357 static gboolean h225_is_faststart;
1359 static guint32 actrace_frame_num = 0;
1360 static gint32 actrace_trunk = 0;
1361 static gint32 actrace_direction = 0;
1364 /****************************************************************************/
1365 /* whenever a q931_ packet is seen by the tap listener */
1367 q931_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *q931_info _U_)
1370 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1371 h323_calls_info_t *tmp_h323info,*tmp2_h323info;
1372 actrace_isdn_calls_info_t *tmp_actrace_isdn_info;
1373 voip_calls_info_t *tmp_listinfo;
1374 voip_calls_info_t *strinfo = NULL;
1375 h245_address_t *h245_add = NULL;
1378 const q931_packet_info *pi = q931_info;
1380 /* free previously allocated q931_calling/ed_number */
1381 g_free(q931_calling_number);
1382 g_free(q931_called_number);
1384 if (pi->calling_number!=NULL)
1385 q931_calling_number = g_strdup(pi->calling_number);
1387 q931_calling_number = g_strdup("");
1389 if (pi->called_number!=NULL)
1390 q931_called_number = g_strdup(pi->called_number);
1392 q931_called_number = g_strdup("");
1393 q931_cause_value = pi->cause_value;
1394 q931_frame_num = pinfo->fd->num;
1398 /* add staff to H323 calls */
1399 if (h225_frame_num == q931_frame_num) {
1400 tmp_h323info = NULL;
1401 list = g_list_first(tapinfo->strinfo_list);
1404 tmp_listinfo=list->data;
1405 if ( (tmp_listinfo->protocol == VOIP_H323) && (tmp_listinfo->call_num == h225_call_num) ){
1406 tmp_h323info = tmp_listinfo->prot_info;
1407 strinfo = (voip_calls_info_t*)(list->data);
1409 /* Add the CRV to the h323 call */
1410 if (tmp_h323info->q931_crv == -1) {
1411 tmp_h323info->q931_crv = q931_crv;
1412 } else if (tmp_h323info->q931_crv != q931_crv) {
1413 tmp_h323info->q931_crv2 = q931_crv;
1417 list = g_list_next (list);
1420 if (strinfo != NULL) {
1422 if (h225_cstype == H225_SETUP) {
1423 /* set te calling and called number from the Q931 packet */
1424 if (q931_calling_number != NULL){
1425 g_free(strinfo->from_identity);
1426 strinfo->from_identity=g_strdup(q931_calling_number);
1428 if (q931_called_number != NULL){
1429 g_free(strinfo->to_identity);
1430 strinfo->to_identity=g_strdup(q931_called_number);
1433 /* check if there is an LRQ/LCF that match this Setup */
1434 /* TODO: we are just checking the DialedNumer in LRQ/LCF agains the Setup
1435 we should also check if the h225 signaling IP and port match the destination
1436 Setup ip and port */
1437 list = g_list_first(tapinfo->strinfo_list);
1440 tmp_listinfo=list->data;
1441 if (tmp_listinfo->protocol == VOIP_H323){
1442 tmp2_h323info = tmp_listinfo->prot_info;
1444 /* check if the called number match a LRQ/LCF */
1445 if ( (strcmp(strinfo->to_identity, tmp_listinfo->to_identity)==0)
1446 && (memcmp(&tmp2_h323info->guid, &guid_allzero, GUID_LEN) == 0) ){
1447 /* change the call graph to the LRQ/LCF to belong to this call */
1448 strinfo->npackets += change_call_num_graph(tapinfo, tmp_listinfo->call_num, strinfo->call_num);
1450 /* remove this LRQ/LCF call entry because we have found the Setup that match them */
1451 g_free(tmp_listinfo->from_identity);
1452 g_free(tmp_listinfo->to_identity);
1453 g_free(tmp2_h323info->guid);
1455 list2 = g_list_first(tmp2_h323info->h245_list);
1458 h245_add=list2->data;
1459 g_free((void *)h245_add->h245_address.data);
1460 g_free(list2->data);
1461 list2 = g_list_next(list2);
1463 g_list_free(tmp_h323info->h245_list);
1464 tmp_h323info->h245_list = NULL;
1465 g_free(tmp_listinfo->prot_info);
1466 tapinfo->strinfo_list = g_list_remove(tapinfo->strinfo_list, tmp_listinfo);
1470 list = g_list_next (list);
1473 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"),
1474 (h225_is_faststart==TRUE?"on":"off"));
1475 } else if (h225_cstype == H225_RELEASE_COMPLET) {
1476 /* get the Q931 Release cause code */
1477 if (q931_cause_value != 0xFF){
1478 comment = g_strdup_printf("H225 Q931 Rel Cause (%i):%s", q931_cause_value, val_to_str(q931_cause_value, q931_cause_code_vals, "<unknown>"));
1479 } else { /* Cause not set */
1480 comment = g_strdup("H225 No Q931 Rel Cause");
1483 /* change the graph comment for this new one */
1484 if (comment != NULL) {
1485 change_frame_graph(tapinfo, h225_frame_num, NULL, comment);
1489 /* we reset the h225_frame_num to 0 because there could be empty h225 in the same frame
1490 as non empty h225 (e.g connect), so we don't have to be here twice */
1493 /* add staff to H245 */
1494 } else if (h245_labels.frame_num == q931_frame_num) {
1495 /* there are empty H225 frames that don't have guid (guaid=0) but they have h245 info,
1496 so the only way to match those frames is with the Q931 CRV number */
1497 list = g_list_first(tapinfo->strinfo_list);
1500 tmp_listinfo=list->data;
1501 if (tmp_listinfo->protocol == VOIP_H323){
1502 tmp_h323info = tmp_listinfo->prot_info;
1503 if ( ((tmp_h323info->q931_crv == q931_crv) || (tmp_h323info->q931_crv2 == q931_crv)) && (q931_crv!=-1)){
1505 comment = g_strdup("");
1507 /* if the frame number exists in graph, append to it*/
1508 if (!append_to_frame_graph(tapinfo, q931_frame_num, "", comment)) {
1509 /* if not exist, add to the graph */
1510 add_to_graph(tapinfo, pinfo, "", comment, tmp_listinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1511 ++(tmp_listinfo->npackets);
1512 /* increment the packets counter of all calls */
1513 ++(tapinfo->npackets);
1516 /* Add the H245 info if exists to the Graph */
1517 h245_add_to_graph(pinfo->fd->num);
1522 list = g_list_next (list);
1525 /* add staff to ACTRACE */
1526 } else if (actrace_frame_num == q931_frame_num) {
1528 gchar *comment = NULL;
1531 list = g_list_first(tapinfo->strinfo_list);
1534 tmp_listinfo=list->data;
1535 if ( tmp_listinfo->protocol == VOIP_AC_ISDN ){
1536 tmp_actrace_isdn_info = tmp_listinfo->prot_info;
1537 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
1538 if ( (tmp_actrace_isdn_info->crv == q931_crv) && (tmp_actrace_isdn_info->trunk == actrace_trunk) ) {
1539 strinfo = (voip_calls_info_t*)(list->data);
1543 list = g_list_next (list);
1546 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, g_strdup("PSTN"));
1548 /* if it is a new call, add it to the list */
1550 strinfo = g_malloc(sizeof(voip_calls_info_t));
1551 strinfo->call_active_state = VOIP_ACTIVE;
1552 strinfo->call_state = VOIP_CALL_SETUP;
1553 strinfo->from_identity=g_strdup(q931_calling_number);
1554 strinfo->to_identity=g_strdup(q931_called_number);
1555 COPY_ADDRESS(&(strinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
1556 strinfo->first_frame_num=pinfo->fd->num;
1557 strinfo->selected=FALSE;
1558 strinfo->start_sec=pinfo->fd->rel_ts.secs;
1559 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1560 strinfo->protocol=VOIP_AC_ISDN;
1561 strinfo->prot_info=g_malloc(sizeof(actrace_isdn_calls_info_t));
1562 tmp_actrace_isdn_info=strinfo->prot_info;
1563 tmp_actrace_isdn_info->crv=q931_crv;
1564 tmp_actrace_isdn_info->trunk=actrace_trunk;
1565 strinfo->npackets = 0;
1566 strinfo->call_num = tapinfo->ncalls++;
1567 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
1570 strinfo->stop_sec=pinfo->fd->rel_ts.secs;
1571 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1572 strinfo->last_frame_num=pinfo->fd->num;
1573 ++(strinfo->npackets);
1574 /* increment the packets counter of all calls */
1575 ++(tapinfo->npackets);
1577 switch(pi->message_type){
1579 comment = g_strdup_printf("AC_ISDN trunk:%u Calling: %s Called:%s", actrace_trunk, q931_calling_number, q931_called_number);
1580 strinfo->call_state=VOIP_CALL_SETUP;
1583 strinfo->call_state=VOIP_IN_CALL;
1585 case Q931_RELEASE_COMPLETE:
1587 case Q931_DISCONNECT:
1588 if (strinfo->call_state==VOIP_CALL_SETUP){
1589 if (ADDRESSES_EQUAL(&(strinfo->initial_speaker), actrace_direction?&pstn_add:&(pinfo->src) )){ /* forward direction */
1590 strinfo->call_state=VOIP_CANCELLED;
1593 strinfo->call_state=VOIP_REJECTED;
1594 tapinfo->rejected_calls++;
1596 } else if ( (strinfo->call_state!=VOIP_CANCELLED) && (strinfo->call_state!=VOIP_REJECTED) ){
1597 strinfo->call_state=VOIP_COMPLETED;
1598 tapinfo->completed_calls++;
1600 if (q931_cause_value != 0xFF){
1601 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>"));
1602 } else { /* Cause not set */
1603 comment = g_strdup("AC_ISDN No Q931 Rel Cause");
1609 comment = g_strdup_printf("AC_ISDN trunk:%u", actrace_trunk );
1611 add_to_graph(tapinfo, pinfo, val_to_str(pi->message_type, q931_message_type_vals, "<unknown>") , comment, strinfo->call_num,
1612 actrace_direction?&pstn_add:&(pinfo->src),
1613 actrace_direction?&(pinfo->src):&pstn_add,
1617 g_free((char *)pstn_add.data);
1620 tapinfo->redraw = TRUE;
1622 return 1; /* refresh output */
1625 /****************************************************************************/
1626 static gboolean have_q931_tap_listener=FALSE;
1629 q931_calls_init_tap(void)
1631 GString *error_string;
1634 if(have_q931_tap_listener==FALSE)
1636 error_string = register_tap_listener("q931", &(the_tapinfo_struct.q931_dummy),
1638 voip_calls_dlg_reset,
1643 if (error_string != NULL) {
1644 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1646 g_string_free(error_string, TRUE);
1649 have_q931_tap_listener=TRUE;
1653 /****************************************************************************/
1656 remove_tap_listener_q931_calls(void)
1658 protect_thread_critical_region();
1659 remove_tap_listener(&(the_tapinfo_struct.q931_dummy));
1660 unprotect_thread_critical_region();
1662 have_q931_tap_listener=FALSE;
1665 /****************************************************************************/
1666 /****************************TAP for H323 ***********************************/
1667 /****************************************************************************/
1669 static void add_h245_Address(h323_calls_info_t *h323info, h245_address_t *h245_address)
1671 h323info->h245_list = g_list_append(h323info->h245_list, h245_address);
1674 /****************************************************************************/
1675 /* whenever a H225 packet is seen by the tap listener */
1677 H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H225info)
1679 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1680 voip_calls_info_t *tmp_listinfo;
1681 voip_calls_info_t *strinfo = NULL;
1682 h323_calls_info_t *tmp_h323info = NULL;
1686 address tmp_src, tmp_dst;
1687 h245_address_t *h245_add = NULL;
1689 const h225_packet_info *pi = H225info;
1691 /* if not guid and RAS and not LRQ, LCF or LRJ return because did not belong to a call */
1692 /* OR, if not guid and is H225 return because doesn't belong to a call */
1693 if ((memcmp(&pi->guid, &guid_allzero, GUID_LEN) == 0))
1694 if ( ((pi->msg_type == H225_RAS) && ((pi->msg_tag < 18) || (pi->msg_tag > 20))) || (pi->msg_type != H225_RAS) )
1697 /* if it is RAS LCF or LRJ*/
1698 if ( (pi->msg_type == H225_RAS) && ((pi->msg_tag == 19) || (pi->msg_tag == 20))) {
1699 /* if the LCF/LRJ doesn't match to a LRQ, just return */
1700 if (!pi->request_available) return 0;
1702 /* check whether we already have a call with this request SeqNum */
1703 list = g_list_first(tapinfo->strinfo_list);
1706 tmp_listinfo=list->data;
1707 g_assert(tmp_listinfo != NULL);
1708 if (tmp_listinfo->protocol == VOIP_H323){
1709 tmp_h323info = tmp_listinfo->prot_info;
1710 if (tmp_h323info->requestSeqNum == pi->requestSeqNum) {
1711 strinfo = (voip_calls_info_t*)(list->data);
1715 list = g_list_next (list);
1718 /* check whether we already have a call with this guid in the list */
1719 list = g_list_first(tapinfo->strinfo_list);
1722 tmp_listinfo=list->data;
1723 if (tmp_listinfo->protocol == VOIP_H323){
1724 tmp_h323info = tmp_listinfo->prot_info;
1725 g_assert(tmp_h323info != NULL);
1726 if ( (memcmp(tmp_h323info->guid, &guid_allzero, GUID_LEN) != 0) && (memcmp(tmp_h323info->guid, &pi->guid,GUID_LEN)==0) ){
1727 strinfo = (voip_calls_info_t*)(list->data);
1731 list = g_list_next (list);
1735 h225_cstype = pi->cs_type;
1736 h225_is_faststart = pi->is_faststart;
1738 /* not in the list? then create a new entry */
1739 if ((strinfo==NULL)){
1740 strinfo = g_malloc(sizeof(voip_calls_info_t));
1741 strinfo->call_active_state = VOIP_ACTIVE;
1742 strinfo->call_state = VOIP_UNKNOWN;
1743 strinfo->from_identity=g_strdup("");
1744 strinfo->to_identity=g_strdup("");
1745 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
1746 strinfo->selected=FALSE;
1747 strinfo->first_frame_num=pinfo->fd->num;
1748 strinfo->start_sec=pinfo->fd->rel_ts.secs;
1749 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1750 strinfo->protocol=VOIP_H323;
1751 strinfo->prot_info=g_malloc(sizeof(h323_calls_info_t));
1752 tmp_h323info = strinfo->prot_info;
1753 g_assert(tmp_h323info != NULL);
1754 tmp_h323info->guid = g_memdup(&pi->guid, sizeof pi->guid);
1755 tmp_h323info->h225SetupAddr.type = AT_NONE;
1756 tmp_h323info->h225SetupAddr.len = 0;
1757 tmp_h323info->h245_list = NULL;
1758 tmp_h323info->is_faststart_Setup = FALSE;
1759 tmp_h323info->is_faststart_Proc = FALSE;
1760 tmp_h323info->is_h245Tunneling = FALSE;
1761 tmp_h323info->is_h245 = FALSE;
1762 tmp_h323info->q931_crv = -1;
1763 tmp_h323info->q931_crv2 = -1;
1764 tmp_h323info->requestSeqNum = 0;
1765 strinfo->call_num = tapinfo->ncalls++;
1766 strinfo->npackets = 0;
1768 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
1773 h225_frame_num = pinfo->fd->num;
1774 h225_call_num = strinfo->call_num;
1776 /* let's analyze the call state */
1778 COPY_ADDRESS(&(tmp_src),&(pinfo->src));
1779 COPY_ADDRESS(&(tmp_dst),&(pinfo->dst));
1781 strinfo->stop_sec=pinfo->fd->rel_ts.secs;
1782 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1783 strinfo->last_frame_num=pinfo->fd->num;
1784 ++(strinfo->npackets);
1785 /* increment the packets counter of all calls */
1786 ++(tapinfo->npackets);
1789 /* XXX: it is supposed to be initialized isn't it? */
1790 g_assert(tmp_h323info != NULL);
1792 /* change the status */
1793 if (pi->msg_type == H225_CS){
1795 /* this is still IPv4 only, because the dissector is */
1796 if (pi->is_h245 == TRUE){
1797 h245_add = g_malloc(sizeof (h245_address_t));
1798 h245_add->h245_address.type=AT_IPv4;
1799 h245_add->h245_address.len=4;
1800 h245_add->h245_address.data = g_malloc(sizeof(pi->h245_address));
1801 g_memmove((void *)(h245_add->h245_address.data), &(pi->h245_address), 4);
1802 h245_add->h245_port = pi->h245_port;
1803 add_h245_Address(tmp_h323info, h245_add);
1806 if (pi->cs_type != H225_RELEASE_COMPLET) tmp_h323info->is_h245Tunneling = pi->is_h245Tunneling;
1808 frame_label = g_strdup(pi->frame_label);
1810 switch(pi->cs_type){
1812 tmp_h323info->is_faststart_Setup = pi->is_faststart;
1814 /* Set the Setup address if it was not set */
1815 if (tmp_h323info->h225SetupAddr.type == AT_NONE)
1816 COPY_ADDRESS(&(tmp_h323info->h225SetupAddr), &(pinfo->src));
1817 strinfo->call_state=VOIP_CALL_SETUP;
1818 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1819 (pi->is_faststart==TRUE?"on":"off"));
1822 strinfo->call_state=VOIP_IN_CALL;
1823 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1824 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1825 (pi->is_faststart==TRUE?"on":"off"));
1827 case H225_RELEASE_COMPLET:
1828 COPY_ADDRESS(&tmp_src,&(pinfo->src));
1829 if (strinfo->call_state==VOIP_CALL_SETUP){
1830 if (ADDRESSES_EQUAL(&(tmp_h323info->h225SetupAddr),&tmp_src)){ /* forward direction */
1831 strinfo->call_state=VOIP_CANCELLED;
1834 strinfo->call_state=VOIP_REJECTED;
1835 tapinfo->rejected_calls++;
1838 strinfo->call_state=VOIP_COMPLETED;
1839 tapinfo->completed_calls++;
1841 comment = g_strdup("H225 No Q931 Rel Cause");
1845 case H225_CALL_PROCEDING:
1846 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1847 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1848 (pi->is_faststart==TRUE?"on":"off"));
1851 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1852 (pi->is_faststart==TRUE?"on":"off"));
1856 else if (pi->msg_type == H225_RAS){
1857 switch(pi->msg_tag){
1859 if (!pi->is_duplicate){
1860 g_free(strinfo->to_identity);
1861 strinfo->to_identity=g_strdup(pi->dialedDigits);
1862 tmp_h323info->requestSeqNum = pi->requestSeqNum;
1865 if (strlen(pi->dialedDigits))
1866 comment = g_strdup_printf("H225 RAS dialedDigits: %s", pi->dialedDigits);
1868 comment = g_strdup("H225 RAS");
1871 comment = g_strdup("H225 RAS");
1873 frame_label = g_strdup_printf("%s", val_to_str(pi->msg_tag, RasMessage_vals, "<unknown>"));
1875 frame_label = g_strdup("H225: Unknown");
1876 comment = g_strdup("");
1879 /* add to graph analysis */
1881 /* if the frame number exists in graph, append to it*/
1882 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, comment)) {
1883 /* if not exist, add to the graph */
1884 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1885 g_free((void *)tmp_src.data);
1886 g_free((void *)tmp_dst.data);
1889 /* Add the H245 info if exists to the Graph */
1890 h245_add_to_graph(pinfo->fd->num);
1892 g_free(frame_label);
1897 tapinfo->redraw = TRUE;
1899 return 1; /* refresh output */
1903 /****************************************************************************/
1905 /****************************************************************************/
1906 static gboolean have_H225_tap_listener=FALSE;
1907 /****************************************************************************/
1909 h225_calls_init_tap(void)
1911 GString *error_string;
1913 if(have_H225_tap_listener==FALSE)
1915 /* don't register tap listener, if we have it already */
1916 error_string = register_tap_listener("h225", &(the_tapinfo_struct.h225_dummy), NULL,
1917 voip_calls_dlg_reset,
1922 if (error_string != NULL) {
1923 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1925 g_string_free(error_string, TRUE);
1928 have_H225_tap_listener=TRUE;
1932 /****************************************************************************/
1934 remove_tap_listener_h225_calls(void)
1936 protect_thread_critical_region();
1937 remove_tap_listener(&(the_tapinfo_struct.h225_dummy));
1938 unprotect_thread_critical_region();
1940 have_H225_tap_listener=FALSE;
1943 /* Add the h245 label info to the graph */
1944 void h245_add_to_graph(guint32 new_frame_num)
1948 if (new_frame_num != h245_labels.frame_num) return;
1950 for (n=0; n<h245_labels.labels_count; n++) {
1951 append_to_frame_graph(&the_tapinfo_struct, new_frame_num, h245_labels.labels[n].frame_label, h245_labels.labels[n].comment);
1952 g_free(h245_labels.labels[n].frame_label);
1953 h245_labels.labels[n].frame_label = NULL;
1954 g_free(h245_labels.labels[n].comment);
1955 h245_labels.labels[n].comment = NULL;
1957 h245_labels.frame_num = 0;
1958 h245_labels.labels_count = 0;
1961 /* free the h245_labels if the frame number is different */
1962 static void h245_free_labels(guint32 new_frame_num)
1966 if (new_frame_num == h245_labels.frame_num) return;
1968 for (n=0; n<h245_labels.labels_count; n++) {
1969 g_free(h245_labels.labels[n].frame_label);
1970 h245_labels.labels[n].frame_label = NULL;
1971 g_free(h245_labels.labels[n].comment);
1972 h245_labels.labels[n].comment = NULL;
1974 h245_labels.frame_num = 0;
1975 h245_labels.labels_count = 0;
1978 /* add the frame_label and comment to h245_labels and free the actual one if it is different frame num */
1979 static void h245_add_label(guint32 new_frame_num, gchar *frame_label, gchar *comment)
1981 h245_free_labels(new_frame_num);
1983 h245_labels.frame_num = new_frame_num;
1984 h245_labels.labels[h245_labels.labels_count].frame_label = g_strdup(frame_label);
1985 h245_labels.labels[h245_labels.labels_count].comment = g_strdup(comment);
1987 if (h245_labels.labels_count < (H245_MAX-1))
1988 h245_labels.labels_count++;
1992 /****************************************************************************/
1993 /* whenever a H245dg packet is seen by the tap listener (when H245 tunneling is ON) */
1995 H245dgcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H245info)
1997 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1998 voip_calls_info_t *tmp_listinfo;
1999 voip_calls_info_t *strinfo = NULL;
2000 h323_calls_info_t *tmp_h323info;
2005 address tmp_src, tmp_dst;
2006 h245_address_t *h245_add = NULL;
2008 const h245_packet_info *pi = H245info;
2010 /* check if Tunneling is OFF and we have a call with this H245 add */
2011 list = g_list_first(tapinfo->strinfo_list);
2014 tmp_listinfo=list->data;
2015 if (tmp_listinfo->protocol == VOIP_H323){
2016 tmp_h323info = tmp_listinfo->prot_info;
2018 COPY_ADDRESS(&(tmp_src), &(pinfo->src));
2019 COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
2020 list2 = g_list_first(tmp_h323info->h245_list);
2023 h245_add=list2->data;
2024 if ( (ADDRESSES_EQUAL(&(h245_add->h245_address),&tmp_src) && (h245_add->h245_port == pinfo->srcport))
2025 || (ADDRESSES_EQUAL(&(h245_add->h245_address),&tmp_dst) && (h245_add->h245_port == pinfo->destport)) ){
2026 strinfo = (voip_calls_info_t*)(list->data);
2028 ++(strinfo->npackets);
2029 /* increment the packets counter of all calls */
2030 ++(tapinfo->npackets);
2034 list2 = g_list_next(list2);
2036 if (strinfo!=NULL) break;
2037 g_free((void *)tmp_src.data);
2038 g_free((void *)tmp_dst.data);
2040 list = g_list_next(list);
2043 /* Tunnel is OFF, and we matched the h245 add so we add it to graph */
2045 ++(strinfo->npackets);
2046 /* increment the packets counter of all calls */
2047 ++(tapinfo->npackets);
2048 frame_label = g_strdup(pi->frame_label);
2049 comment = g_strdup(pi->comment);
2050 /* if the frame number exists in graph, append to it*/
2051 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, frame_label, comment)) {
2052 /* if not exist, add to the graph */
2053 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2055 g_free(frame_label);
2058 /* Tunnel is ON, so we save the label info to use it into h225 or q931 tap. OR may be
2059 tunnel OFF but we did not matched the h245 add, in this case nobady will set this label
2060 since the frame_num will not match */
2062 h245_add_label(pinfo->fd->num, (gchar *) pi->frame_label, (gchar *) pi->comment);
2065 tapinfo->redraw = TRUE;
2067 return 1; /* refresh output */
2071 /****************************************************************************/
2073 /****************************************************************************/
2074 static gboolean have_H245dg_tap_listener=FALSE;
2075 /****************************************************************************/
2077 h245dg_calls_init_tap(void)
2079 GString *error_string;
2081 if(have_H245dg_tap_listener==FALSE)
2083 /* don't register tap listener, if we have it already */
2084 error_string = register_tap_listener("h245dg", &(the_tapinfo_struct.h245dg_dummy), NULL,
2085 voip_calls_dlg_reset,
2090 if (error_string != NULL) {
2091 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2093 g_string_free(error_string, TRUE);
2096 have_H245dg_tap_listener=TRUE;
2100 /****************************************************************************/
2102 remove_tap_listener_h245dg_calls(void)
2104 protect_thread_critical_region();
2105 remove_tap_listener(&(the_tapinfo_struct.h245dg_dummy));
2106 unprotect_thread_critical_region();
2108 have_H245dg_tap_listener=FALSE;
2111 /****************************************************************************/
2112 /****************************TAP for SDP PROTOCOL ***************************/
2113 /****************************************************************************/
2114 /* whenever a SDP packet is seen by the tap listener */
2116 SDPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SDPinfo)
2118 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2119 const sdp_packet_info *pi = SDPinfo;
2121 /* There are protocols like MGCP/SIP where the SDP is called before the tap for the
2122 MGCP/SIP packet, in those cases we assign the SPD summary to global lastSDPsummary
2125 g_free(sdp_summary);
2126 sdp_frame_num = pinfo->fd->num;
2127 /* Append to graph the SDP summary if the packet exists */
2128 sdp_summary = g_strdup_printf("SDP (%s)", pi->summary_str);
2129 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2131 tapinfo->redraw = TRUE;
2133 return 1; /* refresh output */
2137 /****************************************************************************/
2139 /****************************************************************************/
2140 static gboolean have_sdp_tap_listener=FALSE;
2141 /****************************************************************************/
2143 sdp_calls_init_tap(void)
2145 GString *error_string;
2147 if(have_sdp_tap_listener==FALSE)
2149 /* don't register tap listener, if we have it already */
2150 error_string = register_tap_listener("sdp", &(the_tapinfo_struct.sdp_dummy), NULL,
2151 voip_calls_dlg_reset,
2156 if (error_string != NULL) {
2157 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2159 g_string_free(error_string, TRUE);
2162 have_sdp_tap_listener=TRUE;
2166 /****************************************************************************/
2168 remove_tap_listener_sdp_calls(void)
2170 protect_thread_critical_region();
2171 remove_tap_listener(&(the_tapinfo_struct.sdp_dummy));
2172 unprotect_thread_critical_region();
2174 have_sdp_tap_listener=FALSE;
2179 /****************************************************************************/
2180 /* ***************************TAP for MGCP **********************************/
2181 /****************************************************************************/
2184 This function will look for a signal/event in the SignalReq/ObsEvent string
2185 and return true if it is found
2187 static gboolean isSignal(const gchar *signal, const gchar *signalStr)
2190 gchar **resultArray;
2192 /* if there is no signalStr, just return false */
2193 if (signalStr == NULL) return FALSE;
2195 /* if are both "blank" return true */
2196 if ( (*signal == '\0') && (*signalStr == '\0') ) return TRUE;
2198 /* look for signal in signalSre */
2199 resultArray = g_strsplit(signalStr, ",", 10);
2201 for (i = 0; resultArray[i]; i++) {
2202 g_strstrip(resultArray[i]);
2203 if (strcmp(resultArray[i], signal) == 0) return TRUE;
2206 g_strfreev(resultArray);
2212 This function will get the Caller ID info and replace the current string
2213 This is how it looks the caller Id: rg, ci(02/16/08/29, "3035550002","Ale Sipura 2")
2215 static void mgcpCallerID(gchar *signalStr, gchar **callerId)
2219 /* if there is no signalStr, just return false */
2220 if (signalStr == NULL) return;
2222 arrayStr = g_strsplit(signalStr, "\"", 10);
2224 if (arrayStr[0] == NULL) return;
2226 /* look for the ci signal */
2227 if (strstr(arrayStr[0], "ci(") && (arrayStr[1] != NULL) ) {
2228 /* free the previous "From" field of the call, and assign the new */
2230 *callerId = g_strdup(arrayStr[1]);
2232 g_strfreev(arrayStr);
2239 This function will get the Dialed Digits and replace the current string
2240 This is how it looks the dialed digits 5,5,5,0,0,0,2,#,*
2242 static void mgcpDialedDigits(gchar *signalStr, gchar **dialedDigits)
2245 gchar resultStr[50];
2248 /* if there is no signalStr, just return false */
2249 if (signalStr == NULL) return;
2251 tmpStr = g_strdup(signalStr);
2253 for ( i = 0 ; tmpStr[i] ; i++) {
2254 switch (tmpStr[i]) {
2255 case '0' : case '1' : case '2' : case '3' : case '4' :
2256 case '5' : case '6' : case '7' : case '8' : case '9' :
2257 case '#' : case '*' :
2265 for (i = 0, j = 0; tmpStr[i] && i<50; i++) {
2266 if (tmpStr[i] != '?')
2267 resultStr[j++] = tmpStr[i];
2269 resultStr[j] = '\0';
2271 if (*resultStr == '\0') return;
2273 g_free(*dialedDigits);
2274 *dialedDigits = g_strdup(resultStr);
2282 /****************************************************************************/
2283 /* whenever a MGCP packet is seen by the tap listener */
2285 MGCPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *MGCPinfo)
2287 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2289 voip_calls_info_t *tmp_listinfo;
2290 voip_calls_info_t *strinfo = NULL;
2291 mgcp_calls_info_t *tmp_mgcpinfo = NULL;
2294 gchar *frame_label = NULL;
2295 gchar *comment = NULL;
2296 graph_analysis_item_t *gai;
2297 gboolean new = FALSE;
2298 gboolean fromEndpoint = FALSE; /* true for calls originated in Endpoints, false for calls from MGC */
2301 const mgcp_info_t *pi = MGCPinfo;
2304 if ((pi->mgcp_type == MGCP_REQUEST) && !pi->is_duplicate ){
2305 /* check whether we already have a call with this Endpoint and it is active*/
2306 list = g_list_first(tapinfo->strinfo_list);
2309 tmp_listinfo=list->data;
2310 if ((tmp_listinfo->protocol == VOIP_MGCP) && (tmp_listinfo->call_active_state == VOIP_ACTIVE)){
2311 tmp_mgcpinfo = tmp_listinfo->prot_info;
2312 if (pi->endpointId != NULL){
2313 if (g_strcasecmp(tmp_mgcpinfo->endpointId,pi->endpointId) == 0){
2315 check first if it is an ended call. We can still match packets to this Endpoint 2 seconds
2316 after the call has been released
2318 diff_time = nstime_to_sec(&pinfo->fd->rel_ts) - tmp_listinfo->stop_sec - (double)tmp_listinfo->stop_usec/1000000;
2319 if ( ((tmp_listinfo->call_state == VOIP_CANCELLED) ||
2320 (tmp_listinfo->call_state == VOIP_COMPLETED) ||
2321 (tmp_listinfo->call_state == VOIP_REJECTED)) &&
2324 tmp_listinfo->call_active_state = VOIP_INACTIVE;
2326 strinfo = (voip_calls_info_t*)(list->data);
2332 list = g_list_next (list);
2335 /* there is no call with this Endpoint, lets see if this a new call or not */
2336 if (strinfo == NULL){
2337 if ( (strcmp(pi->code, "NTFY") == 0) && isSignal("hd", pi->observedEvents) ){ /* off hook transition */
2338 /* this is a new call from the Endpoint */
2339 fromEndpoint = TRUE;
2341 } else if (strcmp(pi->code, "CRCX") == 0){
2342 /* this is a new call from the MGC */
2343 fromEndpoint = FALSE;
2348 } else if ( ((pi->mgcp_type == MGCP_RESPONSE) && pi->request_available) ||
2349 ((pi->mgcp_type == MGCP_REQUEST) && pi->is_duplicate) ) {
2350 /* if it is a response OR if it is a duplicated Request, lets look in the Graph to see
2351 if there is a request that matches */
2352 listGraph = g_list_first(tapinfo->graph_analysis->list);
2355 gai = listGraph->data;
2356 if (gai->frame_num == pi->req_num){
2357 /* there is a request that match, so look the associated call with this call_num */
2358 list = g_list_first(tapinfo->strinfo_list);
2361 tmp_listinfo=list->data;
2362 if (tmp_listinfo->protocol == VOIP_MGCP){
2363 if (tmp_listinfo->call_num == gai->conv_num){
2364 tmp_mgcpinfo = tmp_listinfo->prot_info;
2365 strinfo = (voip_calls_info_t*)(list->data);
2369 list = g_list_next (list);
2371 if (strinfo != NULL) break;
2373 listGraph = g_list_next(listGraph);
2375 /* if there is not a matching request, just return */
2376 if (strinfo == NULL) return 0;
2379 /* not in the list? then create a new entry */
2381 strinfo = g_malloc(sizeof(voip_calls_info_t));
2382 strinfo->call_active_state = VOIP_ACTIVE;
2383 strinfo->call_state = VOIP_CALL_SETUP;
2385 strinfo->from_identity=g_strdup(pi->endpointId);
2386 strinfo->to_identity=g_strdup("");
2388 strinfo->from_identity=g_strdup("");
2389 strinfo->to_identity=g_strdup(pi->endpointId);
2391 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
2392 strinfo->first_frame_num=pinfo->fd->num;
2393 strinfo->selected=FALSE;
2394 strinfo->start_sec=pinfo->fd->rel_ts.secs;
2395 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
2396 strinfo->protocol=VOIP_MGCP;
2397 strinfo->prot_info=g_malloc(sizeof(mgcp_calls_info_t));
2398 tmp_mgcpinfo=strinfo->prot_info;
2399 tmp_mgcpinfo->endpointId = g_strdup(pi->endpointId);
2400 tmp_mgcpinfo->fromEndpoint = fromEndpoint;
2401 strinfo->npackets = 0;
2402 strinfo->call_num = tapinfo->ncalls++;
2403 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
2406 g_assert(tmp_mgcpinfo != NULL);
2408 /* change call state and add to graph */
2409 switch (pi->mgcp_type)
2412 if ( (strcmp(pi->code, "NTFY") == 0) && (pi->observedEvents != NULL) ){
2413 frame_label = g_strdup_printf("%s ObsEvt:%s",pi->code, pi->observedEvents);
2415 if (tmp_mgcpinfo->fromEndpoint){
2416 /* use the Dialed digits to fill the "To" for the call, but use the first NTFY */
2417 if (strinfo->to_identity[0] == '\0') mgcpDialedDigits(pi->observedEvents, &(strinfo->to_identity));
2419 /* from MGC and the user picked up, the call is connected */
2420 } else if (isSignal("hd", pi->observedEvents))
2421 strinfo->call_state=VOIP_IN_CALL;
2423 /* hung up signal */
2424 if (isSignal("hu", pi->observedEvents)) {
2425 if ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state == VOIP_RINGING)){
2426 strinfo->call_state = VOIP_CANCELLED;
2428 strinfo->call_state = VOIP_COMPLETED;
2432 } else if (strcmp(pi->code, "RQNT") == 0) {
2433 /* for calls from Endpoint: if there is a "no signal" RQNT and the call was RINGING, we assume this is the CONNECT */
2434 if ( tmp_mgcpinfo->fromEndpoint && isSignal("", pi->signalReq) && (strinfo->call_state == VOIP_RINGING) ) {
2435 strinfo->call_state = VOIP_IN_CALL;
2438 /* if there is ringback or ring tone, change state to ringing */
2439 if ( isSignal("rg", pi->signalReq) || isSignal("rt", pi->signalReq) ) {
2440 strinfo->call_state = VOIP_RINGING;
2443 /* if there is a Busy or ReorderTone, and the call was Ringing or Setup the call is Rejected */
2444 if ( (isSignal("ro", pi->signalReq) || isSignal("bz", pi->signalReq)) && ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state = VOIP_RINGING)) ) {
2445 strinfo->call_state = VOIP_REJECTED;
2448 if (pi->signalReq != NULL)
2449 frame_label = g_strdup_printf("%s%sSigReq:%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"", pi->signalReq);
2451 frame_label = g_strdup_printf("%s%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"");
2453 /* use the CallerID info to fill the "From" for the call */
2454 if (!tmp_mgcpinfo->fromEndpoint) mgcpCallerID(pi->signalReq, &(strinfo->from_identity));
2456 } else if (strcmp(pi->code, "DLCX") == 0) {
2458 if there is a DLCX in a call To an Endpoint and the call was not connected, we use
2459 the DLCX as the end of the call
2461 if (!tmp_mgcpinfo->fromEndpoint){
2462 if ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state == VOIP_RINGING)){
2463 strinfo->call_state = VOIP_CANCELLED;
2468 if (frame_label == NULL) frame_label = g_strdup_printf("%s",pi->code);
2471 frame_label = g_strdup_printf("%u (%s)",pi->rspcode, pi->code);
2474 /* XXX what to do? */
2479 comment = g_strdup_printf("MGCP %s %s%s", tmp_mgcpinfo->endpointId, (pi->mgcp_type == MGCP_REQUEST)?"Request":"Response", pi->is_duplicate?" Duplicate":"");
2481 strinfo->stop_sec=pinfo->fd->rel_ts.secs;
2482 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
2483 strinfo->last_frame_num=pinfo->fd->num;
2484 ++(strinfo->npackets);
2485 /* increment the packets counter of all calls */
2486 ++(tapinfo->npackets);
2488 /* add to the graph */
2489 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2491 g_free(frame_label);
2493 /* add SDP info if apply */
2494 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
2495 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2496 g_free(sdp_summary);
2500 tapinfo->redraw = TRUE;
2502 return 1; /* refresh output */
2506 /****************************************************************************/
2508 /****************************************************************************/
2509 static gboolean have_MGCP_tap_listener=FALSE;
2510 /****************************************************************************/
2512 mgcp_calls_init_tap(void)
2514 GString *error_string;
2516 if(have_MGCP_tap_listener==FALSE)
2518 /* don't register tap listener, if we have it already */
2519 /* we send an empty filter, to force a non null "tree" in the mgcp dissector */
2520 error_string = register_tap_listener("mgcp", &(the_tapinfo_struct.mgcp_dummy), strdup(""),
2521 voip_calls_dlg_reset,
2525 if (error_string != NULL) {
2526 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2528 g_string_free(error_string, TRUE);
2531 have_MGCP_tap_listener=TRUE;
2535 /****************************************************************************/
2537 remove_tap_listener_mgcp_calls(void)
2539 protect_thread_critical_region();
2540 remove_tap_listener(&(the_tapinfo_struct.mgcp_dummy));
2541 unprotect_thread_critical_region();
2543 have_MGCP_tap_listener=FALSE;
2547 /****************************************************************************/
2548 /****************************TAP for ACTRACE (AudioCodes trace)**************/
2549 /****************************************************************************/
2551 /* whenever a ACTRACE packet is seen by the tap listener */
2553 ACTRACEcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *ACTRACEinfo)
2555 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2556 const actrace_info_t *pi = ACTRACEinfo;
2558 actrace_cas_calls_info_t *tmp_actrace_cas_info;
2559 voip_calls_info_t *tmp_listinfo;
2560 voip_calls_info_t *strinfo = NULL;
2563 actrace_frame_num = pinfo->fd->num;
2564 actrace_trunk = pi->trunk;
2565 actrace_direction = pi->direction;
2567 if (pi->type == 1){ /* is CAS protocol */
2569 gchar *comment = NULL;
2572 list = g_list_first(tapinfo->strinfo_list);
2575 tmp_listinfo=list->data;
2576 if ( tmp_listinfo->protocol == VOIP_AC_CAS ){
2577 tmp_actrace_cas_info = tmp_listinfo->prot_info;
2578 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
2579 if ( (tmp_actrace_cas_info->bchannel == pi->cas_bchannel) && (tmp_actrace_cas_info->trunk == actrace_trunk) ) {
2580 strinfo = (voip_calls_info_t*)(list->data);
2584 list = g_list_next (list);
2587 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, g_strdup("PSTN"));
2589 /* if it is a new call, add it to the list */
2591 strinfo = g_malloc(sizeof(voip_calls_info_t));
2592 strinfo->call_active_state = VOIP_ACTIVE;
2593 strinfo->call_state = VOIP_CALL_SETUP;
2594 strinfo->from_identity=g_strdup("N/A");
2595 strinfo->to_identity=g_strdup("N/A");
2596 COPY_ADDRESS(&(strinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
2597 strinfo->first_frame_num=pinfo->fd->num;
2598 strinfo->selected=FALSE;
2599 strinfo->start_sec=pinfo->fd->rel_ts.secs;
2600 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
2601 strinfo->protocol=VOIP_AC_CAS;
2602 strinfo->prot_info=g_malloc(sizeof(actrace_cas_calls_info_t));
2603 tmp_actrace_cas_info=strinfo->prot_info;
2604 tmp_actrace_cas_info->bchannel=pi->cas_bchannel;
2605 tmp_actrace_cas_info->trunk=actrace_trunk;
2606 strinfo->npackets = 0;
2607 strinfo->call_num = tapinfo->ncalls++;
2608 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
2611 strinfo->stop_sec=pinfo->fd->rel_ts.secs;
2612 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
2613 strinfo->last_frame_num=pinfo->fd->num;
2614 ++(strinfo->npackets);
2615 /* increment the packets counter of all calls */
2616 ++(tapinfo->npackets);
2619 comment = g_strdup_printf("AC_CAS trunk:%u", actrace_trunk );
2621 add_to_graph(tapinfo, pinfo, pi->cas_frame_label , comment, strinfo->call_num,
2622 actrace_direction?&pstn_add:&(pinfo->src),
2623 actrace_direction?&(pinfo->src):&pstn_add,
2627 g_free((char *)pstn_add.data);
2630 tapinfo->redraw = TRUE;
2632 return 1; /* refresh output */
2636 /****************************************************************************/
2638 /****************************************************************************/
2639 static gboolean have_actrace_tap_listener=FALSE;
2640 /****************************************************************************/
2642 actrace_calls_init_tap(void)
2644 GString *error_string;
2646 if(have_actrace_tap_listener==FALSE)
2648 /* don't register tap listener, if we have it already */
2649 error_string = register_tap_listener("actrace", &(the_tapinfo_struct.actrace_dummy), NULL,
2650 voip_calls_dlg_reset,
2651 ACTRACEcalls_packet,
2655 if (error_string != NULL) {
2656 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2658 g_string_free(error_string, TRUE);
2661 have_actrace_tap_listener=TRUE;
2665 /****************************************************************************/
2667 remove_tap_listener_actrace_calls(void)
2669 protect_thread_critical_region();
2670 remove_tap_listener(&(the_tapinfo_struct.actrace_dummy));
2671 unprotect_thread_critical_region();
2673 have_actrace_tap_listener=FALSE;
2676 /****************************************************************************/
2677 /* ***************************TAP for OTHER PROTOCOL **********************************/
2678 /****************************************************************************/
2680 /****************************************************************************/
2681 /* whenever a prot_ packet is seen by the tap listener */
2684 prot_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info _U_)
2686 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2688 strinfo->stop_sec=pinfo->fd->rel_secs;
2689 strinfo->stop_usec=pinfo->fd->rel_usecs;
2690 strinfo->last_frame_num=pinfo->fd->num;
2691 ++(strinfo->npackets);
2692 ++(tapinfo->npackets);
2695 tapinfo->redraw = TRUE;
2700 /****************************************************************************/
2702 static gboolean have_prot__tap_listener=FALSE;
2705 prot_calls_init_tap(void)
2707 GString *error_string;
2709 if(have_prot__tap_listener==FALSE)
2711 error_string = register_tap_listener("prot_", &(the_tapinfo_struct.prot__dummy),
2713 voip_calls_dlg_reset,
2718 if (error_string != NULL) {
2719 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2721 g_string_free(error_string, TRUE);
2724 have_prot__tap_listener=TRUE;
2728 /****************************************************************************/
2731 remove_tap_listener_prot__calls(void)
2733 protect_thread_critical_region();
2734 remove_tap_listener(&(the_tapinfo_struct.prot__dummy));
2735 unprotect_thread_critical_region();
2737 have_prot__tap_listener=FALSE;