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/tap-voip.h>
51 #include <epan/dissectors/packet-sip.h>
52 #include <epan/dissectors/packet-mtp3.h>
53 #include <epan/dissectors/packet-isup.h>
54 #include <epan/dissectors/packet-h225.h>
55 #include <epan/dissectors/packet-h245.h>
56 #include <epan/dissectors/packet-q931.h>
57 #include <epan/dissectors/packet-sdp.h>
58 #include <epan/dissectors/packet-mgcp.h>
59 #include <epan/dissectors/packet-actrace.h>
60 #include <epan/dissectors/packet-rtp.h>
61 #include <epan/dissectors/packet-rtp-events.h>
62 #include <epan/dissectors/packet-t38.h>
63 #include <epan/dissectors/packet-t30.h>
64 #include <epan/dissectors/packet-h248.h>
65 #include <epan/dissectors/packet-sccp.h>
66 #include <plugins/unistim/packet-unistim.h>
67 #include <epan/conversation.h>
68 #include <epan/rtp_pt.h>
69 #include <epan/ws_strsplit.h>
71 #include "alert_box.h"
72 #include "simple_dialog.h"
74 #ifdef HAVE_LIBPORTAUDIO
75 #if GTK_MAJOR_VERSION >= 2
76 #include "rtp_player.h"
77 #endif /* GTK_MAJOR_VERSION >= 2 */
78 #endif /* HAVE_LIBPORTAUDIO */
80 #ifdef NEED_G_ASCII_STRCASECMP_H
81 #include "../epan/g_ascii_strcasecmp.h"
84 const char *voip_call_state_name[8]={
95 /* defines whether we can consider the call active */
96 const char *voip_protocol_name[]={
122 graph_str labels[H245_MAX];
125 static h245_labels_t h245_labels;
127 /****************************************************************************/
128 /* the one and only global voip_calls_tapinfo_t structure */
129 static voip_calls_tapinfo_t the_tapinfo_struct =
130 {0, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
132 /* the one and only global voip_rtp_tapinfo_t structure */
133 static voip_rtp_tapinfo_t the_tapinfo_rtp_struct =
136 /****************************************************************************/
137 /* when there is a [re]reading of packet's */
138 void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
140 voip_calls_info_t *callsinfo;
141 voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
142 voip_rtp_stream_info_t *strinfo;
143 graph_analysis_item_t *graph_item;
146 #ifdef HAVE_LIBPORTAUDIO
147 #if GTK_MAJOR_VERSION >= 2
148 /* reset the RTP player */
153 /* free the data items first */
154 list = g_list_first(tapinfo->callsinfo_list);
157 callsinfo = list->data;
158 if (callsinfo->call_id)
159 g_free(callsinfo->call_id);
160 g_free(callsinfo->from_identity);
161 g_free(callsinfo->to_identity);
162 g_free((void *)(callsinfo->initial_speaker.data));
163 if (callsinfo->protocol_name)
164 g_free(callsinfo->protocol_name);
165 if (callsinfo->call_comment)
166 g_free(callsinfo->call_comment);
168 if (callsinfo->free_prot_info && callsinfo->prot_info)
169 callsinfo->free_prot_info(callsinfo->prot_info);
172 list = g_list_next(list);
174 g_list_free(tapinfo->callsinfo_list);
175 tapinfo->callsinfo_list = NULL;
177 tapinfo->npackets = 0;
178 tapinfo->start_packets = 0;
179 tapinfo->completed_calls = 0;
180 tapinfo->rejected_calls = 0;
182 /* free the graph data items first */
183 list = g_list_first(tapinfo->graph_analysis->list);
186 graph_item = list->data;
187 g_free(graph_item->frame_label);
188 g_free(graph_item->comment);
189 g_free((void *)graph_item->src_addr.data);
190 g_free((void *)graph_item->dst_addr.data);
192 list = g_list_next(list);
194 g_list_free(tapinfo->graph_analysis->list);
195 tapinfo->graph_analysis->nconv = 0;
196 tapinfo->graph_analysis->list = NULL;
198 ++(tapinfo->launch_count);
200 /* free the strinfo data items first */
201 list = g_list_first(rtp_tapinfo->list);
204 strinfo = list->data;
205 g_free(strinfo->pt_str);
206 list = g_list_next(list);
209 g_list_free(rtp_tapinfo->list);
210 rtp_tapinfo->list = NULL;
215 /****************************************************************************/
216 void graph_analysis_data_init(void){
217 the_tapinfo_struct.graph_analysis = g_malloc(sizeof(graph_analysis_info_t));
218 the_tapinfo_struct.graph_analysis->nconv = 0;
219 the_tapinfo_struct.graph_analysis->list = NULL;
222 /****************************************************************************/
223 /* Add a new item into the graph */
224 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)
226 graph_analysis_item_t *gai;
228 gai = g_malloc(sizeof(graph_analysis_item_t));
229 gai->frame_num = pinfo->fd->num;
230 gai->time= nstime_to_sec(&pinfo->fd->rel_ts);
231 COPY_ADDRESS(&(gai->src_addr),src_addr);
232 COPY_ADDRESS(&(gai->dst_addr),dst_addr);
234 gai->port_src=pinfo->srcport;
235 gai->port_dst=pinfo->destport;
236 if (frame_label != NULL)
237 gai->frame_label = g_strdup(frame_label);
239 gai->frame_label = g_strdup("");
242 gai->comment = g_strdup(comment);
244 gai->comment = g_strdup("");
245 gai->conv_num=call_num;
246 gai->line_style=line_style;
249 tapinfo->graph_analysis->list = g_list_append(tapinfo->graph_analysis->list, gai);
255 /****************************************************************************/
256 /* Append str to frame_label and comment in a graph item */
257 /* return 0 if the frame_num is not in the graph list */
258 static int append_to_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
260 graph_analysis_item_t *gai;
262 gchar *tmp_str = NULL;
263 gchar *tmp_str2 = NULL;
265 list = g_list_first(tapinfo->graph_analysis->list);
269 if (gai->frame_num == frame_num){
270 tmp_str = gai->frame_label;
271 tmp_str2 = gai->comment;
273 if (new_frame_label != NULL){
274 gai->frame_label = g_strdup_printf("%s %s", gai->frame_label, new_frame_label);
279 if (new_comment != NULL){
280 gai->comment = g_strdup_printf("%s %s", gai->comment, new_comment);
285 list = g_list_next (list);
287 if (tmp_str == NULL) return 0; /* it is not in the list */
292 /****************************************************************************/
293 /* Change the frame_label and comment in a graph item if not NULL*/
294 /* return 0 if the frame_num is not in the graph list */
295 static int change_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
297 graph_analysis_item_t *gai;
299 gchar *tmp_str = NULL;
300 gchar *tmp_str2 = NULL;
302 list = g_list_first(tapinfo->graph_analysis->list);
306 if (gai->frame_num == frame_num){
307 tmp_str = gai->frame_label;
308 tmp_str2 = gai->comment;
310 if (new_frame_label != NULL){
311 gai->frame_label = g_strdup(new_frame_label);
315 if (new_comment != NULL){
316 gai->comment = g_strdup(new_comment);
321 list = g_list_next (list);
323 if (tmp_str == NULL) return 0; /* it is not in the list */
328 /****************************************************************************/
329 /* Change all the graph items with call_num to new_call_num */
330 static guint change_call_num_graph(voip_calls_tapinfo_t *tapinfo _U_, guint16 call_num, guint16 new_call_num)
332 graph_analysis_item_t *gai;
337 list = g_list_first(tapinfo->graph_analysis->list);
341 if (gai->conv_num == call_num){
342 gai->conv_num = new_call_num;
345 list = g_list_next (list);
347 return items_changed;
353 /****************************************************************************/
354 /* Insert the item in the graph list */
355 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)
357 graph_analysis_item_t *gai, *new_gai;
362 new_gai = g_malloc(sizeof(graph_analysis_item_t));
363 new_gai->frame_num = frame_num;
365 COPY_ADDRESS(&(new_gai->src_addr),src_addr);
366 COPY_ADDRESS(&(new_gai->dst_addr),dst_addr);
368 new_gai->port_src=pinfo->srcport;
369 new_gai->port_dst=pinfo->destport;
370 if (frame_label != NULL)
371 new_gai->frame_label = g_strdup(frame_label);
373 new_gai->frame_label = g_strdup("");
376 new_gai->comment = g_strdup(comment);
378 new_gai->comment = g_strdup("");
379 new_gai->conv_num=call_num;
380 new_gai->line_style=line_style;
381 new_gai->display=FALSE;
385 list = g_list_first(tapinfo->graph_analysis->list);
389 if (gai->frame_num > frame_num){
390 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item_num);
394 list = g_list_next (list);
398 if ( !inserted) tapinfo->graph_analysis->list = g_list_append(tapinfo->graph_analysis->list, new_gai);
401 /****************************************************************************/
402 /* ***************************TAP for RTP Events*****************************/
403 /****************************************************************************/
405 static guint32 rtp_evt_frame_num = 0;
406 static guint8 rtp_evt = 0;
407 static gboolean rtp_evt_end = FALSE;
408 /*static guint32 rtp_evt_setup_frame_num = 0;*/
410 /****************************************************************************/
411 /* whenever a rtp event packet is seen by the tap listener */
413 rtp_event_packet(void *ptr _U_, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *rtp_event_info)
415 const struct _rtp_event_info *pi = rtp_event_info;
417 /* do not consider RTP events packets without a setup frame */
418 if (pi->info_setup_frame_num == 0){
422 rtp_evt_frame_num = pinfo->fd->num;
423 rtp_evt = pi->info_rtp_evt;
424 rtp_evt_end = pi->info_end;
429 /****************************************************************************/
430 static gboolean have_rtp_event_tap_listener=FALSE;
433 rtp_event_init_tap(void)
435 GString *error_string;
438 if(have_rtp_event_tap_listener==FALSE)
440 error_string = register_tap_listener("rtpevent", &(the_tapinfo_rtp_struct.rtp_event_dummy),
447 if (error_string != NULL) {
448 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
450 g_string_free(error_string, TRUE);
453 have_rtp_event_tap_listener=TRUE;
457 /****************************************************************************/
460 remove_tap_listener_rtp_event(void)
462 protect_thread_critical_region();
463 remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_event_dummy));
464 unprotect_thread_critical_region();
466 have_rtp_event_tap_listener=FALSE;
469 /****************************************************************************/
470 /* ***************************TAP for RTP **********************************/
471 /****************************************************************************/
473 /****************************************************************************/
474 /* when there is a [re]reading of RTP packet's */
475 static void voip_rtp_reset(void *ptr _U_)
477 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
479 /* free the data items first */
480 list = g_list_first(tapinfo->list);
484 list = g_list_next(list);
486 g_list_free(tapinfo->list);
487 tapinfo->list = NULL;
488 tapinfo->nstreams = 0;
492 /****************************************************************************/
493 /* whenever a RTP packet is seen by the tap listener */
495 RTP_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void const *RTPinfo)
497 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
498 voip_rtp_stream_info_t *tmp_listinfo;
499 voip_rtp_stream_info_t *strinfo = NULL;
501 struct _rtp_conversation_info *p_conv_data = NULL;
503 const struct _rtp_info *pi = RTPinfo;
505 /* do not consider RTP packets without a setup frame */
506 if (pi->info_setup_frame_num == 0){
510 /* add this RTP for future listening using the RTP Player*/
511 #if GTK_MAJOR_VERSION >= 2
512 #ifdef HAVE_LIBPORTAUDIO
513 add_rtp_packet(pi, pinfo);
517 /* check wether we already have a RTP stream with this setup frame and ssrc in the list */
518 list = g_list_first(tapinfo->list);
521 tmp_listinfo=list->data;
522 if ( (tmp_listinfo->setup_frame_number == pi->info_setup_frame_num)
523 && (tmp_listinfo->ssrc == pi->info_sync_src) && (tmp_listinfo->end_stream == FALSE)){
524 /* if the payload type has changed, we mark the stream as finished to create a new one
525 this is to show multiple payload changes in the Graph for example for DTMF RFC2833 */
526 if ( tmp_listinfo->pt != pi->info_payload_type ) {
527 tmp_listinfo->end_stream = TRUE;
529 strinfo = (voip_rtp_stream_info_t*)(list->data);
533 list = g_list_next (list);
536 /* if this is a duplicated RTP Event End, just return */
537 if ((rtp_evt_frame_num == pinfo->fd->num) && !strinfo && (rtp_evt_end == TRUE)) {
541 /* not in the list? then create a new entry */
543 strinfo = g_malloc(sizeof(voip_rtp_stream_info_t));
544 COPY_ADDRESS(&(strinfo->src_addr), &(pinfo->src));
545 strinfo->src_port = pinfo->srcport;
546 COPY_ADDRESS(&(strinfo->dest_addr), &(pinfo->dst));
547 strinfo->dest_port = pinfo->destport;
548 strinfo->ssrc = pi->info_sync_src;
549 strinfo->end_stream = FALSE;
550 strinfo->pt = pi->info_payload_type;
551 strinfo->pt_str = NULL;
552 strinfo->is_srtp = pi->info_is_srtp;
553 /* if it is dynamic payload, let use the conv data to see if it is defined */
554 if ( (strinfo->pt>95) && (strinfo->pt<128) ) {
555 /* Use existing packet info if available */
556 p_conv_data = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name("rtp"));
558 strinfo->pt_str = g_strdup(g_hash_table_lookup(p_conv_data->rtp_dyn_payload, &strinfo->pt));
560 if (!strinfo->pt_str) strinfo->pt_str = g_strdup(val_to_str(strinfo->pt, rtp_payload_type_short_vals, "%u"));
561 strinfo->npackets = 0;
562 strinfo->first_frame_num = pinfo->fd->num;
563 strinfo->start_rel_sec = (guint32) (pinfo->fd->rel_ts.secs);
564 strinfo->start_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
565 strinfo->setup_frame_number = pi->info_setup_frame_num;
566 strinfo->rtp_event = -1;
567 tapinfo->list = g_list_append(tapinfo->list, strinfo);
571 /* Add the info to the existing RTP stream */
573 strinfo->stop_rel_sec = (guint32) (pinfo->fd->rel_ts.secs);
574 strinfo->stop_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
576 /* process RTP Event */
577 if (rtp_evt_frame_num == pinfo->fd->num) {
578 strinfo->rtp_event = rtp_evt;
579 if (rtp_evt_end == TRUE) {
580 strinfo->end_stream = TRUE;
585 the_tapinfo_struct.redraw = TRUE;
590 /****************************************************************************/
591 /* whenever a redraw in the RTP tap listener */
592 static void RTP_packet_draw(void *prs _U_)
594 voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
595 GList* rtp_streams_list;
596 voip_rtp_stream_info_t *rtp_listinfo;
597 GList* voip_calls_graph_list;
599 graph_analysis_item_t *gai;
600 graph_analysis_item_t *new_gai;
604 /* add each rtp stream to the graph */
605 rtp_streams_list = g_list_first(rtp_tapinfo->list);
606 while (rtp_streams_list)
608 rtp_listinfo = rtp_streams_list->data;
610 /* using the setup frame number of the RTP stream, we get the call number that it belongs */
611 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
612 while (voip_calls_graph_list)
614 gai = voip_calls_graph_list->data;
615 conv_num = gai->conv_num;
616 /* if we get the setup frame number, then get the time position to graph the RTP arrow */
617 if (rtp_listinfo->setup_frame_number == gai->frame_num){
618 /* look again from the begining because there are cases where the Setup frame is after the RTP */
619 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
621 while(voip_calls_graph_list){
622 gai = voip_calls_graph_list->data;
623 /* if RTP was already in the Graph, just update the comment information */
624 if (rtp_listinfo->first_frame_num == gai->frame_num){
625 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
626 g_free(gai->comment);
627 gai->comment = g_strdup_printf("%s Num packets:%u Duration:%u.%03us SSRC:0x%X",
628 (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->npackets,
629 duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
633 /* we increment the list here to be able to check if it is the last item in this calls, which means the RTP is after so we have to draw it */
634 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
635 if (!voip_calls_graph_list) item++;
637 /* add the RTP item to the graph if was not there*/
638 if (rtp_listinfo->first_frame_num<gai->frame_num || !voip_calls_graph_list){
639 new_gai = g_malloc(sizeof(graph_analysis_item_t));
640 new_gai->frame_num = rtp_listinfo->first_frame_num;
641 new_gai->time = (double)rtp_listinfo->start_rel_sec + (double)rtp_listinfo->start_rel_usec/1000000;
642 COPY_ADDRESS(&(new_gai->src_addr),&(rtp_listinfo->src_addr));
643 COPY_ADDRESS(&(new_gai->dst_addr),&(rtp_listinfo->dest_addr));
644 new_gai->port_src = rtp_listinfo->src_port;
645 new_gai->port_dst = rtp_listinfo->dest_port;
646 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
647 new_gai->frame_label = g_strdup_printf("%s (%s) %s", (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->pt_str, (rtp_listinfo->rtp_event == -1)?"":val_to_str(rtp_listinfo->rtp_event, rtp_event_type_values, "Unknown RTP Event"));
648 new_gai->comment = g_strdup_printf("%s Num packets:%u Duration:%u.%03us SSRC:0x%X",
649 (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->npackets,
650 duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
651 new_gai->conv_num = conv_num;
652 new_gai->display=FALSE;
653 new_gai->line_style = 2; /* the arrow line will be 2 pixels width */
654 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item);
657 if (voip_calls_graph_list) item++;
661 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
663 rtp_streams_list = g_list_next(rtp_streams_list);
667 static gboolean have_RTP_tap_listener=FALSE;
668 /****************************************************************************/
672 GString *error_string;
674 if(have_RTP_tap_listener==FALSE)
676 /* don't register tap listener, if we have it already */
677 error_string = register_tap_listener("rtp", &(the_tapinfo_rtp_struct.rtp_dummy), NULL,
682 if (error_string != NULL) {
683 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
685 g_string_free(error_string, TRUE);
688 have_RTP_tap_listener=TRUE;
692 /****************************************************************************/
694 remove_tap_listener_rtp(void)
696 protect_thread_critical_region();
697 remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_dummy));
698 unprotect_thread_critical_region();
700 have_RTP_tap_listener=FALSE;
703 /* XXX just copied from gtk/rpc_stat.c */
704 void protect_thread_critical_region(void);
705 void unprotect_thread_critical_region(void);
707 /****************************************************************************/
708 /******************************TAP for T38 **********************************/
709 /****************************************************************************/
711 /****************************************************************************/
712 /* whenever a T38 packet is seen by the tap listener */
714 T38_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *T38info)
716 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
718 voip_calls_info_t *callsinfo = NULL;
719 voip_calls_info_t *tmp_listinfo;
720 GList* voip_calls_graph_list;
722 gchar *frame_label = NULL;
723 gchar *comment = NULL;
724 graph_analysis_item_t *tmp_gai, *gai = NULL;
725 guint16 line_style = 2;
729 const t38_packet_info *pi = T38info;
731 if (pi->setup_frame_number != 0) {
732 /* using the setup frame number of the T38 packet, we get the call number that it belongs */
733 voip_calls_graph_list = g_list_first(tapinfo->graph_analysis->list);
734 while (voip_calls_graph_list)
736 tmp_gai = voip_calls_graph_list->data;
737 if (pi->setup_frame_number == tmp_gai->frame_num){
741 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
743 if (gai) conv_num = (int) gai->conv_num;
746 /* 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
747 * have the associated Voip calls. It probably means the the packet was decoded using the default t38 port, or using "Decode as.."
748 * in this case we create a "voip" call that only have t38 media (no signaling)
749 * OR if we have not found the Setup message in the graph.
751 if ( (pi->setup_frame_number == 0) || (gai == NULL) ){
752 /* check whether we already have a call with these parameters in the list */
753 list = g_list_first(tapinfo->callsinfo_list);
756 tmp_listinfo=list->data;
757 if (tmp_listinfo->protocol == MEDIA_T38){
758 callsinfo = (voip_calls_info_t*)(list->data);
761 list = g_list_next (list);
764 /* not in the list? then create a new entry */
765 if (callsinfo==NULL){
766 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
767 callsinfo->call_active_state = VOIP_ACTIVE;
768 callsinfo->call_state = VOIP_UNKNOWN;
769 callsinfo->from_identity=g_strdup("T38 Media only");
770 callsinfo->to_identity=g_strdup("T38 Media only");
771 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
772 callsinfo->first_frame_num=pinfo->fd->num;
773 callsinfo->selected=FALSE;
774 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
775 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
776 callsinfo->protocol=MEDIA_T38;
777 callsinfo->prot_info=NULL;
778 callsinfo->free_prot_info = NULL;
779 callsinfo->npackets = 0;
780 callsinfo->call_num = tapinfo->ncalls++;
781 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
783 ++(callsinfo->npackets);
784 /* increment the packets counter of all calls */
785 ++(tapinfo->npackets);
787 conv_num = (int) callsinfo->call_num;
790 /* at this point we should have found the call num for this t38 packets belong */
791 if (conv_num == -1) {
795 /* add the item to the graph list */
796 if (pi->type_msg == 0) { /* 0=t30-indicator */
797 frame_label = g_strdup(val_to_str(pi->t30ind_value, t38_T30_indicator_vals, "Ukn (0x%02X)") );
798 comment = g_strdup_printf("t38:t30 Ind:%s",val_to_str(pi->t30ind_value, t38_T30_indicator_vals, "Ukn (0x%02X)") );
800 } else if (pi->type_msg == 1) { /* 1=data */
801 switch(pi->Data_Field_field_type_value){
802 case 0: /* hdlc-data */
804 case 2: /* hdlc-fcs-OK */
805 case 4: /* hdlc-fcs-OK-sig-end */
806 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);
807 comment = g_strdup_printf("t38:%s:HDLC:%s",val_to_str(pi->data_value, t38_T30_data_vals, "Ukn (0x%02X)"), val_to_str(pi->t30_Facsimile_Control & 0x7F, t30_facsimile_control_field_vals, "Ukn (0x%02X)"));
809 case 3: /* hdlc-fcs-BAD */
810 case 5: /* hdlc-fcs-BAD-sig-end */
811 frame_label = g_strdup(pi->Data_Field_field_type_value == 3 ? "fcs-BAD" : "fcs-BAD-sig-end");
812 comment = g_strdup_printf("WARNING: received t38:%s:HDLC:%s", val_to_str(pi->data_value, t38_T30_data_vals, "Ukn (0x%02X)"), pi->Data_Field_field_type_value == 3 ? "fcs-BAD" : "fcs-BAD-sig-end");
814 case 7: /* t4-non-ecm-sig-end */
815 duration = nstime_to_sec(&pinfo->fd->rel_ts) - pi->time_first_t4_data;
816 frame_label = g_strdup_printf("t4-non-ecm-data:%s",val_to_str(pi->data_value, t38_T30_data_vals, "Ukn (0x%02X)") );
817 comment = g_strdup_printf("t38:t4-non-ecm-data:%s Duration: %.2fs %s",val_to_str(pi->data_value, t38_T30_data_vals, "Ukn (0x%02X)"), duration, pi->desc_comment );
818 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);
823 if (frame_label && !(pi->Data_Field_field_type_value == 7 && pi->type_msg == 1)) {
824 add_to_graph(tapinfo, pinfo, frame_label, comment, (guint16)conv_num, &(pinfo->src), &(pinfo->dst), line_style);
830 tapinfo->redraw = TRUE;
832 return 1; /* refresh output */
835 static gboolean have_T38_tap_listener=FALSE;
836 /****************************************************************************/
840 GString *error_string;
842 if(have_T38_tap_listener==FALSE)
844 /* don't register tap listener, if we have it already */
845 error_string = register_tap_listener("t38", &(the_tapinfo_struct.t38_dummy), NULL,
846 voip_calls_dlg_reset,
850 if (error_string != NULL) {
851 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
853 g_string_free(error_string, TRUE);
856 have_T38_tap_listener=TRUE;
860 /****************************************************************************/
862 remove_tap_listener_t38(void)
864 protect_thread_critical_region();
865 remove_tap_listener(&(the_tapinfo_struct.t38_dummy));
866 unprotect_thread_critical_region();
868 have_T38_tap_listener=FALSE;
872 /****************************************************************************/
873 static gchar *sdp_summary = NULL;
874 static guint32 sdp_frame_num = 0;
876 /****************************************************************************/
877 /* ***************************TAP for SIP **********************************/
878 /****************************************************************************/
881 static void free_sip_info(gpointer p) {
882 sip_calls_info_t *si = p;
884 if (si->call_identifier) g_free(si->call_identifier);
888 /****************************************************************************/
889 /* whenever a SIP packet is seen by the tap listener */
891 SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SIPinfo)
893 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
894 /* we just take note of the ISUP data here; when we receive the MTP3 part everything will
895 be compared with existing calls */
897 voip_calls_info_t *tmp_listinfo;
898 voip_calls_info_t *callsinfo = NULL;
899 sip_calls_info_t *tmp_sipinfo = NULL;
901 address tmp_src, tmp_dst;
902 gchar *frame_label = NULL;
903 gchar *comment = NULL;
905 const sip_info_value_t *pi = SIPinfo;
907 /* do not consider packets without call_id */
908 if (pi->tap_call_id ==NULL){
912 /* check whether we already have a call with these parameters in the list */
913 list = g_list_first(tapinfo->callsinfo_list);
916 tmp_listinfo=list->data;
917 if (tmp_listinfo->protocol == VOIP_SIP){
918 tmp_sipinfo = tmp_listinfo->prot_info;
919 if (strcmp(tmp_sipinfo->call_identifier,pi->tap_call_id)==0){
920 callsinfo = (voip_calls_info_t*)(list->data);
924 list = g_list_next (list);
927 /* not in the list? then create a new entry if the message is INVITE -i.e. if this session is a call*/
928 if ((callsinfo==NULL) &&(pi->request_method!=NULL)){
929 if (strcmp(pi->request_method,"INVITE")==0){
930 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
931 callsinfo->call_active_state = VOIP_ACTIVE;
932 callsinfo->call_state = VOIP_CALL_SETUP;
933 callsinfo->from_identity=g_strdup(pi->tap_from_addr);
934 callsinfo->to_identity=g_strdup(pi->tap_to_addr);
935 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
936 callsinfo->first_frame_num=pinfo->fd->num;
937 callsinfo->selected=FALSE;
938 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
939 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
940 callsinfo->protocol=VOIP_SIP;
941 callsinfo->prot_info=g_malloc(sizeof(sip_calls_info_t));
942 callsinfo->free_prot_info = free_sip_info;
943 tmp_sipinfo = callsinfo->prot_info;
944 tmp_sipinfo->call_identifier = g_strdup(pi->tap_call_id);
945 tmp_sipinfo->sip_state = SIP_INVITE_SENT;
946 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
947 callsinfo->npackets = 0;
948 callsinfo->call_num = tapinfo->ncalls++;
949 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
953 if (callsinfo!=NULL){
955 /* let's analyze the call state */
957 COPY_ADDRESS(&(tmp_src), &(pinfo->src));
958 COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
960 if (pi->request_method == NULL){
961 frame_label = g_strdup_printf("%u %s", pi->response_code, pi->reason_phrase );
962 comment = g_strdup_printf("SIP Status");
964 if ((tmp_sipinfo && pi->tap_cseq_number == tmp_sipinfo->invite_cseq)&&(ADDRESSES_EQUAL(&tmp_dst,&(callsinfo->initial_speaker)))){
965 if ((pi->response_code > 199) && (pi->response_code<300) && (tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
966 tmp_sipinfo->sip_state = SIP_200_REC;
968 else if ((pi->response_code>299)&&(tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
969 callsinfo->call_state = VOIP_REJECTED;
970 tapinfo->rejected_calls++;
976 frame_label = g_strdup(pi->request_method);
978 if ((strcmp(pi->request_method,"INVITE")==0)&&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))){
979 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
980 callsinfo->call_state = VOIP_CALL_SETUP;
981 comment = g_strdup_printf("SIP From: %s To:%s", callsinfo->from_identity, callsinfo->to_identity);
983 else if ((strcmp(pi->request_method,"ACK")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
984 &&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))&&(tmp_sipinfo->sip_state==SIP_200_REC)
985 &&(callsinfo->call_state == VOIP_CALL_SETUP)){
986 callsinfo->call_state = VOIP_IN_CALL;
987 comment = g_strdup_printf("SIP Request");
989 else if (strcmp(pi->request_method,"BYE")==0){
990 callsinfo->call_state = VOIP_COMPLETED;
991 tapinfo->completed_calls++;
992 comment = g_strdup_printf("SIP Request");
994 else if ((strcmp(pi->request_method,"CANCEL")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
995 &&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))&&(callsinfo->call_state==VOIP_CALL_SETUP)){
996 callsinfo->call_state = VOIP_CANCELLED;
997 tmp_sipinfo->sip_state = SIP_CANCEL_SENT;
998 comment = g_strdup_printf("SIP Request");
1000 comment = g_strdup_printf("SIP Request");
1004 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
1005 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1006 callsinfo->last_frame_num=pinfo->fd->num;
1007 ++(callsinfo->npackets);
1008 /* increment the packets counter of all calls */
1009 ++(tapinfo->npackets);
1011 /* add to the graph */
1012 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1014 g_free(frame_label);
1015 g_free((void *)tmp_src.data);
1016 g_free((void *)tmp_dst.data);
1018 /* add SDP info if apply */
1019 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
1020 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
1021 g_free(sdp_summary);
1026 tapinfo->redraw = TRUE;
1028 return 1; /* refresh output */
1032 /****************************************************************************/
1033 voip_calls_tapinfo_t* voip_calls_get_info(void)
1035 return &the_tapinfo_struct;
1039 /****************************************************************************/
1041 /****************************************************************************/
1042 static gboolean have_SIP_tap_listener=FALSE;
1043 /****************************************************************************/
1045 sip_calls_init_tap(void)
1047 GString *error_string;
1049 if(have_SIP_tap_listener==FALSE)
1051 /* don't register tap listener, if we have it already */
1052 error_string = register_tap_listener("sip", &(the_tapinfo_struct.sip_dummy), NULL,
1053 voip_calls_dlg_reset,
1057 if (error_string != NULL) {
1058 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1060 g_string_free(error_string, TRUE);
1063 have_SIP_tap_listener=TRUE;
1067 /****************************************************************************/
1069 remove_tap_listener_sip_calls(void)
1071 protect_thread_critical_region();
1072 remove_tap_listener(&(the_tapinfo_struct.sip_dummy));
1073 unprotect_thread_critical_region();
1075 have_SIP_tap_listener=FALSE;
1078 /****************************************************************************/
1079 /* ***************************TAP for ISUP **********************************/
1080 /****************************************************************************/
1082 static guint32 mtp3_opc, mtp3_dpc;
1083 static guint8 mtp3_ni;
1084 static guint32 mtp3_frame_num;
1087 /****************************************************************************/
1088 /* whenever a isup_ packet is seen by the tap listener */
1090 isup_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *isup_info _U_)
1092 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1093 voip_calls_info_t *tmp_listinfo;
1094 voip_calls_info_t *callsinfo = NULL;
1095 isup_calls_info_t *tmp_isupinfo;
1096 gboolean found = FALSE;
1097 gboolean forward = FALSE;
1098 gboolean right_pair;
1100 gchar *frame_label = NULL;
1101 gchar *comment = NULL;
1104 /*voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct; unused */
1105 const isup_tap_rec_t *pi = isup_info;
1107 /* check if the lower layer is MTP matching the frame number */
1108 if (mtp3_frame_num != pinfo->fd->num) return 0;
1110 /* check whether we already have a call with these parameters in the list */
1111 list = g_list_first(tapinfo->callsinfo_list);
1115 tmp_listinfo=list->data;
1116 if ((tmp_listinfo->protocol == VOIP_ISUP)&&(tmp_listinfo->call_active_state==VOIP_ACTIVE)){
1117 tmp_isupinfo = tmp_listinfo->prot_info;
1118 if ((tmp_isupinfo->cic == pinfo->circuit_id)&&(tmp_isupinfo->ni == mtp3_ni)) {
1119 if ((tmp_isupinfo->opc == mtp3_opc)&&(tmp_isupinfo->dpc == mtp3_dpc)){
1121 } else if ((tmp_isupinfo->dpc == mtp3_opc)&&(tmp_isupinfo->opc == mtp3_dpc)){
1128 /* if there is an IAM for a call that is not in setup state, that means the previous call in the same
1129 cic is no longer active */
1130 if (tmp_listinfo->call_state == VOIP_CALL_SETUP){
1132 } else if (pi->message_type != 1){
1135 tmp_listinfo->call_active_state=VOIP_INACTIVE;
1140 callsinfo = (voip_calls_info_t*)(list->data);
1145 list = g_list_next (list);
1148 /* not in the list? then create a new entry if the message is IAM
1149 -i.e. if this session is a call*/
1152 if ((callsinfo==NULL) &&(pi->message_type==1)){
1153 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
1154 callsinfo->call_active_state = VOIP_ACTIVE;
1155 callsinfo->call_state = VOIP_UNKNOWN;
1156 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
1157 callsinfo->selected=FALSE;
1158 callsinfo->first_frame_num=pinfo->fd->num;
1159 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
1160 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1161 callsinfo->protocol=VOIP_ISUP;
1162 if (pi->calling_number!=NULL){
1163 callsinfo->from_identity=g_strdup(pi->calling_number);
1165 if (pi->called_number!=NULL){
1166 callsinfo->to_identity=g_strdup(pi->called_number);
1168 callsinfo->prot_info=g_malloc(sizeof(isup_calls_info_t));
1169 callsinfo->free_prot_info = g_free;
1170 tmp_isupinfo=callsinfo->prot_info;
1171 tmp_isupinfo->opc = mtp3_opc;
1172 tmp_isupinfo->dpc = mtp3_dpc;
1173 tmp_isupinfo->ni = mtp3_ni;
1174 tmp_isupinfo->cic = pinfo->circuit_id;
1175 callsinfo->npackets = 0;
1176 callsinfo->call_num = tapinfo->ncalls++;
1177 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
1181 if (callsinfo!=NULL){
1182 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
1183 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1184 callsinfo->last_frame_num=pinfo->fd->num;
1185 ++(callsinfo->npackets);
1187 /* Let's analyze the call state */
1190 for (i=0;(isup_message_type_value[i].strptr!=NULL)&& (isup_message_type_value[i].value!=pi->message_type);i++);
1192 if (isup_message_type_value[i].value==pi->message_type){
1193 frame_label = g_strdup(isup_message_type_value_acro[i].strptr);
1196 frame_label = g_strdup_printf("Unknown");
1199 if (callsinfo->npackets == 1){ /* this is the first packet, that must be an IAM */
1201 if ((pi->calling_number!=NULL)&&(pi->called_number !=NULL)){
1202 comment = g_strdup_printf("Call from %s to %s",
1203 pi->calling_number, pi->called_number);
1205 } else if (callsinfo->npackets == 2){ /* in the second packet we show the SPs */
1207 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
1209 mtp3_ni, mtp3_dpc, pinfo->circuit_id);
1211 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
1213 mtp3_ni, mtp3_opc, pinfo->circuit_id);
1218 switch(pi->message_type){
1220 callsinfo->call_state=VOIP_CALL_SETUP;
1222 case 7: /* CONNECT */
1223 case 9: /* ANSWER */
1224 callsinfo->call_state=VOIP_IN_CALL;
1226 case 12: /* RELEASE */
1227 if (callsinfo->call_state==VOIP_CALL_SETUP){
1229 callsinfo->call_state=VOIP_CANCELLED;
1232 callsinfo->call_state=VOIP_REJECTED;
1233 tapinfo->rejected_calls++;
1236 else if (callsinfo->call_state == VOIP_IN_CALL){
1237 callsinfo->call_state = VOIP_COMPLETED;
1238 tapinfo->completed_calls++;
1240 for (i=0;(q931_cause_code_vals[i].strptr!=NULL)&& (q931_cause_code_vals[i].value!=pi->cause_value);i++);
1241 if (q931_cause_code_vals[i].value==pi->cause_value){
1242 comment = g_strdup_printf("Cause %i - %s",pi->cause_value, q931_cause_code_vals[i].strptr);
1245 comment = g_strdup_printf("Cause %i",pi->cause_value);
1250 /* increment the packets counter of all calls */
1251 ++(tapinfo->npackets);
1253 /* add to the graph */
1254 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1256 g_free(frame_label);
1259 tapinfo->redraw = TRUE;
1261 return 1; /* refresh output */
1264 /****************************************************************************/
1266 static gboolean have_isup_tap_listener=FALSE;
1269 isup_calls_init_tap(void)
1271 GString *error_string;
1274 if(have_isup_tap_listener==FALSE)
1276 error_string = register_tap_listener("isup", &(the_tapinfo_struct.isup_dummy),
1278 voip_calls_dlg_reset,
1283 if (error_string != NULL) {
1284 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1286 g_string_free(error_string, TRUE);
1289 have_isup_tap_listener=TRUE;
1293 /****************************************************************************/
1296 remove_tap_listener_isup_calls(void)
1298 protect_thread_critical_region();
1299 remove_tap_listener(&(the_tapinfo_struct.isup_dummy));
1300 unprotect_thread_critical_region();
1302 have_isup_tap_listener=FALSE;
1306 /****************************************************************************/
1307 /* ***************************TAP for MTP3 **********************************/
1308 /****************************************************************************/
1311 /****************************************************************************/
1312 /* whenever a mtp3_ packet is seen by the tap listener */
1314 mtp3_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *mtp3_info _U_)
1316 const mtp3_tap_rec_t *pi = mtp3_info;
1318 /* keep the data in memory to use when the ISUP information arrives */
1320 mtp3_opc = pi->addr_opc.pc;
1321 mtp3_dpc = pi->addr_dpc.pc;
1322 mtp3_ni = pi->addr_opc.ni;
1323 mtp3_frame_num = pinfo->fd->num;
1328 /****************************************************************************/
1330 static gboolean have_mtp3_tap_listener=FALSE;
1331 static gboolean have_m3ua_tap_listener=FALSE;
1334 mtp3_calls_init_tap(void)
1336 GString *error_string;
1339 if(have_mtp3_tap_listener==FALSE)
1341 error_string = register_tap_listener("mtp3", &(the_tapinfo_struct.mtp3_dummy),
1343 voip_calls_dlg_reset,
1348 if (error_string != NULL) {
1349 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1351 g_string_free(error_string, TRUE);
1354 have_mtp3_tap_listener=TRUE;
1357 if(have_m3ua_tap_listener==FALSE)
1359 error_string = register_tap_listener("m3ua", &(the_tapinfo_struct.mtp3_dummy),
1361 voip_calls_dlg_reset,
1366 if (error_string != NULL) {
1367 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1369 g_string_free(error_string, TRUE);
1372 have_m3ua_tap_listener=TRUE;
1377 /****************************************************************************/
1380 remove_tap_listener_mtp3_calls(void)
1382 protect_thread_critical_region();
1383 remove_tap_listener(&(the_tapinfo_struct.mtp3_dummy));
1384 remove_tap_listener(&(the_tapinfo_struct.m3ua_dummy));
1385 unprotect_thread_critical_region();
1387 have_mtp3_tap_listener=FALSE;
1388 have_m3ua_tap_listener=FALSE;
1391 /****************************************************************************/
1392 /* ***************************TAP for Q931 **********************************/
1393 /****************************************************************************/
1394 void h245_add_to_graph(guint32 new_frame_num);
1395 static const e_guid_t guid_allzero = {0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };
1396 /* defines specific H323 data */
1398 static gchar *q931_calling_number;
1399 static gchar *q931_called_number;
1400 static guint8 q931_cause_value;
1401 static gint32 q931_crv;
1402 static guint32 q931_frame_num;
1404 static guint32 h225_frame_num = 0;
1405 static guint16 h225_call_num = 0;
1406 static h225_cs_type h225_cstype = H225_OTHER;
1407 static gboolean h225_is_faststart;
1409 static guint32 actrace_frame_num = 0;
1410 static gint32 actrace_trunk = 0;
1411 static gint32 actrace_direction = 0;
1414 /****************************************************************************/
1415 /* whenever a q931_ packet is seen by the tap listener */
1417 q931_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *q931_info _U_)
1420 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1421 h323_calls_info_t *tmp_h323info,*tmp2_h323info;
1422 actrace_isdn_calls_info_t *tmp_actrace_isdn_info;
1423 voip_calls_info_t *tmp_listinfo;
1424 voip_calls_info_t *callsinfo = NULL;
1425 h245_address_t *h245_add = NULL;
1428 const q931_packet_info *pi = q931_info;
1430 /* free previously allocated q931_calling/ed_number */
1431 g_free(q931_calling_number);
1432 g_free(q931_called_number);
1434 if (pi->calling_number!=NULL)
1435 q931_calling_number = g_strdup(pi->calling_number);
1437 q931_calling_number = g_strdup("");
1439 if (pi->called_number!=NULL)
1440 q931_called_number = g_strdup(pi->called_number);
1442 q931_called_number = g_strdup("");
1443 q931_cause_value = pi->cause_value;
1444 q931_frame_num = pinfo->fd->num;
1448 /* add staff to H323 calls */
1449 if (h225_frame_num == q931_frame_num) {
1450 tmp_h323info = NULL;
1451 list = g_list_first(tapinfo->callsinfo_list);
1454 tmp_listinfo=list->data;
1455 if ( (tmp_listinfo->protocol == VOIP_H323) && (tmp_listinfo->call_num == h225_call_num) ){
1456 tmp_h323info = tmp_listinfo->prot_info;
1457 callsinfo = (voip_calls_info_t*)(list->data);
1459 /* Add the CRV to the h323 call */
1460 if (tmp_h323info->q931_crv == -1) {
1461 tmp_h323info->q931_crv = q931_crv;
1462 } else if (tmp_h323info->q931_crv != q931_crv) {
1463 tmp_h323info->q931_crv2 = q931_crv;
1467 list = g_list_next (list);
1470 if (callsinfo != NULL) {
1472 if (h225_cstype == H225_SETUP) {
1473 /* set te calling and called number from the Q931 packet */
1474 if (q931_calling_number != NULL){
1475 g_free(callsinfo->from_identity);
1476 callsinfo->from_identity=g_strdup(q931_calling_number);
1478 if (q931_called_number != NULL){
1479 g_free(callsinfo->to_identity);
1480 callsinfo->to_identity=g_strdup(q931_called_number);
1483 /* check if there is an LRQ/LCF that match this Setup */
1484 /* TODO: we are just checking the DialedNumer in LRQ/LCF agains the Setup
1485 we should also check if the h225 signaling IP and port match the destination
1486 Setup ip and port */
1487 list = g_list_first(tapinfo->callsinfo_list);
1490 tmp_listinfo=list->data;
1491 if (tmp_listinfo->protocol == VOIP_H323){
1492 tmp2_h323info = tmp_listinfo->prot_info;
1494 /* check if the called number match a LRQ/LCF */
1495 if ( (strcmp(callsinfo->to_identity, tmp_listinfo->to_identity)==0)
1496 && (memcmp(&tmp2_h323info->guid, &guid_allzero, GUID_LEN) == 0) ){
1497 /* change the call graph to the LRQ/LCF to belong to this call */
1498 callsinfo->npackets += change_call_num_graph(tapinfo, tmp_listinfo->call_num, callsinfo->call_num);
1500 /* remove this LRQ/LCF call entry because we have found the Setup that match them */
1501 g_free(tmp_listinfo->from_identity);
1502 g_free(tmp_listinfo->to_identity);
1503 g_free(tmp2_h323info->guid);
1505 list2 = g_list_first(tmp2_h323info->h245_list);
1508 h245_add=list2->data;
1509 g_free((void *)h245_add->h245_address.data);
1510 g_free(list2->data);
1511 list2 = g_list_next(list2);
1513 g_list_free(tmp_h323info->h245_list);
1514 tmp_h323info->h245_list = NULL;
1515 g_free(tmp_listinfo->prot_info);
1516 tapinfo->callsinfo_list = g_list_remove(tapinfo->callsinfo_list, tmp_listinfo);
1520 list = g_list_next (list);
1523 comment = g_strdup_printf("H225 From: %s To:%s TunnH245:%s FS:%s", callsinfo->from_identity, callsinfo->to_identity, (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1524 (h225_is_faststart==TRUE?"on":"off"));
1525 } else if (h225_cstype == H225_RELEASE_COMPLET) {
1526 /* get the Q931 Release cause code */
1527 if (q931_cause_value != 0xFF){
1528 comment = g_strdup_printf("H225 Q931 Rel Cause (%i):%s", q931_cause_value, val_to_str(q931_cause_value, q931_cause_code_vals, "<unknown>"));
1529 } else { /* Cause not set */
1530 comment = g_strdup("H225 No Q931 Rel Cause");
1533 /* change the graph comment for this new one */
1534 if (comment != NULL) {
1535 change_frame_graph(tapinfo, h225_frame_num, NULL, comment);
1539 /* we reset the h225_frame_num to 0 because there could be empty h225 in the same frame
1540 as non empty h225 (e.g connect), so we don't have to be here twice */
1543 /* add staff to H245 */
1544 } else if (h245_labels.frame_num == q931_frame_num) {
1545 /* there are empty H225 frames that don't have guid (guaid=0) but they have h245 info,
1546 so the only way to match those frames is with the Q931 CRV number */
1547 list = g_list_first(tapinfo->callsinfo_list);
1550 tmp_listinfo=list->data;
1551 if (tmp_listinfo->protocol == VOIP_H323){
1552 tmp_h323info = tmp_listinfo->prot_info;
1553 if ( ((tmp_h323info->q931_crv == q931_crv) || (tmp_h323info->q931_crv2 == q931_crv)) && (q931_crv!=-1)){
1555 comment = g_strdup("");
1557 /* if the frame number exists in graph, append to it*/
1558 if (!append_to_frame_graph(tapinfo, q931_frame_num, "", comment)) {
1559 /* if not exist, add to the graph */
1560 add_to_graph(tapinfo, pinfo, "", comment, tmp_listinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1561 ++(tmp_listinfo->npackets);
1562 /* increment the packets counter of all calls */
1563 ++(tapinfo->npackets);
1566 /* Add the H245 info if exists to the Graph */
1567 h245_add_to_graph(pinfo->fd->num);
1572 list = g_list_next (list);
1575 /* add staff to ACTRACE */
1576 } else if (actrace_frame_num == q931_frame_num) {
1578 gchar *comment = NULL;
1581 list = g_list_first(tapinfo->callsinfo_list);
1584 tmp_listinfo=list->data;
1585 if ( tmp_listinfo->protocol == VOIP_AC_ISDN ){
1586 tmp_actrace_isdn_info = tmp_listinfo->prot_info;
1587 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
1588 if ( (tmp_actrace_isdn_info->crv == q931_crv) && (tmp_actrace_isdn_info->trunk == actrace_trunk) ) {
1589 callsinfo = (voip_calls_info_t*)(list->data);
1593 list = g_list_next (list);
1596 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, g_strdup("PSTN"));
1598 /* if it is a new call, add it to the list */
1600 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
1601 callsinfo->call_active_state = VOIP_ACTIVE;
1602 callsinfo->call_state = VOIP_CALL_SETUP;
1603 callsinfo->from_identity=g_strdup(q931_calling_number);
1604 callsinfo->to_identity=g_strdup(q931_called_number);
1605 COPY_ADDRESS(&(callsinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
1606 callsinfo->first_frame_num=pinfo->fd->num;
1607 callsinfo->selected=FALSE;
1608 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
1609 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1610 callsinfo->protocol=VOIP_AC_ISDN;
1611 callsinfo->prot_info=g_malloc(sizeof(actrace_isdn_calls_info_t));
1612 callsinfo->free_prot_info = g_free;
1613 tmp_actrace_isdn_info=callsinfo->prot_info;
1614 tmp_actrace_isdn_info->crv=q931_crv;
1615 tmp_actrace_isdn_info->trunk=actrace_trunk;
1616 callsinfo->npackets = 0;
1617 callsinfo->call_num = tapinfo->ncalls++;
1618 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
1621 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
1622 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1623 callsinfo->last_frame_num=pinfo->fd->num;
1624 ++(callsinfo->npackets);
1625 /* increment the packets counter of all calls */
1626 ++(tapinfo->npackets);
1628 switch(pi->message_type){
1630 comment = g_strdup_printf("AC_ISDN trunk:%u Calling: %s Called:%s", actrace_trunk, q931_calling_number, q931_called_number);
1631 callsinfo->call_state=VOIP_CALL_SETUP;
1634 callsinfo->call_state=VOIP_IN_CALL;
1636 case Q931_RELEASE_COMPLETE:
1638 case Q931_DISCONNECT:
1639 if (callsinfo->call_state==VOIP_CALL_SETUP){
1640 if (ADDRESSES_EQUAL(&(callsinfo->initial_speaker), actrace_direction?&pstn_add:&(pinfo->src) )){ /* forward direction */
1641 callsinfo->call_state=VOIP_CANCELLED;
1644 callsinfo->call_state=VOIP_REJECTED;
1645 tapinfo->rejected_calls++;
1647 } else if ( (callsinfo->call_state!=VOIP_CANCELLED) && (callsinfo->call_state!=VOIP_REJECTED) ){
1648 callsinfo->call_state=VOIP_COMPLETED;
1649 tapinfo->completed_calls++;
1651 if (q931_cause_value != 0xFF){
1652 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>"));
1653 } else { /* Cause not set */
1654 comment = g_strdup("AC_ISDN No Q931 Rel Cause");
1660 comment = g_strdup_printf("AC_ISDN trunk:%u", actrace_trunk );
1662 add_to_graph(tapinfo, pinfo, val_to_str(pi->message_type, q931_message_type_vals, "<unknown>") , comment, callsinfo->call_num,
1663 actrace_direction?&pstn_add:&(pinfo->src),
1664 actrace_direction?&(pinfo->src):&pstn_add,
1668 g_free((char *)pstn_add.data);
1671 tapinfo->redraw = TRUE;
1673 return 1; /* refresh output */
1676 /****************************************************************************/
1677 static gboolean have_q931_tap_listener=FALSE;
1680 q931_calls_init_tap(void)
1682 GString *error_string;
1685 if(have_q931_tap_listener==FALSE)
1687 error_string = register_tap_listener("q931", &(the_tapinfo_struct.q931_dummy),
1689 voip_calls_dlg_reset,
1694 if (error_string != NULL) {
1695 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1697 g_string_free(error_string, TRUE);
1700 have_q931_tap_listener=TRUE;
1704 /****************************************************************************/
1707 remove_tap_listener_q931_calls(void)
1709 protect_thread_critical_region();
1710 remove_tap_listener(&(the_tapinfo_struct.q931_dummy));
1711 unprotect_thread_critical_region();
1713 have_q931_tap_listener=FALSE;
1716 /****************************************************************************/
1717 /****************************TAP for H323 ***********************************/
1718 /****************************************************************************/
1720 static void add_h245_Address(h323_calls_info_t *h323info, h245_address_t *h245_address)
1722 h323info->h245_list = g_list_append(h323info->h245_list, h245_address);
1726 static void free_h225_info(gpointer p) {
1727 h323_calls_info_t *tmp_h323info = p;
1729 if (tmp_h323info->guid) g_free(tmp_h323info->guid);
1731 if (tmp_h323info->h245_list) {
1732 GList* list2 = g_list_first(tmp_h323info->h245_list);
1735 h245_address_t *h245_add=list2->data;
1736 g_free((void *)h245_add->h245_address.data);
1737 g_free(list2->data);
1738 list2 = g_list_next(list2);
1741 g_list_free(tmp_h323info->h245_list);
1747 /****************************************************************************/
1748 /* whenever a H225 packet is seen by the tap listener */
1750 H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H225info)
1752 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1753 voip_calls_info_t *tmp_listinfo;
1754 voip_calls_info_t *callsinfo = NULL;
1755 h323_calls_info_t *tmp_h323info = NULL;
1759 address tmp_src, tmp_dst;
1760 h245_address_t *h245_add = NULL;
1762 const h225_packet_info *pi = H225info;
1764 /* if not guid and RAS and not LRQ, LCF or LRJ return because did not belong to a call */
1765 /* OR, if not guid and is H225 return because doesn't belong to a call */
1766 if ((memcmp(&pi->guid, &guid_allzero, GUID_LEN) == 0))
1767 if ( ((pi->msg_type == H225_RAS) && ((pi->msg_tag < 18) || (pi->msg_tag > 20))) || (pi->msg_type != H225_RAS) )
1770 /* if it is RAS LCF or LRJ*/
1771 if ( (pi->msg_type == H225_RAS) && ((pi->msg_tag == 19) || (pi->msg_tag == 20))) {
1772 /* if the LCF/LRJ doesn't match to a LRQ, just return */
1773 if (!pi->request_available) return 0;
1775 /* check whether we already have a call with this request SeqNum */
1776 list = g_list_first(tapinfo->callsinfo_list);
1779 tmp_listinfo=list->data;
1780 g_assert(tmp_listinfo != NULL);
1781 if (tmp_listinfo->protocol == VOIP_H323){
1782 tmp_h323info = tmp_listinfo->prot_info;
1783 if (tmp_h323info->requestSeqNum == pi->requestSeqNum) {
1784 callsinfo = (voip_calls_info_t*)(list->data);
1788 list = g_list_next (list);
1791 /* check whether we already have a call with this guid in the list */
1792 list = g_list_first(tapinfo->callsinfo_list);
1795 tmp_listinfo=list->data;
1796 if (tmp_listinfo->protocol == VOIP_H323){
1797 tmp_h323info = tmp_listinfo->prot_info;
1798 g_assert(tmp_h323info != NULL);
1799 if ( (memcmp(tmp_h323info->guid, &guid_allzero, GUID_LEN) != 0) && (memcmp(tmp_h323info->guid, &pi->guid,GUID_LEN)==0) ){
1800 callsinfo = (voip_calls_info_t*)(list->data);
1804 list = g_list_next (list);
1808 h225_cstype = pi->cs_type;
1809 h225_is_faststart = pi->is_faststart;
1811 /* not in the list? then create a new entry */
1812 if ((callsinfo==NULL)){
1813 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
1814 callsinfo->call_active_state = VOIP_ACTIVE;
1815 callsinfo->call_state = VOIP_UNKNOWN;
1816 callsinfo->from_identity=g_strdup("");
1817 callsinfo->to_identity=g_strdup("");
1818 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
1819 callsinfo->selected=FALSE;
1820 callsinfo->first_frame_num=pinfo->fd->num;
1821 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
1822 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1823 callsinfo->protocol=VOIP_H323;
1824 callsinfo->prot_info=g_malloc(sizeof(h323_calls_info_t));
1825 callsinfo->free_prot_info = free_h225_info;
1827 tmp_h323info = callsinfo->prot_info;
1828 g_assert(tmp_h323info != NULL);
1829 tmp_h323info->guid = g_memdup(&pi->guid, sizeof pi->guid);
1830 tmp_h323info->h225SetupAddr.type = AT_NONE;
1831 tmp_h323info->h225SetupAddr.len = 0;
1832 tmp_h323info->h245_list = NULL;
1833 tmp_h323info->is_faststart_Setup = FALSE;
1834 tmp_h323info->is_faststart_Proc = FALSE;
1835 tmp_h323info->is_h245Tunneling = FALSE;
1836 tmp_h323info->is_h245 = FALSE;
1837 tmp_h323info->q931_crv = -1;
1838 tmp_h323info->q931_crv2 = -1;
1839 tmp_h323info->requestSeqNum = 0;
1840 callsinfo->call_num = tapinfo->ncalls++;
1841 callsinfo->npackets = 0;
1843 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
1846 if (callsinfo!=NULL){
1848 h225_frame_num = pinfo->fd->num;
1849 h225_call_num = callsinfo->call_num;
1851 /* let's analyze the call state */
1853 COPY_ADDRESS(&(tmp_src),&(pinfo->src));
1854 COPY_ADDRESS(&(tmp_dst),&(pinfo->dst));
1856 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
1857 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1858 callsinfo->last_frame_num=pinfo->fd->num;
1859 ++(callsinfo->npackets);
1860 /* increment the packets counter of all calls */
1861 ++(tapinfo->npackets);
1864 /* XXX: it is supposed to be initialized isn't it? */
1865 g_assert(tmp_h323info != NULL);
1867 /* change the status */
1868 if (pi->msg_type == H225_CS){
1870 /* this is still IPv4 only, because the dissector is */
1871 if (pi->is_h245 == TRUE){
1872 h245_add = g_malloc(sizeof (h245_address_t));
1873 h245_add->h245_address.type=AT_IPv4;
1874 h245_add->h245_address.len=4;
1875 h245_add->h245_address.data = g_malloc(sizeof(pi->h245_address));
1876 memcpy((void *)(h245_add->h245_address.data), &(pi->h245_address), 4);
1877 h245_add->h245_port = pi->h245_port;
1878 add_h245_Address(tmp_h323info, h245_add);
1881 if (pi->cs_type != H225_RELEASE_COMPLET) tmp_h323info->is_h245Tunneling = pi->is_h245Tunneling;
1883 frame_label = g_strdup(pi->frame_label);
1885 switch(pi->cs_type){
1887 tmp_h323info->is_faststart_Setup = pi->is_faststart;
1889 /* Set the Setup address if it was not set */
1890 if (tmp_h323info->h225SetupAddr.type == AT_NONE)
1891 COPY_ADDRESS(&(tmp_h323info->h225SetupAddr), &(pinfo->src));
1892 callsinfo->call_state=VOIP_CALL_SETUP;
1893 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1894 (pi->is_faststart==TRUE?"on":"off"));
1897 callsinfo->call_state=VOIP_IN_CALL;
1898 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1899 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1900 (pi->is_faststart==TRUE?"on":"off"));
1902 case H225_RELEASE_COMPLET:
1903 COPY_ADDRESS(&tmp_src,&(pinfo->src));
1904 if (callsinfo->call_state==VOIP_CALL_SETUP){
1905 if (ADDRESSES_EQUAL(&(tmp_h323info->h225SetupAddr),&tmp_src)){ /* forward direction */
1906 callsinfo->call_state=VOIP_CANCELLED;
1909 callsinfo->call_state=VOIP_REJECTED;
1910 tapinfo->rejected_calls++;
1913 callsinfo->call_state=VOIP_COMPLETED;
1914 tapinfo->completed_calls++;
1916 comment = g_strdup("H225 No Q931 Rel Cause");
1920 case H225_CALL_PROCEDING:
1921 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1922 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1923 (pi->is_faststart==TRUE?"on":"off"));
1926 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1927 (pi->is_faststart==TRUE?"on":"off"));
1931 else if (pi->msg_type == H225_RAS){
1932 switch(pi->msg_tag){
1934 if (!pi->is_duplicate){
1935 g_free(callsinfo->to_identity);
1936 callsinfo->to_identity=g_strdup(pi->dialedDigits);
1937 tmp_h323info->requestSeqNum = pi->requestSeqNum;
1940 if (strlen(pi->dialedDigits))
1941 comment = g_strdup_printf("H225 RAS dialedDigits: %s", pi->dialedDigits);
1943 comment = g_strdup("H225 RAS");
1946 comment = g_strdup("H225 RAS");
1948 frame_label = g_strdup_printf("%s", val_to_str(pi->msg_tag, h225_RasMessage_vals, "<unknown>"));
1950 frame_label = g_strdup("H225: Unknown");
1951 comment = g_strdup("");
1954 /* add to graph analysis */
1956 /* if the frame number exists in graph, append to it*/
1957 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, comment)) {
1958 /* if not exist, add to the graph */
1959 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1960 g_free((void *)tmp_src.data);
1961 g_free((void *)tmp_dst.data);
1964 /* Add the H245 info if exists to the Graph */
1965 h245_add_to_graph(pinfo->fd->num);
1967 g_free(frame_label);
1972 tapinfo->redraw = TRUE;
1974 return 1; /* refresh output */
1978 /****************************************************************************/
1980 /****************************************************************************/
1981 static gboolean have_H225_tap_listener=FALSE;
1982 /****************************************************************************/
1984 h225_calls_init_tap(void)
1986 GString *error_string;
1988 if(have_H225_tap_listener==FALSE)
1990 /* don't register tap listener, if we have it already */
1991 error_string = register_tap_listener("h225", &(the_tapinfo_struct.h225_dummy), NULL,
1992 voip_calls_dlg_reset,
1997 if (error_string != NULL) {
1998 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2000 g_string_free(error_string, TRUE);
2003 have_H225_tap_listener=TRUE;
2007 /****************************************************************************/
2009 remove_tap_listener_h225_calls(void)
2011 protect_thread_critical_region();
2012 remove_tap_listener(&(the_tapinfo_struct.h225_dummy));
2013 unprotect_thread_critical_region();
2015 have_H225_tap_listener=FALSE;
2018 /* Add the h245 label info to the graph */
2019 void h245_add_to_graph(guint32 new_frame_num)
2023 if (new_frame_num != h245_labels.frame_num) return;
2025 for (n=0; n<h245_labels.labels_count; n++) {
2026 append_to_frame_graph(&the_tapinfo_struct, new_frame_num, h245_labels.labels[n].frame_label, h245_labels.labels[n].comment);
2027 g_free(h245_labels.labels[n].frame_label);
2028 h245_labels.labels[n].frame_label = NULL;
2029 g_free(h245_labels.labels[n].comment);
2030 h245_labels.labels[n].comment = NULL;
2032 h245_labels.frame_num = 0;
2033 h245_labels.labels_count = 0;
2036 /* free the h245_labels if the frame number is different */
2037 static void h245_free_labels(guint32 new_frame_num)
2041 if (new_frame_num == h245_labels.frame_num) return;
2043 for (n=0; n<h245_labels.labels_count; n++) {
2044 g_free(h245_labels.labels[n].frame_label);
2045 h245_labels.labels[n].frame_label = NULL;
2046 g_free(h245_labels.labels[n].comment);
2047 h245_labels.labels[n].comment = NULL;
2049 h245_labels.frame_num = 0;
2050 h245_labels.labels_count = 0;
2053 /* add the frame_label and comment to h245_labels and free the actual one if it is different frame num */
2054 static void h245_add_label(guint32 new_frame_num, const gchar *frame_label, const gchar *comment)
2056 h245_free_labels(new_frame_num);
2058 h245_labels.frame_num = new_frame_num;
2059 h245_labels.labels[h245_labels.labels_count].frame_label = g_strdup(frame_label);
2060 h245_labels.labels[h245_labels.labels_count].comment = g_strdup(comment);
2062 if (h245_labels.labels_count < (H245_MAX-1))
2063 h245_labels.labels_count++;
2067 /****************************************************************************/
2068 /* whenever a H245dg packet is seen by the tap listener (when H245 tunneling is ON) */
2070 H245dgcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H245info)
2072 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2073 voip_calls_info_t *tmp_listinfo;
2074 voip_calls_info_t *callsinfo = NULL;
2075 h323_calls_info_t *tmp_h323info;
2080 address tmp_src, tmp_dst;
2081 h245_address_t *h245_add = NULL;
2083 const h245_packet_info *pi = H245info;
2085 /* check if Tunneling is OFF and we have a call with this H245 add */
2086 list = g_list_first(tapinfo->callsinfo_list);
2089 tmp_listinfo=list->data;
2090 if (tmp_listinfo->protocol == VOIP_H323){
2091 tmp_h323info = tmp_listinfo->prot_info;
2093 COPY_ADDRESS(&(tmp_src), &(pinfo->src));
2094 COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
2095 list2 = g_list_first(tmp_h323info->h245_list);
2098 h245_add=list2->data;
2099 if ( (ADDRESSES_EQUAL(&(h245_add->h245_address),&tmp_src) && (h245_add->h245_port == pinfo->srcport))
2100 || (ADDRESSES_EQUAL(&(h245_add->h245_address),&tmp_dst) && (h245_add->h245_port == pinfo->destport)) ){
2101 callsinfo = (voip_calls_info_t*)(list->data);
2103 ++(callsinfo->npackets);
2104 /* increment the packets counter of all calls */
2105 ++(tapinfo->npackets);
2109 list2 = g_list_next(list2);
2111 if (callsinfo!=NULL) break;
2112 g_free((void *)tmp_src.data);
2113 g_free((void *)tmp_dst.data);
2115 list = g_list_next(list);
2118 /* Tunnel is OFF, and we matched the h245 add so we add it to graph */
2119 if (callsinfo!=NULL){
2120 ++(callsinfo->npackets);
2121 /* increment the packets counter of all calls */
2122 ++(tapinfo->npackets);
2123 frame_label = g_strdup(pi->frame_label);
2124 comment = g_strdup(pi->comment);
2125 /* if the frame number exists in graph, append to it*/
2126 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, frame_label, comment)) {
2127 /* if not exist, add to the graph */
2128 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2130 g_free(frame_label);
2133 /* Tunnel is ON, so we save the label info to use it into h225 or q931 tap. OR may be
2134 tunnel OFF but we did not matched the h245 add, in this case nobady will set this label
2135 since the frame_num will not match */
2137 h245_add_label(pinfo->fd->num, (gchar *) pi->frame_label, (gchar *) pi->comment);
2140 tapinfo->redraw = TRUE;
2142 return 1; /* refresh output */
2146 /****************************************************************************/
2148 /****************************************************************************/
2149 static gboolean have_H245dg_tap_listener=FALSE;
2150 /****************************************************************************/
2152 h245dg_calls_init_tap(void)
2154 GString *error_string;
2156 if(have_H245dg_tap_listener==FALSE)
2158 /* don't register tap listener, if we have it already */
2159 error_string = register_tap_listener("h245dg", &(the_tapinfo_struct.h245dg_dummy), NULL,
2160 voip_calls_dlg_reset,
2165 if (error_string != NULL) {
2166 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2168 g_string_free(error_string, TRUE);
2171 have_H245dg_tap_listener=TRUE;
2175 /****************************************************************************/
2177 remove_tap_listener_h245dg_calls(void)
2179 protect_thread_critical_region();
2180 remove_tap_listener(&(the_tapinfo_struct.h245dg_dummy));
2181 unprotect_thread_critical_region();
2183 have_H245dg_tap_listener=FALSE;
2186 /****************************************************************************/
2187 /****************************TAP for SDP PROTOCOL ***************************/
2188 /****************************************************************************/
2189 /* whenever a SDP packet is seen by the tap listener */
2191 SDPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SDPinfo)
2193 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2194 const sdp_packet_info *pi = SDPinfo;
2196 /* There are protocols like MGCP/SIP where the SDP is called before the tap for the
2197 MGCP/SIP packet, in those cases we assign the SPD summary to global lastSDPsummary
2200 g_free(sdp_summary);
2201 sdp_frame_num = pinfo->fd->num;
2202 /* Append to graph the SDP summary if the packet exists */
2203 sdp_summary = g_strdup_printf("SDP (%s)", pi->summary_str);
2204 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2206 tapinfo->redraw = TRUE;
2208 return 1; /* refresh output */
2212 /****************************************************************************/
2214 /****************************************************************************/
2215 static gboolean have_sdp_tap_listener=FALSE;
2216 /****************************************************************************/
2218 sdp_calls_init_tap(void)
2220 GString *error_string;
2222 if(have_sdp_tap_listener==FALSE)
2224 /* don't register tap listener, if we have it already */
2225 error_string = register_tap_listener("sdp", &(the_tapinfo_struct.sdp_dummy), NULL,
2226 voip_calls_dlg_reset,
2231 if (error_string != NULL) {
2232 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2234 g_string_free(error_string, TRUE);
2237 have_sdp_tap_listener=TRUE;
2241 /****************************************************************************/
2243 remove_tap_listener_sdp_calls(void)
2245 protect_thread_critical_region();
2246 remove_tap_listener(&(the_tapinfo_struct.sdp_dummy));
2247 unprotect_thread_critical_region();
2249 have_sdp_tap_listener=FALSE;
2254 /****************************************************************************/
2255 /* ***************************TAP for MGCP **********************************/
2256 /****************************************************************************/
2259 This function will look for a signal/event in the SignalReq/ObsEvent string
2260 and return true if it is found
2262 static gboolean isSignal(const gchar *signal, const gchar *signalStr)
2265 gchar **resultArray;
2267 /* if there is no signalStr, just return false */
2268 if (signalStr == NULL) return FALSE;
2270 /* if are both "blank" return true */
2271 if ( (*signal == '\0') && (*signalStr == '\0') ) return TRUE;
2273 /* look for signal in signalSre */
2274 resultArray = g_strsplit(signalStr, ",", 10);
2276 for (i = 0; resultArray[i]; i++) {
2277 g_strstrip(resultArray[i]);
2278 if (strcmp(resultArray[i], signal) == 0) return TRUE;
2281 g_strfreev(resultArray);
2287 This function will get the Caller ID info and replace the current string
2288 This is how it looks the caller Id: rg, ci(02/16/08/29, "3035550002","Ale Sipura 2")
2290 static void mgcpCallerID(gchar *signalStr, gchar **callerId)
2294 /* if there is no signalStr, just return false */
2295 if (signalStr == NULL) return;
2297 arrayStr = g_strsplit(signalStr, "\"", 10);
2299 if (arrayStr[0] == NULL) return;
2301 /* look for the ci signal */
2302 if (strstr(arrayStr[0], "ci(") && (arrayStr[1] != NULL) ) {
2303 /* free the previous "From" field of the call, and assign the new */
2305 *callerId = g_strdup(arrayStr[1]);
2307 g_strfreev(arrayStr);
2314 This function will get the Dialed Digits and replace the current string
2315 This is how it looks the dialed digits 5,5,5,0,0,0,2,#,*
2317 static void mgcpDialedDigits(gchar *signalStr, gchar **dialedDigits)
2320 gchar resultStr[50];
2323 /* if there is no signalStr, just return false */
2324 if (signalStr == NULL) return;
2326 tmpStr = g_strdup(signalStr);
2328 for ( i = 0 ; tmpStr[i] ; i++) {
2329 switch (tmpStr[i]) {
2330 case '0' : case '1' : case '2' : case '3' : case '4' :
2331 case '5' : case '6' : case '7' : case '8' : case '9' :
2332 case '#' : case '*' :
2340 for (i = 0, j = 0; tmpStr[i] && i<50; i++) {
2341 if (tmpStr[i] != '?')
2342 resultStr[j++] = tmpStr[i];
2344 resultStr[j] = '\0';
2346 if (*resultStr == '\0') return;
2348 g_free(*dialedDigits);
2349 *dialedDigits = g_strdup(resultStr);
2357 /****************************************************************************/
2358 /* whenever a MGCP packet is seen by the tap listener */
2360 MGCPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *MGCPinfo)
2362 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2364 voip_calls_info_t *tmp_listinfo;
2365 voip_calls_info_t *callsinfo = NULL;
2366 mgcp_calls_info_t *tmp_mgcpinfo = NULL;
2369 gchar *frame_label = NULL;
2370 gchar *comment = NULL;
2371 graph_analysis_item_t *gai;
2372 gboolean new = FALSE;
2373 gboolean fromEndpoint = FALSE; /* true for calls originated in Endpoints, false for calls from MGC */
2376 const mgcp_info_t *pi = MGCPinfo;
2379 if ((pi->mgcp_type == MGCP_REQUEST) && !pi->is_duplicate ){
2380 /* check whether we already have a call with this Endpoint and it is active*/
2381 list = g_list_first(tapinfo->callsinfo_list);
2384 tmp_listinfo=list->data;
2385 if ((tmp_listinfo->protocol == VOIP_MGCP) && (tmp_listinfo->call_active_state == VOIP_ACTIVE)){
2386 tmp_mgcpinfo = tmp_listinfo->prot_info;
2387 if (pi->endpointId != NULL){
2388 if (g_ascii_strcasecmp(tmp_mgcpinfo->endpointId,pi->endpointId) == 0){
2390 check first if it is an ended call. We can still match packets to this Endpoint 2 seconds
2391 after the call has been released
2393 diff_time = nstime_to_sec(&pinfo->fd->rel_ts) - tmp_listinfo->stop_sec - (double)tmp_listinfo->stop_usec/1000000;
2394 if ( ((tmp_listinfo->call_state == VOIP_CANCELLED) ||
2395 (tmp_listinfo->call_state == VOIP_COMPLETED) ||
2396 (tmp_listinfo->call_state == VOIP_REJECTED)) &&
2399 tmp_listinfo->call_active_state = VOIP_INACTIVE;
2401 callsinfo = (voip_calls_info_t*)(list->data);
2407 list = g_list_next (list);
2410 /* there is no call with this Endpoint, lets see if this a new call or not */
2411 if (callsinfo == NULL){
2412 if ( (strcmp(pi->code, "NTFY") == 0) && isSignal("hd", pi->observedEvents) ){ /* off hook transition */
2413 /* this is a new call from the Endpoint */
2414 fromEndpoint = TRUE;
2416 } else if (strcmp(pi->code, "CRCX") == 0){
2417 /* this is a new call from the MGC */
2418 fromEndpoint = FALSE;
2423 } else if ( ((pi->mgcp_type == MGCP_RESPONSE) && pi->request_available) ||
2424 ((pi->mgcp_type == MGCP_REQUEST) && pi->is_duplicate) ) {
2425 /* if it is a response OR if it is a duplicated Request, lets look in the Graph to see
2426 if there is a request that matches */
2427 listGraph = g_list_first(tapinfo->graph_analysis->list);
2430 gai = listGraph->data;
2431 if (gai->frame_num == pi->req_num){
2432 /* there is a request that match, so look the associated call with this call_num */
2433 list = g_list_first(tapinfo->callsinfo_list);
2436 tmp_listinfo=list->data;
2437 if (tmp_listinfo->protocol == VOIP_MGCP){
2438 if (tmp_listinfo->call_num == gai->conv_num){
2439 tmp_mgcpinfo = tmp_listinfo->prot_info;
2440 callsinfo = (voip_calls_info_t*)(list->data);
2444 list = g_list_next (list);
2446 if (callsinfo != NULL) break;
2448 listGraph = g_list_next(listGraph);
2450 /* if there is not a matching request, just return */
2451 if (callsinfo == NULL) return 0;
2454 /* not in the list? then create a new entry */
2455 if (callsinfo==NULL){
2456 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2457 callsinfo->call_active_state = VOIP_ACTIVE;
2458 callsinfo->call_state = VOIP_CALL_SETUP;
2460 callsinfo->from_identity=g_strdup(pi->endpointId);
2461 callsinfo->to_identity=g_strdup("");
2463 callsinfo->from_identity=g_strdup("");
2464 callsinfo->to_identity=g_strdup(pi->endpointId);
2466 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
2467 callsinfo->first_frame_num=pinfo->fd->num;
2468 callsinfo->selected=FALSE;
2469 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
2470 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
2471 callsinfo->protocol=VOIP_MGCP;
2472 callsinfo->prot_info=g_malloc(sizeof(mgcp_calls_info_t));
2473 callsinfo->free_prot_info = g_free;
2474 tmp_mgcpinfo=callsinfo->prot_info;
2475 tmp_mgcpinfo->endpointId = g_strdup(pi->endpointId);
2476 tmp_mgcpinfo->fromEndpoint = fromEndpoint;
2477 callsinfo->npackets = 0;
2478 callsinfo->call_num = tapinfo->ncalls++;
2479 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2482 g_assert(tmp_mgcpinfo != NULL);
2484 /* change call state and add to graph */
2485 switch (pi->mgcp_type)
2488 if ( (strcmp(pi->code, "NTFY") == 0) && (pi->observedEvents != NULL) ){
2489 frame_label = g_strdup_printf("%s ObsEvt:%s",pi->code, pi->observedEvents);
2491 if (tmp_mgcpinfo->fromEndpoint){
2492 /* use the Dialed digits to fill the "To" for the call, but use the first NTFY */
2493 if (callsinfo->to_identity[0] == '\0') mgcpDialedDigits(pi->observedEvents, &(callsinfo->to_identity));
2495 /* from MGC and the user picked up, the call is connected */
2496 } else if (isSignal("hd", pi->observedEvents))
2497 callsinfo->call_state=VOIP_IN_CALL;
2499 /* hung up signal */
2500 if (isSignal("hu", pi->observedEvents)) {
2501 if ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state == VOIP_RINGING)){
2502 callsinfo->call_state = VOIP_CANCELLED;
2504 callsinfo->call_state = VOIP_COMPLETED;
2508 } else if (strcmp(pi->code, "RQNT") == 0) {
2509 /* for calls from Endpoint: if there is a "no signal" RQNT and the call was RINGING, we assume this is the CONNECT */
2510 if ( tmp_mgcpinfo->fromEndpoint && isSignal("", pi->signalReq) && (callsinfo->call_state == VOIP_RINGING) ) {
2511 callsinfo->call_state = VOIP_IN_CALL;
2514 /* if there is ringback or ring tone, change state to ringing */
2515 if ( isSignal("rg", pi->signalReq) || isSignal("rt", pi->signalReq) ) {
2516 callsinfo->call_state = VOIP_RINGING;
2519 /* if there is a Busy or ReorderTone, and the call was Ringing or Setup the call is Rejected */
2520 if ( (isSignal("ro", pi->signalReq) || isSignal("bz", pi->signalReq)) && ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state = VOIP_RINGING)) ) {
2521 callsinfo->call_state = VOIP_REJECTED;
2524 if (pi->signalReq != NULL)
2525 frame_label = g_strdup_printf("%s%sSigReq:%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"", pi->signalReq);
2527 frame_label = g_strdup_printf("%s%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"");
2529 /* use the CallerID info to fill the "From" for the call */
2530 if (!tmp_mgcpinfo->fromEndpoint) mgcpCallerID(pi->signalReq, &(callsinfo->from_identity));
2532 } else if (strcmp(pi->code, "DLCX") == 0) {
2534 if there is a DLCX in a call To an Endpoint and the call was not connected, we use
2535 the DLCX as the end of the call
2537 if (!tmp_mgcpinfo->fromEndpoint){
2538 if ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state == VOIP_RINGING)){
2539 callsinfo->call_state = VOIP_CANCELLED;
2544 if (frame_label == NULL) frame_label = g_strdup_printf("%s",pi->code);
2547 frame_label = g_strdup_printf("%u (%s)",pi->rspcode, pi->code);
2550 /* XXX what to do? */
2555 comment = g_strdup_printf("MGCP %s %s%s", tmp_mgcpinfo->endpointId, (pi->mgcp_type == MGCP_REQUEST)?"Request":"Response", pi->is_duplicate?" Duplicate":"");
2557 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
2558 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
2559 callsinfo->last_frame_num=pinfo->fd->num;
2560 ++(callsinfo->npackets);
2561 /* increment the packets counter of all calls */
2562 ++(tapinfo->npackets);
2564 /* add to the graph */
2565 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2567 g_free(frame_label);
2569 /* add SDP info if apply */
2570 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
2571 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2572 g_free(sdp_summary);
2576 tapinfo->redraw = TRUE;
2578 return 1; /* refresh output */
2582 /****************************************************************************/
2584 /****************************************************************************/
2585 static gboolean have_MGCP_tap_listener=FALSE;
2586 /****************************************************************************/
2588 mgcp_calls_init_tap(void)
2590 GString *error_string;
2592 if(have_MGCP_tap_listener==FALSE)
2594 /* don't register tap listener, if we have it already */
2595 /* we send an empty filter, to force a non null "tree" in the mgcp dissector */
2596 error_string = register_tap_listener("mgcp", &(the_tapinfo_struct.mgcp_dummy), strdup(""),
2597 voip_calls_dlg_reset,
2601 if (error_string != NULL) {
2602 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2604 g_string_free(error_string, TRUE);
2607 have_MGCP_tap_listener=TRUE;
2611 /****************************************************************************/
2613 remove_tap_listener_mgcp_calls(void)
2615 protect_thread_critical_region();
2616 remove_tap_listener(&(the_tapinfo_struct.mgcp_dummy));
2617 unprotect_thread_critical_region();
2619 have_MGCP_tap_listener=FALSE;
2623 /****************************************************************************/
2624 /****************************TAP for ACTRACE (AudioCodes trace)**************/
2625 /****************************************************************************/
2627 /* whenever a ACTRACE packet is seen by the tap listener */
2629 ACTRACEcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *ACTRACEinfo)
2631 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2632 const actrace_info_t *pi = ACTRACEinfo;
2634 actrace_cas_calls_info_t *tmp_actrace_cas_info;
2635 voip_calls_info_t *tmp_listinfo;
2636 voip_calls_info_t *callsinfo = NULL;
2639 actrace_frame_num = pinfo->fd->num;
2640 actrace_trunk = pi->trunk;
2641 actrace_direction = pi->direction;
2643 if (pi->type == 1){ /* is CAS protocol */
2645 gchar *comment = NULL;
2648 list = g_list_first(tapinfo->callsinfo_list);
2651 tmp_listinfo=list->data;
2652 if ( tmp_listinfo->protocol == VOIP_AC_CAS ){
2653 tmp_actrace_cas_info = tmp_listinfo->prot_info;
2654 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
2655 if ( (tmp_actrace_cas_info->bchannel == pi->cas_bchannel) && (tmp_actrace_cas_info->trunk == actrace_trunk) ) {
2656 callsinfo = (voip_calls_info_t*)(list->data);
2660 list = g_list_next (list);
2663 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, g_strdup("PSTN"));
2665 /* if it is a new call, add it to the list */
2667 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2668 callsinfo->call_active_state = VOIP_ACTIVE;
2669 callsinfo->call_state = VOIP_CALL_SETUP;
2670 callsinfo->from_identity=g_strdup("N/A");
2671 callsinfo->to_identity=g_strdup("N/A");
2672 COPY_ADDRESS(&(callsinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
2673 callsinfo->first_frame_num=pinfo->fd->num;
2674 callsinfo->selected=FALSE;
2675 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
2676 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
2677 callsinfo->protocol=VOIP_AC_CAS;
2678 callsinfo->prot_info=g_malloc(sizeof(actrace_cas_calls_info_t));
2679 callsinfo->free_prot_info = g_free;
2681 tmp_actrace_cas_info=callsinfo->prot_info;
2682 tmp_actrace_cas_info->bchannel=pi->cas_bchannel;
2683 tmp_actrace_cas_info->trunk=actrace_trunk;
2684 callsinfo->npackets = 0;
2685 callsinfo->call_num = tapinfo->ncalls++;
2686 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2689 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
2690 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
2691 callsinfo->last_frame_num=pinfo->fd->num;
2692 ++(callsinfo->npackets);
2693 /* increment the packets counter of all calls */
2694 ++(tapinfo->npackets);
2697 comment = g_strdup_printf("AC_CAS trunk:%u", actrace_trunk );
2699 add_to_graph(tapinfo, pinfo, pi->cas_frame_label , comment, callsinfo->call_num,
2700 actrace_direction?&pstn_add:&(pinfo->src),
2701 actrace_direction?&(pinfo->src):&pstn_add,
2705 g_free((char *)pstn_add.data);
2708 tapinfo->redraw = TRUE;
2710 return 1; /* refresh output */
2714 /****************************************************************************/
2716 /****************************************************************************/
2717 static gboolean have_actrace_tap_listener=FALSE;
2718 /****************************************************************************/
2720 actrace_calls_init_tap(void)
2722 GString *error_string;
2724 if(have_actrace_tap_listener==FALSE)
2726 /* don't register tap listener, if we have it already */
2727 error_string = register_tap_listener("actrace", &(the_tapinfo_struct.actrace_dummy), NULL,
2728 voip_calls_dlg_reset,
2729 ACTRACEcalls_packet,
2733 if (error_string != NULL) {
2734 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2736 g_string_free(error_string, TRUE);
2739 have_actrace_tap_listener=TRUE;
2743 /****************************************************************************/
2745 remove_tap_listener_actrace_calls(void)
2747 protect_thread_critical_region();
2748 remove_tap_listener(&(the_tapinfo_struct.actrace_dummy));
2749 unprotect_thread_critical_region();
2751 have_actrace_tap_listener=FALSE;
2758 /**************************** TAP for H248/MEGACO **********************************/
2759 static gboolean have_h248_tap_listener = FALSE;
2760 static gboolean have_megaco_tap_listener = FALSE;
2762 #define gcp_is_req(type) ( type == GCP_CMD_ADD_REQ || type == GCP_CMD_MOVE_REQ || type == GCP_CMD_MOD_REQ || \
2763 type == GCP_CMD_SUB_REQ || type == GCP_CMD_AUDITCAP_REQ || type == GCP_CMD_AUDITVAL_REQ || \
2764 type == GCP_CMD_NOTIFY_REQ || type == GCP_CMD_SVCCHG_REQ || type == GCP_CMD_TOPOLOGY_REQ || \
2765 type == GCP_CMD_CTX_ATTR_AUDIT_REQ )
2767 static int h248_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
2768 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2769 const gcp_cmd_t* cmd = prot_info;
2771 voip_calls_info_t *callsinfo = NULL;
2774 gchar mgw_addr[128];
2776 if (cmd->ctx->id == NULL_CONTEXT || cmd->ctx->id == ALL_CONTEXTS ) {
2780 if ( gcp_is_req(cmd->type) ) {
2781 mgw = &(pinfo->dst);
2782 mgc = &(pinfo->src);
2784 mgc = &(pinfo->dst);
2785 mgw = &(pinfo->src);
2788 address_to_str_buf(mgw, mgw_addr, 128);
2790 /* check whether we already have this context in the list */
2791 list = g_list_first(tapinfo->callsinfo_list);
2794 voip_calls_info_t* tmp_listinfo = list->data;
2796 if (tmp_listinfo->protocol == TEL_H248){
2797 if (tmp_listinfo->prot_info == cmd->ctx){
2798 callsinfo = (voip_calls_info_t*)(list->data);
2802 list = g_list_next (list);
2805 if (callsinfo==NULL){
2807 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2808 callsinfo->call_state = VOIP_NO_STATE;
2809 callsinfo->call_active_state = VOIP_ACTIVE;
2810 callsinfo->from_identity = g_strdup_printf("%s : %.8x", mgw_addr, cmd->ctx->id);
2811 callsinfo->to_identity = g_strdup("");
2812 callsinfo->prot_info = cmd->ctx;
2813 callsinfo->free_prot_info = NULL;
2815 callsinfo->npackets = 1;
2816 callsinfo->first_frame_num=pinfo->fd->num;
2817 callsinfo->last_frame_num=pinfo->fd->num;
2819 COPY_ADDRESS(&(callsinfo->initial_speaker), mgc);
2821 callsinfo->protocol = TEL_H248;
2822 callsinfo->call_num = tapinfo->ncalls++;
2823 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
2824 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs;
2825 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
2826 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
2828 callsinfo->selected = FALSE;
2830 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2833 GString* s = g_string_new("");
2834 gcp_terms_t *ctx_term;
2836 g_free(callsinfo->from_identity);
2837 callsinfo->from_identity = g_strdup_printf("%s : %.8x", mgw_addr, ((gcp_ctx_t*)callsinfo->prot_info)->id);
2839 g_free(callsinfo->to_identity);
2841 for (ctx_term = ((gcp_ctx_t*)callsinfo->prot_info)->terms.next;
2843 ctx_term = ctx_term->next ) {
2844 if ( ctx_term->term && ctx_term->term->str) {
2845 g_string_sprintfa(s," %s",ctx_term->term->str);
2849 callsinfo->to_identity = s->str;
2850 g_string_free(s,FALSE);
2852 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
2853 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
2854 callsinfo->last_frame_num=pinfo->fd->num;
2855 ++(callsinfo->npackets);
2858 add_to_graph(tapinfo, pinfo, cmd->str ? cmd->str : "unknown Msg",
2859 ep_strdup_printf("TrxId = %u, CtxId = %.8x",cmd->trx->id,cmd->ctx->id),
2860 callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2862 ++(tapinfo->npackets);
2864 tapinfo->redraw = TRUE;
2869 void h248_calls_init_tap(void)
2871 GString *error_string;
2874 if(have_megaco_tap_listener==FALSE)
2876 error_string = register_tap_listener("megaco", &(the_tapinfo_struct.megaco_dummy),
2878 voip_calls_dlg_reset,
2880 voip_calls_dlg_draw);
2882 if (error_string != NULL) {
2883 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2885 g_string_free(error_string, TRUE);
2889 have_megaco_tap_listener=TRUE;
2892 if(have_h248_tap_listener==FALSE)
2894 error_string = register_tap_listener("h248", &(the_tapinfo_struct.h248_dummy),
2896 voip_calls_dlg_reset,
2898 voip_calls_dlg_draw);
2900 if (error_string != NULL) {
2901 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2903 g_string_free(error_string, TRUE);
2907 have_h248_tap_listener=TRUE;
2912 remove_tap_listener_h248_calls(void)
2914 protect_thread_critical_region();
2915 remove_tap_listener(&(the_tapinfo_struct.h248_dummy));
2916 remove_tap_listener(&(the_tapinfo_struct.megaco_dummy));
2917 unprotect_thread_critical_region();
2919 have_megaco_tap_listener=FALSE;
2920 have_h248_tap_listener=FALSE;
2924 /**************************** TAP for SCCP and SUA **********************************/
2925 /**************************** ( RANAP and BSSAP ) **********************************/
2926 static gboolean have_sccp_tap_listener = FALSE;
2927 static gboolean have_sua_tap_listener = FALSE;
2929 static const voip_protocol sccp_proto_map[] = {
2934 #define SP2VP(ap) ((ap) < SCCP_PLOAD_NUM_PLOADS ? sccp_proto_map[(ap)] : TEL_SCCP)
2935 const value_string* sccp_payload_values;
2937 static int sccp_calls(packet_info *pinfo, const void *prot_info) {
2938 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2939 const sccp_msg_info_t* msg = prot_info;
2940 sccp_assoc_info_t* assoc = msg->data.co.assoc;
2942 voip_calls_info_t *callsinfo = NULL;
2943 const gchar* label = NULL;
2944 const gchar* comment = NULL;
2945 /* check whether we already have this assoc in the list */
2947 for(list = g_list_first(tapinfo->callsinfo_list) ; list ; list = g_list_next (list) ) {
2948 if ( ((voip_calls_info_t*)(list->data))->prot_info == assoc ){
2949 callsinfo = (voip_calls_info_t*)(list->data);
2954 if (callsinfo==NULL){
2955 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2956 callsinfo->call_state = VOIP_CALL_SETUP;
2957 callsinfo->call_active_state = VOIP_ACTIVE;
2958 if ( assoc->calling_party ) {
2959 callsinfo->from_identity = g_strdup(assoc->calling_party);
2961 callsinfo->from_identity = g_strdup("Unknown");
2964 if ( assoc->called_party ) {
2965 callsinfo->to_identity = g_strdup(assoc->called_party);
2967 callsinfo->to_identity = g_strdup("Unknown");
2970 callsinfo->prot_info = (void*)assoc;
2971 callsinfo->free_prot_info = NULL;
2973 callsinfo->npackets = 1;
2974 callsinfo->first_frame_num=pinfo->fd->num;
2975 callsinfo->last_frame_num=pinfo->fd->num;
2977 COPY_ADDRESS(&(callsinfo->initial_speaker), &(pinfo->src));
2979 callsinfo->protocol = SP2VP(assoc->payload);
2980 callsinfo->start_sec=(gint32) pinfo->fd->rel_ts.secs;
2981 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs;
2982 callsinfo->stop_sec=(gint32) pinfo->fd->rel_ts.secs;
2983 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
2985 callsinfo->selected = FALSE;
2986 callsinfo->call_num = tapinfo->ncalls++;
2988 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2991 if ( assoc->calling_party ) {
2992 if (callsinfo->from_identity) g_free(callsinfo->from_identity );
2993 callsinfo->from_identity = g_strdup(assoc->calling_party);
2996 if ( assoc->called_party ) {
2997 if (callsinfo->to_identity) g_free(callsinfo->to_identity );
2998 callsinfo->to_identity = g_strdup(assoc->called_party);
3001 callsinfo->protocol = SP2VP(assoc->payload);
3002 callsinfo->stop_sec=(gint32) pinfo->fd->rel_ts.secs;
3003 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
3004 callsinfo->last_frame_num=pinfo->fd->num;
3005 ++(callsinfo->npackets);
3007 switch (msg->type) {
3008 case SCCP_MSG_TYPE_CC:
3009 callsinfo->call_state = VOIP_IN_CALL;
3011 case SCCP_MSG_TYPE_RLC:
3012 callsinfo->call_state = VOIP_COMPLETED;
3013 callsinfo->call_active_state = VOIP_INACTIVE;
3020 if (msg->data.co.label) {
3021 label = msg->data.co.label;
3023 label = val_to_str(msg->type, sccp_payload_values, "Unknown(%d)");
3026 if (msg->data.co.comment) {
3027 comment = msg->data.co.comment;
3032 add_to_graph(tapinfo, pinfo, label,(void*) comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3034 ++(tapinfo->npackets);
3036 tapinfo->redraw = TRUE;
3041 static int sccp_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
3042 sccp_payload_values = sccp_message_type_acro_values;
3043 return sccp_calls(pinfo, prot_info);
3047 static int sua_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
3048 sccp_payload_values = sua_co_class_type_acro_values;
3049 return sccp_calls(pinfo, prot_info);
3053 void sccp_calls_init_tap(void)
3055 GString *error_string;
3057 if(have_sccp_tap_listener==FALSE)
3059 error_string = register_tap_listener("sccp", &(the_tapinfo_struct.sccp_dummy),
3061 voip_calls_dlg_reset,
3063 voip_calls_dlg_draw);
3065 if (error_string != NULL) {
3066 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3068 g_string_free(error_string, TRUE);
3072 have_sccp_tap_listener=TRUE;
3075 if(have_sua_tap_listener==FALSE)
3077 error_string = register_tap_listener("sua", &(the_tapinfo_struct.sua_dummy),
3079 voip_calls_dlg_reset,
3081 voip_calls_dlg_draw);
3083 if (error_string != NULL) {
3084 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3086 g_string_free(error_string, TRUE);
3090 have_sua_tap_listener=TRUE;
3096 remove_tap_listener_sccp_calls(void)
3098 protect_thread_critical_region();
3099 remove_tap_listener(&(the_tapinfo_struct.sccp_dummy));
3100 unprotect_thread_critical_region();
3102 have_sccp_tap_listener=FALSE;
3103 have_sua_tap_listener=FALSE;
3107 /****************************************************************************/
3108 /****************************TAP for UNISTIM ********************************/
3109 /****************************************************************************/
3112 unistim_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *unistim_info)
3114 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3115 voip_calls_info_t *tmp_listinfo;
3116 voip_calls_info_t *callsinfo = NULL;
3117 unistim_info_t *tmp_unistim_info = NULL;
3119 GString *g_tmp = NULL;
3120 gchar *frame_label = NULL;
3121 gchar *comment = NULL;
3123 /* Fetch specific packet infos */
3124 const unistim_info_t *pi = unistim_info;
3127 g_tmp = g_string_new(NULL);
3129 /* Check to see if this is a dup */
3130 list = g_list_first(tapinfo->callsinfo_list);
3134 tmp_listinfo = list->data;
3136 if(tmp_listinfo->protocol == VOIP_UNISTIM){
3138 tmp_unistim_info = tmp_listinfo->prot_info;
3140 /* Search by termid if possible, otherwise use ni/it ip + port.. */
3141 if(pi->termid != 0){
3142 if(tmp_unistim_info->termid == pi->termid){
3143 /* If the call has ended, then we can reuse it.. */
3144 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
3147 callsinfo = (voip_calls_info_t*)(list->data);
3152 /* If no term id use ips / port to find entry */
3153 if(ADDRESSES_EQUAL(&tmp_unistim_info->it_ip, &pinfo->dst) && ADDRESSES_EQUAL(&tmp_unistim_info->ni_ip,&pinfo->src) && (tmp_unistim_info->it_port == pinfo->destport)){
3154 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
3155 /* Do nothing previous call */
3157 callsinfo = (voip_calls_info_t*)(list->data);
3161 else if(ADDRESSES_EQUAL(&tmp_unistim_info->it_ip, &pinfo->src) && ADDRESSES_EQUAL(&tmp_unistim_info->ni_ip,&pinfo->dst) && (tmp_unistim_info->it_port == pinfo->srcport)) {
3162 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
3163 /* Do nothing, it ain't our call.. */
3165 callsinfo = (voip_calls_info_t*)(list->data);
3172 /* Otherwise, go to the next one.. */
3173 list = g_list_next(list);
3176 if(pi->payload_type == 2 || pi->payload_type == 1){
3178 if(pi->key_state == 1 || pi->hook_state == 1){
3180 /* If the user hits a button,
3181 Session will be SETUP */
3183 /* If new add to list */
3184 if (callsinfo==NULL){
3186 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3187 callsinfo->call_active_state = VOIP_ACTIVE;
3188 callsinfo->call_state = VOIP_CALL_SETUP;
3189 callsinfo->from_identity=g_strdup_printf("%x",pi->termid);
3190 callsinfo->to_identity=g_strdup_printf("UNKNOWN");
3191 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
3192 callsinfo->first_frame_num=pinfo->fd->num;
3193 callsinfo->selected=FALSE;
3195 /* Set this on init of struct so in case the call doesn't complete, we'll have a ref. */
3196 /* Otherwise if the call is completed we'll have the open/close streams to ref actual call duration */
3197 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3198 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3200 callsinfo->protocol=VOIP_UNISTIM;
3201 callsinfo->prot_info=g_malloc(sizeof(unistim_info_t));
3203 tmp_unistim_info = callsinfo->prot_info;
3205 /* Clear tap struct */
3206 tmp_unistim_info->rudp_type = 0;
3207 tmp_unistim_info->payload_type = 0;
3208 tmp_unistim_info->sequence = pi->sequence;
3209 tmp_unistim_info->termid = pi->termid;
3210 tmp_unistim_info->key_val = -1;
3211 tmp_unistim_info->key_state = -1;
3212 tmp_unistim_info->hook_state = -1;
3213 tmp_unistim_info->stream_connect = -1;
3214 tmp_unistim_info->trans_connect = -1;
3215 tmp_unistim_info->set_termid = -1;
3216 tmp_unistim_info->string_data = NULL;
3217 tmp_unistim_info->key_buffer = NULL;
3219 COPY_ADDRESS(&(tmp_unistim_info->it_ip),&(pi->it_ip));
3220 COPY_ADDRESS(&(tmp_unistim_info->ni_ip),&(pi->ni_ip));
3221 tmp_unistim_info->it_port = pi->it_port;
3223 callsinfo->free_prot_info = g_free;
3224 callsinfo->npackets = 0;
3225 callsinfo->call_num = tapinfo->ncalls++;
3226 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3230 /* Set up call wide info struct */
3231 tmp_unistim_info = callsinfo->prot_info;
3232 tmp_unistim_info->sequence = pi->sequence;
3235 /* Each packet COULD BE OUR LAST!!!! */
3236 callsinfo->stop_sec=(gint32)(pinfo->fd->rel_ts.secs);
3237 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
3238 callsinfo->last_frame_num=pinfo->fd->num;
3240 /* This is a valid packet so increment counter */
3241 ++(callsinfo->npackets);
3243 /* increment the packets counter of all calls */
3244 ++(tapinfo->npackets);
3246 /* Key was depressed.. update key buffer.. */
3247 if(pi->key_val >= 0 && pi->key_val <= 11){
3249 if(tmp_unistim_info->key_buffer != NULL){
3251 /* assign to temp variable */
3252 g_string_assign(g_tmp,tmp_unistim_info->key_buffer);
3254 /* Manipulate the data */
3255 if(pi->key_val == 10) {
3256 tmp_unistim_info->key_buffer = g_strdup_printf("%s*",g_tmp->str);
3257 } else if(pi->key_val == 11) {
3258 tmp_unistim_info->key_buffer = g_strdup_printf("%s#",g_tmp->str);
3260 tmp_unistim_info->key_buffer = g_strdup_printf("%s%d",g_tmp->str,pi->key_val);
3265 /* Create new string */
3266 if(pi->key_val == 10) {
3267 tmp_unistim_info->key_buffer = g_strdup_printf("*");
3268 } else if(pi->key_val == 11) {
3269 tmp_unistim_info->key_buffer = g_strdup_printf("#");
3271 tmp_unistim_info->key_buffer = g_strdup_printf("%d",pi->key_val);
3276 /* Select for non-digit characters */
3277 if(pi->key_val == 10) {
3278 comment = g_strdup_printf("Key Input Sent: * (%d)", pi->sequence);
3279 } else if(pi->key_val == 11) {
3280 comment = g_strdup_printf("Key Input Sent: # (%d)", pi->sequence);
3282 comment = g_strdup_printf("Key Input Sent: %d (%d)",pi->key_val, pi->sequence);
3284 } else if(pi->key_val == 12) {
3285 /* Set label and comment for graph */
3286 comment = g_strdup_printf("Key Input Sent: UP (%d)", pi->sequence);
3287 } else if(pi->key_val == 13) {
3288 /* Set label and comment for graph */
3289 comment = g_strdup_printf("Key Input Sent: DOWN (%d)", pi->sequence);
3290 } else if(pi->key_val == 14) {
3291 /* Set label and comment for graph */
3292 comment = g_strdup_printf("Key Input Sent: RIGHT (%d)", pi->sequence);
3293 } else if(pi->key_val == 15) {
3294 if(pi->key_buffer != NULL){
3296 g_string_assign(g_tmp,pi->key_buffer);
3298 /* Manipulate the data */
3299 g_string_truncate(g_tmp,g_tmp->len-1);
3301 /* Insert new data */
3302 tmp_unistim_info->key_buffer = g_strdup_printf("%s",g_tmp->str);
3305 /* Set label and comment for graph */
3306 comment = g_strdup_printf("Key Input Sent: LEFT (%d)", pi->sequence);
3307 } else if(pi->key_val == 20) {
3308 /* User pressed the soft key 0 probably dial */
3309 comment = g_strdup_printf("Key Input Sent: S0 (%d)", pi->sequence);
3310 } else if(pi->key_val == 21) {
3311 /* User pressed the soft key 1 */
3312 comment = g_strdup_printf("Key Input Sent: S1 (%d)", pi->sequence);
3313 } else if(pi->key_val == 22) {
3314 /* User pressed the soft key 2 */
3315 /* On cs2k phones, soft key 2 is backspace. */
3316 if(pi->key_buffer != NULL) {
3319 g_string_assign(g_tmp,pi->key_buffer);
3321 /* Manipulate the data */
3322 g_string_truncate(g_tmp,g_tmp->len-1);
3324 /* Insert new data */
3325 tmp_unistim_info->key_buffer = g_strdup_printf("%s",g_tmp->str);
3328 /* add label and comment */
3329 comment = g_strdup_printf("Key Input Sent: S2 (%d)", pi->sequence);
3330 } else if(pi->key_val == 28) {
3331 /* User pressed something */
3332 comment = g_strdup_printf("Key Input Sent: Release (%d)", pi->sequence);
3333 } else if(pi->key_val == 23) {
3334 /* User pressed the soft key 3 */
3335 /* Cancel on cs2k so clear buffer */
3336 /* On mcs its config which will clear the buffer too */
3337 tmp_unistim_info->key_buffer = g_strdup_printf("\n");
3339 /* User pressed something, set labels*/
3340 comment = g_strdup_printf("Key Input Sent: S3 (%d)", pi->sequence);
3341 } else if(pi->key_val == 27) {
3342 /* User pressed something */
3343 comment = g_strdup_printf("Key Input Sent: Hold (%d)", pi->sequence);
3344 } else if(pi->key_val == 29) {
3345 /* User pressed something */
3346 comment = g_strdup_printf("Key Input Sent: Mute (%d)", pi->sequence);
3347 } else if(pi->key_val == 30) {
3348 /* User pressed something */
3349 comment = g_strdup_printf("Key Input Sent: Headset (%d)", pi->sequence);
3350 } else if(pi->key_val == 31) {
3351 /* Handsfree button */
3352 comment = g_strdup_printf("Key Input Sent: Handsfree (%d)", pi->sequence);
3353 } else if(pi->key_val >= 32 && pi->key_val <= 56) {
3355 comment = g_strdup_printf("Key Input Sent: Prog%d (%d)", (pi->key_val & 31), pi->sequence);
3358 if(pi->key_val != -1) {
3360 frame_label = g_strdup_printf("KEY INPUT");
3362 if (comment == NULL)
3363 /* Ouch! What do you do!? */
3364 /* User pressed something */
3365 comment = g_strdup_printf("Key Input Sent: UNKNOWN - %d (%d)", pi->key_val, pi->sequence);
3367 /* add to the graph */
3368 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3372 if(pi->hook_state == 1) {
3374 /* Phone is off hook */
3375 frame_label = g_strdup_printf("OFF HOOK");
3376 comment = g_strdup_printf("Off Hook (%d)", pi->sequence);
3378 /* add to the graph */
3379 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3380 } else if(pi->hook_state == 0) {
3382 /* Phone is on hook */
3383 frame_label = g_strdup_printf("ON HOOK");
3384 comment = g_strdup_printf("On Hook (%d)", pi->sequence);
3386 /* add to the graph */
3387 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3392 /* Open stream was sent from server */
3393 if(pi->stream_connect == 1 && callsinfo != NULL) {
3396 /* Signifies the start of the call so set start_sec & start_usec */
3397 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3398 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3400 /* Local packets too */
3401 ++(callsinfo->npackets);
3403 /* increment the packets counter of all calls */
3404 ++(tapinfo->npackets);
3406 /* ?? means we're not quite sure if this is accurate. Since Unistim isn't a true
3407 Call control protocol, we can only guess at the destination by messing with
3409 if(tmp_unistim_info->key_buffer != NULL){
3410 callsinfo->to_identity = g_strdup_printf("?? %s",tmp_unistim_info->key_buffer);
3413 /* change sequence number for ACK detection */
3414 tmp_unistim_info->sequence = pi->sequence;
3416 /* State changes too */
3417 callsinfo->call_active_state = VOIP_ACTIVE;
3418 callsinfo->call_state = VOIP_IN_CALL;
3420 /* Add graph data */
3421 frame_label = g_strdup_printf("STREAM OPENED");
3422 comment = g_strdup_printf("Stream Opened (%d)",pi->sequence);
3424 /* add to the graph */
3425 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3427 /* Redraw the scree */
3428 tapinfo->redraw = TRUE;
3431 } else if(pi->stream_connect == 1 && callsinfo == NULL) {
3433 /* Research indicates some nortel products initiate stream first
3434 * without keypresses. therefore creating this solely on a keypress is
3436 * Sometimes calls start immediately with open stream.
3438 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3439 callsinfo->call_active_state = VOIP_ACTIVE;
3440 callsinfo->call_state = VOIP_CALL_SETUP;
3441 callsinfo->from_identity=g_strdup_printf("UNKNOWN");
3442 callsinfo->to_identity=g_strdup_printf("UNKNOWN");
3443 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
3444 callsinfo->first_frame_num=pinfo->fd->num;
3445 callsinfo->selected=FALSE;
3447 /* Set this on init of struct so in case the call doesn't complete, we'll have a ref. */
3448 /* Otherwise if the call is completed we'll have the open/close streams to ref actual call duration */
3449 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3450 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3452 callsinfo->protocol=VOIP_UNISTIM;
3453 callsinfo->prot_info=g_malloc(sizeof(unistim_info_t));
3455 tmp_unistim_info = callsinfo->prot_info;
3457 /* Clear tap struct */
3458 tmp_unistim_info->rudp_type = 0;
3459 tmp_unistim_info->payload_type = 0;
3460 tmp_unistim_info->sequence = pi->sequence;
3461 tmp_unistim_info->termid = 0;
3462 tmp_unistim_info->key_val = -1;
3463 tmp_unistim_info->key_state = -1;
3464 tmp_unistim_info->hook_state = -1;
3465 tmp_unistim_info->stream_connect = -1;
3466 tmp_unistim_info->trans_connect = -1;
3467 tmp_unistim_info->set_termid = -1;
3468 tmp_unistim_info->string_data = NULL;
3469 tmp_unistim_info->key_buffer = NULL;
3471 COPY_ADDRESS(&(tmp_unistim_info->it_ip),&(pi->it_ip));
3472 COPY_ADDRESS(&(tmp_unistim_info->ni_ip),&(pi->ni_ip));
3473 tmp_unistim_info->it_port = pi->it_port;
3475 callsinfo->free_prot_info = g_free;
3476 callsinfo->npackets = 0;
3477 callsinfo->call_num = tapinfo->ncalls++;
3478 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3481 /* Signifies the start of the call so set start_sec & start_usec */
3482 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3483 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3485 /* Local packets too */
3486 ++(callsinfo->npackets);
3488 /* increment the packets counter of all calls */
3489 ++(tapinfo->npackets);
3491 /* ?? means we're not quite sure if this is accurate. Since Unistim isn't a true
3492 Call control protocol, we can only guess at the destination by messing with
3494 if(tmp_unistim_info->key_buffer != NULL){
3495 callsinfo->to_identity = g_strdup_printf("?? %s",tmp_unistim_info->key_buffer);
3498 /* change sequence number for ACK detection */
3499 tmp_unistim_info->sequence = pi->sequence;
3501 /* State changes too */
3502 callsinfo->call_active_state = VOIP_ACTIVE;
3503 callsinfo->call_state = VOIP_IN_CALL;
3505 /* Add graph data */
3506 frame_label = g_strdup_printf("STREAM OPENED");
3507 comment = g_strdup_printf("Stream Opened (%d)",pi->sequence);
3509 /* add to the graph */
3510 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3512 /* Redraw the scree */
3513 tapinfo->redraw = TRUE;
3517 } else if(pi->stream_connect == 0 && callsinfo != NULL) {
3520 /* Set stop seconds + usec */
3521 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
3522 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
3523 callsinfo->last_frame_num=pinfo->fd->num;
3525 tmp_unistim_info->sequence = pi->sequence;
3527 if(callsinfo->call_state == VOIP_IN_CALL){
3528 callsinfo->call_active_state = VOIP_INACTIVE;
3529 callsinfo->call_state = VOIP_COMPLETED;
3531 callsinfo->call_state = VOIP_UNKNOWN;
3532 callsinfo->call_active_state = VOIP_INACTIVE;
3535 frame_label = g_strdup_printf("STREAM CLOSED");
3536 comment = g_strdup_printf("Stream Closed (%d)",pi->sequence);
3538 /* add to the graph */
3539 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3543 } else if(pi->rudp_type == 1 && callsinfo != NULL) {
3545 /* Only show acks for processed seq #s */
3546 if(tmp_unistim_info->sequence == pi->sequence) {
3548 frame_label = g_strdup_printf("ACK");
3549 comment = g_strdup_printf("ACK for sequence %d",pi->sequence);
3551 /* add to the graph */
3552 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3556 } else if(pi->rudp_type == 0 && callsinfo != NULL) {
3559 frame_label = g_strdup_printf("NAK");
3560 comment = g_strdup_printf("NAK for sequence %d",pi->sequence);
3562 /* add to the graph */
3563 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3568 g_free(frame_label);
3571 tapinfo->redraw = TRUE;
3576 /****************************************************************************/
3578 /****************************************************************************/
3579 static gboolean have_unistim_tap_listener=FALSE;
3580 /****************************************************************************/
3582 unistim_calls_init_tap(void){
3584 GString *error_string;
3586 if(have_unistim_tap_listener==FALSE) {
3588 error_string = register_tap_listener("unistim", &(the_tapinfo_struct.unistim_dummy),
3590 voip_calls_dlg_reset,
3591 unistim_calls_packet,
3595 if (error_string != NULL) {
3596 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3598 g_string_free(error_string, TRUE);
3602 have_unistim_tap_listener=TRUE;
3606 /****************************************************************************/
3608 remove_tap_listener_unistim_calls(void)
3610 protect_thread_critical_region();
3611 remove_tap_listener(&(the_tapinfo_struct.unistim_dummy));
3612 unprotect_thread_critical_region();
3614 have_unistim_tap_listener=FALSE;
3617 /****************************************************************************/
3618 /* ***************************TAP for OTHER PROTOCOL **********************************/
3619 /****************************************************************************/
3622 VoIPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *VoIPinfo _U_)
3624 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3625 voip_calls_info_t *callsinfo = NULL;
3626 voip_calls_info_t *tmp_listinfo;
3628 const voip_packet_info_t *pi = VoIPinfo;
3631 list = g_list_first(tapinfo->callsinfo_list);
3633 tmp_listinfo = list->data;
3634 if ( tmp_listinfo->protocol == VOIP_COMMON ) {
3635 if (!strcmp(pi->call_id, tmp_listinfo->call_id)) {
3636 callsinfo = (voip_calls_info_t*)(list->data);
3640 list = g_list_next(list);
3643 if (callsinfo == NULL) {
3644 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3645 callsinfo->call_active_state = pi->call_active_state;
3646 callsinfo->call_state = pi->call_state;
3647 callsinfo->call_id=g_strdup((pi->call_id)?pi->call_id:"");
3648 callsinfo->from_identity = g_strdup((pi->from_identity)?pi->from_identity:"");
3649 callsinfo->to_identity = g_strdup((pi->to_identity)?pi->to_identity:"");
3650 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
3651 callsinfo->selected=FALSE;
3652 callsinfo->first_frame_num=pinfo->fd->num;
3653 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3654 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3655 callsinfo->protocol=VOIP_COMMON;
3656 callsinfo->protocol_name=g_strdup((pi->protocol_name)?pi->protocol_name:"");
3657 callsinfo->call_comment=g_strdup((pi->call_comment)?pi->call_comment:"");
3658 callsinfo->prot_info=NULL;
3659 callsinfo->free_prot_info = NULL;
3661 callsinfo->call_num = tapinfo->ncalls++;
3662 callsinfo->npackets = 0;
3664 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3667 if (callsinfo != NULL) {
3668 callsinfo->call_active_state = pi->call_active_state;
3669 if ((callsinfo->call_state != VOIP_COMPLETED) && (pi->call_state == VOIP_COMPLETED))
3670 tapinfo->completed_calls++;
3671 if (pi->call_state != VOIP_NO_STATE)
3672 callsinfo->call_state = pi->call_state;
3673 callsinfo->stop_sec=(gint32)(pinfo->fd->rel_ts.secs);
3674 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
3675 callsinfo->last_frame_num=pinfo->fd->num;
3676 ++(callsinfo->npackets);
3677 ++(tapinfo->npackets);
3680 /* add to the graph */
3681 add_to_graph(tapinfo, pinfo, (pi->frame_label)?pi->frame_label:"VoIP msg", (pi->frame_comment)?pi->frame_comment:"", callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3683 tapinfo->redraw = TRUE;
3687 /****************************************************************************/
3688 static gboolean have_voip_tap_listener=FALSE;
3691 VoIPcalls_init_tap(void)
3693 GString *error_string;
3695 if(have_voip_tap_listener==FALSE)
3697 error_string = register_tap_listener("voip", &(the_tapinfo_struct.voip_dummy),
3699 voip_calls_dlg_reset,
3704 if (error_string != NULL) {
3705 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3707 g_string_free(error_string, TRUE);
3710 have_voip_tap_listener=TRUE;
3713 /****************************************************************************/
3715 remove_tap_listener_voip_calls(void)
3717 protect_thread_critical_region();
3718 remove_tap_listener(&(the_tapinfo_struct.voip_dummy));
3719 unprotect_thread_critical_region();
3721 have_voip_tap_listener=FALSE;
3725 /****************************************************************************/
3726 /* ***************************TAP for OTHER PROTOCOL **********************************/
3727 /****************************************************************************/
3729 /****************************************************************************/
3730 /* whenever a prot_ packet is seen by the tap listener */
3733 prot_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info _U_)
3735 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3736 if (callsinfo!=NULL){
3737 callsinfo->stop_sec=pinfo->fd->rel_secs;
3738 callsinfo->stop_usec=pinfo->fd->rel_usecs;
3739 callsinfo->last_frame_num=pinfo->fd->num;
3740 ++(callsinfo->npackets);
3741 ++(tapinfo->npackets);
3744 tapinfo->redraw = TRUE;
3749 /****************************************************************************/
3751 static gboolean have_prot__tap_listener=FALSE;
3754 prot_calls_init_tap(void)
3756 GString *error_string;
3758 if(have_prot__tap_listener==FALSE)
3760 error_string = register_tap_listener("prot_", &(the_tapinfo_struct.prot__dummy),
3762 voip_calls_dlg_reset,
3767 if (error_string != NULL) {
3768 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3770 g_string_free(error_string, TRUE);
3773 have_prot__tap_listener=TRUE;
3777 /****************************************************************************/
3780 remove_tap_listener_prot__calls(void)
3782 protect_thread_critical_region();
3783 remove_tap_listener(&(the_tapinfo_struct.prot__dummy));
3784 unprotect_thread_critical_region();
3786 have_prot__tap_listener=FALSE;