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.
41 #include <epan/epan.h>
42 #include <epan/packet.h>
44 #include <epan/tap-voip.h>
45 #include <epan/dissectors/packet-sip.h>
46 #include <epan/dissectors/packet-mtp3.h>
47 #include <epan/dissectors/packet-isup.h>
48 #include <epan/dissectors/packet-h225.h>
49 #include <epan/dissectors/packet-h245.h>
50 #include <epan/dissectors/packet-q931.h>
51 #include <epan/dissectors/packet-sdp.h>
52 #include <epan/dissectors/packet-mgcp.h>
53 #include <epan/dissectors/packet-actrace.h>
54 #include <epan/dissectors/packet-rtp.h>
55 #include <epan/dissectors/packet-rtp-events.h>
56 #include <epan/dissectors/packet-t38.h>
57 #include <epan/dissectors/packet-t30.h>
58 #include <epan/dissectors/packet-h248.h>
59 #include <epan/dissectors/packet-sccp.h>
60 #include <plugins/unistim/packet-unistim.h>
61 #include <epan/dissectors/packet-skinny.h>
62 #include <epan/dissectors/packet-iax2.h>
63 #include <epan/rtp_pt.h>
65 #include "../alert_box.h"
66 #include "../simple_dialog.h"
68 #include "gtk/graph_analysis.h"
69 #include "gtk/voip_calls.h"
70 #include "gtk/voip_calls_dlg.h"
73 #ifdef HAVE_LIBPORTAUDIO
74 #include "gtk/rtp_player.h"
75 #endif /* HAVE_LIBPORTAUDIO */
78 const char *voip_call_state_name[8]={
89 /* defines whether we can consider the call active */
90 const char *voip_protocol_name[]={
118 graph_str labels[H245_MAX];
121 static h245_labels_t h245_labels;
123 /****************************************************************************/
124 /* the one and only global voip_calls_tapinfo_t structure */
125 static voip_calls_tapinfo_t the_tapinfo_struct =
126 {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, 0, 0};
128 /* the one and only global voip_rtp_tapinfo_t structure */
129 static voip_rtp_tapinfo_t the_tapinfo_rtp_struct =
132 /****************************************************************************/
133 /* when there is a [re]reading of packet's */
134 void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
136 voip_calls_info_t *callsinfo;
137 voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
138 voip_rtp_stream_info_t *strinfo;
139 graph_analysis_item_t *graph_item;
142 #ifdef HAVE_LIBPORTAUDIO
143 /* reset the RTP player */
147 /* free the data items first */
148 list = g_list_first(tapinfo->callsinfo_list);
151 callsinfo = list->data;
152 g_free(callsinfo->call_id);
153 g_free(callsinfo->from_identity);
154 g_free(callsinfo->to_identity);
155 g_free((void *)(callsinfo->initial_speaker.data));
156 g_free(callsinfo->protocol_name);
157 g_free(callsinfo->call_comment);
159 if (callsinfo->free_prot_info && callsinfo->prot_info)
160 callsinfo->free_prot_info(callsinfo->prot_info);
163 list = g_list_next(list);
165 g_list_free(tapinfo->callsinfo_list);
166 tapinfo->callsinfo_list = NULL;
168 tapinfo->npackets = 0;
169 tapinfo->start_packets = 0;
170 tapinfo->completed_calls = 0;
171 tapinfo->rejected_calls = 0;
173 /* free the graph data items first */
174 list = g_list_first(tapinfo->graph_analysis->list);
177 graph_item = list->data;
178 g_free(graph_item->frame_label);
179 g_free(graph_item->comment);
180 g_free((void *)graph_item->src_addr.data);
181 g_free((void *)graph_item->dst_addr.data);
183 list = g_list_next(list);
185 g_list_free(tapinfo->graph_analysis->list);
186 tapinfo->graph_analysis->nconv = 0;
187 tapinfo->graph_analysis->list = NULL;
189 ++(tapinfo->launch_count);
191 /* free the strinfo data items first */
192 list = g_list_first(rtp_tapinfo->list);
195 strinfo = list->data;
196 g_free(strinfo->pt_str);
197 list = g_list_next(list);
199 g_list_free(rtp_tapinfo->list);
200 rtp_tapinfo->list = NULL;
205 /****************************************************************************/
206 void graph_analysis_data_init(void){
207 the_tapinfo_struct.graph_analysis = g_malloc(sizeof(graph_analysis_info_t));
208 the_tapinfo_struct.graph_analysis->nconv = 0;
209 the_tapinfo_struct.graph_analysis->list = NULL;
212 /****************************************************************************/
213 /* Add a new item into the graph */
214 static void add_to_graph(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, const gchar *frame_label, const gchar *comment, guint16 call_num, address *src_addr, address *dst_addr, guint16 line_style)
216 graph_analysis_item_t *gai;
218 gai = g_malloc(sizeof(graph_analysis_item_t));
219 gai->frame_num = pinfo->fd->num;
220 gai->time= nstime_to_sec(&pinfo->fd->rel_ts);
221 COPY_ADDRESS(&(gai->src_addr),src_addr);
222 COPY_ADDRESS(&(gai->dst_addr),dst_addr);
224 gai->port_src=pinfo->srcport;
225 gai->port_dst=pinfo->destport;
226 if (frame_label != NULL)
227 gai->frame_label = g_strdup(frame_label);
229 gai->frame_label = g_strdup("");
232 gai->comment = g_strdup(comment);
234 gai->comment = g_strdup("");
235 gai->conv_num=call_num;
236 gai->line_style=line_style;
239 tapinfo->graph_analysis->list = g_list_append(tapinfo->graph_analysis->list, gai);
243 /****************************************************************************/
244 /* Append str to frame_label and comment in a graph item */
245 /* return 0 if the frame_num is not in the graph list */
246 static int append_to_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
248 graph_analysis_item_t *gai;
250 gchar *frame_label = NULL;
251 gchar *comment = NULL;
253 list = g_list_first(tapinfo->graph_analysis->list);
257 if (gai->frame_num == frame_num){
258 frame_label = gai->frame_label;
259 comment = gai->comment;
261 if (new_frame_label != NULL){
262 gai->frame_label = g_strdup_printf("%s %s", frame_label, new_frame_label);
266 if (new_comment != NULL){
267 gai->comment = g_strdup_printf("%s %s", comment, new_comment);
272 list = g_list_next(list);
279 /****************************************************************************/
280 /* Change the frame_label and comment in a graph item if not NULL*/
281 /* return 0 if the frame_num is not in the graph list */
282 static int change_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
284 graph_analysis_item_t *gai;
286 gchar *frame_label = NULL;
287 gchar *comment = NULL;
289 list = g_list_first(tapinfo->graph_analysis->list);
293 if (gai->frame_num == frame_num){
294 frame_label = gai->frame_label;
295 comment = gai->comment;
297 if (new_frame_label != NULL){
298 gai->frame_label = g_strdup(new_frame_label);
302 if (new_comment != NULL){
303 gai->comment = g_strdup(new_comment);
308 list = g_list_next(list);
315 /****************************************************************************/
316 /* Change all the graph items with call_num to new_call_num */
317 static guint change_call_num_graph(voip_calls_tapinfo_t *tapinfo _U_, guint16 call_num, guint16 new_call_num)
319 graph_analysis_item_t *gai;
324 list = g_list_first(tapinfo->graph_analysis->list);
328 if (gai->conv_num == call_num){
329 gai->conv_num = new_call_num;
332 list = g_list_next(list);
334 return items_changed;
337 /****************************************************************************/
338 /* Insert the item in the graph list */
339 static void insert_to_graph(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, const gchar *frame_label, const gchar *comment, guint16 call_num, address *src_addr, address *dst_addr, guint16 line_style, double time_val, guint32 frame_num)
341 graph_analysis_item_t *gai, *new_gai;
346 new_gai = g_malloc(sizeof(graph_analysis_item_t));
347 new_gai->frame_num = frame_num;
348 new_gai->time= time_val;
349 COPY_ADDRESS(&(new_gai->src_addr),src_addr);
350 COPY_ADDRESS(&(new_gai->dst_addr),dst_addr);
352 new_gai->port_src=pinfo->srcport;
353 new_gai->port_dst=pinfo->destport;
354 if (frame_label != NULL)
355 new_gai->frame_label = g_strdup(frame_label);
357 new_gai->frame_label = g_strdup("");
360 new_gai->comment = g_strdup(comment);
362 new_gai->comment = g_strdup("");
363 new_gai->conv_num=call_num;
364 new_gai->line_style=line_style;
365 new_gai->display=FALSE;
369 list = g_list_first(tapinfo->graph_analysis->list);
373 if (gai->frame_num > frame_num){
374 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item_num);
378 list = g_list_next(list);
382 if (!inserted) tapinfo->graph_analysis->list = g_list_append(tapinfo->graph_analysis->list, new_gai);
385 /****************************************************************************/
386 /* ***************************TAP for RTP Events*****************************/
387 /****************************************************************************/
389 static guint32 rtp_evt_frame_num = 0;
390 static guint8 rtp_evt = 0;
391 static gboolean rtp_evt_end = FALSE;
392 /*static guint32 rtp_evt_setup_frame_num = 0;*/
394 /****************************************************************************/
395 /* whenever a rtp event packet is seen by the tap listener */
397 rtp_event_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *rtp_event_info)
399 const struct _rtp_event_info *pi = rtp_event_info;
401 /* do not consider RTP events packets without a setup frame */
402 if (pi->info_setup_frame_num == 0){
406 rtp_evt_frame_num = pinfo->fd->num;
407 rtp_evt = pi->info_rtp_evt;
408 rtp_evt_end = pi->info_end;
413 /****************************************************************************/
414 static gboolean have_rtp_event_tap_listener=FALSE;
417 rtp_event_init_tap(void)
419 GString *error_string;
422 if(have_rtp_event_tap_listener==FALSE)
424 error_string = register_tap_listener("rtpevent", &(the_tapinfo_rtp_struct.rtp_event_dummy),
432 if (error_string != NULL) {
433 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
434 "%s", error_string->str);
435 g_string_free(error_string, TRUE);
438 have_rtp_event_tap_listener=TRUE;
442 /****************************************************************************/
445 remove_tap_listener_rtp_event(void)
447 protect_thread_critical_region();
448 remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_event_dummy));
449 unprotect_thread_critical_region();
451 have_rtp_event_tap_listener=FALSE;
454 /****************************************************************************/
455 /* ***************************TAP for RTP **********************************/
456 /****************************************************************************/
458 /****************************************************************************/
459 /* when there is a [re]reading of RTP packet's */
460 static void voip_rtp_reset(void *ptr _U_)
462 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
464 /* free the data items first */
465 list = g_list_first(tapinfo->list);
469 list = g_list_next(list);
471 g_list_free(tapinfo->list);
472 tapinfo->list = NULL;
473 tapinfo->nstreams = 0;
477 /****************************************************************************/
478 /* whenever a RTP packet is seen by the tap listener */
480 RTP_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void const *RTPinfo)
482 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
483 voip_rtp_stream_info_t *tmp_listinfo;
484 voip_rtp_stream_info_t *strinfo = NULL;
486 struct _rtp_conversation_info *p_conv_data = NULL;
488 const struct _rtp_info *pi = RTPinfo;
490 /* do not consider RTP packets without a setup frame */
491 if (pi->info_setup_frame_num == 0){
495 /* add this RTP for future listening using the RTP Player*/
496 #ifdef HAVE_LIBPORTAUDIO
497 add_rtp_packet(pi, pinfo);
500 /* check whether we already have a RTP stream with this setup frame and ssrc in the list */
501 list = g_list_first(tapinfo->list);
504 tmp_listinfo=list->data;
505 if ( (tmp_listinfo->setup_frame_number == pi->info_setup_frame_num)
506 && (tmp_listinfo->ssrc == pi->info_sync_src) && (tmp_listinfo->end_stream == FALSE)){
507 /* if the payload type has changed, we mark the stream as finished to create a new one
508 this is to show multiple payload changes in the Graph for example for DTMF RFC2833 */
509 if ( tmp_listinfo->pt != pi->info_payload_type ) {
510 tmp_listinfo->end_stream = TRUE;
512 strinfo = (voip_rtp_stream_info_t*)(list->data);
516 list = g_list_next(list);
519 /* if this is a duplicated RTP Event End, just return */
520 if ((rtp_evt_frame_num == pinfo->fd->num) && !strinfo && (rtp_evt_end == TRUE)) {
524 /* not in the list? then create a new entry */
526 strinfo = g_malloc(sizeof(voip_rtp_stream_info_t));
527 COPY_ADDRESS(&(strinfo->src_addr), &(pinfo->src));
528 strinfo->src_port = pinfo->srcport;
529 COPY_ADDRESS(&(strinfo->dest_addr), &(pinfo->dst));
530 strinfo->dest_port = pinfo->destport;
531 strinfo->ssrc = pi->info_sync_src;
532 strinfo->end_stream = FALSE;
533 strinfo->pt = pi->info_payload_type;
534 strinfo->pt_str = NULL;
535 strinfo->is_srtp = pi->info_is_srtp;
536 /* if it is dynamic payload, let use the conv data to see if it is defined */
537 if ( (strinfo->pt >= PT_UNDF_96) && (strinfo->pt <= PT_UNDF_127) ) {
538 /* Use existing packet info if available */
539 p_conv_data = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name("rtp"));
540 if (p_conv_data && p_conv_data->rtp_dyn_payload) {
541 encoding_name_and_rate_t *encoding_name_and_rate_pt = NULL;
542 encoding_name_and_rate_pt = g_hash_table_lookup(p_conv_data->rtp_dyn_payload, &strinfo->pt);
543 if (encoding_name_and_rate_pt) {
544 strinfo->pt_str = g_strdup(encoding_name_and_rate_pt->encoding_name);
548 if (!strinfo->pt_str) strinfo->pt_str = g_strdup(val_to_str_ext(strinfo->pt, &rtp_payload_type_short_vals_ext, "%u"));
549 strinfo->npackets = 0;
550 strinfo->first_frame_num = pinfo->fd->num;
551 strinfo->start_abs = pinfo->fd->abs_ts;
552 strinfo->start_rel = pinfo->fd->rel_ts;
553 strinfo->setup_frame_number = pi->info_setup_frame_num;
554 strinfo->rtp_event = -1;
555 tapinfo->list = g_list_append(tapinfo->list, strinfo);
559 /* Add the info to the existing RTP stream */
561 strinfo->stop_abs = pinfo->fd->abs_ts;
562 strinfo->stop_rel = pinfo->fd->rel_ts;
564 /* process RTP Event */
565 if (rtp_evt_frame_num == pinfo->fd->num) {
566 strinfo->rtp_event = rtp_evt;
567 if (rtp_evt_end == TRUE) {
568 strinfo->end_stream = TRUE;
573 the_tapinfo_struct.redraw = TRUE;
578 /****************************************************************************/
579 /* whenever a redraw in the RTP tap listener */
580 static void RTP_packet_draw(void *prs _U_)
582 voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
583 GList *rtp_streams_list;
584 voip_rtp_stream_info_t *rtp_listinfo;
585 GList *voip_calls_graph_list;
587 graph_analysis_item_t *gai;
588 graph_analysis_item_t *new_gai;
592 /* add each rtp stream to the graph */
593 rtp_streams_list = g_list_first(rtp_tapinfo->list);
594 while (rtp_streams_list)
596 rtp_listinfo = rtp_streams_list->data;
598 /* using the setup frame number of the RTP stream, we get the call number that it belongs */
599 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
600 while (voip_calls_graph_list)
602 gai = voip_calls_graph_list->data;
603 conv_num = gai->conv_num;
604 /* if we get the setup frame number, then get the time position to graph the RTP arrow */
605 if (rtp_listinfo->setup_frame_number == gai->frame_num){
606 /* look again from the begining because there are cases where the Setup frame is after the RTP */
607 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
609 while(voip_calls_graph_list){
610 gai = voip_calls_graph_list->data;
611 /* if RTP was already in the Graph, just update the comment information */
612 if (rtp_listinfo->first_frame_num == gai->frame_num){
613 duration = (guint32)(nstime_to_msec(&rtp_listinfo->stop_rel) - nstime_to_msec(&rtp_listinfo->start_rel));
614 g_free(gai->comment);
615 gai->comment = g_strdup_printf("%s Num packets:%u Duration:%u.%03us SSRC:0x%X",
616 (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->npackets,
617 duration/1000,(duration%1000), rtp_listinfo->ssrc);
621 /* 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 */
622 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
623 if (!voip_calls_graph_list) item++;
625 /* add the RTP item to the graph if was not there*/
626 if (rtp_listinfo->first_frame_num<gai->frame_num || !voip_calls_graph_list){
627 new_gai = g_malloc(sizeof(graph_analysis_item_t));
628 new_gai->frame_num = rtp_listinfo->first_frame_num;
629 new_gai->time = nstime_to_sec(&rtp_listinfo->start_rel);
630 COPY_ADDRESS(&(new_gai->src_addr),&(rtp_listinfo->src_addr));
631 COPY_ADDRESS(&(new_gai->dst_addr),&(rtp_listinfo->dest_addr));
632 new_gai->port_src = rtp_listinfo->src_port;
633 new_gai->port_dst = rtp_listinfo->dest_port;
634 duration = (guint32)(nstime_to_msec(&rtp_listinfo->stop_rel) - nstime_to_msec(&rtp_listinfo->start_rel));
635 new_gai->frame_label = g_strdup_printf("%s (%s) %s",
636 (rtp_listinfo->is_srtp)?"SRTP":"RTP",
637 rtp_listinfo->pt_str,
638 (rtp_listinfo->rtp_event == -1)?
639 "":val_to_str_const(rtp_listinfo->rtp_event, rtp_event_type_values, "Unknown RTP Event"));
640 new_gai->comment = g_strdup_printf("%s Num packets:%u Duration:%u.%03us SSRC:0x%X",
641 (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->npackets,
642 duration/1000,(duration%1000), rtp_listinfo->ssrc);
643 new_gai->conv_num = conv_num;
644 new_gai->display=FALSE;
645 new_gai->line_style = 2; /* the arrow line will be 2 pixels width */
646 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item);
649 if (voip_calls_graph_list) item++;
653 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
655 rtp_streams_list = g_list_next(rtp_streams_list);
659 static gboolean have_RTP_tap_listener=FALSE;
660 /****************************************************************************/
664 GString *error_string;
666 if(have_RTP_tap_listener==FALSE)
668 /* don't register tap listener, if we have it already */
669 error_string = register_tap_listener("rtp", &(the_tapinfo_rtp_struct.rtp_dummy), NULL,
675 if (error_string != NULL) {
676 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
677 "%s", error_string->str);
678 g_string_free(error_string, TRUE);
681 have_RTP_tap_listener=TRUE;
685 /****************************************************************************/
687 remove_tap_listener_rtp(void)
689 protect_thread_critical_region();
690 remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_dummy));
691 unprotect_thread_critical_region();
693 have_RTP_tap_listener=FALSE;
696 /****************************************************************************/
697 /******************************TAP for T38 **********************************/
698 /****************************************************************************/
700 /****************************************************************************/
701 /* whenever a T38 packet is seen by the tap listener */
703 T38_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *T38info)
705 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
707 voip_calls_info_t *callsinfo = NULL;
708 voip_calls_info_t *tmp_listinfo;
709 GList *voip_calls_graph_list;
711 gchar *frame_label = NULL;
712 gchar *comment = NULL;
713 graph_analysis_item_t *tmp_gai, *gai = NULL;
714 guint16 line_style = 2;
718 const t38_packet_info *pi = T38info;
720 if (pi->setup_frame_number != 0) {
721 /* using the setup frame number of the T38 packet, we get the call number that it belongs */
722 voip_calls_graph_list = g_list_first(tapinfo->graph_analysis->list);
723 while (voip_calls_graph_list)
725 tmp_gai = voip_calls_graph_list->data;
726 if (pi->setup_frame_number == tmp_gai->frame_num){
730 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
732 if (gai) conv_num = (int) gai->conv_num;
735 /* 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
736 * have the associated Voip calls. It probably means the the packet was decoded using the default t38 port, or using "Decode as.."
737 * in this case we create a "voip" call that only have t38 media (no signaling)
738 * OR if we have not found the Setup message in the graph.
740 if ( (pi->setup_frame_number == 0) || (gai == NULL) ){
741 /* check whether we already have a call with these parameters in the list */
742 list = g_list_first(tapinfo->callsinfo_list);
745 tmp_listinfo=list->data;
746 if (tmp_listinfo->protocol == MEDIA_T38){
747 callsinfo = (voip_calls_info_t*)(list->data);
750 list = g_list_next (list);
753 /* not in the list? then create a new entry */
754 if (callsinfo==NULL){
755 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
756 callsinfo->call_active_state = VOIP_ACTIVE;
757 callsinfo->call_state = VOIP_UNKNOWN;
758 callsinfo->from_identity=g_strdup("T38 Media only");
759 callsinfo->to_identity=g_strdup("T38 Media only");
760 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
761 callsinfo->first_frame_num=pinfo->fd->num;
762 callsinfo->selected=FALSE;
763 callsinfo->start_abs = pinfo->fd->abs_ts;
764 callsinfo->start_rel = pinfo->fd->rel_ts;
765 callsinfo->protocol=MEDIA_T38;
766 callsinfo->prot_info=NULL;
767 callsinfo->free_prot_info = NULL;
768 callsinfo->npackets = 0;
769 callsinfo->call_num = tapinfo->ncalls++;
770 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
772 ++(callsinfo->npackets);
773 /* increment the packets counter of all calls */
774 ++(tapinfo->npackets);
776 conv_num = (int) callsinfo->call_num;
779 /* at this point we should have found the call num for this t38 packets belong */
780 if (conv_num == -1) {
784 /* add the item to the graph list */
785 if (pi->type_msg == 0) { /* 0=t30-indicator */
786 frame_label = g_strdup(val_to_str(pi->t30ind_value, t38_T30_indicator_vals, "Ukn (0x%02X)") );
787 comment = g_strdup_printf("t38:t30 Ind:%s",val_to_str(pi->t30ind_value, t38_T30_indicator_vals, "Ukn (0x%02X)") );
789 } else if (pi->type_msg == 1) { /* 1=data */
790 switch(pi->Data_Field_field_type_value){
791 case 0: /* hdlc-data */
793 case 2: /* hdlc-fcs-OK */
794 case 4: /* hdlc-fcs-OK-sig-end */
795 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);
796 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)"));
798 case 3: /* hdlc-fcs-BAD */
799 case 5: /* hdlc-fcs-BAD-sig-end */
800 frame_label = g_strdup(pi->Data_Field_field_type_value == 3 ? "fcs-BAD" : "fcs-BAD-sig-end");
801 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");
803 case 7: /* t4-non-ecm-sig-end */
804 duration = nstime_to_sec(&pinfo->fd->rel_ts) - pi->time_first_t4_data;
805 frame_label = g_strdup_printf("t4-non-ecm-data:%s",val_to_str(pi->data_value, t38_T30_data_vals, "Ukn (0x%02X)") );
806 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 );
807 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);
812 if (frame_label && !(pi->Data_Field_field_type_value == 7 && pi->type_msg == 1)) {
813 add_to_graph(tapinfo, pinfo, frame_label, comment, (guint16)conv_num, &(pinfo->src), &(pinfo->dst), line_style);
819 tapinfo->redraw = TRUE;
821 return 1; /* refresh output */
824 static gboolean have_T38_tap_listener=FALSE;
825 /****************************************************************************/
829 GString *error_string;
831 if(have_T38_tap_listener==FALSE)
833 /* don't register tap listener, if we have it already */
834 error_string = register_tap_listener("t38", &(the_tapinfo_struct.t38_dummy), NULL,
836 voip_calls_dlg_reset,
840 if (error_string != NULL) {
841 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
842 "%s", error_string->str);
843 g_string_free(error_string, TRUE);
846 have_T38_tap_listener=TRUE;
850 /****************************************************************************/
852 remove_tap_listener_t38(void)
854 protect_thread_critical_region();
855 remove_tap_listener(&(the_tapinfo_struct.t38_dummy));
856 unprotect_thread_critical_region();
858 have_T38_tap_listener=FALSE;
862 /****************************************************************************/
863 static gchar *sdp_summary = NULL;
864 static guint32 sdp_frame_num = 0;
866 /****************************************************************************/
867 /* ***************************TAP for SIP **********************************/
868 /****************************************************************************/
871 static void free_sip_info(gpointer p) {
872 sip_calls_info_t *si = p;
874 g_free(si->call_identifier);
878 /****************************************************************************/
879 /* whenever a SIP packet is seen by the tap listener */
881 SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SIPinfo)
883 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
884 /* we just take note of the ISUP data here; when we receive the MTP3 part everything will
885 be compared with existing calls */
887 voip_calls_info_t *tmp_listinfo;
888 voip_calls_info_t *callsinfo = NULL;
889 sip_calls_info_t *tmp_sipinfo = NULL;
891 address tmp_src, tmp_dst;
892 gchar *frame_label = NULL;
893 gchar *comment = NULL;
895 const sip_info_value_t *pi = SIPinfo;
897 /* do not consider packets without call_id */
898 if (pi->tap_call_id ==NULL){
902 /* check whether we already have a call with these parameters in the list */
903 list = g_list_first(tapinfo->callsinfo_list);
906 tmp_listinfo=list->data;
907 if (tmp_listinfo->protocol == VOIP_SIP){
908 tmp_sipinfo = tmp_listinfo->prot_info;
909 if (strcmp(tmp_sipinfo->call_identifier,pi->tap_call_id)==0){
910 callsinfo = (voip_calls_info_t*)(list->data);
914 list = g_list_next (list);
917 /* not in the list? then create a new entry if the message is INVITE -i.e. if this session is a call*/
918 if ((callsinfo==NULL) &&(pi->request_method!=NULL)){
919 if (strcmp(pi->request_method,"INVITE")==0){
920 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
921 callsinfo->call_active_state = VOIP_ACTIVE;
922 callsinfo->call_state = VOIP_CALL_SETUP;
923 callsinfo->from_identity=g_strdup(pi->tap_from_addr);
924 callsinfo->to_identity=g_strdup(pi->tap_to_addr);
925 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
926 callsinfo->first_frame_num=pinfo->fd->num;
927 callsinfo->selected=FALSE;
928 callsinfo->start_abs=pinfo->fd->abs_ts;
929 callsinfo->start_rel=pinfo->fd->rel_ts;
930 callsinfo->protocol=VOIP_SIP;
931 callsinfo->prot_info=g_malloc(sizeof(sip_calls_info_t));
932 callsinfo->free_prot_info = free_sip_info;
933 tmp_sipinfo = callsinfo->prot_info;
934 tmp_sipinfo->call_identifier = g_strdup(pi->tap_call_id);
935 tmp_sipinfo->sip_state = SIP_INVITE_SENT;
936 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
937 callsinfo->npackets = 0;
938 callsinfo->call_num = tapinfo->ncalls++;
939 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
943 if (callsinfo!=NULL){
945 /* let's analyze the call state */
947 COPY_ADDRESS(&(tmp_src), &(pinfo->src));
948 COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
950 if (pi->request_method == NULL){
951 frame_label = g_strdup_printf("%u %s", pi->response_code, pi->reason_phrase );
952 comment = g_strdup("SIP Status");
954 if ((tmp_sipinfo && pi->tap_cseq_number == tmp_sipinfo->invite_cseq)&&(ADDRESSES_EQUAL(&tmp_dst,&(callsinfo->initial_speaker)))){
955 if ((pi->response_code > 199) && (pi->response_code<300) && (tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
956 tmp_sipinfo->sip_state = SIP_200_REC;
958 else if ((pi->response_code>299)&&(tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
959 callsinfo->call_state = VOIP_REJECTED;
960 tapinfo->rejected_calls++;
966 frame_label = g_strdup(pi->request_method);
968 if ((strcmp(pi->request_method,"INVITE")==0)&&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))){
969 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
970 callsinfo->call_state = VOIP_CALL_SETUP;
971 comment = g_strdup_printf("SIP From: %s To:%s", callsinfo->from_identity, callsinfo->to_identity);
973 else if ((strcmp(pi->request_method,"ACK")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
974 &&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))&&(tmp_sipinfo->sip_state==SIP_200_REC)
975 &&(callsinfo->call_state == VOIP_CALL_SETUP)){
976 callsinfo->call_state = VOIP_IN_CALL;
977 comment = g_strdup("SIP Request");
979 else if (strcmp(pi->request_method,"BYE")==0){
980 callsinfo->call_state = VOIP_COMPLETED;
981 tapinfo->completed_calls++;
982 comment = g_strdup("SIP Request");
984 else if ((strcmp(pi->request_method,"CANCEL")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
985 &&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))&&(callsinfo->call_state==VOIP_CALL_SETUP)){
986 callsinfo->call_state = VOIP_CANCELLED;
987 tmp_sipinfo->sip_state = SIP_CANCEL_SENT;
988 comment = g_strdup("SIP Request");
990 comment = g_strdup("SIP Request");
994 callsinfo->stop_abs = pinfo->fd->abs_ts;
995 callsinfo->stop_rel = pinfo->fd->rel_ts;
996 callsinfo->last_frame_num=pinfo->fd->num;
997 ++(callsinfo->npackets);
998 /* increment the packets counter of all calls */
999 ++(tapinfo->npackets);
1001 /* add to the graph */
1002 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1004 g_free(frame_label);
1005 g_free((void *)tmp_src.data);
1006 g_free((void *)tmp_dst.data);
1008 /* add SDP info if apply */
1009 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
1010 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
1011 g_free(sdp_summary);
1016 tapinfo->redraw = TRUE;
1018 return 1; /* refresh output */
1022 /****************************************************************************/
1023 voip_calls_tapinfo_t* voip_calls_get_info(void)
1025 return &the_tapinfo_struct;
1029 /****************************************************************************/
1031 /****************************************************************************/
1032 static gboolean have_SIP_tap_listener=FALSE;
1033 /****************************************************************************/
1035 sip_calls_init_tap(void)
1037 GString *error_string;
1039 if(have_SIP_tap_listener==FALSE)
1041 /* don't register tap listener, if we have it already */
1042 error_string = register_tap_listener("sip", &(the_tapinfo_struct.sip_dummy), NULL,
1044 voip_calls_dlg_reset,
1048 if (error_string != NULL) {
1049 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1050 "%s", error_string->str);
1051 g_string_free(error_string, TRUE);
1054 have_SIP_tap_listener=TRUE;
1058 /****************************************************************************/
1060 remove_tap_listener_sip_calls(void)
1062 protect_thread_critical_region();
1063 remove_tap_listener(&(the_tapinfo_struct.sip_dummy));
1064 unprotect_thread_critical_region();
1066 have_SIP_tap_listener=FALSE;
1069 /****************************************************************************/
1070 /* ***************************TAP for ISUP **********************************/
1071 /****************************************************************************/
1073 static guint32 mtp3_opc, mtp3_dpc;
1074 static guint8 mtp3_ni;
1075 static guint32 mtp3_frame_num;
1078 /****************************************************************************/
1079 /* whenever a isup_ packet is seen by the tap listener */
1081 isup_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *isup_info _U_)
1083 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1084 voip_calls_info_t *tmp_listinfo;
1085 voip_calls_info_t *callsinfo = NULL;
1086 isup_calls_info_t *tmp_isupinfo;
1087 gboolean found = FALSE;
1088 gboolean forward = FALSE;
1089 gboolean right_pair;
1091 gchar *frame_label = NULL;
1092 gchar *comment = NULL;
1094 /*voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct; unused */
1095 const isup_tap_rec_t *pi = isup_info;
1097 /* check if the lower layer is MTP matching the frame number */
1098 if (mtp3_frame_num != pinfo->fd->num) return 0;
1100 /* check whether we already have a call with these parameters in the list */
1101 list = g_list_first(tapinfo->callsinfo_list);
1105 tmp_listinfo=list->data;
1106 if ((tmp_listinfo->protocol == VOIP_ISUP)&&(tmp_listinfo->call_active_state==VOIP_ACTIVE)){
1107 tmp_isupinfo = tmp_listinfo->prot_info;
1108 if ((tmp_isupinfo->cic == pinfo->circuit_id)&&(tmp_isupinfo->ni == mtp3_ni)) {
1109 if ((tmp_isupinfo->opc == mtp3_opc)&&(tmp_isupinfo->dpc == mtp3_dpc)){
1111 } else if ((tmp_isupinfo->dpc == mtp3_opc)&&(tmp_isupinfo->opc == mtp3_dpc)){
1118 /* if there is an IAM for a call that is not in setup state, that means the previous call in the same
1119 cic is no longer active */
1120 if (tmp_listinfo->call_state == VOIP_CALL_SETUP){
1122 } else if (pi->message_type != 1){
1125 tmp_listinfo->call_active_state=VOIP_INACTIVE;
1130 callsinfo = (voip_calls_info_t*)(list->data);
1135 list = g_list_next (list);
1138 /* not in the list? then create a new entry if the message is IAM
1139 -i.e. if this session is a call*/
1142 if ((callsinfo==NULL) &&(pi->message_type==1)){
1143 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
1144 callsinfo->call_active_state = VOIP_ACTIVE;
1145 callsinfo->call_state = VOIP_UNKNOWN;
1146 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
1147 callsinfo->selected=FALSE;
1148 callsinfo->first_frame_num=pinfo->fd->num;
1149 callsinfo->start_abs=pinfo->fd->abs_ts;
1150 callsinfo->start_rel=pinfo->fd->rel_ts;
1151 callsinfo->protocol=VOIP_ISUP;
1152 if (pi->calling_number!=NULL){
1153 callsinfo->from_identity=g_strdup(pi->calling_number);
1155 if (pi->called_number!=NULL){
1156 callsinfo->to_identity=g_strdup(pi->called_number);
1158 callsinfo->prot_info=g_malloc(sizeof(isup_calls_info_t));
1159 callsinfo->free_prot_info = g_free;
1160 tmp_isupinfo=callsinfo->prot_info;
1161 tmp_isupinfo->opc = mtp3_opc;
1162 tmp_isupinfo->dpc = mtp3_dpc;
1163 tmp_isupinfo->ni = mtp3_ni;
1164 tmp_isupinfo->cic = pinfo->circuit_id;
1165 callsinfo->npackets = 0;
1166 callsinfo->call_num = tapinfo->ncalls++;
1167 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
1171 if (callsinfo!=NULL){
1172 callsinfo->stop_abs = pinfo->fd->abs_ts;
1173 callsinfo->stop_rel = pinfo->fd->rel_ts;
1174 callsinfo->last_frame_num=pinfo->fd->num;
1175 ++(callsinfo->npackets);
1177 /* Let's analyze the call state */
1179 frame_label = g_strdup(val_to_str_ext_const(pi->message_type, &isup_message_type_value_acro_ext, "Unknown"));
1181 if (callsinfo->npackets == 1){ /* this is the first packet, that must be an IAM */
1183 if ((pi->calling_number!=NULL)&&(pi->called_number !=NULL)){
1184 comment = g_strdup_printf("Call from %s to %s",
1185 pi->calling_number, pi->called_number);
1187 } else if (callsinfo->npackets == 2){ /* in the second packet we show the SPs */
1189 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
1191 mtp3_ni, mtp3_dpc, pinfo->circuit_id);
1193 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
1195 mtp3_ni, mtp3_opc, pinfo->circuit_id);
1200 switch(pi->message_type){
1202 callsinfo->call_state=VOIP_CALL_SETUP;
1204 case 7: /* CONNECT */
1205 case 9: /* ANSWER */
1206 callsinfo->call_state=VOIP_IN_CALL;
1208 case 12: /* RELEASE */
1209 if (callsinfo->call_state==VOIP_CALL_SETUP){
1211 callsinfo->call_state=VOIP_CANCELLED;
1214 callsinfo->call_state=VOIP_REJECTED;
1215 tapinfo->rejected_calls++;
1218 else if (callsinfo->call_state == VOIP_IN_CALL){
1219 callsinfo->call_state = VOIP_COMPLETED;
1220 tapinfo->completed_calls++;
1222 comment = g_strdup_printf("Cause %i - %s",
1224 val_to_str_ext_const(pi->cause_value, &q931_cause_code_vals_ext, "(Unknown)"));
1228 /* increment the packets counter of all calls */
1229 ++(tapinfo->npackets);
1231 /* add to the graph */
1232 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1234 g_free(frame_label);
1237 tapinfo->redraw = TRUE;
1239 return 1; /* refresh output */
1242 /****************************************************************************/
1244 static gboolean have_isup_tap_listener=FALSE;
1247 isup_calls_init_tap(void)
1249 GString *error_string;
1252 if(have_isup_tap_listener==FALSE)
1254 error_string = register_tap_listener("isup", &(the_tapinfo_struct.isup_dummy),
1257 voip_calls_dlg_reset,
1262 if (error_string != NULL) {
1263 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1264 "%s", error_string->str);
1265 g_string_free(error_string, TRUE);
1268 have_isup_tap_listener=TRUE;
1272 /****************************************************************************/
1275 remove_tap_listener_isup_calls(void)
1277 protect_thread_critical_region();
1278 remove_tap_listener(&(the_tapinfo_struct.isup_dummy));
1279 unprotect_thread_critical_region();
1281 have_isup_tap_listener=FALSE;
1285 /****************************************************************************/
1286 /* ***************************TAP for MTP3 **********************************/
1287 /****************************************************************************/
1290 /****************************************************************************/
1291 /* whenever a mtp3_ packet is seen by the tap listener */
1293 mtp3_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *mtp3_info _U_)
1295 const mtp3_tap_rec_t *pi = mtp3_info;
1297 /* keep the data in memory to use when the ISUP information arrives */
1299 mtp3_opc = pi->addr_opc.pc;
1300 mtp3_dpc = pi->addr_dpc.pc;
1301 mtp3_ni = pi->addr_opc.ni;
1302 mtp3_frame_num = pinfo->fd->num;
1307 /****************************************************************************/
1309 static gboolean have_mtp3_tap_listener=FALSE;
1310 static gboolean have_m3ua_tap_listener=FALSE;
1313 mtp3_calls_init_tap(void)
1315 GString *error_string;
1318 if(have_mtp3_tap_listener==FALSE)
1320 error_string = register_tap_listener("mtp3", &(the_tapinfo_struct.mtp3_dummy),
1323 voip_calls_dlg_reset,
1328 if (error_string != NULL) {
1329 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1330 "%s", error_string->str);
1331 g_string_free(error_string, TRUE);
1334 have_mtp3_tap_listener=TRUE;
1337 if(have_m3ua_tap_listener==FALSE)
1339 error_string = register_tap_listener("m3ua", &(the_tapinfo_struct.mtp3_dummy),
1342 voip_calls_dlg_reset,
1347 if (error_string != NULL) {
1348 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1349 "%s", error_string->str);
1350 g_string_free(error_string, TRUE);
1353 have_m3ua_tap_listener=TRUE;
1358 /****************************************************************************/
1361 remove_tap_listener_mtp3_calls(void)
1363 protect_thread_critical_region();
1364 remove_tap_listener(&(the_tapinfo_struct.mtp3_dummy));
1365 remove_tap_listener(&(the_tapinfo_struct.m3ua_dummy));
1366 unprotect_thread_critical_region();
1368 have_mtp3_tap_listener=FALSE;
1369 have_m3ua_tap_listener=FALSE;
1372 /****************************************************************************/
1373 /* ***************************TAP for Q931 **********************************/
1374 /****************************************************************************/
1375 void h245_add_to_graph(guint32 new_frame_num);
1376 static const e_guid_t guid_allzero = {0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };
1377 /* defines specific H323 data */
1379 static gchar *q931_calling_number;
1380 static gchar *q931_called_number;
1381 static guint8 q931_cause_value;
1382 static gint32 q931_crv;
1383 static guint32 q931_frame_num;
1385 static guint32 h225_frame_num = 0;
1386 static guint16 h225_call_num = 0;
1387 static h225_cs_type h225_cstype = H225_OTHER;
1388 static gboolean h225_is_faststart;
1390 static guint32 actrace_frame_num = 0;
1391 static gint32 actrace_trunk = 0;
1392 static gint32 actrace_direction = 0;
1395 /****************************************************************************/
1396 /* whenever a q931_ packet is seen by the tap listener */
1398 q931_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *q931_info)
1401 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1402 h323_calls_info_t *tmp_h323info,*tmp2_h323info;
1403 actrace_isdn_calls_info_t *tmp_actrace_isdn_info;
1404 voip_calls_info_t *tmp_listinfo;
1405 voip_calls_info_t *callsinfo = NULL;
1406 h245_address_t *h245_add = NULL;
1409 const q931_packet_info *pi = q931_info;
1411 /* free previously allocated q931_calling/ed_number */
1412 g_free(q931_calling_number);
1413 g_free(q931_called_number);
1415 if (pi->calling_number!=NULL)
1416 q931_calling_number = g_strdup(pi->calling_number);
1418 q931_calling_number = g_strdup("");
1420 if (pi->called_number!=NULL)
1421 q931_called_number = g_strdup(pi->called_number);
1423 q931_called_number = g_strdup("");
1424 q931_cause_value = pi->cause_value;
1425 q931_frame_num = pinfo->fd->num;
1429 /* add staff to H323 calls */
1430 if (h225_frame_num == q931_frame_num) {
1431 tmp_h323info = NULL;
1432 list = g_list_first(tapinfo->callsinfo_list);
1435 tmp_listinfo=list->data;
1436 if ( (tmp_listinfo->protocol == VOIP_H323) && (tmp_listinfo->call_num == h225_call_num) ){
1437 tmp_h323info = tmp_listinfo->prot_info;
1438 callsinfo = (voip_calls_info_t*)(list->data);
1440 /* Add the CRV to the h323 call */
1441 if (tmp_h323info->q931_crv == -1) {
1442 tmp_h323info->q931_crv = q931_crv;
1443 } else if (tmp_h323info->q931_crv != q931_crv) {
1444 tmp_h323info->q931_crv2 = q931_crv;
1448 list = g_list_next (list);
1451 if (callsinfo != NULL) {
1453 if (h225_cstype == H225_SETUP) {
1454 /* set te calling and called number from the Q931 packet */
1455 if (q931_calling_number != NULL){
1456 g_free(callsinfo->from_identity);
1457 callsinfo->from_identity=g_strdup(q931_calling_number);
1459 if (q931_called_number != NULL){
1460 g_free(callsinfo->to_identity);
1461 callsinfo->to_identity=g_strdup(q931_called_number);
1464 /* check if there is an LRQ/LCF that match this Setup */
1465 /* TODO: we are just checking the DialedNumer in LRQ/LCF agains the Setup
1466 we should also check if the h225 signaling IP and port match the destination
1467 Setup ip and port */
1468 list = g_list_first(tapinfo->callsinfo_list);
1471 tmp_listinfo=list->data;
1472 if (tmp_listinfo->protocol == VOIP_H323){
1473 tmp2_h323info = tmp_listinfo->prot_info;
1475 /* check if the called number match a LRQ/LCF */
1476 if ( (strcmp(callsinfo->to_identity, tmp_listinfo->to_identity)==0)
1477 && (memcmp(&tmp2_h323info->guid, &guid_allzero, GUID_LEN) == 0) ){
1478 /* change the call graph to the LRQ/LCF to belong to this call */
1479 callsinfo->npackets += change_call_num_graph(tapinfo, tmp_listinfo->call_num, callsinfo->call_num);
1481 /* remove this LRQ/LCF call entry because we have found the Setup that match them */
1482 g_free(tmp_listinfo->from_identity);
1483 g_free(tmp_listinfo->to_identity);
1484 g_free(tmp2_h323info->guid);
1486 list2 = g_list_first(tmp2_h323info->h245_list);
1489 h245_add=list2->data;
1490 g_free((void *)h245_add->h245_address.data);
1491 g_free(list2->data);
1492 list2 = g_list_next(list2);
1494 g_list_free(tmp_h323info->h245_list);
1495 tmp_h323info->h245_list = NULL;
1496 g_free(tmp_listinfo->prot_info);
1497 tapinfo->callsinfo_list = g_list_remove(tapinfo->callsinfo_list, tmp_listinfo);
1501 list = g_list_next (list);
1504 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"),
1505 (h225_is_faststart==TRUE?"on":"off"));
1506 } else if (h225_cstype == H225_RELEASE_COMPLET) {
1507 /* get the Q931 Release cause code */
1508 if (q931_cause_value != 0xFF){
1509 comment = g_strdup_printf("H225 Q931 Rel Cause (%i):%s", q931_cause_value,
1510 val_to_str_ext_const(q931_cause_value, &q931_cause_code_vals_ext, "<unknown>"));
1511 } else { /* Cause not set */
1512 comment = g_strdup("H225 No Q931 Rel Cause");
1515 /* change the graph comment for this new one */
1516 if (comment != NULL) {
1517 change_frame_graph(tapinfo, h225_frame_num, NULL, comment);
1521 /* we reset the h225_frame_num to 0 because there could be empty h225 in the same frame
1522 as non empty h225 (e.g connect), so we don't have to be here twice */
1525 /* add staff to H245 */
1526 } else if (h245_labels.frame_num == q931_frame_num) {
1527 /* there are empty H225 frames that don't have guid (guaid=0) but they have h245 info,
1528 so the only way to match those frames is with the Q931 CRV number */
1529 list = g_list_first(tapinfo->callsinfo_list);
1532 tmp_listinfo=list->data;
1533 if (tmp_listinfo->protocol == VOIP_H323){
1534 tmp_h323info = tmp_listinfo->prot_info;
1535 if ( ((tmp_h323info->q931_crv == q931_crv) || (tmp_h323info->q931_crv2 == q931_crv)) && (q931_crv!=-1)){
1536 /* if the frame number exists in graph, append to it*/
1537 if (!append_to_frame_graph(tapinfo, q931_frame_num, NULL, NULL)) {
1538 /* if not exist, add to the graph */
1539 add_to_graph(tapinfo, pinfo, NULL, NULL, tmp_listinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1540 ++(tmp_listinfo->npackets);
1541 /* increment the packets counter of all calls */
1542 ++(tapinfo->npackets);
1545 /* Add the H245 info if exists to the Graph */
1546 h245_add_to_graph(pinfo->fd->num);
1550 list = g_list_next (list);
1553 /* add staff to ACTRACE */
1554 } else if (actrace_frame_num == q931_frame_num) {
1559 list = g_list_first(tapinfo->callsinfo_list);
1562 tmp_listinfo=list->data;
1563 if ( tmp_listinfo->protocol == VOIP_AC_ISDN ){
1564 tmp_actrace_isdn_info = tmp_listinfo->prot_info;
1565 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
1566 if ( (tmp_actrace_isdn_info->crv == q931_crv) && (tmp_actrace_isdn_info->trunk == actrace_trunk) ) {
1567 callsinfo = (voip_calls_info_t*)(list->data);
1571 list = g_list_next (list);
1574 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, g_strdup("PSTN"));
1576 /* if it is a new call, add it to the list */
1578 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
1579 callsinfo->call_active_state = VOIP_ACTIVE;
1580 callsinfo->call_state = VOIP_CALL_SETUP;
1581 callsinfo->from_identity=g_strdup(q931_calling_number);
1582 callsinfo->to_identity=g_strdup(q931_called_number);
1583 COPY_ADDRESS(&(callsinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
1584 callsinfo->first_frame_num=pinfo->fd->num;
1585 callsinfo->selected=FALSE;
1586 callsinfo->start_abs=pinfo->fd->abs_ts;
1587 callsinfo->start_rel=pinfo->fd->rel_ts;
1588 callsinfo->protocol=VOIP_AC_ISDN;
1589 callsinfo->prot_info=g_malloc(sizeof(actrace_isdn_calls_info_t));
1590 callsinfo->free_prot_info = g_free;
1591 tmp_actrace_isdn_info=callsinfo->prot_info;
1592 tmp_actrace_isdn_info->crv=q931_crv;
1593 tmp_actrace_isdn_info->trunk=actrace_trunk;
1594 callsinfo->npackets = 0;
1595 callsinfo->call_num = tapinfo->ncalls++;
1596 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
1599 callsinfo->stop_abs = pinfo->fd->abs_ts;
1600 callsinfo->stop_rel = pinfo->fd->rel_ts;
1601 callsinfo->last_frame_num=pinfo->fd->num;
1602 ++(callsinfo->npackets);
1603 /* increment the packets counter of all calls */
1604 ++(tapinfo->npackets);
1606 switch(pi->message_type){
1608 comment = g_strdup_printf("AC_ISDN trunk:%u Calling: %s Called:%s", actrace_trunk, q931_calling_number, q931_called_number);
1609 callsinfo->call_state=VOIP_CALL_SETUP;
1612 callsinfo->call_state=VOIP_IN_CALL;
1614 case Q931_RELEASE_COMPLETE:
1616 case Q931_DISCONNECT:
1617 if (callsinfo->call_state==VOIP_CALL_SETUP){
1618 if (ADDRESSES_EQUAL(&(callsinfo->initial_speaker), actrace_direction?&pstn_add:&(pinfo->src) )){ /* forward direction */
1619 callsinfo->call_state=VOIP_CANCELLED;
1622 callsinfo->call_state=VOIP_REJECTED;
1623 tapinfo->rejected_calls++;
1625 } else if ( (callsinfo->call_state!=VOIP_CANCELLED) && (callsinfo->call_state!=VOIP_REJECTED) ){
1626 callsinfo->call_state=VOIP_COMPLETED;
1627 tapinfo->completed_calls++;
1629 if (q931_cause_value != 0xFF){
1630 comment = g_strdup_printf("AC_ISDN trunk:%u Q931 Rel Cause (%i):%s", actrace_trunk, q931_cause_value,
1631 val_to_str_ext_const(q931_cause_value, &q931_cause_code_vals_ext, "<unknown>"));
1632 } else { /* Cause not set */
1633 comment = g_strdup("AC_ISDN No Q931 Rel Cause");
1639 comment = g_strdup_printf("AC_ISDN trunk:%u", actrace_trunk );
1641 add_to_graph(tapinfo, pinfo, val_to_str(pi->message_type, q931_message_type_vals, "<unknown>") , comment, callsinfo->call_num,
1642 actrace_direction?&pstn_add:&(pinfo->src),
1643 actrace_direction?&(pinfo->src):&pstn_add,
1647 g_free((char *)pstn_add.data);
1650 tapinfo->redraw = TRUE;
1652 return 1; /* refresh output */
1655 /****************************************************************************/
1656 static gboolean have_q931_tap_listener=FALSE;
1659 q931_calls_init_tap(void)
1661 GString *error_string;
1664 if(have_q931_tap_listener==FALSE)
1666 error_string = register_tap_listener("q931", &(the_tapinfo_struct.q931_dummy),
1669 voip_calls_dlg_reset,
1674 if (error_string != NULL) {
1675 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1676 "%s", error_string->str);
1677 g_string_free(error_string, TRUE);
1680 have_q931_tap_listener=TRUE;
1684 /****************************************************************************/
1687 remove_tap_listener_q931_calls(void)
1689 protect_thread_critical_region();
1690 remove_tap_listener(&(the_tapinfo_struct.q931_dummy));
1691 unprotect_thread_critical_region();
1693 have_q931_tap_listener=FALSE;
1696 /****************************************************************************/
1697 /****************************TAP for H323 ***********************************/
1698 /****************************************************************************/
1700 static void add_h245_Address(h323_calls_info_t *h323info, h245_address_t *h245_address)
1702 h323info->h245_list = g_list_append(h323info->h245_list, h245_address);
1706 static void free_h225_info(gpointer p) {
1707 h323_calls_info_t *tmp_h323info = p;
1709 g_free(tmp_h323info->guid);
1711 if (tmp_h323info->h245_list) {
1712 GList *list2 = g_list_first(tmp_h323info->h245_list);
1715 h245_address_t *h245_add=list2->data;
1716 g_free((void *)h245_add->h245_address.data);
1717 g_free(list2->data);
1718 list2 = g_list_next(list2);
1721 g_list_free(tmp_h323info->h245_list);
1727 /****************************************************************************/
1728 /* whenever a H225 packet is seen by the tap listener */
1730 H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H225info)
1732 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1733 voip_calls_info_t *tmp_listinfo;
1734 voip_calls_info_t *callsinfo = NULL;
1735 h323_calls_info_t *tmp_h323info = NULL;
1739 h245_address_t *h245_add = NULL;
1741 const h225_packet_info *pi = H225info;
1743 /* if not guid and RAS and not LRQ, LCF or LRJ return because did not belong to a call */
1744 /* OR, if not guid and is H225 return because doesn't belong to a call */
1745 if ((memcmp(&pi->guid, &guid_allzero, GUID_LEN) == 0))
1746 if ( ((pi->msg_type == H225_RAS) && ((pi->msg_tag < 18) || (pi->msg_tag > 20))) || (pi->msg_type != H225_RAS) )
1749 /* if it is RAS LCF or LRJ*/
1750 if ( (pi->msg_type == H225_RAS) && ((pi->msg_tag == 19) || (pi->msg_tag == 20))) {
1751 /* if the LCF/LRJ doesn't match to a LRQ, just return */
1752 if (!pi->request_available) return 0;
1754 /* check whether we already have a call with this request SeqNum */
1755 list = g_list_first(tapinfo->callsinfo_list);
1758 tmp_listinfo=list->data;
1759 g_assert(tmp_listinfo != NULL);
1760 if (tmp_listinfo->protocol == VOIP_H323){
1761 tmp_h323info = tmp_listinfo->prot_info;
1762 if (tmp_h323info->requestSeqNum == pi->requestSeqNum) {
1763 callsinfo = (voip_calls_info_t*)(list->data);
1767 list = g_list_next (list);
1770 /* check whether we already have a call with this guid in the list */
1771 list = g_list_first(tapinfo->callsinfo_list);
1774 tmp_listinfo=list->data;
1775 if (tmp_listinfo->protocol == VOIP_H323){
1776 tmp_h323info = tmp_listinfo->prot_info;
1777 g_assert(tmp_h323info != NULL);
1778 if ( (memcmp(tmp_h323info->guid, &guid_allzero, GUID_LEN) != 0) && (memcmp(tmp_h323info->guid, &pi->guid,GUID_LEN)==0) ){
1779 callsinfo = (voip_calls_info_t*)(list->data);
1783 list = g_list_next (list);
1787 h225_cstype = pi->cs_type;
1788 h225_is_faststart = pi->is_faststart;
1790 /* not in the list? then create a new entry */
1791 if (callsinfo==NULL){
1792 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
1793 callsinfo->call_active_state = VOIP_ACTIVE;
1794 callsinfo->call_state = VOIP_UNKNOWN;
1795 callsinfo->from_identity=g_strdup("");
1796 callsinfo->to_identity=g_strdup("");
1797 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
1798 callsinfo->selected=FALSE;
1799 callsinfo->first_frame_num=pinfo->fd->num;
1800 callsinfo->start_abs=pinfo->fd->abs_ts;
1801 callsinfo->start_rel=pinfo->fd->rel_ts;
1802 callsinfo->protocol=VOIP_H323;
1803 callsinfo->prot_info=g_malloc(sizeof(h323_calls_info_t));
1804 callsinfo->free_prot_info = free_h225_info;
1806 tmp_h323info = callsinfo->prot_info;
1807 g_assert(tmp_h323info != NULL);
1808 tmp_h323info->guid = g_memdup(&pi->guid, sizeof pi->guid);
1809 tmp_h323info->h225SetupAddr.type = AT_NONE;
1810 tmp_h323info->h225SetupAddr.len = 0;
1811 tmp_h323info->h245_list = NULL;
1812 tmp_h323info->is_faststart_Setup = FALSE;
1813 tmp_h323info->is_faststart_Proc = FALSE;
1814 tmp_h323info->is_h245Tunneling = FALSE;
1815 tmp_h323info->is_h245 = FALSE;
1816 tmp_h323info->q931_crv = -1;
1817 tmp_h323info->q931_crv2 = -1;
1818 tmp_h323info->requestSeqNum = 0;
1819 callsinfo->call_num = tapinfo->ncalls++;
1820 callsinfo->npackets = 0;
1822 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
1825 if (callsinfo!=NULL){
1827 h225_frame_num = pinfo->fd->num;
1828 h225_call_num = callsinfo->call_num;
1830 /* let's analyze the call state */
1832 callsinfo->stop_abs = pinfo->fd->abs_ts;
1833 callsinfo->stop_rel = pinfo->fd->rel_ts;
1834 callsinfo->last_frame_num=pinfo->fd->num;
1835 ++(callsinfo->npackets);
1836 /* increment the packets counter of all calls */
1837 ++(tapinfo->npackets);
1840 /* XXX: it is supposed to be initialized isn't it? */
1841 g_assert(tmp_h323info != NULL);
1843 /* change the status */
1844 if (pi->msg_type == H225_CS){
1846 /* this is still IPv4 only, because the dissector is */
1847 if (pi->is_h245 == TRUE){
1848 h245_add = g_malloc(sizeof (h245_address_t));
1849 h245_add->h245_address.type=AT_IPv4;
1850 h245_add->h245_address.len=4;
1851 h245_add->h245_address.data = g_malloc(sizeof(pi->h245_address));
1852 memcpy((void *)(h245_add->h245_address.data), &(pi->h245_address), 4);
1853 h245_add->h245_port = pi->h245_port;
1854 add_h245_Address(tmp_h323info, h245_add);
1857 if (pi->cs_type != H225_RELEASE_COMPLET) tmp_h323info->is_h245Tunneling = pi->is_h245Tunneling;
1859 frame_label = g_strdup(pi->frame_label);
1861 switch(pi->cs_type){
1863 tmp_h323info->is_faststart_Setup = pi->is_faststart;
1865 /* Set the Setup address if it was not set */
1866 if (tmp_h323info->h225SetupAddr.type == AT_NONE)
1867 COPY_ADDRESS(&(tmp_h323info->h225SetupAddr), &(pinfo->src));
1868 callsinfo->call_state=VOIP_CALL_SETUP;
1869 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1870 (pi->is_faststart==TRUE?"on":"off"));
1873 callsinfo->call_state=VOIP_IN_CALL;
1874 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1875 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1876 (pi->is_faststart==TRUE?"on":"off"));
1878 case H225_RELEASE_COMPLET:
1879 if (callsinfo->call_state==VOIP_CALL_SETUP){
1880 if (ADDRESSES_EQUAL(&(tmp_h323info->h225SetupAddr),&(pinfo->src))){ /* forward direction */
1881 callsinfo->call_state=VOIP_CANCELLED;
1884 callsinfo->call_state=VOIP_REJECTED;
1885 tapinfo->rejected_calls++;
1888 callsinfo->call_state=VOIP_COMPLETED;
1889 tapinfo->completed_calls++;
1891 comment = g_strdup("H225 No Q931 Rel Cause");
1895 case H225_CALL_PROCEDING:
1896 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1897 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1898 (pi->is_faststart==TRUE?"on":"off"));
1901 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1902 (pi->is_faststart==TRUE?"on":"off"));
1906 else if (pi->msg_type == H225_RAS){
1907 switch(pi->msg_tag){
1909 if (!pi->is_duplicate){
1910 g_free(callsinfo->to_identity);
1911 callsinfo->to_identity=g_strdup(pi->dialedDigits);
1912 tmp_h323info->requestSeqNum = pi->requestSeqNum;
1915 if (strlen(pi->dialedDigits))
1916 comment = g_strdup_printf("H225 RAS dialedDigits: %s", pi->dialedDigits);
1918 comment = g_strdup("H225 RAS");
1921 comment = g_strdup("H225 RAS");
1923 frame_label = g_strdup(val_to_str_const(pi->msg_tag, h225_RasMessage_vals, "<unknown>"));
1925 frame_label = g_strdup("H225: Unknown");
1929 /* add to graph analysis */
1931 /* if the frame number exists in graph, append to it*/
1932 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, comment)) {
1933 /* if not exist, add to the graph */
1934 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1937 /* Add the H245 info if exists to the Graph */
1938 h245_add_to_graph(pinfo->fd->num);
1940 g_free(frame_label);
1944 tapinfo->redraw = TRUE;
1946 return 1; /* refresh output */
1950 /****************************************************************************/
1952 /****************************************************************************/
1953 static gboolean have_H225_tap_listener=FALSE;
1954 /****************************************************************************/
1956 h225_calls_init_tap(void)
1958 GString *error_string;
1960 if(have_H225_tap_listener==FALSE)
1962 /* don't register tap listener, if we have it already */
1963 error_string = register_tap_listener("h225", &(the_tapinfo_struct.h225_dummy), NULL,
1965 voip_calls_dlg_reset,
1970 if (error_string != NULL) {
1971 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1972 "%s", error_string->str);
1973 g_string_free(error_string, TRUE);
1976 have_H225_tap_listener=TRUE;
1980 /****************************************************************************/
1982 remove_tap_listener_h225_calls(void)
1984 protect_thread_critical_region();
1985 remove_tap_listener(&(the_tapinfo_struct.h225_dummy));
1986 unprotect_thread_critical_region();
1988 have_H225_tap_listener=FALSE;
1991 /* Add the h245 label info to the graph */
1992 void h245_add_to_graph(guint32 new_frame_num)
1996 if (new_frame_num != h245_labels.frame_num) return;
1998 for (n=0; n<h245_labels.labels_count; n++) {
1999 append_to_frame_graph(&the_tapinfo_struct, new_frame_num, h245_labels.labels[n].frame_label, h245_labels.labels[n].comment);
2000 g_free(h245_labels.labels[n].frame_label);
2001 h245_labels.labels[n].frame_label = NULL;
2002 g_free(h245_labels.labels[n].comment);
2003 h245_labels.labels[n].comment = NULL;
2005 h245_labels.frame_num = 0;
2006 h245_labels.labels_count = 0;
2009 /* free the h245_labels if the frame number is different */
2010 static void h245_free_labels(guint32 new_frame_num)
2014 if (new_frame_num == h245_labels.frame_num) return;
2016 for (n=0; n<h245_labels.labels_count; n++) {
2017 g_free(h245_labels.labels[n].frame_label);
2018 h245_labels.labels[n].frame_label = NULL;
2019 g_free(h245_labels.labels[n].comment);
2020 h245_labels.labels[n].comment = NULL;
2022 h245_labels.frame_num = 0;
2023 h245_labels.labels_count = 0;
2026 /* add the frame_label and comment to h245_labels and free the actual one if it is different frame num */
2027 static void h245_add_label(guint32 new_frame_num, const gchar *frame_label, const gchar *comment)
2029 h245_free_labels(new_frame_num);
2031 h245_labels.frame_num = new_frame_num;
2032 h245_labels.labels[h245_labels.labels_count].frame_label = g_strdup(frame_label);
2033 h245_labels.labels[h245_labels.labels_count].comment = g_strdup(comment);
2035 if (h245_labels.labels_count < (H245_MAX-1))
2036 h245_labels.labels_count++;
2040 /****************************************************************************/
2041 /* whenever a H245dg packet is seen by the tap listener (when H245 tunneling is ON) */
2043 H245dgcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H245info)
2045 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2046 voip_calls_info_t *tmp_listinfo;
2047 voip_calls_info_t *callsinfo = NULL;
2048 h323_calls_info_t *tmp_h323info;
2051 h245_address_t *h245_add = NULL;
2053 const h245_packet_info *pi = H245info;
2055 /* check if Tunneling is OFF and we have a call with this H245 add */
2056 list = g_list_first(tapinfo->callsinfo_list);
2059 tmp_listinfo=list->data;
2060 if (tmp_listinfo->protocol == VOIP_H323){
2061 tmp_h323info = tmp_listinfo->prot_info;
2063 list2 = g_list_first(tmp_h323info->h245_list);
2066 h245_add=list2->data;
2067 if ( (ADDRESSES_EQUAL(&(h245_add->h245_address),&(pinfo->src)) && (h245_add->h245_port == pinfo->srcport))
2068 || (ADDRESSES_EQUAL(&(h245_add->h245_address),&(pinfo->dst)) && (h245_add->h245_port == pinfo->destport)) ){
2069 callsinfo = (voip_calls_info_t*)(list->data);
2071 ++(callsinfo->npackets);
2072 /* increment the packets counter of all calls */
2073 ++(tapinfo->npackets);
2077 list2 = g_list_next(list2);
2079 if (callsinfo!=NULL) break;
2081 list = g_list_next(list);
2084 /* Tunnel is OFF, and we matched the h245 add so we add it to graph */
2085 if (callsinfo!=NULL){
2086 ++(callsinfo->npackets);
2087 /* increment the packets counter of all calls */
2088 ++(tapinfo->npackets);
2089 /* if the frame number exists in graph, append to it*/
2090 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, pi->comment)) {
2091 /* if not exist, add to the graph */
2092 add_to_graph(tapinfo, pinfo, pi->frame_label, pi->comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2095 /* Tunnel is ON, so we save the label info to use it into h225 or q931 tap. OR may be
2096 tunnel OFF but we did not matched the h245 add, in this case nobady will set this label
2097 since the frame_num will not match */
2099 h245_add_label(pinfo->fd->num, (gchar *) pi->frame_label, (gchar *) pi->comment);
2102 tapinfo->redraw = TRUE;
2104 return 1; /* refresh output */
2108 /****************************************************************************/
2110 /****************************************************************************/
2111 static gboolean have_H245dg_tap_listener=FALSE;
2112 /****************************************************************************/
2114 h245dg_calls_init_tap(void)
2116 GString *error_string;
2118 if(have_H245dg_tap_listener==FALSE)
2120 /* don't register tap listener, if we have it already */
2121 error_string = register_tap_listener("h245dg", &(the_tapinfo_struct.h245dg_dummy), NULL,
2123 voip_calls_dlg_reset,
2128 if (error_string != NULL) {
2129 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2130 "%s", error_string->str);
2131 g_string_free(error_string, TRUE);
2134 have_H245dg_tap_listener=TRUE;
2138 /****************************************************************************/
2140 remove_tap_listener_h245dg_calls(void)
2142 protect_thread_critical_region();
2143 remove_tap_listener(&(the_tapinfo_struct.h245dg_dummy));
2144 unprotect_thread_critical_region();
2146 have_H245dg_tap_listener=FALSE;
2149 /****************************************************************************/
2150 /****************************TAP for SDP PROTOCOL ***************************/
2151 /****************************************************************************/
2152 /* whenever a SDP packet is seen by the tap listener */
2154 SDPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SDPinfo)
2156 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2157 const sdp_packet_info *pi = SDPinfo;
2159 /* There are protocols like MGCP/SIP where the SDP is called before the tap for the
2160 MGCP/SIP packet, in those cases we assign the SPD summary to global lastSDPsummary
2163 g_free(sdp_summary);
2164 sdp_frame_num = pinfo->fd->num;
2165 /* Append to graph the SDP summary if the packet exists */
2166 sdp_summary = g_strdup_printf("SDP (%s)", pi->summary_str);
2167 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2169 tapinfo->redraw = TRUE;
2171 return 1; /* refresh output */
2175 /****************************************************************************/
2177 /****************************************************************************/
2178 static gboolean have_sdp_tap_listener=FALSE;
2179 /****************************************************************************/
2181 sdp_calls_init_tap(void)
2183 GString *error_string;
2185 if(have_sdp_tap_listener==FALSE)
2187 /* don't register tap listener, if we have it already */
2188 error_string = register_tap_listener("sdp", &(the_tapinfo_struct.sdp_dummy), NULL,
2190 voip_calls_dlg_reset,
2195 if (error_string != NULL) {
2196 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2197 "%s", error_string->str);
2198 g_string_free(error_string, TRUE);
2201 have_sdp_tap_listener=TRUE;
2205 /****************************************************************************/
2207 remove_tap_listener_sdp_calls(void)
2209 protect_thread_critical_region();
2210 remove_tap_listener(&(the_tapinfo_struct.sdp_dummy));
2211 unprotect_thread_critical_region();
2213 have_sdp_tap_listener=FALSE;
2218 /****************************************************************************/
2219 /* ***************************TAP for MGCP **********************************/
2220 /****************************************************************************/
2223 This function will look for a signal/event in the SignalReq/ObsEvent string
2224 and return true if it is found
2226 static gboolean isSignal(const gchar *signal_str_p, const gchar *signalStr)
2229 gchar **resultArray;
2231 /* if there is no signalStr, just return false */
2232 if (signalStr == NULL) return FALSE;
2234 /* if are both "blank" return true */
2235 if ( (*signal_str_p == '\0') && (*signalStr == '\0') ) return TRUE;
2237 /* look for signal in signalStr */
2238 resultArray = g_strsplit(signalStr, ",", 10);
2240 for (i = 0; resultArray[i]; i++) {
2241 g_strstrip(resultArray[i]);
2242 if (strcmp(resultArray[i], signal_str_p) == 0) return TRUE;
2245 g_strfreev(resultArray);
2251 This function will get the Caller ID info and replace the current string
2252 This is how it looks the caller Id: rg, ci(02/16/08/29, "3035550002","Ale Sipura 2")
2254 static void mgcpCallerID(gchar *signalStr, gchar **callerId)
2258 /* if there is no signalStr, just return false */
2259 if (signalStr == NULL) return;
2261 arrayStr = g_strsplit(signalStr, "\"", 10);
2263 if (arrayStr[0] == NULL) return;
2265 /* look for the ci signal */
2266 if (strstr(arrayStr[0], "ci(") && (arrayStr[1] != NULL) ) {
2267 /* free the previous "From" field of the call, and assign the new */
2269 *callerId = g_strdup(arrayStr[1]);
2271 g_strfreev(arrayStr);
2278 This function will get the Dialed Digits and replace the current string
2279 This is how it looks the dialed digits 5,5,5,0,0,0,2,#,*
2281 static void mgcpDialedDigits(gchar *signalStr, gchar **dialedDigits)
2284 gchar resultStr[50];
2287 /* if there is no signalStr, just return false */
2288 if (signalStr == NULL) return;
2290 tmpStr = g_strdup(signalStr);
2292 for ( i = 0 ; tmpStr[i] ; i++) {
2293 switch (tmpStr[i]) {
2294 case '0' : case '1' : case '2' : case '3' : case '4' :
2295 case '5' : case '6' : case '7' : case '8' : case '9' :
2296 case '#' : case '*' :
2304 for (i = 0, j = 0; tmpStr[i] && i<50; i++) {
2305 if (tmpStr[i] != '?')
2306 resultStr[j++] = tmpStr[i];
2308 resultStr[j] = '\0';
2310 if (*resultStr == '\0') return;
2312 g_free(*dialedDigits);
2313 *dialedDigits = g_strdup(resultStr);
2321 /****************************************************************************/
2322 /* whenever a MGCP packet is seen by the tap listener */
2324 MGCPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *MGCPinfo)
2326 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2328 voip_calls_info_t *tmp_listinfo;
2329 voip_calls_info_t *callsinfo = NULL;
2330 mgcp_calls_info_t *tmp_mgcpinfo = NULL;
2333 gchar *frame_label = NULL;
2334 gchar *comment = NULL;
2335 graph_analysis_item_t *gai;
2336 gboolean new = FALSE;
2337 gboolean fromEndpoint = FALSE; /* true for calls originated in Endpoints, false for calls from MGC */
2340 const mgcp_info_t *pi = MGCPinfo;
2343 if ((pi->mgcp_type == MGCP_REQUEST) && !pi->is_duplicate ){
2344 /* check whether we already have a call with this Endpoint and it is active*/
2345 list = g_list_first(tapinfo->callsinfo_list);
2348 tmp_listinfo=list->data;
2349 if ((tmp_listinfo->protocol == VOIP_MGCP) && (tmp_listinfo->call_active_state == VOIP_ACTIVE)){
2350 tmp_mgcpinfo = tmp_listinfo->prot_info;
2351 if (pi->endpointId != NULL){
2352 if (g_ascii_strcasecmp(tmp_mgcpinfo->endpointId,pi->endpointId) == 0){
2354 check first if it is an ended call. We can still match packets to this Endpoint 2 seconds
2355 after the call has been released
2357 diff_time = nstime_to_sec(&pinfo->fd->rel_ts) - nstime_to_sec(&tmp_listinfo->stop_rel);
2358 if ( ((tmp_listinfo->call_state == VOIP_CANCELLED) ||
2359 (tmp_listinfo->call_state == VOIP_COMPLETED) ||
2360 (tmp_listinfo->call_state == VOIP_REJECTED)) &&
2363 tmp_listinfo->call_active_state = VOIP_INACTIVE;
2365 callsinfo = (voip_calls_info_t*)(list->data);
2371 list = g_list_next (list);
2374 /* there is no call with this Endpoint, lets see if this a new call or not */
2375 if (callsinfo == NULL){
2376 if ( (strcmp(pi->code, "NTFY") == 0) && isSignal("hd", pi->observedEvents) ){ /* off hook transition */
2377 /* this is a new call from the Endpoint */
2378 fromEndpoint = TRUE;
2380 } else if (strcmp(pi->code, "CRCX") == 0){
2381 /* this is a new call from the MGC */
2382 fromEndpoint = FALSE;
2387 } else if ( ((pi->mgcp_type == MGCP_RESPONSE) && pi->request_available) ||
2388 ((pi->mgcp_type == MGCP_REQUEST) && pi->is_duplicate) ) {
2389 /* if it is a response OR if it is a duplicated Request, lets look in the Graph to see
2390 if there is a request that matches */
2391 listGraph = g_list_first(tapinfo->graph_analysis->list);
2394 gai = listGraph->data;
2395 if (gai->frame_num == pi->req_num){
2396 /* there is a request that match, so look the associated call with this call_num */
2397 list = g_list_first(tapinfo->callsinfo_list);
2400 tmp_listinfo=list->data;
2401 if (tmp_listinfo->protocol == VOIP_MGCP){
2402 if (tmp_listinfo->call_num == gai->conv_num){
2403 tmp_mgcpinfo = tmp_listinfo->prot_info;
2404 callsinfo = (voip_calls_info_t*)(list->data);
2408 list = g_list_next (list);
2410 if (callsinfo != NULL) break;
2412 listGraph = g_list_next(listGraph);
2414 /* if there is not a matching request, just return */
2415 if (callsinfo == NULL) return 0;
2418 /* not in the list? then create a new entry */
2419 if (callsinfo==NULL){
2420 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2421 callsinfo->call_active_state = VOIP_ACTIVE;
2422 callsinfo->call_state = VOIP_CALL_SETUP;
2424 callsinfo->from_identity=g_strdup(pi->endpointId);
2425 callsinfo->to_identity=g_strdup("");
2427 callsinfo->from_identity=g_strdup("");
2428 callsinfo->to_identity=g_strdup(pi->endpointId);
2430 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
2431 callsinfo->first_frame_num=pinfo->fd->num;
2432 callsinfo->selected=FALSE;
2433 callsinfo->start_abs=pinfo->fd->abs_ts;
2434 callsinfo->start_rel=pinfo->fd->rel_ts;
2435 callsinfo->protocol=VOIP_MGCP;
2436 callsinfo->prot_info=g_malloc(sizeof(mgcp_calls_info_t));
2437 callsinfo->free_prot_info = g_free;
2438 tmp_mgcpinfo=callsinfo->prot_info;
2439 tmp_mgcpinfo->endpointId = g_strdup(pi->endpointId);
2440 tmp_mgcpinfo->fromEndpoint = fromEndpoint;
2441 callsinfo->npackets = 0;
2442 callsinfo->call_num = tapinfo->ncalls++;
2443 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2446 g_assert(tmp_mgcpinfo != NULL);
2448 /* change call state and add to graph */
2449 switch (pi->mgcp_type)
2452 if ( (strcmp(pi->code, "NTFY") == 0) && (pi->observedEvents != NULL) ){
2453 frame_label = g_strdup_printf("%s ObsEvt:%s",pi->code, pi->observedEvents);
2455 if (tmp_mgcpinfo->fromEndpoint){
2456 /* use the Dialed digits to fill the "To" for the call, but use the first NTFY */
2457 if (callsinfo->to_identity[0] == '\0') mgcpDialedDigits(pi->observedEvents, &(callsinfo->to_identity));
2459 /* from MGC and the user picked up, the call is connected */
2460 } else if (isSignal("hd", pi->observedEvents))
2461 callsinfo->call_state=VOIP_IN_CALL;
2463 /* hung up signal */
2464 if (isSignal("hu", pi->observedEvents)) {
2465 if ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state == VOIP_RINGING)){
2466 callsinfo->call_state = VOIP_CANCELLED;
2468 callsinfo->call_state = VOIP_COMPLETED;
2472 } else if (strcmp(pi->code, "RQNT") == 0) {
2473 /* for calls from Endpoint: if there is a "no signal" RQNT and the call was RINGING, we assume this is the CONNECT */
2474 if ( tmp_mgcpinfo->fromEndpoint && isSignal("", pi->signalReq) && (callsinfo->call_state == VOIP_RINGING) ) {
2475 callsinfo->call_state = VOIP_IN_CALL;
2478 /* if there is ringback or ring tone, change state to ringing */
2479 if ( isSignal("rg", pi->signalReq) || isSignal("rt", pi->signalReq) ) {
2480 callsinfo->call_state = VOIP_RINGING;
2483 /* if there is a Busy or ReorderTone, and the call was Ringing or Setup the call is Rejected */
2484 if ( (isSignal("ro", pi->signalReq) || isSignal("bz", pi->signalReq)) && ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state == VOIP_RINGING)) ) {
2485 callsinfo->call_state = VOIP_REJECTED;
2488 if (pi->signalReq != NULL)
2489 frame_label = g_strdup_printf("%s%sSigReq:%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"", pi->signalReq);
2491 frame_label = g_strdup_printf("%s%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"");
2493 /* use the CallerID info to fill the "From" for the call */
2494 if (!tmp_mgcpinfo->fromEndpoint) mgcpCallerID(pi->signalReq, &(callsinfo->from_identity));
2496 } else if (strcmp(pi->code, "DLCX") == 0) {
2498 if there is a DLCX in a call To an Endpoint and the call was not connected, we use
2499 the DLCX as the end of the call
2501 if (!tmp_mgcpinfo->fromEndpoint){
2502 if ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state == VOIP_RINGING)){
2503 callsinfo->call_state = VOIP_CANCELLED;
2508 if (frame_label == NULL) frame_label = g_strdup(pi->code);
2511 frame_label = g_strdup_printf("%u (%s)",pi->rspcode, pi->code);
2514 /* XXX what to do? */
2519 comment = g_strdup_printf("MGCP %s %s%s", tmp_mgcpinfo->endpointId, (pi->mgcp_type == MGCP_REQUEST)?"Request":"Response", pi->is_duplicate?" Duplicate":"");
2521 callsinfo->stop_abs = pinfo->fd->abs_ts;
2522 callsinfo->stop_rel = pinfo->fd->rel_ts;
2523 callsinfo->last_frame_num=pinfo->fd->num;
2524 ++(callsinfo->npackets);
2525 /* increment the packets counter of all calls */
2526 ++(tapinfo->npackets);
2528 /* add to the graph */
2529 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2531 g_free(frame_label);
2533 /* add SDP info if apply */
2534 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
2535 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2536 g_free(sdp_summary);
2540 tapinfo->redraw = TRUE;
2542 return 1; /* refresh output */
2546 /****************************************************************************/
2548 /****************************************************************************/
2549 static gboolean have_MGCP_tap_listener=FALSE;
2550 /****************************************************************************/
2552 mgcp_calls_init_tap(void)
2554 GString *error_string;
2556 if(have_MGCP_tap_listener==FALSE)
2559 * Don't register the tap listener if we have it already.
2560 * We set TL_REQUIRES_PROTO_TREE to force a non-null "tree"
2561 * in the MGCP dissector; otherwise, the dissector
2562 * doesn't fill in the info passed to the tap's packet
2565 error_string = register_tap_listener("mgcp",
2566 &(the_tapinfo_struct.mgcp_dummy),
2568 TL_REQUIRES_PROTO_TREE,
2569 voip_calls_dlg_reset,
2573 if (error_string != NULL) {
2574 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2575 "%s", error_string->str);
2576 g_string_free(error_string, TRUE);
2579 have_MGCP_tap_listener=TRUE;
2583 /****************************************************************************/
2585 remove_tap_listener_mgcp_calls(void)
2587 protect_thread_critical_region();
2588 remove_tap_listener(&(the_tapinfo_struct.mgcp_dummy));
2589 unprotect_thread_critical_region();
2591 have_MGCP_tap_listener=FALSE;
2595 /****************************************************************************/
2596 /****************************TAP for ACTRACE (AudioCodes trace)**************/
2597 /****************************************************************************/
2599 /* whenever a ACTRACE packet is seen by the tap listener */
2601 ACTRACEcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *ACTRACEinfo)
2603 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2604 const actrace_info_t *pi = ACTRACEinfo;
2606 actrace_cas_calls_info_t *tmp_actrace_cas_info;
2607 voip_calls_info_t *tmp_listinfo;
2608 voip_calls_info_t *callsinfo = NULL;
2611 actrace_frame_num = pinfo->fd->num;
2612 actrace_trunk = pi->trunk;
2613 actrace_direction = pi->direction;
2615 if (pi->type == 1){ /* is CAS protocol */
2617 gchar *comment = NULL;
2620 list = g_list_first(tapinfo->callsinfo_list);
2623 tmp_listinfo=list->data;
2624 if ( tmp_listinfo->protocol == VOIP_AC_CAS ){
2625 tmp_actrace_cas_info = tmp_listinfo->prot_info;
2626 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
2627 if ( (tmp_actrace_cas_info->bchannel == pi->cas_bchannel) && (tmp_actrace_cas_info->trunk == actrace_trunk) ) {
2628 callsinfo = (voip_calls_info_t*)(list->data);
2632 list = g_list_next (list);
2635 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, "PSTN");
2637 /* if it is a new call, add it to the list */
2639 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2640 callsinfo->call_active_state = VOIP_ACTIVE;
2641 callsinfo->call_state = VOIP_CALL_SETUP;
2642 callsinfo->from_identity=g_strdup("N/A");
2643 callsinfo->to_identity=g_strdup("N/A");
2644 COPY_ADDRESS(&(callsinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
2645 callsinfo->first_frame_num=pinfo->fd->num;
2646 callsinfo->selected=FALSE;
2647 callsinfo->start_abs=pinfo->fd->abs_ts;
2648 callsinfo->start_rel=pinfo->fd->rel_ts;
2649 callsinfo->protocol=VOIP_AC_CAS;
2650 callsinfo->prot_info=g_malloc(sizeof(actrace_cas_calls_info_t));
2651 callsinfo->free_prot_info = g_free;
2653 tmp_actrace_cas_info=callsinfo->prot_info;
2654 tmp_actrace_cas_info->bchannel=pi->cas_bchannel;
2655 tmp_actrace_cas_info->trunk=actrace_trunk;
2656 callsinfo->npackets = 0;
2657 callsinfo->call_num = tapinfo->ncalls++;
2658 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2661 callsinfo->stop_abs = pinfo->fd->abs_ts;
2662 callsinfo->stop_rel = pinfo->fd->rel_ts;
2663 callsinfo->last_frame_num=pinfo->fd->num;
2664 ++(callsinfo->npackets);
2665 /* increment the packets counter of all calls */
2666 ++(tapinfo->npackets);
2668 comment = g_strdup_printf("AC_CAS trunk:%u", actrace_trunk);
2670 add_to_graph(tapinfo, pinfo, pi->cas_frame_label, comment, callsinfo->call_num,
2671 actrace_direction?&pstn_add:&(pinfo->src),
2672 actrace_direction?&(pinfo->src):&pstn_add,
2678 tapinfo->redraw = TRUE;
2680 return 1; /* refresh output */
2684 /****************************************************************************/
2686 /****************************************************************************/
2687 static gboolean have_actrace_tap_listener=FALSE;
2688 /****************************************************************************/
2690 actrace_calls_init_tap(void)
2692 GString *error_string;
2694 if(have_actrace_tap_listener==FALSE)
2696 /* don't register tap listener, if we have it already */
2697 error_string = register_tap_listener("actrace", &(the_tapinfo_struct.actrace_dummy), NULL,
2699 voip_calls_dlg_reset,
2700 ACTRACEcalls_packet,
2704 if (error_string != NULL) {
2705 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2706 "%s", error_string->str);
2707 g_string_free(error_string, TRUE);
2710 have_actrace_tap_listener=TRUE;
2714 /****************************************************************************/
2716 remove_tap_listener_actrace_calls(void)
2718 protect_thread_critical_region();
2719 remove_tap_listener(&(the_tapinfo_struct.actrace_dummy));
2720 unprotect_thread_critical_region();
2722 have_actrace_tap_listener=FALSE;
2726 /****************************************************************************/
2727 /**************************** TAP for H248/MEGACO **********************************/
2728 /****************************************************************************/
2729 static gboolean have_h248_tap_listener = FALSE;
2730 static gboolean have_megaco_tap_listener = FALSE;
2732 #define gcp_is_req(type) ( type == GCP_CMD_ADD_REQ || type == GCP_CMD_MOVE_REQ || type == GCP_CMD_MOD_REQ || \
2733 type == GCP_CMD_SUB_REQ || type == GCP_CMD_AUDITCAP_REQ || type == GCP_CMD_AUDITVAL_REQ || \
2734 type == GCP_CMD_NOTIFY_REQ || type == GCP_CMD_SVCCHG_REQ || type == GCP_CMD_TOPOLOGY_REQ || \
2735 type == GCP_CMD_CTX_ATTR_AUDIT_REQ )
2737 static int h248_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
2738 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2739 const gcp_cmd_t *cmd = prot_info;
2741 voip_calls_info_t *callsinfo = NULL;
2744 gchar mgw_addr[128];
2746 if (cmd->ctx->id == NULL_CONTEXT || cmd->ctx->id == ALL_CONTEXTS ) {
2750 if ( gcp_is_req(cmd->type) ) {
2751 mgw = &(pinfo->dst);
2752 mgc = &(pinfo->src);
2754 mgc = &(pinfo->dst);
2755 mgw = &(pinfo->src);
2758 address_to_str_buf(mgw, mgw_addr, 128);
2760 /* check whether we already have this context in the list */
2761 list = g_list_first(tapinfo->callsinfo_list);
2764 voip_calls_info_t* tmp_listinfo = list->data;
2766 if (tmp_listinfo->protocol == TEL_H248){
2767 if (tmp_listinfo->prot_info == cmd->ctx){
2768 callsinfo = (voip_calls_info_t*)(list->data);
2772 list = g_list_next (list);
2775 if (callsinfo==NULL){
2777 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2778 callsinfo->call_state = VOIP_NO_STATE;
2779 callsinfo->call_active_state = VOIP_ACTIVE;
2780 callsinfo->from_identity = g_strdup_printf("%s : %.8x", mgw_addr, cmd->ctx->id);
2781 callsinfo->to_identity = g_strdup("");
2782 callsinfo->prot_info = cmd->ctx;
2783 callsinfo->free_prot_info = NULL;
2785 callsinfo->npackets = 1;
2786 callsinfo->first_frame_num=pinfo->fd->num;
2787 callsinfo->last_frame_num=pinfo->fd->num;
2789 COPY_ADDRESS(&(callsinfo->initial_speaker), mgc);
2791 callsinfo->protocol = TEL_H248;
2792 callsinfo->call_num = tapinfo->ncalls++;
2793 callsinfo->start_abs = pinfo->fd->abs_ts;
2794 callsinfo->start_rel = pinfo->fd->rel_ts;
2795 callsinfo->stop_abs = pinfo->fd->abs_ts;
2796 callsinfo->stop_rel = pinfo->fd->rel_ts;
2798 callsinfo->selected = FALSE;
2800 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2803 GString *s = g_string_new("");
2804 gcp_terms_t *ctx_term;
2806 g_free(callsinfo->from_identity);
2807 callsinfo->from_identity = g_strdup_printf("%s : %.8x", mgw_addr, ((gcp_ctx_t*)callsinfo->prot_info)->id);
2809 g_free(callsinfo->to_identity);
2811 for (ctx_term = ((gcp_ctx_t*)callsinfo->prot_info)->terms.next;
2813 ctx_term = ctx_term->next ) {
2814 if ( ctx_term->term && ctx_term->term->str) {
2815 g_string_append_printf(s," %s",ctx_term->term->str);
2819 callsinfo->to_identity = s->str;
2820 g_string_free(s,FALSE);
2822 callsinfo->stop_abs = pinfo->fd->abs_ts;
2823 callsinfo->stop_rel = pinfo->fd->rel_ts;
2824 callsinfo->last_frame_num=pinfo->fd->num;
2825 ++(callsinfo->npackets);
2828 add_to_graph(tapinfo, pinfo, cmd->str ? cmd->str : "unknown Msg",
2829 ep_strdup_printf("TrxId = %u, CtxId = %.8x",cmd->trx->id,cmd->ctx->id),
2830 callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2832 ++(tapinfo->npackets);
2834 tapinfo->redraw = TRUE;
2839 void h248_calls_init_tap(void)
2841 GString *error_string;
2844 if(have_megaco_tap_listener==FALSE)
2846 error_string = register_tap_listener("megaco", &(the_tapinfo_struct.megaco_dummy),
2849 voip_calls_dlg_reset,
2851 voip_calls_dlg_draw);
2853 if (error_string != NULL) {
2854 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2855 "%s", error_string->str);
2856 g_string_free(error_string, TRUE);
2860 have_megaco_tap_listener=TRUE;
2863 if(have_h248_tap_listener==FALSE)
2865 error_string = register_tap_listener("h248", &(the_tapinfo_struct.h248_dummy),
2868 voip_calls_dlg_reset,
2870 voip_calls_dlg_draw);
2872 if (error_string != NULL) {
2873 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2874 "%s", error_string->str);
2875 g_string_free(error_string, TRUE);
2879 have_h248_tap_listener=TRUE;
2884 remove_tap_listener_h248_calls(void)
2886 protect_thread_critical_region();
2887 remove_tap_listener(&(the_tapinfo_struct.h248_dummy));
2888 remove_tap_listener(&(the_tapinfo_struct.megaco_dummy));
2889 unprotect_thread_critical_region();
2891 have_megaco_tap_listener=FALSE;
2892 have_h248_tap_listener=FALSE;
2895 /****************************************************************************/
2896 /**************************** TAP for SCCP and SUA **********************************/
2897 /**************************** ( RANAP and BSSAP ) **********************************/
2898 /****************************************************************************/
2900 static gboolean have_sccp_tap_listener = FALSE;
2901 static gboolean have_sua_tap_listener = FALSE;
2903 static const voip_protocol sccp_proto_map[] = {
2908 #define SP2VP(ap) ((ap) < SCCP_PLOAD_NUM_PLOADS ? sccp_proto_map[(ap)] : TEL_SCCP)
2909 const value_string* sccp_payload_values;
2911 static int sccp_calls(packet_info *pinfo, const void *prot_info) {
2912 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2913 const sccp_msg_info_t* msg = prot_info;
2914 sccp_assoc_info_t* assoc = msg->data.co.assoc;
2916 voip_calls_info_t *callsinfo = NULL;
2917 const gchar *label = NULL;
2918 const gchar *comment = NULL;
2919 /* check whether we already have this assoc in the list */
2921 for(list = g_list_first(tapinfo->callsinfo_list) ; list ; list = g_list_next (list) ) {
2922 if ( ((voip_calls_info_t*)(list->data))->prot_info == assoc ){
2923 callsinfo = (voip_calls_info_t*)(list->data);
2928 if (callsinfo==NULL){
2929 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2930 callsinfo->call_state = VOIP_CALL_SETUP;
2931 callsinfo->call_active_state = VOIP_ACTIVE;
2932 if ( assoc->calling_party ) {
2933 callsinfo->from_identity = g_strdup(assoc->calling_party);
2935 callsinfo->from_identity = g_strdup("Unknown");
2938 if ( assoc->called_party ) {
2939 callsinfo->to_identity = g_strdup(assoc->called_party);
2941 callsinfo->to_identity = g_strdup("Unknown");
2944 callsinfo->prot_info = (void*)assoc;
2945 callsinfo->free_prot_info = NULL;
2947 callsinfo->npackets = 1;
2948 callsinfo->first_frame_num=pinfo->fd->num;
2949 callsinfo->last_frame_num=pinfo->fd->num;
2951 COPY_ADDRESS(&(callsinfo->initial_speaker), &(pinfo->src));
2953 callsinfo->protocol = SP2VP(assoc->payload);
2954 callsinfo->start_abs = pinfo->fd->abs_ts;
2955 callsinfo->start_rel = pinfo->fd->rel_ts;
2956 callsinfo->stop_abs = pinfo->fd->abs_ts;
2957 callsinfo->stop_rel = pinfo->fd->rel_ts;
2959 callsinfo->selected = FALSE;
2960 callsinfo->call_num = tapinfo->ncalls++;
2962 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2965 if ( assoc->calling_party ) {
2966 g_free(callsinfo->from_identity);
2967 callsinfo->from_identity = g_strdup(assoc->calling_party);
2970 if ( assoc->called_party ) {
2971 g_free(callsinfo->to_identity);
2972 callsinfo->to_identity = g_strdup(assoc->called_party);
2975 callsinfo->protocol = SP2VP(assoc->payload);
2976 callsinfo->stop_abs = pinfo->fd->abs_ts;
2977 callsinfo->stop_rel = pinfo->fd->rel_ts;
2978 callsinfo->last_frame_num=pinfo->fd->num;
2979 ++(callsinfo->npackets);
2981 switch (msg->type) {
2982 case SCCP_MSG_TYPE_CC:
2983 callsinfo->call_state = VOIP_IN_CALL;
2985 case SCCP_MSG_TYPE_RLC:
2986 callsinfo->call_state = VOIP_COMPLETED;
2987 callsinfo->call_active_state = VOIP_INACTIVE;
2994 if (msg->data.co.label) {
2995 label = msg->data.co.label;
2997 label = val_to_str(msg->type, sccp_payload_values, "Unknown(%d)");
3000 if (msg->data.co.comment) {
3001 comment = msg->data.co.comment;
3006 add_to_graph(tapinfo, pinfo, label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3008 ++(tapinfo->npackets);
3010 tapinfo->redraw = TRUE;
3015 static int sccp_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
3016 sccp_payload_values = sccp_message_type_acro_values;
3017 return sccp_calls(pinfo, prot_info);
3021 static int sua_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
3022 sccp_payload_values = sua_co_class_type_acro_values;
3023 return sccp_calls(pinfo, prot_info);
3027 void sccp_calls_init_tap(void)
3029 GString *error_string;
3031 if(have_sccp_tap_listener==FALSE)
3033 error_string = register_tap_listener("sccp", &(the_tapinfo_struct.sccp_dummy),
3036 voip_calls_dlg_reset,
3038 voip_calls_dlg_draw);
3040 if (error_string != NULL) {
3041 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3042 "%s", error_string->str);
3043 g_string_free(error_string, TRUE);
3047 have_sccp_tap_listener=TRUE;
3050 if(have_sua_tap_listener==FALSE)
3052 error_string = register_tap_listener("sua", &(the_tapinfo_struct.sua_dummy),
3055 voip_calls_dlg_reset,
3057 voip_calls_dlg_draw);
3059 if (error_string != NULL) {
3060 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3061 "%s", error_string->str);
3062 g_string_free(error_string, TRUE);
3066 have_sua_tap_listener=TRUE;
3072 remove_tap_listener_sccp_calls(void)
3074 protect_thread_critical_region();
3075 remove_tap_listener(&(the_tapinfo_struct.sccp_dummy));
3076 unprotect_thread_critical_region();
3078 have_sccp_tap_listener=FALSE;
3079 have_sua_tap_listener=FALSE;
3083 /****************************************************************************/
3084 /****************************TAP for UNISTIM ********************************/
3085 /****************************************************************************/
3088 unistim_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *unistim_info)
3090 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3091 voip_calls_info_t *tmp_listinfo;
3092 voip_calls_info_t *callsinfo = NULL;
3093 unistim_info_t *tmp_unistim_info = NULL;
3095 GString *g_tmp = NULL;
3096 gchar *frame_label = NULL;
3097 gchar *comment = NULL;
3099 /* Fetch specific packet infos */
3100 const unistim_info_t *pi = unistim_info;
3103 g_tmp = g_string_new(NULL);
3105 /* Check to see if this is a dup */
3106 list = g_list_first(tapinfo->callsinfo_list);
3110 tmp_listinfo = list->data;
3112 if(tmp_listinfo->protocol == VOIP_UNISTIM){
3114 tmp_unistim_info = tmp_listinfo->prot_info;
3116 /* Search by termid if possible, otherwise use ni/it ip + port.. */
3117 if(pi->termid != 0){
3118 if(tmp_unistim_info->termid == pi->termid){
3119 /* If the call has ended, then we can reuse it.. */
3120 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
3123 callsinfo = (voip_calls_info_t*)(list->data);
3128 /* If no term id use ips / port to find entry */
3129 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)){
3130 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
3131 /* Do nothing previous call */
3133 callsinfo = (voip_calls_info_t*)(list->data);
3137 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)) {
3138 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
3139 /* Do nothing, it ain't our call.. */
3141 callsinfo = (voip_calls_info_t*)(list->data);
3148 /* Otherwise, go to the next one.. */
3149 list = g_list_next(list);
3152 if(pi->payload_type == 2 || pi->payload_type == 1){
3154 if(pi->key_state == 1 || pi->hook_state == 1){
3156 /* If the user hits a button,
3157 Session will be SETUP */
3159 /* If new add to list */
3160 if (callsinfo==NULL){
3162 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3163 callsinfo->call_active_state = VOIP_ACTIVE;
3164 callsinfo->call_state = VOIP_CALL_SETUP;
3165 callsinfo->from_identity=g_strdup_printf("%x",pi->termid);
3166 callsinfo->to_identity=g_strdup("UNKNOWN");
3167 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
3168 callsinfo->first_frame_num=pinfo->fd->num;
3169 callsinfo->selected=FALSE;
3171 /* Set this on init of struct so in case the call doesn't complete, we'll have a ref. */
3172 /* Otherwise if the call is completed we'll have the open/close streams to ref actual call duration */
3173 callsinfo->start_abs=pinfo->fd->abs_ts;
3174 callsinfo->start_rel=pinfo->fd->rel_ts;
3176 callsinfo->protocol=VOIP_UNISTIM;
3177 callsinfo->prot_info=g_malloc(sizeof(unistim_info_t));
3179 tmp_unistim_info = callsinfo->prot_info;
3181 /* Clear tap struct */
3182 tmp_unistim_info->rudp_type = 0;
3183 tmp_unistim_info->payload_type = 0;
3184 tmp_unistim_info->sequence = pi->sequence;
3185 tmp_unistim_info->termid = pi->termid;
3186 tmp_unistim_info->key_val = -1;
3187 tmp_unistim_info->key_state = -1;
3188 tmp_unistim_info->hook_state = -1;
3189 tmp_unistim_info->stream_connect = -1;
3190 tmp_unistim_info->trans_connect = -1;
3191 tmp_unistim_info->set_termid = -1;
3192 tmp_unistim_info->string_data = NULL;
3193 tmp_unistim_info->key_buffer = NULL;
3195 COPY_ADDRESS(&(tmp_unistim_info->it_ip),&(pi->it_ip));
3196 COPY_ADDRESS(&(tmp_unistim_info->ni_ip),&(pi->ni_ip));
3197 tmp_unistim_info->it_port = pi->it_port;
3199 callsinfo->free_prot_info = g_free;
3200 callsinfo->npackets = 0;
3201 callsinfo->call_num = tapinfo->ncalls++;
3202 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3206 /* Set up call wide info struct */
3207 tmp_unistim_info = callsinfo->prot_info;
3208 tmp_unistim_info->sequence = pi->sequence;
3211 /* Each packet COULD BE OUR LAST!!!! */
3212 callsinfo->stop_abs = pinfo->fd->abs_ts;
3213 callsinfo->stop_rel = pinfo->fd->rel_ts;
3214 callsinfo->last_frame_num=pinfo->fd->num;
3216 /* This is a valid packet so increment counter */
3217 ++(callsinfo->npackets);
3219 /* increment the packets counter of all calls */
3220 ++(tapinfo->npackets);
3222 /* Key was depressed.. update key buffer.. */
3223 if(pi->key_val >= 0 && pi->key_val <= 11){
3225 if(tmp_unistim_info->key_buffer != NULL){
3227 /* assign to temp variable */
3228 g_string_assign(g_tmp,tmp_unistim_info->key_buffer);
3230 /* Manipulate the data */
3231 if(pi->key_val == 10) {
3232 tmp_unistim_info->key_buffer = g_strdup_printf("%s*",g_tmp->str);
3233 } else if(pi->key_val == 11) {
3234 tmp_unistim_info->key_buffer = g_strdup_printf("%s#",g_tmp->str);
3236 tmp_unistim_info->key_buffer = g_strdup_printf("%s%d",g_tmp->str,pi->key_val);
3241 /* Create new string */
3242 if(pi->key_val == 10) {
3243 tmp_unistim_info->key_buffer = g_strdup("*");
3244 } else if(pi->key_val == 11) {
3245 tmp_unistim_info->key_buffer = g_strdup("#");
3247 tmp_unistim_info->key_buffer = g_strdup_printf("%d",pi->key_val);
3252 /* Select for non-digit characters */
3253 if(pi->key_val == 10) {
3254 comment = g_strdup_printf("Key Input Sent: * (%d)", pi->sequence);
3255 } else if(pi->key_val == 11) {
3256 comment = g_strdup_printf("Key Input Sent: # (%d)", pi->sequence);
3258 comment = g_strdup_printf("Key Input Sent: %d (%d)",pi->key_val, pi->sequence);
3260 } else if(pi->key_val == 12) {
3261 /* Set label and comment for graph */
3262 comment = g_strdup_printf("Key Input Sent: UP (%d)", pi->sequence);
3263 } else if(pi->key_val == 13) {
3264 /* Set label and comment for graph */
3265 comment = g_strdup_printf("Key Input Sent: DOWN (%d)", pi->sequence);
3266 } else if(pi->key_val == 14) {
3267 /* Set label and comment for graph */
3268 comment = g_strdup_printf("Key Input Sent: RIGHT (%d)", pi->sequence);
3269 } else if(pi->key_val == 15) {
3270 if(pi->key_buffer != NULL){
3272 g_string_assign(g_tmp,pi->key_buffer);
3274 /* Manipulate the data */
3275 g_string_truncate(g_tmp,g_tmp->len-1);
3277 /* Insert new data */
3278 tmp_unistim_info->key_buffer = g_strdup(g_tmp->str);
3281 /* Set label and comment for graph */
3282 comment = g_strdup_printf("Key Input Sent: LEFT (%d)", pi->sequence);
3283 } else if(pi->key_val == 20) {
3284 /* User pressed the soft key 0 probably dial */
3285 comment = g_strdup_printf("Key Input Sent: S0 (%d)", pi->sequence);
3286 } else if(pi->key_val == 21) {
3287 /* User pressed the soft key 1 */
3288 comment = g_strdup_printf("Key Input Sent: S1 (%d)", pi->sequence);
3289 } else if(pi->key_val == 22) {
3290 /* User pressed the soft key 2 */
3291 /* On cs2k phones, soft key 2 is backspace. */
3292 if(pi->key_buffer != NULL) {
3295 g_string_assign(g_tmp,pi->key_buffer);
3297 /* Manipulate the data */
3298 g_string_truncate(g_tmp,g_tmp->len-1);
3300 /* Insert new data */
3301 tmp_unistim_info->key_buffer = g_strdup(g_tmp->str);
3304 /* add label and comment */
3305 comment = g_strdup_printf("Key Input Sent: S2 (%d)", pi->sequence);
3306 } else if(pi->key_val == 28) {
3307 /* User pressed something */
3308 comment = g_strdup_printf("Key Input Sent: Release (%d)", pi->sequence);
3309 } else if(pi->key_val == 23) {
3310 /* User pressed the soft key 3 */
3311 /* Cancel on cs2k so clear buffer */
3312 /* On mcs its config which will clear the buffer too */
3313 tmp_unistim_info->key_buffer = g_strdup("\n");
3315 /* User pressed something, set labels*/
3316 comment = g_strdup_printf("Key Input Sent: S3 (%d)", pi->sequence);
3317 } else if(pi->key_val == 27) {
3318 /* User pressed something */
3319 comment = g_strdup_printf("Key Input Sent: Hold (%d)", pi->sequence);
3320 } else if(pi->key_val == 29) {
3321 /* User pressed something */
3322 comment = g_strdup_printf("Key Input Sent: Mute (%d)", pi->sequence);
3323 } else if(pi->key_val == 30) {
3324 /* User pressed something */
3325 comment = g_strdup_printf("Key Input Sent: Headset (%d)", pi->sequence);
3326 } else if(pi->key_val == 31) {
3327 /* Handsfree button */
3328 comment = g_strdup_printf("Key Input Sent: Handsfree (%d)", pi->sequence);
3329 } else if(pi->key_val >= 32 && pi->key_val <= 56) {
3331 comment = g_strdup_printf("Key Input Sent: Prog%d (%d)", (pi->key_val & 31), pi->sequence);
3334 if(pi->key_val != -1) {
3336 frame_label = "KEY INPUT";
3338 if (comment == NULL)
3339 /* Ouch! What do you do!? */
3340 /* User pressed something */
3341 comment = g_strdup_printf("Key Input Sent: UNKNOWN - %d (%d)", pi->key_val, pi->sequence);
3343 /* add to the graph */
3344 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3349 if(pi->hook_state == 1) {
3351 /* Phone is off hook */
3352 frame_label = "OFF HOOK";
3353 comment = g_strdup_printf("Off Hook (%d)", pi->sequence);
3355 /* add to the graph */
3356 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3359 } else if(pi->hook_state == 0) {
3361 /* Phone is on hook */
3362 frame_label = "ON HOOK";
3363 comment = g_strdup_printf("On Hook (%d)", pi->sequence);
3365 /* add to the graph */
3366 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3372 /* Open stream was sent from server */
3373 if(pi->stream_connect == 1 && callsinfo != NULL) {
3376 /* Signifies the start of the call so set start_sec & start_usec */
3377 callsinfo->start_abs=pinfo->fd->abs_ts;
3378 callsinfo->start_rel=pinfo->fd->rel_ts;
3380 /* Local packets too */
3381 ++(callsinfo->npackets);
3383 /* increment the packets counter of all calls */
3384 ++(tapinfo->npackets);
3386 /* ?? means we're not quite sure if this is accurate. Since Unistim isn't a true
3387 Call control protocol, we can only guess at the destination by messing with
3389 if(tmp_unistim_info->key_buffer != NULL){
3390 callsinfo->to_identity = g_strdup_printf("?? %s",tmp_unistim_info->key_buffer);
3393 /* change sequence number for ACK detection */
3394 tmp_unistim_info->sequence = pi->sequence;
3396 /* State changes too */
3397 callsinfo->call_active_state = VOIP_ACTIVE;
3398 callsinfo->call_state = VOIP_IN_CALL;
3400 /* Add graph data */
3401 frame_label = "STREAM OPENED";
3402 comment = g_strdup_printf("Stream Opened (%d)",pi->sequence);
3404 /* add to the graph */
3405 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3407 } else if(pi->stream_connect == 1 && callsinfo == NULL) {
3409 /* Research indicates some nortel products initiate stream first
3410 * without keypresses. therefore creating this solely on a keypress is
3412 * Sometimes calls start immediately with open stream.
3414 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3415 callsinfo->call_active_state = VOIP_ACTIVE;
3416 callsinfo->call_state = VOIP_CALL_SETUP;
3417 callsinfo->from_identity=g_strdup("UNKNOWN");
3418 callsinfo->to_identity=g_strdup("UNKNOWN");
3419 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
3420 callsinfo->first_frame_num=pinfo->fd->num;
3421 callsinfo->selected=FALSE;
3423 /* Set this on init of struct so in case the call doesn't complete, we'll have a ref. */
3424 /* Otherwise if the call is completed we'll have the open/close streams to ref actual call duration */
3425 callsinfo->start_abs=pinfo->fd->abs_ts;
3426 callsinfo->start_rel=pinfo->fd->rel_ts;
3428 callsinfo->protocol=VOIP_UNISTIM;
3429 callsinfo->prot_info=g_malloc(sizeof(unistim_info_t));
3431 tmp_unistim_info = callsinfo->prot_info;
3433 /* Clear tap struct */
3434 tmp_unistim_info->rudp_type = 0;
3435 tmp_unistim_info->payload_type = 0;
3436 tmp_unistim_info->sequence = pi->sequence;
3437 tmp_unistim_info->termid = 0;
3438 tmp_unistim_info->key_val = -1;
3439 tmp_unistim_info->key_state = -1;
3440 tmp_unistim_info->hook_state = -1;
3441 tmp_unistim_info->stream_connect = -1;
3442 tmp_unistim_info->trans_connect = -1;
3443 tmp_unistim_info->set_termid = -1;
3444 tmp_unistim_info->string_data = NULL;
3445 tmp_unistim_info->key_buffer = NULL;
3447 COPY_ADDRESS(&(tmp_unistim_info->it_ip),&(pi->it_ip));
3448 COPY_ADDRESS(&(tmp_unistim_info->ni_ip),&(pi->ni_ip));
3449 tmp_unistim_info->it_port = pi->it_port;
3451 callsinfo->free_prot_info = g_free;
3452 callsinfo->npackets = 0;
3453 callsinfo->call_num = tapinfo->ncalls++;
3454 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3457 /* Signifies the start of the call so set start_sec & start_usec */
3458 callsinfo->start_abs=pinfo->fd->abs_ts;
3459 callsinfo->start_rel=pinfo->fd->rel_ts;
3461 /* Local packets too */
3462 ++(callsinfo->npackets);
3464 /* increment the packets counter of all calls */
3465 ++(tapinfo->npackets);
3467 /* ?? means we're not quite sure if this is accurate. Since Unistim isn't a true
3468 Call control protocol, we can only guess at the destination by messing with
3470 if(tmp_unistim_info->key_buffer != NULL){
3471 callsinfo->to_identity = g_strdup_printf("?? %s",tmp_unistim_info->key_buffer);
3474 /* change sequence number for ACK detection */
3475 tmp_unistim_info->sequence = pi->sequence;
3477 /* State changes too */
3478 callsinfo->call_active_state = VOIP_ACTIVE;
3479 callsinfo->call_state = VOIP_IN_CALL;
3481 /* Add graph data */
3482 frame_label = "STREAM OPENED";
3483 comment = g_strdup_printf("Stream Opened (%d)",pi->sequence);
3485 /* add to the graph */
3486 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3488 } else if(pi->stream_connect == 0 && callsinfo != NULL) {
3491 /* Set stop seconds + usec */
3492 callsinfo->stop_abs = pinfo->fd->abs_ts;
3493 callsinfo->stop_rel = pinfo->fd->rel_ts;
3494 callsinfo->last_frame_num=pinfo->fd->num;
3496 tmp_unistim_info->sequence = pi->sequence;
3498 if(callsinfo->call_state == VOIP_IN_CALL){
3499 callsinfo->call_active_state = VOIP_INACTIVE;
3500 callsinfo->call_state = VOIP_COMPLETED;
3502 callsinfo->call_state = VOIP_UNKNOWN;
3503 callsinfo->call_active_state = VOIP_INACTIVE;
3506 frame_label = "STREAM CLOSED";
3507 comment = g_strdup_printf("Stream Closed (%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);
3515 } else if(pi->rudp_type == 1 && callsinfo != NULL) {
3517 /* Only show acks for processed seq #s */
3518 if(tmp_unistim_info->sequence == pi->sequence) {
3520 frame_label = "ACK";
3521 comment = g_strdup_printf("ACK for sequence %d",pi->sequence);
3523 /* add to the graph */
3524 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3528 } else if(pi->rudp_type == 0 && callsinfo != NULL) {
3531 frame_label = "NAK";
3532 comment = g_strdup_printf("NAK for sequence %d",pi->sequence);
3534 /* add to the graph */
3535 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3542 tapinfo->redraw = TRUE;
3547 /****************************************************************************/
3549 /****************************************************************************/
3550 static gboolean have_unistim_tap_listener=FALSE;
3551 /****************************************************************************/
3553 unistim_calls_init_tap(void){
3555 GString *error_string;
3557 if(have_unistim_tap_listener==FALSE) {
3559 error_string = register_tap_listener("unistim", &(the_tapinfo_struct.unistim_dummy),
3562 voip_calls_dlg_reset,
3563 unistim_calls_packet,
3567 if (error_string != NULL) {
3568 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3569 "%s", error_string->str);
3570 g_string_free(error_string, TRUE);
3574 have_unistim_tap_listener=TRUE;
3578 /****************************************************************************/
3580 remove_tap_listener_unistim_calls(void)
3582 protect_thread_critical_region();
3583 remove_tap_listener(&(the_tapinfo_struct.unistim_dummy));
3584 unprotect_thread_critical_region();
3586 have_unistim_tap_listener=FALSE;
3589 /****************************************************************************/
3590 /* ***************************TAP for SKINNY **********************************/
3591 /****************************************************************************/
3593 /* Telecaster to tap-voip call state mapping */
3594 static const voip_call_state skinny_tap_voip_state[] = {
3613 skinny_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *skinny_info)
3615 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3617 voip_calls_info_t *callsinfo = NULL;
3619 const skinny_info_t *si = skinny_info;
3620 skinny_calls_info_t *tmp_skinnyinfo;
3623 if (si == NULL || (si->callId == 0 && si->passThruId == 0))
3625 /* check whether we already have this context in the list */
3626 list = g_list_first(tapinfo->callsinfo_list);
3629 voip_calls_info_t* tmp_listinfo = list->data;
3630 if (tmp_listinfo->protocol == VOIP_SKINNY){
3631 tmp_skinnyinfo = tmp_listinfo->prot_info;
3632 if (tmp_skinnyinfo->callId == si->callId ||
3633 tmp_skinnyinfo->callId == si->passThruId){
3634 callsinfo = (voip_calls_info_t*)(list->data);
3638 list = g_list_next (list);
3641 if (si->messId >= 256)
3642 phone = &(pinfo->dst);
3644 phone = &(pinfo->src);
3646 if (callsinfo==NULL){
3647 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3648 callsinfo->call_state = VOIP_NO_STATE;
3649 callsinfo->call_active_state = VOIP_ACTIVE;
3650 /* callsinfo->from_identity = g_strdup_printf("%s : %.8x", "Skinny", 1); */
3651 callsinfo->from_identity = g_strdup("");
3652 callsinfo->to_identity = g_strdup("");
3653 callsinfo->prot_info = g_malloc(sizeof(skinny_calls_info_t));
3654 callsinfo->free_prot_info = g_free;
3655 tmp_skinnyinfo = callsinfo->prot_info;
3656 tmp_skinnyinfo->callId = si->callId ? si->callId : si->passThruId;
3657 callsinfo->npackets = 1;
3658 callsinfo->first_frame_num=pinfo->fd->num;
3659 callsinfo->last_frame_num=pinfo->fd->num;
3661 COPY_ADDRESS(&(callsinfo->initial_speaker), phone);
3663 callsinfo->protocol = VOIP_SKINNY;
3664 callsinfo->call_num = tapinfo->ncalls++;
3665 callsinfo->start_abs = pinfo->fd->abs_ts;
3666 callsinfo->start_rel = pinfo->fd->rel_ts;
3667 callsinfo->stop_abs = pinfo->fd->abs_ts;
3668 callsinfo->stop_rel = pinfo->fd->rel_ts;
3670 callsinfo->selected = FALSE;
3671 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3673 if (si->callingParty) {
3674 g_free(callsinfo->from_identity);
3675 callsinfo->from_identity = g_strdup(si->callingParty);
3677 if (si->calledParty) {
3678 g_free(callsinfo->to_identity);
3679 callsinfo->to_identity = g_strdup(si->calledParty);
3681 if ((si->callState > 0) && (si->callState < (sizeof(skinny_tap_voip_state)/sizeof(skinny_tap_voip_state[0]))))
3682 callsinfo->call_state = skinny_tap_voip_state[si->callState];
3684 callsinfo->stop_abs = pinfo->fd->abs_ts;
3685 callsinfo->stop_rel = pinfo->fd->rel_ts;
3686 callsinfo->last_frame_num=pinfo->fd->num;
3687 ++(callsinfo->npackets);
3692 comment = g_strdup_printf("CallId = %u, PTId = %u", si->callId, si->passThruId);
3694 comment = g_strdup_printf("CallId = %u, LineId = %u", si->callId, si->lineId);
3697 comment = g_strdup_printf("PTId = %u", si->passThruId);
3702 add_to_graph(tapinfo, pinfo, si->messageName, comment,
3703 callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3710 /****************************************************************************/
3712 /****************************************************************************/
3713 static gboolean have_skinny_tap_listener=FALSE;
3714 /****************************************************************************/
3716 skinny_calls_init_tap(void)
3718 GString *error_string;
3720 if(have_skinny_tap_listener==FALSE)
3723 * Don't register the tap listener if we have it already.
3724 * We set TL_REQUIRES_PROTO_TREE to force a non-null "tree"
3725 * in the SKINNY dissector; otherwise, the dissector
3726 * doesn't fill in the info passed to the tap's packet
3729 error_string = register_tap_listener("skinny",
3730 &(the_tapinfo_struct.skinny_dummy),
3732 TL_REQUIRES_PROTO_TREE,
3733 voip_calls_dlg_reset,
3734 skinny_calls_packet,
3737 if (error_string != NULL) {
3738 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3739 "%s", error_string->str);
3740 g_string_free(error_string, TRUE);
3743 have_skinny_tap_listener=TRUE;
3747 /****************************************************************************/
3749 remove_tap_listener_skinny_calls(void)
3751 protect_thread_critical_region();
3752 remove_tap_listener(&(the_tapinfo_struct.skinny_dummy));
3753 unprotect_thread_critical_region();
3755 have_skinny_tap_listener=FALSE;
3758 /****************************************************************************/
3759 /* ***************************TAP for IAX2 **********************************/
3760 /****************************************************************************/
3762 /* IAX2 to tap-voip call state mapping */
3763 static const voip_call_state tap_iax_voip_state[] = {
3765 VOIP_CALL_SETUP, /*NEW*/
3768 VOIP_COMPLETED, /*HANGUP*/
3769 VOIP_REJECTED, /*REJECT*/
3770 VOIP_RINGING, /*ACCEPT*/
3785 VOIP_CALL_SETUP, /*DIAL*/
3804 static void free_iax2_info(gpointer p) {
3805 iax2_info_t *ii = p;
3811 /****************************************************************************/
3812 /* whenever a IAX2 packet is seen by the tap listener */
3814 iax2_calls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *iax2_info)
3816 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3818 voip_calls_info_t *callsinfo = NULL;
3820 const iax2_info_t *ii = iax2_info;
3821 iax2_info_t *tmp_iax2info;
3824 if (ii == NULL || ii->ptype != IAX2_FULL_PACKET || (ii->scallno == 0 && ii->dcallno == 0))
3826 /* check whether we already have this context in the list */
3827 list = g_list_first(tapinfo->callsinfo_list);
3830 voip_calls_info_t* tmp_listinfo = list->data;
3831 if (tmp_listinfo->protocol == VOIP_IAX2){
3832 tmp_iax2info = tmp_listinfo->prot_info;
3833 if (tmp_iax2info->scallno == ii->scallno ||
3834 tmp_iax2info->scallno == ii->dcallno){
3835 callsinfo = (voip_calls_info_t*)(list->data);
3839 list = g_list_next (list);
3841 phone = &(pinfo->src);
3844 if (callsinfo==NULL){
3845 /* We only care about real calls, i.e., no registration stuff */
3846 if (ii->ftype != AST_FRAME_IAX || ii->csub != IAX_COMMAND_NEW)
3848 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3849 callsinfo->call_state = VOIP_NO_STATE;
3850 callsinfo->call_active_state = VOIP_ACTIVE;
3851 callsinfo->prot_info=g_malloc(sizeof(iax2_info_t));
3852 callsinfo->free_prot_info = free_iax2_info;
3853 tmp_iax2info = callsinfo->prot_info;
3855 tmp_iax2info->scallno = ii->scallno;
3856 if (tmp_iax2info->scallno == 0) tmp_iax2info->scallno = ii->dcallno;
3857 tmp_iax2info->callState = tap_iax_voip_state[ii->callState];
3859 callsinfo->npackets = 1;
3860 callsinfo->first_frame_num=pinfo->fd->num;
3861 callsinfo->last_frame_num=pinfo->fd->num;
3863 COPY_ADDRESS(&(callsinfo->initial_speaker), phone);
3864 callsinfo->from_identity = g_strdup(ii->callingParty);
3865 callsinfo->to_identity = g_strdup(ii->calledParty);
3867 callsinfo->protocol = VOIP_IAX2;
3868 callsinfo->call_num = tapinfo->ncalls++;
3869 callsinfo->start_abs=pinfo->fd->abs_ts;
3870 callsinfo->start_rel=pinfo->fd->rel_ts;
3871 callsinfo->stop_abs = pinfo->fd->abs_ts;
3872 callsinfo->stop_rel = pinfo->fd->rel_ts;
3874 callsinfo->selected = FALSE;
3875 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3878 if ((ii->callState > 0) && (ii->callState < (sizeof(tap_iax_voip_state)/sizeof(tap_iax_voip_state[0]))))
3879 callsinfo->call_state = tap_iax_voip_state[ii->callState];
3881 callsinfo->stop_abs = pinfo->fd->abs_ts;
3882 callsinfo->stop_rel = pinfo->fd->rel_ts;
3883 callsinfo->last_frame_num=pinfo->fd->num;
3884 ++(callsinfo->npackets);
3889 add_to_graph(tapinfo, pinfo, ii->messageName, comment,
3890 callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3897 /****************************************************************************/
3899 /****************************************************************************/
3900 static gboolean have_iax2_tap_listener=FALSE;
3901 /****************************************************************************/
3903 iax2_calls_init_tap(void)
3905 GString *error_string;
3907 if(have_iax2_tap_listener==FALSE)
3910 * Don't register the tap listener if we have it already.
3911 * We set TL_REQUIRES_PROTO_TREE to force a non-null "tree"
3912 * in the IAX2 dissector; otherwise, the dissector
3913 * doesn't fill in the info passed to the tap's packet
3915 * XXX - that appears to be true of the MGCP and SKINNY
3916 * dissectors, but, unless I've missed something, it doesn't
3917 * appear to be true of the IAX2 dissector.
3919 error_string = register_tap_listener("IAX2",
3920 &(the_tapinfo_struct.iax2_dummy),
3922 TL_REQUIRES_PROTO_TREE,
3923 voip_calls_dlg_reset,
3927 if (error_string != NULL) {
3928 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s",
3930 g_string_free(error_string, TRUE);
3933 have_iax2_tap_listener=TRUE;
3937 /****************************************************************************/
3939 remove_tap_listener_iax2_calls(void)
3941 protect_thread_critical_region();
3942 remove_tap_listener(&(the_tapinfo_struct.iax2_dummy));
3943 unprotect_thread_critical_region();
3945 have_iax2_tap_listener=FALSE;
3948 /****************************************************************************/
3949 /* ***************************TAP for OTHER PROTOCOL **********************************/
3950 /****************************************************************************/
3953 VoIPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *VoIPinfo)
3955 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3956 voip_calls_info_t *callsinfo = NULL;
3957 voip_calls_info_t *tmp_listinfo;
3959 const voip_packet_info_t *pi = VoIPinfo;
3962 list = g_list_first(tapinfo->callsinfo_list);
3964 tmp_listinfo = list->data;
3965 if ( tmp_listinfo->protocol == VOIP_COMMON ) {
3966 if (!strcmp(pi->call_id, tmp_listinfo->call_id)) {
3967 callsinfo = (voip_calls_info_t*)(list->data);
3971 list = g_list_next(list);
3974 if (callsinfo == NULL) {
3975 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3976 callsinfo->call_active_state = pi->call_active_state;
3977 callsinfo->call_state = pi->call_state;
3978 callsinfo->call_id=g_strdup((pi->call_id)?pi->call_id:"");
3979 callsinfo->from_identity = g_strdup((pi->from_identity)?pi->from_identity:"");
3980 callsinfo->to_identity = g_strdup((pi->to_identity)?pi->to_identity:"");
3981 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
3982 callsinfo->selected=FALSE;
3983 callsinfo->first_frame_num=pinfo->fd->num;
3984 callsinfo->start_abs=pinfo->fd->abs_ts;
3985 callsinfo->start_rel=pinfo->fd->rel_ts;
3986 callsinfo->protocol=VOIP_COMMON;
3987 callsinfo->protocol_name=g_strdup((pi->protocol_name)?pi->protocol_name:"");
3988 callsinfo->call_comment=g_strdup((pi->call_comment)?pi->call_comment:"");
3989 callsinfo->prot_info=NULL;
3990 callsinfo->free_prot_info = NULL;
3992 callsinfo->call_num = tapinfo->ncalls++;
3993 callsinfo->npackets = 0;
3995 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3998 if (callsinfo != NULL) {
3999 callsinfo->call_active_state = pi->call_active_state;
4000 if ((callsinfo->call_state != VOIP_COMPLETED) && (pi->call_state == VOIP_COMPLETED))
4001 tapinfo->completed_calls++;
4002 if (pi->call_state != VOIP_NO_STATE)
4003 callsinfo->call_state = pi->call_state;
4004 if (pi->call_comment) {
4005 g_free(callsinfo->call_comment);
4006 callsinfo->call_comment=g_strdup(pi->call_comment);
4008 callsinfo->stop_abs = pinfo->fd->abs_ts;
4009 callsinfo->stop_rel = pinfo->fd->rel_ts;
4010 callsinfo->last_frame_num=pinfo->fd->num;
4011 ++(callsinfo->npackets);
4012 ++(tapinfo->npackets);
4015 /* add to the graph */
4016 add_to_graph(tapinfo, pinfo, (pi->frame_label)?pi->frame_label:"VoIP msg", pi->frame_comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
4018 tapinfo->redraw = TRUE;
4022 /****************************************************************************/
4023 static gboolean have_voip_tap_listener=FALSE;
4026 VoIPcalls_init_tap(void)
4028 GString *error_string;
4030 if(have_voip_tap_listener==FALSE)
4032 error_string = register_tap_listener("voip", &(the_tapinfo_struct.voip_dummy),
4035 voip_calls_dlg_reset,
4040 if (error_string != NULL) {
4041 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4042 "%s", error_string->str);
4043 g_string_free(error_string, TRUE);
4046 have_voip_tap_listener=TRUE;
4049 /****************************************************************************/
4051 remove_tap_listener_voip_calls(void)
4053 protect_thread_critical_region();
4054 remove_tap_listener(&(the_tapinfo_struct.voip_dummy));
4055 unprotect_thread_critical_region();
4057 have_voip_tap_listener=FALSE;
4061 /****************************************************************************/
4062 /* ***************************TAP for OTHER PROTOCOL **********************************/
4063 /****************************************************************************/
4065 /****************************************************************************/
4066 /* whenever a prot_ packet is seen by the tap listener */
4069 prot_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info _U_)
4071 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
4072 if (callsinfo!=NULL){
4073 callsinfo->stop_abs = pinfo->fd->abs_ts;
4074 callsinfo->stop_rel = pinfo->fd->rel_ts;
4075 callsinfo->last_frame_num=pinfo->fd->num;
4076 ++(callsinfo->npackets);
4077 ++(tapinfo->npackets);
4080 tapinfo->redraw = TRUE;
4085 /****************************************************************************/
4087 static gboolean have_prot__tap_listener=FALSE;
4090 prot_calls_init_tap(void)
4092 GString *error_string;
4094 if(have_prot__tap_listener==FALSE)
4096 error_string = register_tap_listener("prot_", &(the_tapinfo_struct.prot__dummy),
4099 voip_calls_dlg_reset,
4104 if (error_string != NULL) {
4105 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4106 "%s", error_string->str);
4107 g_string_free(error_string, TRUE);
4110 have_prot__tap_listener=TRUE;
4114 /****************************************************************************/
4117 remove_tap_listener_prot__calls(void)
4119 protect_thread_critical_region();
4120 remove_tap_listener(&(the_tapinfo_struct.prot__dummy));
4121 unprotect_thread_critical_region();
4123 have_prot__tap_listener=FALSE;