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"
67 #include "../ui_util.h"
69 #include "gtk/graph_analysis.h"
70 #include "gtk/voip_calls.h"
71 #include "gtk/voip_calls_dlg.h"
74 #ifdef HAVE_LIBPORTAUDIO
75 #include "gtk/rtp_player.h"
76 #endif /* HAVE_LIBPORTAUDIO */
79 const char *voip_call_state_name[8]={
90 /* defines whether we can consider the call active */
91 const char *voip_protocol_name[]={
119 graph_str labels[H245_MAX];
122 static h245_labels_t h245_labels;
124 /* defines a RTP stream */
125 typedef struct _voip_rtp_stream_info {
137 guint32 setup_frame_number; /* frame number of setup message */
138 /* The frame_data struct holds the frame number and timing information needed. */
139 frame_data *start_fd;
142 } voip_rtp_stream_info_t;
144 /****************************************************************************/
145 /* the one and only global voip_calls_tapinfo_t structure */
146 static voip_calls_tapinfo_t the_tapinfo_struct =
147 {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};
149 /* the one and only global voip_rtp_tapinfo_t structure */
150 static voip_rtp_tapinfo_t the_tapinfo_rtp_struct =
153 /****************************************************************************/
154 /* when there is a [re]reading of packet's */
155 void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
157 voip_calls_info_t *callsinfo;
158 voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
159 voip_rtp_stream_info_t *strinfo;
160 graph_analysis_item_t *graph_item;
163 #ifdef HAVE_LIBPORTAUDIO
164 /* reset the RTP player */
168 /* free the data items first */
169 list = g_list_first(tapinfo->callsinfo_list);
172 callsinfo = list->data;
173 g_free(callsinfo->call_id);
174 g_free(callsinfo->from_identity);
175 g_free(callsinfo->to_identity);
176 g_free((void *)(callsinfo->initial_speaker.data));
177 g_free(callsinfo->protocol_name);
178 g_free(callsinfo->call_comment);
180 if (callsinfo->free_prot_info && callsinfo->prot_info)
181 callsinfo->free_prot_info(callsinfo->prot_info);
184 list = g_list_next(list);
186 g_list_free(tapinfo->callsinfo_list);
187 tapinfo->callsinfo_list = NULL;
189 tapinfo->npackets = 0;
190 tapinfo->start_packets = 0;
191 tapinfo->completed_calls = 0;
192 tapinfo->rejected_calls = 0;
194 /* free the graph data items first */
195 list = g_list_first(tapinfo->graph_analysis->list);
198 graph_item = list->data;
199 g_free(graph_item->frame_label);
200 g_free(graph_item->comment);
201 g_free((void *)graph_item->src_addr.data);
202 g_free((void *)graph_item->dst_addr.data);
204 list = g_list_next(list);
206 g_list_free(tapinfo->graph_analysis->list);
207 tapinfo->graph_analysis->nconv = 0;
208 tapinfo->graph_analysis->list = NULL;
210 ++(tapinfo->launch_count);
212 /* free the strinfo data items first */
213 list = g_list_first(rtp_tapinfo->list);
216 strinfo = list->data;
217 g_free(strinfo->pt_str);
218 list = g_list_next(list);
220 g_list_free(rtp_tapinfo->list);
221 rtp_tapinfo->list = NULL;
226 /****************************************************************************/
227 void graph_analysis_data_init(void){
228 the_tapinfo_struct.graph_analysis = g_malloc(sizeof(graph_analysis_info_t));
229 the_tapinfo_struct.graph_analysis->nconv = 0;
230 the_tapinfo_struct.graph_analysis->list = NULL;
233 /****************************************************************************/
234 /* Add a new item into the graph */
235 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)
237 graph_analysis_item_t *gai;
239 gai = g_malloc(sizeof(graph_analysis_item_t));
241 COPY_ADDRESS(&(gai->src_addr),src_addr);
242 COPY_ADDRESS(&(gai->dst_addr),dst_addr);
244 gai->port_src=pinfo->srcport;
245 gai->port_dst=pinfo->destport;
246 if (frame_label != NULL)
247 gai->frame_label = g_strdup(frame_label);
249 gai->frame_label = g_strdup("");
252 gai->comment = g_strdup(comment);
254 gai->comment = g_strdup("");
255 gai->conv_num=call_num;
256 gai->line_style=line_style;
259 tapinfo->graph_analysis->list = g_list_append(tapinfo->graph_analysis->list, gai);
263 /****************************************************************************/
264 /* Append str to frame_label and comment in a graph item */
265 /* return 0 if the frame_num is not in the graph list */
266 static int append_to_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
268 graph_analysis_item_t *gai;
270 gchar *frame_label = NULL;
271 gchar *comment = NULL;
273 list = g_list_first(tapinfo->graph_analysis->list);
277 if (gai->fd->num == frame_num){
278 frame_label = gai->frame_label;
279 comment = gai->comment;
281 if (new_frame_label != NULL){
282 gai->frame_label = g_strdup_printf("%s %s", frame_label, new_frame_label);
286 if (new_comment != NULL){
287 gai->comment = g_strdup_printf("%s %s", comment, new_comment);
292 list = g_list_next(list);
299 /****************************************************************************/
300 /* Change the frame_label and comment in a graph item if not NULL*/
301 /* return 0 if the frame_num is not in the graph list */
302 static int change_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
304 graph_analysis_item_t *gai;
306 gchar *frame_label = NULL;
307 gchar *comment = NULL;
309 list = g_list_first(tapinfo->graph_analysis->list);
313 if (gai->fd->num == frame_num){
314 frame_label = gai->frame_label;
315 comment = gai->comment;
317 if (new_frame_label != NULL){
318 gai->frame_label = g_strdup(new_frame_label);
322 if (new_comment != NULL){
323 gai->comment = g_strdup(new_comment);
328 list = g_list_next(list);
335 /****************************************************************************/
336 /* Change all the graph items with call_num to new_call_num */
337 static guint change_call_num_graph(voip_calls_tapinfo_t *tapinfo _U_, guint16 call_num, guint16 new_call_num)
339 graph_analysis_item_t *gai;
344 list = g_list_first(tapinfo->graph_analysis->list);
348 if (gai->conv_num == call_num){
349 gai->conv_num = new_call_num;
352 list = g_list_next(list);
354 return items_changed;
357 /****************************************************************************/
358 /* Insert the item in the graph list */
359 static void insert_to_graph_t38(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, guint32 frame_num)
361 graph_analysis_item_t *gai, *new_gai;
366 new_gai = g_malloc(sizeof(graph_analysis_item_t));
367 new_gai->fd = new_packet_list_get_row_data(frame_num);
368 COPY_ADDRESS(&(new_gai->src_addr),src_addr);
369 COPY_ADDRESS(&(new_gai->dst_addr),dst_addr);
371 new_gai->port_src=pinfo->srcport;
372 new_gai->port_dst=pinfo->destport;
373 if (frame_label != NULL)
374 new_gai->frame_label = g_strdup(frame_label);
376 new_gai->frame_label = g_strdup("");
379 new_gai->comment = g_strdup(comment);
381 new_gai->comment = g_strdup("");
382 new_gai->conv_num=call_num;
383 new_gai->line_style=line_style;
384 new_gai->display=FALSE;
388 list = g_list_first(tapinfo->graph_analysis->list);
392 if (gai->fd->num > frame_num){
393 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item_num);
397 list = g_list_next(list);
401 if (!inserted) tapinfo->graph_analysis->list = g_list_append(tapinfo->graph_analysis->list, new_gai);
404 /****************************************************************************/
405 /* ***************************TAP for RTP Events*****************************/
406 /****************************************************************************/
408 static guint32 rtp_evt_frame_num = 0;
409 static guint8 rtp_evt = 0;
410 static gboolean rtp_evt_end = FALSE;
411 /*static guint32 rtp_evt_setup_frame_num = 0;*/
413 /****************************************************************************/
414 /* whenever a rtp event packet is seen by the tap listener */
416 rtp_event_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *rtp_event_info)
418 const struct _rtp_event_info *pi = rtp_event_info;
420 /* do not consider RTP events packets without a setup frame */
421 if (pi->info_setup_frame_num == 0){
425 rtp_evt_frame_num = pinfo->fd->num;
426 rtp_evt = pi->info_rtp_evt;
427 rtp_evt_end = pi->info_end;
432 /****************************************************************************/
433 static gboolean have_rtp_event_tap_listener=FALSE;
436 rtp_event_init_tap(void)
438 GString *error_string;
441 if(have_rtp_event_tap_listener==FALSE)
443 error_string = register_tap_listener("rtpevent", &(the_tapinfo_rtp_struct.rtp_event_dummy),
451 if (error_string != NULL) {
452 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
453 "%s", error_string->str);
454 g_string_free(error_string, TRUE);
457 have_rtp_event_tap_listener=TRUE;
461 /****************************************************************************/
464 remove_tap_listener_rtp_event(void)
466 protect_thread_critical_region();
467 remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_event_dummy));
468 unprotect_thread_critical_region();
470 have_rtp_event_tap_listener=FALSE;
473 /****************************************************************************/
474 /* ***************************TAP for RTP **********************************/
475 /****************************************************************************/
477 /****************************************************************************/
478 /* when there is a [re]reading of RTP packet's */
479 static void voip_rtp_reset(void *ptr _U_)
481 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
483 /* free the data items first */
484 list = g_list_first(tapinfo->list);
488 list = g_list_next(list);
490 g_list_free(tapinfo->list);
491 tapinfo->list = NULL;
492 tapinfo->nstreams = 0;
496 /****************************************************************************/
497 /* whenever a RTP packet is seen by the tap listener */
499 RTP_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void const *RTPinfo)
501 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
502 voip_rtp_stream_info_t *tmp_listinfo;
503 voip_rtp_stream_info_t *strinfo = NULL;
505 struct _rtp_conversation_info *p_conv_data = NULL;
507 const struct _rtp_info *pi = RTPinfo;
509 /* do not consider RTP packets without a setup frame */
510 if (pi->info_setup_frame_num == 0){
514 /* add this RTP for future listening using the RTP Player*/
515 #ifdef HAVE_LIBPORTAUDIO
516 add_rtp_packet(pi, pinfo);
519 /* check whether we already have a RTP stream with this setup frame and ssrc in the list */
520 list = g_list_first(tapinfo->list);
523 tmp_listinfo=list->data;
524 if ( (tmp_listinfo->setup_frame_number == pi->info_setup_frame_num)
525 && (tmp_listinfo->ssrc == pi->info_sync_src) && (tmp_listinfo->end_stream == FALSE)){
526 /* if the payload type has changed, we mark the stream as finished to create a new one
527 this is to show multiple payload changes in the Graph for example for DTMF RFC2833 */
528 if ( tmp_listinfo->pt != pi->info_payload_type ) {
529 tmp_listinfo->end_stream = TRUE;
531 strinfo = (voip_rtp_stream_info_t*)(list->data);
535 list = g_list_next(list);
538 /* if this is a duplicated RTP Event End, just return */
539 if ((rtp_evt_frame_num == pinfo->fd->num) && !strinfo && (rtp_evt_end == TRUE)) {
543 /* not in the list? then create a new entry */
545 strinfo = g_malloc(sizeof(voip_rtp_stream_info_t));
546 COPY_ADDRESS(&(strinfo->src_addr), &(pinfo->src));
547 strinfo->src_port = pinfo->srcport;
548 COPY_ADDRESS(&(strinfo->dest_addr), &(pinfo->dst));
549 strinfo->dest_port = pinfo->destport;
550 strinfo->ssrc = pi->info_sync_src;
551 strinfo->end_stream = FALSE;
552 strinfo->pt = pi->info_payload_type;
553 strinfo->pt_str = NULL;
554 strinfo->is_srtp = pi->info_is_srtp;
555 /* if it is dynamic payload, let use the conv data to see if it is defined */
556 if ( (strinfo->pt >= PT_UNDF_96) && (strinfo->pt <= PT_UNDF_127) ) {
557 /* Use existing packet info if available */
558 p_conv_data = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name("rtp"));
559 if (p_conv_data && p_conv_data->rtp_dyn_payload) {
560 encoding_name_and_rate_t *encoding_name_and_rate_pt = NULL;
561 encoding_name_and_rate_pt = g_hash_table_lookup(p_conv_data->rtp_dyn_payload, &strinfo->pt);
562 if (encoding_name_and_rate_pt) {
563 strinfo->pt_str = g_strdup(encoding_name_and_rate_pt->encoding_name);
567 if (!strinfo->pt_str) strinfo->pt_str = g_strdup(val_to_str_ext(strinfo->pt, &rtp_payload_type_short_vals_ext, "%u"));
568 strinfo->npackets = 0;
569 strinfo->start_fd = pinfo->fd;
570 strinfo->setup_frame_number = pi->info_setup_frame_num;
571 strinfo->rtp_event = -1;
572 tapinfo->list = g_list_append(tapinfo->list, strinfo);
576 /* Add the info to the existing RTP stream */
578 strinfo->stop_fd = pinfo->fd;
580 /* process RTP Event */
581 if (rtp_evt_frame_num == pinfo->fd->num) {
582 strinfo->rtp_event = rtp_evt;
583 if (rtp_evt_end == TRUE) {
584 strinfo->end_stream = TRUE;
589 the_tapinfo_struct.redraw = TRUE;
594 /****************************************************************************/
595 /* whenever a redraw in the RTP tap listener */
596 static void RTP_packet_draw(void *prs _U_)
598 voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
599 GList *rtp_streams_list;
600 voip_rtp_stream_info_t *rtp_listinfo;
601 GList *voip_calls_graph_list;
603 graph_analysis_item_t *gai;
604 graph_analysis_item_t *new_gai;
608 /* add each rtp stream to the graph */
609 rtp_streams_list = g_list_first(rtp_tapinfo->list);
610 while (rtp_streams_list)
612 rtp_listinfo = rtp_streams_list->data;
614 /* using the setup frame number of the RTP stream, we get the call number that it belongs */
615 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
616 while (voip_calls_graph_list)
618 gai = voip_calls_graph_list->data;
619 conv_num = gai->conv_num;
620 /* if we get the setup frame number, then get the time position to graph the RTP arrow */
621 if (rtp_listinfo->setup_frame_number == gai->fd->num){
622 /* look again from the begining because there are cases where the Setup frame is after the RTP */
623 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
625 while(voip_calls_graph_list){
626 gai = voip_calls_graph_list->data;
627 /* if RTP was already in the Graph, just update the comment information */
628 if (rtp_listinfo->start_fd->num == gai->fd->num){
629 duration = (guint32)(nstime_to_msec(&rtp_listinfo->stop_fd->rel_ts) - nstime_to_msec(&rtp_listinfo->start_fd->rel_ts));
630 g_free(gai->comment);
631 gai->comment = g_strdup_printf("%s Num packets:%u Duration:%u.%03us SSRC:0x%X",
632 (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->npackets,
633 duration/1000,(duration%1000), rtp_listinfo->ssrc);
637 /* 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 */
638 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
639 if (!voip_calls_graph_list) item++;
641 /* add the RTP item to the graph if was not there*/
642 if (rtp_listinfo->start_fd->num<gai->fd->num || !voip_calls_graph_list){
643 new_gai = g_malloc(sizeof(graph_analysis_item_t));
644 new_gai->fd = rtp_listinfo->start_fd;
645 COPY_ADDRESS(&(new_gai->src_addr),&(rtp_listinfo->src_addr));
646 COPY_ADDRESS(&(new_gai->dst_addr),&(rtp_listinfo->dest_addr));
647 new_gai->port_src = rtp_listinfo->src_port;
648 new_gai->port_dst = rtp_listinfo->dest_port;
649 duration = (guint32)(nstime_to_msec(&rtp_listinfo->stop_fd->rel_ts) - nstime_to_msec(&rtp_listinfo->start_fd->rel_ts));
650 new_gai->frame_label = g_strdup_printf("%s (%s) %s",
651 (rtp_listinfo->is_srtp)?"SRTP":"RTP",
652 rtp_listinfo->pt_str,
653 (rtp_listinfo->rtp_event == -1)?
654 "":val_to_str_const(rtp_listinfo->rtp_event, rtp_event_type_values, "Unknown RTP Event"));
655 new_gai->comment = g_strdup_printf("%s Num packets:%u Duration:%u.%03us SSRC:0x%X",
656 (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->npackets,
657 duration/1000,(duration%1000), rtp_listinfo->ssrc);
658 new_gai->conv_num = conv_num;
659 new_gai->display=FALSE;
660 new_gai->line_style = 2; /* the arrow line will be 2 pixels width */
661 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item);
664 if (voip_calls_graph_list) item++;
668 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
670 rtp_streams_list = g_list_next(rtp_streams_list);
674 static gboolean have_RTP_tap_listener=FALSE;
675 /****************************************************************************/
679 GString *error_string;
681 if(have_RTP_tap_listener==FALSE)
683 /* don't register tap listener, if we have it already */
684 error_string = register_tap_listener("rtp", &(the_tapinfo_rtp_struct.rtp_dummy), NULL,
690 if (error_string != NULL) {
691 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
692 "%s", error_string->str);
693 g_string_free(error_string, TRUE);
696 have_RTP_tap_listener=TRUE;
700 /****************************************************************************/
702 remove_tap_listener_rtp(void)
704 protect_thread_critical_region();
705 remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_dummy));
706 unprotect_thread_critical_region();
708 have_RTP_tap_listener=FALSE;
711 /****************************************************************************/
712 /******************************TAP for T38 **********************************/
713 /****************************************************************************/
715 /****************************************************************************/
716 /* whenever a T38 packet is seen by the tap listener */
718 T38_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *T38info)
720 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
722 voip_calls_info_t *callsinfo = NULL;
723 voip_calls_info_t *tmp_listinfo;
724 GList *voip_calls_graph_list;
726 gchar *frame_label = NULL;
727 gchar *comment = NULL;
728 graph_analysis_item_t *tmp_gai, *gai = NULL;
729 guint16 line_style = 2;
733 const t38_packet_info *pi = T38info;
735 if (pi->setup_frame_number != 0) {
736 /* using the setup frame number of the T38 packet, we get the call number that it belongs */
737 voip_calls_graph_list = g_list_first(tapinfo->graph_analysis->list);
738 while (voip_calls_graph_list)
740 tmp_gai = voip_calls_graph_list->data;
741 if (pi->setup_frame_number == tmp_gai->fd->num){
745 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
747 if (gai) conv_num = (int) gai->conv_num;
750 /* 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
751 * have the associated Voip calls. It probably means the the packet was decoded using the default t38 port, or using "Decode as.."
752 * in this case we create a "voip" call that only have t38 media (no signaling)
753 * OR if we have not found the Setup message in the graph.
755 if ( (pi->setup_frame_number == 0) || (gai == NULL) ){
756 /* check whether we already have a call with these parameters in the list */
757 list = g_list_first(tapinfo->callsinfo_list);
760 tmp_listinfo=list->data;
761 if (tmp_listinfo->protocol == MEDIA_T38){
762 callsinfo = (voip_calls_info_t*)(list->data);
765 list = g_list_next (list);
768 /* not in the list? then create a new entry */
769 if (callsinfo==NULL){
770 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
771 callsinfo->call_active_state = VOIP_ACTIVE;
772 callsinfo->call_state = VOIP_UNKNOWN;
773 callsinfo->from_identity=g_strdup("T38 Media only");
774 callsinfo->to_identity=g_strdup("T38 Media only");
775 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
776 callsinfo->selected=FALSE;
777 callsinfo->start_fd = pinfo->fd;
778 callsinfo->protocol=MEDIA_T38;
779 callsinfo->prot_info=NULL;
780 callsinfo->free_prot_info = NULL;
781 callsinfo->npackets = 0;
782 callsinfo->call_num = tapinfo->ncalls++;
783 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
785 ++(callsinfo->npackets);
786 /* increment the packets counter of all calls */
787 ++(tapinfo->npackets);
789 conv_num = (int) callsinfo->call_num;
792 /* at this point we should have found the call num for this t38 packets belong */
793 if (conv_num == -1) {
797 /* add the item to the graph list */
798 if (pi->type_msg == 0) { /* 0=t30-indicator */
799 frame_label = g_strdup(val_to_str(pi->t30ind_value, t38_T30_indicator_vals, "Ukn (0x%02X)") );
800 comment = g_strdup_printf("t38:t30 Ind:%s",val_to_str(pi->t30ind_value, t38_T30_indicator_vals, "Ukn (0x%02X)") );
802 } else if (pi->type_msg == 1) { /* 1=data */
803 switch(pi->Data_Field_field_type_value){
804 case 0: /* hdlc-data */
806 case 2: /* hdlc-fcs-OK */
807 case 4: /* hdlc-fcs-OK-sig-end */
808 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);
809 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)"));
811 case 3: /* hdlc-fcs-BAD */
812 case 5: /* hdlc-fcs-BAD-sig-end */
813 frame_label = g_strdup(pi->Data_Field_field_type_value == 3 ? "fcs-BAD" : "fcs-BAD-sig-end");
814 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");
816 case 7: /* t4-non-ecm-sig-end */
817 duration = nstime_to_sec(&pinfo->fd->rel_ts) - pi->time_first_t4_data;
818 frame_label = g_strdup_printf("t4-non-ecm-data:%s",val_to_str(pi->data_value, t38_T30_data_vals, "Ukn (0x%02X)") );
819 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 );
820 insert_to_graph_t38(tapinfo, pinfo, frame_label, comment, (guint16)conv_num, &(pinfo->src), &(pinfo->dst), line_style, pi->frame_num_first_t4_data);
825 if (frame_label && !(pi->Data_Field_field_type_value == 7 && pi->type_msg == 1)) {
826 add_to_graph(tapinfo, pinfo, frame_label, comment, (guint16)conv_num, &(pinfo->src), &(pinfo->dst), line_style);
832 tapinfo->redraw = TRUE;
834 return 1; /* refresh output */
837 static gboolean have_T38_tap_listener=FALSE;
838 /****************************************************************************/
842 GString *error_string;
844 if(have_T38_tap_listener==FALSE)
846 /* don't register tap listener, if we have it already */
847 error_string = register_tap_listener("t38", &(the_tapinfo_struct.t38_dummy), NULL,
849 voip_calls_dlg_reset,
853 if (error_string != NULL) {
854 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
855 "%s", error_string->str);
856 g_string_free(error_string, TRUE);
859 have_T38_tap_listener=TRUE;
863 /****************************************************************************/
865 remove_tap_listener_t38(void)
867 protect_thread_critical_region();
868 remove_tap_listener(&(the_tapinfo_struct.t38_dummy));
869 unprotect_thread_critical_region();
871 have_T38_tap_listener=FALSE;
875 /****************************************************************************/
876 static gchar *sdp_summary = NULL;
877 static guint32 sdp_frame_num = 0;
879 /****************************************************************************/
880 /* ***************************TAP for SIP **********************************/
881 /****************************************************************************/
884 static void free_sip_info(gpointer p) {
885 sip_calls_info_t *si = p;
887 g_free(si->call_identifier);
891 /****************************************************************************/
892 /* whenever a SIP packet is seen by the tap listener */
894 SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SIPinfo)
896 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
897 /* we just take note of the ISUP data here; when we receive the MTP3 part everything will
898 be compared with existing calls */
900 voip_calls_info_t *tmp_listinfo;
901 voip_calls_info_t *callsinfo = NULL;
902 sip_calls_info_t *tmp_sipinfo = NULL;
904 address tmp_src, tmp_dst;
905 gchar *frame_label = NULL;
906 gchar *comment = NULL;
908 const sip_info_value_t *pi = SIPinfo;
910 /* do not consider packets without call_id */
911 if (pi->tap_call_id ==NULL){
915 /* check whether we already have a call with these parameters in the list */
916 list = g_list_first(tapinfo->callsinfo_list);
919 tmp_listinfo=list->data;
920 if (tmp_listinfo->protocol == VOIP_SIP){
921 tmp_sipinfo = tmp_listinfo->prot_info;
922 if (strcmp(tmp_sipinfo->call_identifier,pi->tap_call_id)==0){
923 callsinfo = (voip_calls_info_t*)(list->data);
927 list = g_list_next (list);
930 /* not in the list? then create a new entry if the message is INVITE -i.e. if this session is a call*/
931 if ((callsinfo==NULL) &&(pi->request_method!=NULL)){
932 if (strcmp(pi->request_method,"INVITE")==0){
933 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
934 callsinfo->call_active_state = VOIP_ACTIVE;
935 callsinfo->call_state = VOIP_CALL_SETUP;
936 callsinfo->from_identity=g_strdup(pi->tap_from_addr);
937 callsinfo->to_identity=g_strdup(pi->tap_to_addr);
938 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
939 callsinfo->selected=FALSE;
940 callsinfo->start_fd=pinfo->fd;
941 callsinfo->protocol=VOIP_SIP;
942 callsinfo->prot_info=g_malloc(sizeof(sip_calls_info_t));
943 callsinfo->free_prot_info = free_sip_info;
944 tmp_sipinfo = callsinfo->prot_info;
945 tmp_sipinfo->call_identifier = g_strdup(pi->tap_call_id);
946 tmp_sipinfo->sip_state = SIP_INVITE_SENT;
947 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
948 callsinfo->npackets = 0;
949 callsinfo->call_num = tapinfo->ncalls++;
950 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
954 if (callsinfo!=NULL){
956 /* let's analyze the call state */
958 COPY_ADDRESS(&(tmp_src), &(pinfo->src));
959 COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
961 if (pi->request_method == NULL){
962 frame_label = g_strdup_printf("%u %s", pi->response_code, pi->reason_phrase );
963 comment = g_strdup("SIP Status");
965 if ((tmp_sipinfo && pi->tap_cseq_number == tmp_sipinfo->invite_cseq)&&(ADDRESSES_EQUAL(&tmp_dst,&(callsinfo->initial_speaker)))){
966 if ((pi->response_code > 199) && (pi->response_code<300) && (tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
967 tmp_sipinfo->sip_state = SIP_200_REC;
969 else if ((pi->response_code>299)&&(tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
970 callsinfo->call_state = VOIP_REJECTED;
971 tapinfo->rejected_calls++;
977 frame_label = g_strdup(pi->request_method);
979 if ((strcmp(pi->request_method,"INVITE")==0)&&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))){
980 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
981 callsinfo->call_state = VOIP_CALL_SETUP;
982 comment = g_strdup_printf("SIP From: %s To:%s", callsinfo->from_identity, callsinfo->to_identity);
984 else if ((strcmp(pi->request_method,"ACK")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
985 &&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))&&(tmp_sipinfo->sip_state==SIP_200_REC)
986 &&(callsinfo->call_state == VOIP_CALL_SETUP)){
987 callsinfo->call_state = VOIP_IN_CALL;
988 comment = g_strdup("SIP Request");
990 else if (strcmp(pi->request_method,"BYE")==0){
991 callsinfo->call_state = VOIP_COMPLETED;
992 tapinfo->completed_calls++;
993 comment = g_strdup("SIP Request");
995 else if ((strcmp(pi->request_method,"CANCEL")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
996 &&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))&&(callsinfo->call_state==VOIP_CALL_SETUP)){
997 callsinfo->call_state = VOIP_CANCELLED;
998 tmp_sipinfo->sip_state = SIP_CANCEL_SENT;
999 comment = g_strdup("SIP Request");
1001 comment = g_strdup("SIP Request");
1005 callsinfo->stop_fd = pinfo->fd;
1006 ++(callsinfo->npackets);
1007 /* increment the packets counter of all calls */
1008 ++(tapinfo->npackets);
1010 /* add to the graph */
1011 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1013 g_free(frame_label);
1014 g_free((void *)tmp_src.data);
1015 g_free((void *)tmp_dst.data);
1017 /* add SDP info if apply */
1018 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
1019 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
1020 g_free(sdp_summary);
1025 tapinfo->redraw = TRUE;
1027 return 1; /* refresh output */
1031 /****************************************************************************/
1032 voip_calls_tapinfo_t* voip_calls_get_info(void)
1034 return &the_tapinfo_struct;
1038 /****************************************************************************/
1040 /****************************************************************************/
1041 static gboolean have_SIP_tap_listener=FALSE;
1042 /****************************************************************************/
1044 sip_calls_init_tap(void)
1046 GString *error_string;
1048 if(have_SIP_tap_listener==FALSE)
1050 /* don't register tap listener, if we have it already */
1051 error_string = register_tap_listener("sip", &(the_tapinfo_struct.sip_dummy), NULL,
1053 voip_calls_dlg_reset,
1057 if (error_string != NULL) {
1058 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1059 "%s", error_string->str);
1060 g_string_free(error_string, TRUE);
1063 have_SIP_tap_listener=TRUE;
1067 /****************************************************************************/
1069 remove_tap_listener_sip_calls(void)
1071 protect_thread_critical_region();
1072 remove_tap_listener(&(the_tapinfo_struct.sip_dummy));
1073 unprotect_thread_critical_region();
1075 have_SIP_tap_listener=FALSE;
1078 /****************************************************************************/
1079 /* ***************************TAP for ISUP **********************************/
1080 /****************************************************************************/
1082 static guint32 mtp3_opc, mtp3_dpc;
1083 static guint8 mtp3_ni;
1084 static guint32 mtp3_frame_num;
1087 /****************************************************************************/
1088 /* whenever a isup_ packet is seen by the tap listener */
1090 isup_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *isup_info _U_)
1092 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1093 voip_calls_info_t *tmp_listinfo;
1094 voip_calls_info_t *callsinfo = NULL;
1095 isup_calls_info_t *tmp_isupinfo;
1096 gboolean found = FALSE;
1097 gboolean forward = FALSE;
1098 gboolean right_pair;
1100 gchar *frame_label = NULL;
1101 gchar *comment = NULL;
1103 /*voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct; unused */
1104 const isup_tap_rec_t *pi = isup_info;
1106 /* check if the lower layer is MTP matching the frame number */
1107 if (mtp3_frame_num != pinfo->fd->num) return 0;
1109 /* check whether we already have a call with these parameters in the list */
1110 list = g_list_first(tapinfo->callsinfo_list);
1114 tmp_listinfo=list->data;
1115 if ((tmp_listinfo->protocol == VOIP_ISUP)&&(tmp_listinfo->call_active_state==VOIP_ACTIVE)){
1116 tmp_isupinfo = tmp_listinfo->prot_info;
1117 if ((tmp_isupinfo->cic == pinfo->circuit_id)&&(tmp_isupinfo->ni == mtp3_ni)) {
1118 if ((tmp_isupinfo->opc == mtp3_opc)&&(tmp_isupinfo->dpc == mtp3_dpc)){
1120 } else if ((tmp_isupinfo->dpc == mtp3_opc)&&(tmp_isupinfo->opc == mtp3_dpc)){
1127 /* if there is an IAM for a call that is not in setup state, that means the previous call in the same
1128 cic is no longer active */
1129 if (tmp_listinfo->call_state == VOIP_CALL_SETUP){
1131 } else if (pi->message_type != 1){
1134 tmp_listinfo->call_active_state=VOIP_INACTIVE;
1139 callsinfo = (voip_calls_info_t*)(list->data);
1144 list = g_list_next (list);
1147 /* not in the list? then create a new entry if the message is IAM
1148 -i.e. if this session is a call*/
1151 if ((callsinfo==NULL) &&(pi->message_type==1)){
1152 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
1153 callsinfo->call_active_state = VOIP_ACTIVE;
1154 callsinfo->call_state = VOIP_UNKNOWN;
1155 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
1156 callsinfo->selected=FALSE;
1157 callsinfo->start_fd=pinfo->fd;
1158 callsinfo->protocol=VOIP_ISUP;
1159 if (pi->calling_number!=NULL){
1160 callsinfo->from_identity=g_strdup(pi->calling_number);
1162 if (pi->called_number!=NULL){
1163 callsinfo->to_identity=g_strdup(pi->called_number);
1165 callsinfo->prot_info=g_malloc(sizeof(isup_calls_info_t));
1166 callsinfo->free_prot_info = g_free;
1167 tmp_isupinfo=callsinfo->prot_info;
1168 tmp_isupinfo->opc = mtp3_opc;
1169 tmp_isupinfo->dpc = mtp3_dpc;
1170 tmp_isupinfo->ni = mtp3_ni;
1171 tmp_isupinfo->cic = pinfo->circuit_id;
1172 callsinfo->npackets = 0;
1173 callsinfo->call_num = tapinfo->ncalls++;
1174 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
1178 if (callsinfo!=NULL){
1179 callsinfo->stop_fd = pinfo->fd;
1180 ++(callsinfo->npackets);
1182 /* Let's analyze the call state */
1184 frame_label = g_strdup(val_to_str_ext_const(pi->message_type, &isup_message_type_value_acro_ext, "Unknown"));
1186 if (callsinfo->npackets == 1){ /* this is the first packet, that must be an IAM */
1188 if ((pi->calling_number!=NULL)&&(pi->called_number !=NULL)){
1189 comment = g_strdup_printf("Call from %s to %s",
1190 pi->calling_number, pi->called_number);
1192 } else if (callsinfo->npackets == 2){ /* in the second packet we show the SPs */
1194 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
1196 mtp3_ni, mtp3_dpc, pinfo->circuit_id);
1198 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
1200 mtp3_ni, mtp3_opc, pinfo->circuit_id);
1205 switch(pi->message_type){
1207 callsinfo->call_state=VOIP_CALL_SETUP;
1209 case 7: /* CONNECT */
1210 case 9: /* ANSWER */
1211 callsinfo->call_state=VOIP_IN_CALL;
1213 case 12: /* RELEASE */
1214 if (callsinfo->call_state==VOIP_CALL_SETUP){
1216 callsinfo->call_state=VOIP_CANCELLED;
1219 callsinfo->call_state=VOIP_REJECTED;
1220 tapinfo->rejected_calls++;
1223 else if (callsinfo->call_state == VOIP_IN_CALL){
1224 callsinfo->call_state = VOIP_COMPLETED;
1225 tapinfo->completed_calls++;
1227 comment = g_strdup_printf("Cause %i - %s",
1229 val_to_str_ext_const(pi->cause_value, &q931_cause_code_vals_ext, "(Unknown)"));
1233 /* increment the packets counter of all calls */
1234 ++(tapinfo->npackets);
1236 /* add to the graph */
1237 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1239 g_free(frame_label);
1242 tapinfo->redraw = TRUE;
1244 return 1; /* refresh output */
1247 /****************************************************************************/
1249 static gboolean have_isup_tap_listener=FALSE;
1252 isup_calls_init_tap(void)
1254 GString *error_string;
1257 if(have_isup_tap_listener==FALSE)
1259 error_string = register_tap_listener("isup", &(the_tapinfo_struct.isup_dummy),
1262 voip_calls_dlg_reset,
1267 if (error_string != NULL) {
1268 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1269 "%s", error_string->str);
1270 g_string_free(error_string, TRUE);
1273 have_isup_tap_listener=TRUE;
1277 /****************************************************************************/
1280 remove_tap_listener_isup_calls(void)
1282 protect_thread_critical_region();
1283 remove_tap_listener(&(the_tapinfo_struct.isup_dummy));
1284 unprotect_thread_critical_region();
1286 have_isup_tap_listener=FALSE;
1290 /****************************************************************************/
1291 /* ***************************TAP for MTP3 **********************************/
1292 /****************************************************************************/
1295 /****************************************************************************/
1296 /* whenever a mtp3_ packet is seen by the tap listener */
1298 mtp3_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *mtp3_info _U_)
1300 const mtp3_tap_rec_t *pi = mtp3_info;
1302 /* keep the data in memory to use when the ISUP information arrives */
1304 mtp3_opc = pi->addr_opc.pc;
1305 mtp3_dpc = pi->addr_dpc.pc;
1306 mtp3_ni = pi->addr_opc.ni;
1307 mtp3_frame_num = pinfo->fd->num;
1312 /****************************************************************************/
1314 static gboolean have_mtp3_tap_listener=FALSE;
1315 static gboolean have_m3ua_tap_listener=FALSE;
1318 mtp3_calls_init_tap(void)
1320 GString *error_string;
1323 if(have_mtp3_tap_listener==FALSE)
1325 error_string = register_tap_listener("mtp3", &(the_tapinfo_struct.mtp3_dummy),
1328 voip_calls_dlg_reset,
1333 if (error_string != NULL) {
1334 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1335 "%s", error_string->str);
1336 g_string_free(error_string, TRUE);
1339 have_mtp3_tap_listener=TRUE;
1342 if(have_m3ua_tap_listener==FALSE)
1344 error_string = register_tap_listener("m3ua", &(the_tapinfo_struct.mtp3_dummy),
1347 voip_calls_dlg_reset,
1352 if (error_string != NULL) {
1353 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1354 "%s", error_string->str);
1355 g_string_free(error_string, TRUE);
1358 have_m3ua_tap_listener=TRUE;
1363 /****************************************************************************/
1366 remove_tap_listener_mtp3_calls(void)
1368 protect_thread_critical_region();
1369 remove_tap_listener(&(the_tapinfo_struct.mtp3_dummy));
1370 remove_tap_listener(&(the_tapinfo_struct.m3ua_dummy));
1371 unprotect_thread_critical_region();
1373 have_mtp3_tap_listener=FALSE;
1374 have_m3ua_tap_listener=FALSE;
1377 /****************************************************************************/
1378 /* ***************************TAP for Q931 **********************************/
1379 /****************************************************************************/
1380 void h245_add_to_graph(guint32 new_frame_num);
1381 static const e_guid_t guid_allzero = {0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };
1382 /* defines specific H323 data */
1384 static gchar *q931_calling_number;
1385 static gchar *q931_called_number;
1386 static guint8 q931_cause_value;
1387 static gint32 q931_crv;
1388 static guint32 q931_frame_num;
1390 static guint32 h225_frame_num = 0;
1391 static guint16 h225_call_num = 0;
1392 static h225_cs_type h225_cstype = H225_OTHER;
1393 static gboolean h225_is_faststart;
1395 static guint32 actrace_frame_num = 0;
1396 static gint32 actrace_trunk = 0;
1397 static gint32 actrace_direction = 0;
1400 /****************************************************************************/
1401 /* whenever a q931_ packet is seen by the tap listener */
1403 q931_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *q931_info)
1406 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1407 h323_calls_info_t *tmp_h323info,*tmp2_h323info;
1408 actrace_isdn_calls_info_t *tmp_actrace_isdn_info;
1409 voip_calls_info_t *tmp_listinfo;
1410 voip_calls_info_t *callsinfo = NULL;
1411 h245_address_t *h245_add = NULL;
1414 const q931_packet_info *pi = q931_info;
1416 /* free previously allocated q931_calling/ed_number */
1417 g_free(q931_calling_number);
1418 g_free(q931_called_number);
1420 if (pi->calling_number!=NULL)
1421 q931_calling_number = g_strdup(pi->calling_number);
1423 q931_calling_number = g_strdup("");
1425 if (pi->called_number!=NULL)
1426 q931_called_number = g_strdup(pi->called_number);
1428 q931_called_number = g_strdup("");
1429 q931_cause_value = pi->cause_value;
1430 q931_frame_num = pinfo->fd->num;
1434 /* add staff to H323 calls */
1435 if (h225_frame_num == q931_frame_num) {
1436 tmp_h323info = NULL;
1437 list = g_list_first(tapinfo->callsinfo_list);
1440 tmp_listinfo=list->data;
1441 if ( (tmp_listinfo->protocol == VOIP_H323) && (tmp_listinfo->call_num == h225_call_num) ){
1442 tmp_h323info = tmp_listinfo->prot_info;
1443 callsinfo = (voip_calls_info_t*)(list->data);
1445 /* Add the CRV to the h323 call */
1446 if (tmp_h323info->q931_crv == -1) {
1447 tmp_h323info->q931_crv = q931_crv;
1448 } else if (tmp_h323info->q931_crv != q931_crv) {
1449 tmp_h323info->q931_crv2 = q931_crv;
1453 list = g_list_next (list);
1456 if (callsinfo != NULL) {
1458 if (h225_cstype == H225_SETUP) {
1459 /* set te calling and called number from the Q931 packet */
1460 if (q931_calling_number != NULL){
1461 g_free(callsinfo->from_identity);
1462 callsinfo->from_identity=g_strdup(q931_calling_number);
1464 if (q931_called_number != NULL){
1465 g_free(callsinfo->to_identity);
1466 callsinfo->to_identity=g_strdup(q931_called_number);
1469 /* check if there is an LRQ/LCF that match this Setup */
1470 /* TODO: we are just checking the DialedNumer in LRQ/LCF agains the Setup
1471 we should also check if the h225 signaling IP and port match the destination
1472 Setup ip and port */
1473 list = g_list_first(tapinfo->callsinfo_list);
1476 tmp_listinfo=list->data;
1477 if (tmp_listinfo->protocol == VOIP_H323){
1478 tmp2_h323info = tmp_listinfo->prot_info;
1480 /* check if the called number match a LRQ/LCF */
1481 if ( (strcmp(callsinfo->to_identity, tmp_listinfo->to_identity)==0)
1482 && (memcmp(&tmp2_h323info->guid, &guid_allzero, GUID_LEN) == 0) ){
1483 /* change the call graph to the LRQ/LCF to belong to this call */
1484 callsinfo->npackets += change_call_num_graph(tapinfo, tmp_listinfo->call_num, callsinfo->call_num);
1486 /* remove this LRQ/LCF call entry because we have found the Setup that match them */
1487 g_free(tmp_listinfo->from_identity);
1488 g_free(tmp_listinfo->to_identity);
1489 g_free(tmp2_h323info->guid);
1491 list2 = g_list_first(tmp2_h323info->h245_list);
1494 h245_add=list2->data;
1495 g_free((void *)h245_add->h245_address.data);
1496 g_free(list2->data);
1497 list2 = g_list_next(list2);
1499 g_list_free(tmp_h323info->h245_list);
1500 tmp_h323info->h245_list = NULL;
1501 g_free(tmp_listinfo->prot_info);
1502 tapinfo->callsinfo_list = g_list_remove(tapinfo->callsinfo_list, tmp_listinfo);
1506 list = g_list_next (list);
1509 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"),
1510 (h225_is_faststart==TRUE?"on":"off"));
1511 } else if (h225_cstype == H225_RELEASE_COMPLET) {
1512 /* get the Q931 Release cause code */
1513 if (q931_cause_value != 0xFF){
1514 comment = g_strdup_printf("H225 Q931 Rel Cause (%i):%s", q931_cause_value,
1515 val_to_str_ext_const(q931_cause_value, &q931_cause_code_vals_ext, "<unknown>"));
1516 } else { /* Cause not set */
1517 comment = g_strdup("H225 No Q931 Rel Cause");
1520 /* change the graph comment for this new one */
1521 if (comment != NULL) {
1522 change_frame_graph(tapinfo, h225_frame_num, NULL, comment);
1526 /* we reset the h225_frame_num to 0 because there could be empty h225 in the same frame
1527 as non empty h225 (e.g connect), so we don't have to be here twice */
1530 /* add staff to H245 */
1531 } else if (h245_labels.frame_num == q931_frame_num) {
1532 /* there are empty H225 frames that don't have guid (guaid=0) but they have h245 info,
1533 so the only way to match those frames is with the Q931 CRV number */
1534 list = g_list_first(tapinfo->callsinfo_list);
1537 tmp_listinfo=list->data;
1538 if (tmp_listinfo->protocol == VOIP_H323){
1539 tmp_h323info = tmp_listinfo->prot_info;
1540 if ( ((tmp_h323info->q931_crv == q931_crv) || (tmp_h323info->q931_crv2 == q931_crv)) && (q931_crv!=-1)){
1541 /* if the frame number exists in graph, append to it*/
1542 if (!append_to_frame_graph(tapinfo, q931_frame_num, NULL, NULL)) {
1543 /* if not exist, add to the graph */
1544 add_to_graph(tapinfo, pinfo, NULL, NULL, tmp_listinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1545 ++(tmp_listinfo->npackets);
1546 /* increment the packets counter of all calls */
1547 ++(tapinfo->npackets);
1550 /* Add the H245 info if exists to the Graph */
1551 h245_add_to_graph(pinfo->fd->num);
1555 list = g_list_next (list);
1558 /* add staff to ACTRACE */
1559 } else if (actrace_frame_num == q931_frame_num) {
1564 list = g_list_first(tapinfo->callsinfo_list);
1567 tmp_listinfo=list->data;
1568 if ( tmp_listinfo->protocol == VOIP_AC_ISDN ){
1569 tmp_actrace_isdn_info = tmp_listinfo->prot_info;
1570 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
1571 if ( (tmp_actrace_isdn_info->crv == q931_crv) && (tmp_actrace_isdn_info->trunk == actrace_trunk) ) {
1572 callsinfo = (voip_calls_info_t*)(list->data);
1576 list = g_list_next (list);
1579 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, g_strdup("PSTN"));
1581 /* if it is a new call, add it to the list */
1583 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
1584 callsinfo->call_active_state = VOIP_ACTIVE;
1585 callsinfo->call_state = VOIP_CALL_SETUP;
1586 callsinfo->from_identity=g_strdup(q931_calling_number);
1587 callsinfo->to_identity=g_strdup(q931_called_number);
1588 COPY_ADDRESS(&(callsinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
1589 callsinfo->selected=FALSE;
1590 callsinfo->start_fd=pinfo->fd;
1591 callsinfo->protocol=VOIP_AC_ISDN;
1592 callsinfo->prot_info=g_malloc(sizeof(actrace_isdn_calls_info_t));
1593 callsinfo->free_prot_info = g_free;
1594 tmp_actrace_isdn_info=callsinfo->prot_info;
1595 tmp_actrace_isdn_info->crv=q931_crv;
1596 tmp_actrace_isdn_info->trunk=actrace_trunk;
1597 callsinfo->npackets = 0;
1598 callsinfo->call_num = tapinfo->ncalls++;
1599 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
1602 callsinfo->stop_fd = pinfo->fd;
1603 ++(callsinfo->npackets);
1604 /* increment the packets counter of all calls */
1605 ++(tapinfo->npackets);
1607 switch(pi->message_type){
1609 comment = g_strdup_printf("AC_ISDN trunk:%u Calling: %s Called:%s", actrace_trunk, q931_calling_number, q931_called_number);
1610 callsinfo->call_state=VOIP_CALL_SETUP;
1613 callsinfo->call_state=VOIP_IN_CALL;
1615 case Q931_RELEASE_COMPLETE:
1617 case Q931_DISCONNECT:
1618 if (callsinfo->call_state==VOIP_CALL_SETUP){
1619 if (ADDRESSES_EQUAL(&(callsinfo->initial_speaker), actrace_direction?&pstn_add:&(pinfo->src) )){ /* forward direction */
1620 callsinfo->call_state=VOIP_CANCELLED;
1623 callsinfo->call_state=VOIP_REJECTED;
1624 tapinfo->rejected_calls++;
1626 } else if ( (callsinfo->call_state!=VOIP_CANCELLED) && (callsinfo->call_state!=VOIP_REJECTED) ){
1627 callsinfo->call_state=VOIP_COMPLETED;
1628 tapinfo->completed_calls++;
1630 if (q931_cause_value != 0xFF){
1631 comment = g_strdup_printf("AC_ISDN trunk:%u Q931 Rel Cause (%i):%s", actrace_trunk, q931_cause_value,
1632 val_to_str_ext_const(q931_cause_value, &q931_cause_code_vals_ext, "<unknown>"));
1633 } else { /* Cause not set */
1634 comment = g_strdup("AC_ISDN No Q931 Rel Cause");
1640 comment = g_strdup_printf("AC_ISDN trunk:%u", actrace_trunk );
1642 add_to_graph(tapinfo, pinfo, val_to_str(pi->message_type, q931_message_type_vals, "<unknown>") , comment, callsinfo->call_num,
1643 actrace_direction?&pstn_add:&(pinfo->src),
1644 actrace_direction?&(pinfo->src):&pstn_add,
1648 g_free((char *)pstn_add.data);
1651 tapinfo->redraw = TRUE;
1653 return 1; /* refresh output */
1656 /****************************************************************************/
1657 static gboolean have_q931_tap_listener=FALSE;
1660 q931_calls_init_tap(void)
1662 GString *error_string;
1665 if(have_q931_tap_listener==FALSE)
1667 error_string = register_tap_listener("q931", &(the_tapinfo_struct.q931_dummy),
1670 voip_calls_dlg_reset,
1675 if (error_string != NULL) {
1676 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1677 "%s", error_string->str);
1678 g_string_free(error_string, TRUE);
1681 have_q931_tap_listener=TRUE;
1685 /****************************************************************************/
1688 remove_tap_listener_q931_calls(void)
1690 protect_thread_critical_region();
1691 remove_tap_listener(&(the_tapinfo_struct.q931_dummy));
1692 unprotect_thread_critical_region();
1694 have_q931_tap_listener=FALSE;
1697 /****************************************************************************/
1698 /****************************TAP for H323 ***********************************/
1699 /****************************************************************************/
1701 static void add_h245_Address(h323_calls_info_t *h323info, h245_address_t *h245_address)
1703 h323info->h245_list = g_list_append(h323info->h245_list, h245_address);
1707 static void free_h225_info(gpointer p) {
1708 h323_calls_info_t *tmp_h323info = p;
1710 g_free(tmp_h323info->guid);
1712 if (tmp_h323info->h245_list) {
1713 GList *list2 = g_list_first(tmp_h323info->h245_list);
1716 h245_address_t *h245_add=list2->data;
1717 g_free((void *)h245_add->h245_address.data);
1718 g_free(list2->data);
1719 list2 = g_list_next(list2);
1722 g_list_free(tmp_h323info->h245_list);
1728 /****************************************************************************/
1729 /* whenever a H225 packet is seen by the tap listener */
1731 H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H225info)
1733 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1734 voip_calls_info_t *tmp_listinfo;
1735 voip_calls_info_t *callsinfo = NULL;
1736 h323_calls_info_t *tmp_h323info = NULL;
1740 h245_address_t *h245_add = NULL;
1742 const h225_packet_info *pi = H225info;
1744 /* if not guid and RAS and not LRQ, LCF or LRJ return because did not belong to a call */
1745 /* OR, if not guid and is H225 return because doesn't belong to a call */
1746 if ((memcmp(&pi->guid, &guid_allzero, GUID_LEN) == 0))
1747 if ( ((pi->msg_type == H225_RAS) && ((pi->msg_tag < 18) || (pi->msg_tag > 20))) || (pi->msg_type != H225_RAS) )
1750 /* if it is RAS LCF or LRJ*/
1751 if ( (pi->msg_type == H225_RAS) && ((pi->msg_tag == 19) || (pi->msg_tag == 20))) {
1752 /* if the LCF/LRJ doesn't match to a LRQ, just return */
1753 if (!pi->request_available) return 0;
1755 /* check whether we already have a call with this request SeqNum */
1756 list = g_list_first(tapinfo->callsinfo_list);
1759 tmp_listinfo=list->data;
1760 g_assert(tmp_listinfo != NULL);
1761 if (tmp_listinfo->protocol == VOIP_H323){
1762 tmp_h323info = tmp_listinfo->prot_info;
1763 if (tmp_h323info->requestSeqNum == pi->requestSeqNum) {
1764 callsinfo = (voip_calls_info_t*)(list->data);
1768 list = g_list_next (list);
1771 /* check whether we already have a call with this guid in the list */
1772 list = g_list_first(tapinfo->callsinfo_list);
1775 tmp_listinfo=list->data;
1776 if (tmp_listinfo->protocol == VOIP_H323){
1777 tmp_h323info = tmp_listinfo->prot_info;
1778 g_assert(tmp_h323info != NULL);
1779 if ( (memcmp(tmp_h323info->guid, &guid_allzero, GUID_LEN) != 0) && (memcmp(tmp_h323info->guid, &pi->guid,GUID_LEN)==0) ){
1780 callsinfo = (voip_calls_info_t*)(list->data);
1784 list = g_list_next (list);
1788 h225_cstype = pi->cs_type;
1789 h225_is_faststart = pi->is_faststart;
1791 /* not in the list? then create a new entry */
1792 if (callsinfo==NULL){
1793 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
1794 callsinfo->call_active_state = VOIP_ACTIVE;
1795 callsinfo->call_state = VOIP_UNKNOWN;
1796 callsinfo->from_identity=g_strdup("");
1797 callsinfo->to_identity=g_strdup("");
1798 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
1799 callsinfo->selected=FALSE;
1800 callsinfo->start_fd=pinfo->fd;
1801 callsinfo->protocol=VOIP_H323;
1802 callsinfo->prot_info=g_malloc(sizeof(h323_calls_info_t));
1803 callsinfo->free_prot_info = free_h225_info;
1805 tmp_h323info = callsinfo->prot_info;
1806 g_assert(tmp_h323info != NULL);
1807 tmp_h323info->guid = g_memdup(&pi->guid, sizeof pi->guid);
1808 tmp_h323info->h225SetupAddr.type = AT_NONE;
1809 tmp_h323info->h225SetupAddr.len = 0;
1810 tmp_h323info->h245_list = NULL;
1811 tmp_h323info->is_faststart_Setup = FALSE;
1812 tmp_h323info->is_faststart_Proc = FALSE;
1813 tmp_h323info->is_h245Tunneling = FALSE;
1814 tmp_h323info->is_h245 = FALSE;
1815 tmp_h323info->q931_crv = -1;
1816 tmp_h323info->q931_crv2 = -1;
1817 tmp_h323info->requestSeqNum = 0;
1818 callsinfo->call_num = tapinfo->ncalls++;
1819 callsinfo->npackets = 0;
1821 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
1824 if (callsinfo!=NULL){
1826 h225_frame_num = pinfo->fd->num;
1827 h225_call_num = callsinfo->call_num;
1829 /* let's analyze the call state */
1831 callsinfo->stop_fd = pinfo->fd;
1832 ++(callsinfo->npackets);
1833 /* increment the packets counter of all calls */
1834 ++(tapinfo->npackets);
1837 /* XXX: it is supposed to be initialized isn't it? */
1838 g_assert(tmp_h323info != NULL);
1840 /* change the status */
1841 if (pi->msg_type == H225_CS){
1843 /* this is still IPv4 only, because the dissector is */
1844 if (pi->is_h245 == TRUE){
1845 h245_add = g_malloc(sizeof (h245_address_t));
1846 h245_add->h245_address.type=AT_IPv4;
1847 h245_add->h245_address.len=4;
1848 h245_add->h245_address.data = g_malloc(sizeof(pi->h245_address));
1849 memcpy((void *)(h245_add->h245_address.data), &(pi->h245_address), 4);
1850 h245_add->h245_port = pi->h245_port;
1851 add_h245_Address(tmp_h323info, h245_add);
1854 if (pi->cs_type != H225_RELEASE_COMPLET) tmp_h323info->is_h245Tunneling = pi->is_h245Tunneling;
1856 frame_label = g_strdup(pi->frame_label);
1858 switch(pi->cs_type){
1860 tmp_h323info->is_faststart_Setup = pi->is_faststart;
1862 /* Set the Setup address if it was not set */
1863 if (tmp_h323info->h225SetupAddr.type == AT_NONE)
1864 COPY_ADDRESS(&(tmp_h323info->h225SetupAddr), &(pinfo->src));
1865 callsinfo->call_state=VOIP_CALL_SETUP;
1866 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1867 (pi->is_faststart==TRUE?"on":"off"));
1870 callsinfo->call_state=VOIP_IN_CALL;
1871 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1872 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1873 (pi->is_faststart==TRUE?"on":"off"));
1875 case H225_RELEASE_COMPLET:
1876 if (callsinfo->call_state==VOIP_CALL_SETUP){
1877 if (ADDRESSES_EQUAL(&(tmp_h323info->h225SetupAddr),&(pinfo->src))){ /* forward direction */
1878 callsinfo->call_state=VOIP_CANCELLED;
1881 callsinfo->call_state=VOIP_REJECTED;
1882 tapinfo->rejected_calls++;
1885 callsinfo->call_state=VOIP_COMPLETED;
1886 tapinfo->completed_calls++;
1888 comment = g_strdup("H225 No Q931 Rel Cause");
1892 case H225_CALL_PROCEDING:
1893 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1894 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1895 (pi->is_faststart==TRUE?"on":"off"));
1898 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1899 (pi->is_faststart==TRUE?"on":"off"));
1903 else if (pi->msg_type == H225_RAS){
1904 switch(pi->msg_tag){
1906 if (!pi->is_duplicate){
1907 g_free(callsinfo->to_identity);
1908 callsinfo->to_identity=g_strdup(pi->dialedDigits);
1909 tmp_h323info->requestSeqNum = pi->requestSeqNum;
1912 if (strlen(pi->dialedDigits))
1913 comment = g_strdup_printf("H225 RAS dialedDigits: %s", pi->dialedDigits);
1915 comment = g_strdup("H225 RAS");
1918 comment = g_strdup("H225 RAS");
1920 frame_label = g_strdup(val_to_str_const(pi->msg_tag, h225_RasMessage_vals, "<unknown>"));
1922 frame_label = g_strdup("H225: Unknown");
1926 /* add to graph analysis */
1928 /* if the frame number exists in graph, append to it*/
1929 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, comment)) {
1930 /* if not exist, add to the graph */
1931 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1934 /* Add the H245 info if exists to the Graph */
1935 h245_add_to_graph(pinfo->fd->num);
1937 g_free(frame_label);
1941 tapinfo->redraw = TRUE;
1943 return 1; /* refresh output */
1947 /****************************************************************************/
1949 /****************************************************************************/
1950 static gboolean have_H225_tap_listener=FALSE;
1951 /****************************************************************************/
1953 h225_calls_init_tap(void)
1955 GString *error_string;
1957 if(have_H225_tap_listener==FALSE)
1959 /* don't register tap listener, if we have it already */
1960 error_string = register_tap_listener("h225", &(the_tapinfo_struct.h225_dummy), NULL,
1962 voip_calls_dlg_reset,
1967 if (error_string != NULL) {
1968 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1969 "%s", error_string->str);
1970 g_string_free(error_string, TRUE);
1973 have_H225_tap_listener=TRUE;
1977 /****************************************************************************/
1979 remove_tap_listener_h225_calls(void)
1981 protect_thread_critical_region();
1982 remove_tap_listener(&(the_tapinfo_struct.h225_dummy));
1983 unprotect_thread_critical_region();
1985 have_H225_tap_listener=FALSE;
1988 /* Add the h245 label info to the graph */
1989 void h245_add_to_graph(guint32 new_frame_num)
1993 if (new_frame_num != h245_labels.frame_num) return;
1995 for (n=0; n<h245_labels.labels_count; n++) {
1996 append_to_frame_graph(&the_tapinfo_struct, new_frame_num, h245_labels.labels[n].frame_label, h245_labels.labels[n].comment);
1997 g_free(h245_labels.labels[n].frame_label);
1998 h245_labels.labels[n].frame_label = NULL;
1999 g_free(h245_labels.labels[n].comment);
2000 h245_labels.labels[n].comment = NULL;
2002 h245_labels.frame_num = 0;
2003 h245_labels.labels_count = 0;
2006 /* free the h245_labels if the frame number is different */
2007 static void h245_free_labels(guint32 new_frame_num)
2011 if (new_frame_num == h245_labels.frame_num) return;
2013 for (n=0; n<h245_labels.labels_count; n++) {
2014 g_free(h245_labels.labels[n].frame_label);
2015 h245_labels.labels[n].frame_label = NULL;
2016 g_free(h245_labels.labels[n].comment);
2017 h245_labels.labels[n].comment = NULL;
2019 h245_labels.frame_num = 0;
2020 h245_labels.labels_count = 0;
2023 /* add the frame_label and comment to h245_labels and free the actual one if it is different frame num */
2024 static void h245_add_label(guint32 new_frame_num, const gchar *frame_label, const gchar *comment)
2026 h245_free_labels(new_frame_num);
2028 h245_labels.frame_num = new_frame_num;
2029 h245_labels.labels[h245_labels.labels_count].frame_label = g_strdup(frame_label);
2030 h245_labels.labels[h245_labels.labels_count].comment = g_strdup(comment);
2032 if (h245_labels.labels_count < (H245_MAX-1))
2033 h245_labels.labels_count++;
2037 /****************************************************************************/
2038 /* whenever a H245dg packet is seen by the tap listener (when H245 tunneling is ON) */
2040 H245dgcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H245info)
2042 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2043 voip_calls_info_t *tmp_listinfo;
2044 voip_calls_info_t *callsinfo = NULL;
2045 h323_calls_info_t *tmp_h323info;
2048 h245_address_t *h245_add = NULL;
2050 const h245_packet_info *pi = H245info;
2052 /* check if Tunneling is OFF and we have a call with this H245 add */
2053 list = g_list_first(tapinfo->callsinfo_list);
2056 tmp_listinfo=list->data;
2057 if (tmp_listinfo->protocol == VOIP_H323){
2058 tmp_h323info = tmp_listinfo->prot_info;
2060 list2 = g_list_first(tmp_h323info->h245_list);
2063 h245_add=list2->data;
2064 if ( (ADDRESSES_EQUAL(&(h245_add->h245_address),&(pinfo->src)) && (h245_add->h245_port == pinfo->srcport))
2065 || (ADDRESSES_EQUAL(&(h245_add->h245_address),&(pinfo->dst)) && (h245_add->h245_port == pinfo->destport)) ){
2066 callsinfo = (voip_calls_info_t*)(list->data);
2068 ++(callsinfo->npackets);
2069 /* increment the packets counter of all calls */
2070 ++(tapinfo->npackets);
2074 list2 = g_list_next(list2);
2076 if (callsinfo!=NULL) break;
2078 list = g_list_next(list);
2081 /* Tunnel is OFF, and we matched the h245 add so we add it to graph */
2082 if (callsinfo!=NULL){
2083 ++(callsinfo->npackets);
2084 /* increment the packets counter of all calls */
2085 ++(tapinfo->npackets);
2086 /* if the frame number exists in graph, append to it*/
2087 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, pi->comment)) {
2088 /* if not exist, add to the graph */
2089 add_to_graph(tapinfo, pinfo, pi->frame_label, pi->comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2092 /* Tunnel is ON, so we save the label info to use it into h225 or q931 tap. OR may be
2093 tunnel OFF but we did not matched the h245 add, in this case nobady will set this label
2094 since the frame_num will not match */
2096 h245_add_label(pinfo->fd->num, (gchar *) pi->frame_label, (gchar *) pi->comment);
2099 tapinfo->redraw = TRUE;
2101 return 1; /* refresh output */
2105 /****************************************************************************/
2107 /****************************************************************************/
2108 static gboolean have_H245dg_tap_listener=FALSE;
2109 /****************************************************************************/
2111 h245dg_calls_init_tap(void)
2113 GString *error_string;
2115 if(have_H245dg_tap_listener==FALSE)
2117 /* don't register tap listener, if we have it already */
2118 error_string = register_tap_listener("h245dg", &(the_tapinfo_struct.h245dg_dummy), NULL,
2120 voip_calls_dlg_reset,
2125 if (error_string != NULL) {
2126 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2127 "%s", error_string->str);
2128 g_string_free(error_string, TRUE);
2131 have_H245dg_tap_listener=TRUE;
2135 /****************************************************************************/
2137 remove_tap_listener_h245dg_calls(void)
2139 protect_thread_critical_region();
2140 remove_tap_listener(&(the_tapinfo_struct.h245dg_dummy));
2141 unprotect_thread_critical_region();
2143 have_H245dg_tap_listener=FALSE;
2146 /****************************************************************************/
2147 /****************************TAP for SDP PROTOCOL ***************************/
2148 /****************************************************************************/
2149 /* whenever a SDP packet is seen by the tap listener */
2151 SDPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SDPinfo)
2153 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2154 const sdp_packet_info *pi = SDPinfo;
2156 /* There are protocols like MGCP/SIP where the SDP is called before the tap for the
2157 MGCP/SIP packet, in those cases we assign the SPD summary to global lastSDPsummary
2160 g_free(sdp_summary);
2161 sdp_frame_num = pinfo->fd->num;
2162 /* Append to graph the SDP summary if the packet exists */
2163 sdp_summary = g_strdup_printf("SDP (%s)", pi->summary_str);
2164 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2166 tapinfo->redraw = TRUE;
2168 return 1; /* refresh output */
2172 /****************************************************************************/
2174 /****************************************************************************/
2175 static gboolean have_sdp_tap_listener=FALSE;
2176 /****************************************************************************/
2178 sdp_calls_init_tap(void)
2180 GString *error_string;
2182 if(have_sdp_tap_listener==FALSE)
2184 /* don't register tap listener, if we have it already */
2185 error_string = register_tap_listener("sdp", &(the_tapinfo_struct.sdp_dummy), NULL,
2187 voip_calls_dlg_reset,
2192 if (error_string != NULL) {
2193 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2194 "%s", error_string->str);
2195 g_string_free(error_string, TRUE);
2198 have_sdp_tap_listener=TRUE;
2202 /****************************************************************************/
2204 remove_tap_listener_sdp_calls(void)
2206 protect_thread_critical_region();
2207 remove_tap_listener(&(the_tapinfo_struct.sdp_dummy));
2208 unprotect_thread_critical_region();
2210 have_sdp_tap_listener=FALSE;
2215 /****************************************************************************/
2216 /* ***************************TAP for MGCP **********************************/
2217 /****************************************************************************/
2220 This function will look for a signal/event in the SignalReq/ObsEvent string
2221 and return true if it is found
2223 static gboolean isSignal(const gchar *signal_str_p, const gchar *signalStr)
2226 gchar **resultArray;
2228 /* if there is no signalStr, just return false */
2229 if (signalStr == NULL) return FALSE;
2231 /* if are both "blank" return true */
2232 if ( (*signal_str_p == '\0') && (*signalStr == '\0') ) return TRUE;
2234 /* look for signal in signalStr */
2235 resultArray = g_strsplit(signalStr, ",", 10);
2237 for (i = 0; resultArray[i]; i++) {
2238 g_strstrip(resultArray[i]);
2239 if (strcmp(resultArray[i], signal_str_p) == 0) return TRUE;
2242 g_strfreev(resultArray);
2248 This function will get the Caller ID info and replace the current string
2249 This is how it looks the caller Id: rg, ci(02/16/08/29, "3035550002","Ale Sipura 2")
2251 static void mgcpCallerID(gchar *signalStr, gchar **callerId)
2255 /* if there is no signalStr, just return false */
2256 if (signalStr == NULL) return;
2258 arrayStr = g_strsplit(signalStr, "\"", 10);
2260 if (arrayStr[0] == NULL) return;
2262 /* look for the ci signal */
2263 if (strstr(arrayStr[0], "ci(") && (arrayStr[1] != NULL) ) {
2264 /* free the previous "From" field of the call, and assign the new */
2266 *callerId = g_strdup(arrayStr[1]);
2268 g_strfreev(arrayStr);
2275 This function will get the Dialed Digits and replace the current string
2276 This is how it looks the dialed digits 5,5,5,0,0,0,2,#,*
2278 static void mgcpDialedDigits(gchar *signalStr, gchar **dialedDigits)
2281 gchar resultStr[50];
2284 /* if there is no signalStr, just return false */
2285 if (signalStr == NULL) return;
2287 tmpStr = g_strdup(signalStr);
2289 for ( i = 0 ; tmpStr[i] ; i++) {
2290 switch (tmpStr[i]) {
2291 case '0' : case '1' : case '2' : case '3' : case '4' :
2292 case '5' : case '6' : case '7' : case '8' : case '9' :
2293 case '#' : case '*' :
2301 for (i = 0, j = 0; tmpStr[i] && i<50; i++) {
2302 if (tmpStr[i] != '?')
2303 resultStr[j++] = tmpStr[i];
2305 resultStr[j] = '\0';
2307 if (*resultStr == '\0') return;
2309 g_free(*dialedDigits);
2310 *dialedDigits = g_strdup(resultStr);
2318 /****************************************************************************/
2319 /* whenever a MGCP packet is seen by the tap listener */
2321 MGCPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *MGCPinfo)
2323 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2325 voip_calls_info_t *tmp_listinfo;
2326 voip_calls_info_t *callsinfo = NULL;
2327 mgcp_calls_info_t *tmp_mgcpinfo = NULL;
2330 gchar *frame_label = NULL;
2331 gchar *comment = NULL;
2332 graph_analysis_item_t *gai;
2333 gboolean new = FALSE;
2334 gboolean fromEndpoint = FALSE; /* true for calls originated in Endpoints, false for calls from MGC */
2337 const mgcp_info_t *pi = MGCPinfo;
2340 if ((pi->mgcp_type == MGCP_REQUEST) && !pi->is_duplicate ){
2341 /* check whether we already have a call with this Endpoint and it is active*/
2342 list = g_list_first(tapinfo->callsinfo_list);
2345 tmp_listinfo=list->data;
2346 if ((tmp_listinfo->protocol == VOIP_MGCP) && (tmp_listinfo->call_active_state == VOIP_ACTIVE)){
2347 tmp_mgcpinfo = tmp_listinfo->prot_info;
2348 if (pi->endpointId != NULL){
2349 if (g_ascii_strcasecmp(tmp_mgcpinfo->endpointId,pi->endpointId) == 0){
2351 check first if it is an ended call. We can still match packets to this Endpoint 2 seconds
2352 after the call has been released
2354 diff_time = nstime_to_sec(&pinfo->fd->rel_ts) - nstime_to_sec(&tmp_listinfo->stop_fd->rel_ts);
2355 if ( ((tmp_listinfo->call_state == VOIP_CANCELLED) ||
2356 (tmp_listinfo->call_state == VOIP_COMPLETED) ||
2357 (tmp_listinfo->call_state == VOIP_REJECTED)) &&
2360 tmp_listinfo->call_active_state = VOIP_INACTIVE;
2362 callsinfo = (voip_calls_info_t*)(list->data);
2368 list = g_list_next (list);
2371 /* there is no call with this Endpoint, lets see if this a new call or not */
2372 if (callsinfo == NULL){
2373 if ( (strcmp(pi->code, "NTFY") == 0) && isSignal("hd", pi->observedEvents) ){ /* off hook transition */
2374 /* this is a new call from the Endpoint */
2375 fromEndpoint = TRUE;
2377 } else if (strcmp(pi->code, "CRCX") == 0){
2378 /* this is a new call from the MGC */
2379 fromEndpoint = FALSE;
2384 } else if ( ((pi->mgcp_type == MGCP_RESPONSE) && pi->request_available) ||
2385 ((pi->mgcp_type == MGCP_REQUEST) && pi->is_duplicate) ) {
2386 /* if it is a response OR if it is a duplicated Request, lets look in the Graph to see
2387 if there is a request that matches */
2388 listGraph = g_list_first(tapinfo->graph_analysis->list);
2391 gai = listGraph->data;
2392 if (gai->fd->num == pi->req_num){
2393 /* there is a request that match, so look the associated call with this call_num */
2394 list = g_list_first(tapinfo->callsinfo_list);
2397 tmp_listinfo=list->data;
2398 if (tmp_listinfo->protocol == VOIP_MGCP){
2399 if (tmp_listinfo->call_num == gai->conv_num){
2400 tmp_mgcpinfo = tmp_listinfo->prot_info;
2401 callsinfo = (voip_calls_info_t*)(list->data);
2405 list = g_list_next (list);
2407 if (callsinfo != NULL) break;
2409 listGraph = g_list_next(listGraph);
2411 /* if there is not a matching request, just return */
2412 if (callsinfo == NULL) return 0;
2415 /* not in the list? then create a new entry */
2416 if (callsinfo==NULL){
2417 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2418 callsinfo->call_active_state = VOIP_ACTIVE;
2419 callsinfo->call_state = VOIP_CALL_SETUP;
2421 callsinfo->from_identity=g_strdup(pi->endpointId);
2422 callsinfo->to_identity=g_strdup("");
2424 callsinfo->from_identity=g_strdup("");
2425 callsinfo->to_identity=g_strdup(pi->endpointId);
2427 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
2428 callsinfo->selected=FALSE;
2429 callsinfo->start_fd=pinfo->fd;
2430 callsinfo->protocol=VOIP_MGCP;
2431 callsinfo->prot_info=g_malloc(sizeof(mgcp_calls_info_t));
2432 callsinfo->free_prot_info = g_free;
2433 tmp_mgcpinfo=callsinfo->prot_info;
2434 tmp_mgcpinfo->endpointId = g_strdup(pi->endpointId);
2435 tmp_mgcpinfo->fromEndpoint = fromEndpoint;
2436 callsinfo->npackets = 0;
2437 callsinfo->call_num = tapinfo->ncalls++;
2438 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2441 g_assert(tmp_mgcpinfo != NULL);
2443 /* change call state and add to graph */
2444 switch (pi->mgcp_type)
2447 if ( (strcmp(pi->code, "NTFY") == 0) && (pi->observedEvents != NULL) ){
2448 frame_label = g_strdup_printf("%s ObsEvt:%s",pi->code, pi->observedEvents);
2450 if (tmp_mgcpinfo->fromEndpoint){
2451 /* use the Dialed digits to fill the "To" for the call, but use the first NTFY */
2452 if (callsinfo->to_identity[0] == '\0') mgcpDialedDigits(pi->observedEvents, &(callsinfo->to_identity));
2454 /* from MGC and the user picked up, the call is connected */
2455 } else if (isSignal("hd", pi->observedEvents))
2456 callsinfo->call_state=VOIP_IN_CALL;
2458 /* hung up signal */
2459 if (isSignal("hu", pi->observedEvents)) {
2460 if ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state == VOIP_RINGING)){
2461 callsinfo->call_state = VOIP_CANCELLED;
2463 callsinfo->call_state = VOIP_COMPLETED;
2467 } else if (strcmp(pi->code, "RQNT") == 0) {
2468 /* for calls from Endpoint: if there is a "no signal" RQNT and the call was RINGING, we assume this is the CONNECT */
2469 if ( tmp_mgcpinfo->fromEndpoint && isSignal("", pi->signalReq) && (callsinfo->call_state == VOIP_RINGING) ) {
2470 callsinfo->call_state = VOIP_IN_CALL;
2473 /* if there is ringback or ring tone, change state to ringing */
2474 if ( isSignal("rg", pi->signalReq) || isSignal("rt", pi->signalReq) ) {
2475 callsinfo->call_state = VOIP_RINGING;
2478 /* if there is a Busy or ReorderTone, and the call was Ringing or Setup the call is Rejected */
2479 if ( (isSignal("ro", pi->signalReq) || isSignal("bz", pi->signalReq)) && ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state == VOIP_RINGING)) ) {
2480 callsinfo->call_state = VOIP_REJECTED;
2483 if (pi->signalReq != NULL)
2484 frame_label = g_strdup_printf("%s%sSigReq:%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"", pi->signalReq);
2486 frame_label = g_strdup_printf("%s%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"");
2488 /* use the CallerID info to fill the "From" for the call */
2489 if (!tmp_mgcpinfo->fromEndpoint) mgcpCallerID(pi->signalReq, &(callsinfo->from_identity));
2491 } else if (strcmp(pi->code, "DLCX") == 0) {
2493 if there is a DLCX in a call To an Endpoint and the call was not connected, we use
2494 the DLCX as the end of the call
2496 if (!tmp_mgcpinfo->fromEndpoint){
2497 if ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state == VOIP_RINGING)){
2498 callsinfo->call_state = VOIP_CANCELLED;
2503 if (frame_label == NULL) frame_label = g_strdup(pi->code);
2506 frame_label = g_strdup_printf("%u (%s)",pi->rspcode, pi->code);
2509 /* XXX what to do? */
2514 comment = g_strdup_printf("MGCP %s %s%s", tmp_mgcpinfo->endpointId, (pi->mgcp_type == MGCP_REQUEST)?"Request":"Response", pi->is_duplicate?" Duplicate":"");
2516 callsinfo->stop_fd = pinfo->fd;
2517 ++(callsinfo->npackets);
2518 /* increment the packets counter of all calls */
2519 ++(tapinfo->npackets);
2521 /* add to the graph */
2522 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2524 g_free(frame_label);
2526 /* add SDP info if apply */
2527 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
2528 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2529 g_free(sdp_summary);
2533 tapinfo->redraw = TRUE;
2535 return 1; /* refresh output */
2539 /****************************************************************************/
2541 /****************************************************************************/
2542 static gboolean have_MGCP_tap_listener=FALSE;
2543 /****************************************************************************/
2545 mgcp_calls_init_tap(void)
2547 GString *error_string;
2549 if(have_MGCP_tap_listener==FALSE)
2552 * Don't register the tap listener if we have it already.
2553 * We set TL_REQUIRES_PROTO_TREE to force a non-null "tree"
2554 * in the MGCP dissector; otherwise, the dissector
2555 * doesn't fill in the info passed to the tap's packet
2558 error_string = register_tap_listener("mgcp",
2559 &(the_tapinfo_struct.mgcp_dummy),
2561 TL_REQUIRES_PROTO_TREE,
2562 voip_calls_dlg_reset,
2566 if (error_string != NULL) {
2567 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2568 "%s", error_string->str);
2569 g_string_free(error_string, TRUE);
2572 have_MGCP_tap_listener=TRUE;
2576 /****************************************************************************/
2578 remove_tap_listener_mgcp_calls(void)
2580 protect_thread_critical_region();
2581 remove_tap_listener(&(the_tapinfo_struct.mgcp_dummy));
2582 unprotect_thread_critical_region();
2584 have_MGCP_tap_listener=FALSE;
2588 /****************************************************************************/
2589 /****************************TAP for ACTRACE (AudioCodes trace)**************/
2590 /****************************************************************************/
2592 /* whenever a ACTRACE packet is seen by the tap listener */
2594 ACTRACEcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *ACTRACEinfo)
2596 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2597 const actrace_info_t *pi = ACTRACEinfo;
2599 actrace_cas_calls_info_t *tmp_actrace_cas_info;
2600 voip_calls_info_t *tmp_listinfo;
2601 voip_calls_info_t *callsinfo = NULL;
2604 actrace_frame_num = pinfo->fd->num;
2605 actrace_trunk = pi->trunk;
2606 actrace_direction = pi->direction;
2608 if (pi->type == 1){ /* is CAS protocol */
2610 gchar *comment = NULL;
2613 list = g_list_first(tapinfo->callsinfo_list);
2616 tmp_listinfo=list->data;
2617 if ( tmp_listinfo->protocol == VOIP_AC_CAS ){
2618 tmp_actrace_cas_info = tmp_listinfo->prot_info;
2619 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
2620 if ( (tmp_actrace_cas_info->bchannel == pi->cas_bchannel) && (tmp_actrace_cas_info->trunk == actrace_trunk) ) {
2621 callsinfo = (voip_calls_info_t*)(list->data);
2625 list = g_list_next (list);
2628 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, "PSTN");
2630 /* if it is a new call, add it to the list */
2632 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2633 callsinfo->call_active_state = VOIP_ACTIVE;
2634 callsinfo->call_state = VOIP_CALL_SETUP;
2635 callsinfo->from_identity=g_strdup("N/A");
2636 callsinfo->to_identity=g_strdup("N/A");
2637 COPY_ADDRESS(&(callsinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
2638 callsinfo->selected=FALSE;
2639 callsinfo->start_fd=pinfo->fd;
2640 callsinfo->protocol=VOIP_AC_CAS;
2641 callsinfo->prot_info=g_malloc(sizeof(actrace_cas_calls_info_t));
2642 callsinfo->free_prot_info = g_free;
2644 tmp_actrace_cas_info=callsinfo->prot_info;
2645 tmp_actrace_cas_info->bchannel=pi->cas_bchannel;
2646 tmp_actrace_cas_info->trunk=actrace_trunk;
2647 callsinfo->npackets = 0;
2648 callsinfo->call_num = tapinfo->ncalls++;
2649 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2652 callsinfo->stop_fd = pinfo->fd;
2653 ++(callsinfo->npackets);
2654 /* increment the packets counter of all calls */
2655 ++(tapinfo->npackets);
2657 comment = g_strdup_printf("AC_CAS trunk:%u", actrace_trunk);
2659 add_to_graph(tapinfo, pinfo, pi->cas_frame_label, comment, callsinfo->call_num,
2660 actrace_direction?&pstn_add:&(pinfo->src),
2661 actrace_direction?&(pinfo->src):&pstn_add,
2667 tapinfo->redraw = TRUE;
2669 return 1; /* refresh output */
2673 /****************************************************************************/
2675 /****************************************************************************/
2676 static gboolean have_actrace_tap_listener=FALSE;
2677 /****************************************************************************/
2679 actrace_calls_init_tap(void)
2681 GString *error_string;
2683 if(have_actrace_tap_listener==FALSE)
2685 /* don't register tap listener, if we have it already */
2686 error_string = register_tap_listener("actrace", &(the_tapinfo_struct.actrace_dummy), NULL,
2688 voip_calls_dlg_reset,
2689 ACTRACEcalls_packet,
2693 if (error_string != NULL) {
2694 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2695 "%s", error_string->str);
2696 g_string_free(error_string, TRUE);
2699 have_actrace_tap_listener=TRUE;
2703 /****************************************************************************/
2705 remove_tap_listener_actrace_calls(void)
2707 protect_thread_critical_region();
2708 remove_tap_listener(&(the_tapinfo_struct.actrace_dummy));
2709 unprotect_thread_critical_region();
2711 have_actrace_tap_listener=FALSE;
2715 /****************************************************************************/
2716 /**************************** TAP for H248/MEGACO **********************************/
2717 /****************************************************************************/
2718 static gboolean have_h248_tap_listener = FALSE;
2719 static gboolean have_megaco_tap_listener = FALSE;
2721 #define gcp_is_req(type) ( type == GCP_CMD_ADD_REQ || type == GCP_CMD_MOVE_REQ || type == GCP_CMD_MOD_REQ || \
2722 type == GCP_CMD_SUB_REQ || type == GCP_CMD_AUDITCAP_REQ || type == GCP_CMD_AUDITVAL_REQ || \
2723 type == GCP_CMD_NOTIFY_REQ || type == GCP_CMD_SVCCHG_REQ || type == GCP_CMD_TOPOLOGY_REQ || \
2724 type == GCP_CMD_CTX_ATTR_AUDIT_REQ )
2726 static int h248_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
2727 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2728 const gcp_cmd_t *cmd = prot_info;
2730 voip_calls_info_t *callsinfo = NULL;
2733 gchar mgw_addr[128];
2735 if (cmd->ctx->id == NULL_CONTEXT || cmd->ctx->id == ALL_CONTEXTS ) {
2739 if ( gcp_is_req(cmd->type) ) {
2740 mgw = &(pinfo->dst);
2741 mgc = &(pinfo->src);
2743 mgc = &(pinfo->dst);
2744 mgw = &(pinfo->src);
2747 address_to_str_buf(mgw, mgw_addr, 128);
2749 /* check whether we already have this context in the list */
2750 list = g_list_first(tapinfo->callsinfo_list);
2753 voip_calls_info_t* tmp_listinfo = list->data;
2755 if (tmp_listinfo->protocol == TEL_H248){
2756 if (tmp_listinfo->prot_info == cmd->ctx){
2757 callsinfo = (voip_calls_info_t*)(list->data);
2761 list = g_list_next (list);
2764 if (callsinfo==NULL){
2766 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2767 callsinfo->call_state = VOIP_NO_STATE;
2768 callsinfo->call_active_state = VOIP_ACTIVE;
2769 callsinfo->from_identity = g_strdup_printf("%s : %.8x", mgw_addr, cmd->ctx->id);
2770 callsinfo->to_identity = g_strdup("");
2771 callsinfo->prot_info = cmd->ctx;
2772 callsinfo->free_prot_info = NULL;
2774 callsinfo->npackets = 1;
2776 COPY_ADDRESS(&(callsinfo->initial_speaker), mgc);
2778 callsinfo->protocol = TEL_H248;
2779 callsinfo->call_num = tapinfo->ncalls++;
2780 callsinfo->start_fd = pinfo->fd;
2781 callsinfo->stop_fd = pinfo->fd;
2783 callsinfo->selected = FALSE;
2785 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2788 GString *s = g_string_new("");
2789 gcp_terms_t *ctx_term;
2791 g_free(callsinfo->from_identity);
2792 callsinfo->from_identity = g_strdup_printf("%s : %.8x", mgw_addr, ((gcp_ctx_t*)callsinfo->prot_info)->id);
2794 g_free(callsinfo->to_identity);
2796 for (ctx_term = ((gcp_ctx_t*)callsinfo->prot_info)->terms.next;
2798 ctx_term = ctx_term->next ) {
2799 if ( ctx_term->term && ctx_term->term->str) {
2800 g_string_append_printf(s," %s",ctx_term->term->str);
2804 callsinfo->to_identity = s->str;
2805 g_string_free(s,FALSE);
2807 callsinfo->stop_fd = pinfo->fd;
2808 ++(callsinfo->npackets);
2811 add_to_graph(tapinfo, pinfo, cmd->str ? cmd->str : "unknown Msg",
2812 ep_strdup_printf("TrxId = %u, CtxId = %.8x",cmd->trx->id,cmd->ctx->id),
2813 callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2815 ++(tapinfo->npackets);
2817 tapinfo->redraw = TRUE;
2822 void h248_calls_init_tap(void)
2824 GString *error_string;
2827 if(have_megaco_tap_listener==FALSE)
2829 error_string = register_tap_listener("megaco", &(the_tapinfo_struct.megaco_dummy),
2832 voip_calls_dlg_reset,
2834 voip_calls_dlg_draw);
2836 if (error_string != NULL) {
2837 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2838 "%s", error_string->str);
2839 g_string_free(error_string, TRUE);
2843 have_megaco_tap_listener=TRUE;
2846 if(have_h248_tap_listener==FALSE)
2848 error_string = register_tap_listener("h248", &(the_tapinfo_struct.h248_dummy),
2851 voip_calls_dlg_reset,
2853 voip_calls_dlg_draw);
2855 if (error_string != NULL) {
2856 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2857 "%s", error_string->str);
2858 g_string_free(error_string, TRUE);
2862 have_h248_tap_listener=TRUE;
2867 remove_tap_listener_h248_calls(void)
2869 protect_thread_critical_region();
2870 remove_tap_listener(&(the_tapinfo_struct.h248_dummy));
2871 remove_tap_listener(&(the_tapinfo_struct.megaco_dummy));
2872 unprotect_thread_critical_region();
2874 have_megaco_tap_listener=FALSE;
2875 have_h248_tap_listener=FALSE;
2878 /****************************************************************************/
2879 /**************************** TAP for SCCP and SUA **********************************/
2880 /**************************** ( RANAP and BSSAP ) **********************************/
2881 /****************************************************************************/
2883 static gboolean have_sccp_tap_listener = FALSE;
2884 static gboolean have_sua_tap_listener = FALSE;
2886 static const voip_protocol sccp_proto_map[] = {
2891 #define SP2VP(ap) ((ap) < SCCP_PLOAD_NUM_PLOADS ? sccp_proto_map[(ap)] : TEL_SCCP)
2892 const value_string* sccp_payload_values;
2894 static int sccp_calls(packet_info *pinfo, const void *prot_info) {
2895 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2896 const sccp_msg_info_t* msg = prot_info;
2897 sccp_assoc_info_t* assoc = msg->data.co.assoc;
2899 voip_calls_info_t *callsinfo = NULL;
2900 const gchar *label = NULL;
2901 const gchar *comment = NULL;
2902 /* check whether we already have this assoc in the list */
2904 for(list = g_list_first(tapinfo->callsinfo_list) ; list ; list = g_list_next (list) ) {
2905 if ( ((voip_calls_info_t*)(list->data))->prot_info == assoc ){
2906 callsinfo = (voip_calls_info_t*)(list->data);
2911 if (callsinfo==NULL){
2912 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2913 callsinfo->call_state = VOIP_CALL_SETUP;
2914 callsinfo->call_active_state = VOIP_ACTIVE;
2915 if ( assoc->calling_party ) {
2916 callsinfo->from_identity = g_strdup(assoc->calling_party);
2918 callsinfo->from_identity = g_strdup("Unknown");
2921 if ( assoc->called_party ) {
2922 callsinfo->to_identity = g_strdup(assoc->called_party);
2924 callsinfo->to_identity = g_strdup("Unknown");
2927 callsinfo->prot_info = (void*)assoc;
2928 callsinfo->free_prot_info = NULL;
2930 callsinfo->npackets = 1;
2932 COPY_ADDRESS(&(callsinfo->initial_speaker), &(pinfo->src));
2934 callsinfo->protocol = SP2VP(assoc->payload);
2935 /* Store frame data which holds time and frame number */
2936 callsinfo->start_fd = pinfo->fd;
2937 callsinfo->stop_fd = pinfo->fd;
2939 callsinfo->selected = FALSE;
2940 callsinfo->call_num = tapinfo->ncalls++;
2942 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2945 if ( assoc->calling_party ) {
2946 g_free(callsinfo->from_identity);
2947 callsinfo->from_identity = g_strdup(assoc->calling_party);
2950 if ( assoc->called_party ) {
2951 g_free(callsinfo->to_identity);
2952 callsinfo->to_identity = g_strdup(assoc->called_party);
2955 callsinfo->protocol = SP2VP(assoc->payload);
2956 /* Store frame data which holds stop time and frame number */
2957 callsinfo->stop_fd = pinfo->fd;
2958 ++(callsinfo->npackets);
2960 switch (msg->type) {
2961 case SCCP_MSG_TYPE_CC:
2962 callsinfo->call_state = VOIP_IN_CALL;
2964 case SCCP_MSG_TYPE_RLC:
2965 callsinfo->call_state = VOIP_COMPLETED;
2966 callsinfo->call_active_state = VOIP_INACTIVE;
2973 if (msg->data.co.label) {
2974 label = msg->data.co.label;
2976 label = val_to_str(msg->type, sccp_payload_values, "Unknown(%d)");
2979 if (msg->data.co.comment) {
2980 comment = msg->data.co.comment;
2985 add_to_graph(tapinfo, pinfo, label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2987 ++(tapinfo->npackets);
2989 tapinfo->redraw = TRUE;
2994 static int sccp_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
2995 sccp_payload_values = sccp_message_type_acro_values;
2996 return sccp_calls(pinfo, prot_info);
3000 static int sua_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
3001 sccp_payload_values = sua_co_class_type_acro_values;
3002 return sccp_calls(pinfo, prot_info);
3006 void sccp_calls_init_tap(void)
3008 GString *error_string;
3010 if(have_sccp_tap_listener==FALSE)
3012 error_string = register_tap_listener("sccp", &(the_tapinfo_struct.sccp_dummy),
3015 voip_calls_dlg_reset,
3017 voip_calls_dlg_draw);
3019 if (error_string != NULL) {
3020 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3021 "%s", error_string->str);
3022 g_string_free(error_string, TRUE);
3026 have_sccp_tap_listener=TRUE;
3029 if(have_sua_tap_listener==FALSE)
3031 error_string = register_tap_listener("sua", &(the_tapinfo_struct.sua_dummy),
3034 voip_calls_dlg_reset,
3036 voip_calls_dlg_draw);
3038 if (error_string != NULL) {
3039 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3040 "%s", error_string->str);
3041 g_string_free(error_string, TRUE);
3045 have_sua_tap_listener=TRUE;
3051 remove_tap_listener_sccp_calls(void)
3053 protect_thread_critical_region();
3054 remove_tap_listener(&(the_tapinfo_struct.sccp_dummy));
3055 unprotect_thread_critical_region();
3057 have_sccp_tap_listener=FALSE;
3058 have_sua_tap_listener=FALSE;
3062 /****************************************************************************/
3063 /****************************TAP for UNISTIM ********************************/
3064 /****************************************************************************/
3067 unistim_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *unistim_info)
3069 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3070 voip_calls_info_t *tmp_listinfo;
3071 voip_calls_info_t *callsinfo = NULL;
3072 unistim_info_t *tmp_unistim_info = NULL;
3074 GString *g_tmp = NULL;
3075 gchar *frame_label = NULL;
3076 gchar *comment = NULL;
3078 /* Fetch specific packet infos */
3079 const unistim_info_t *pi = unistim_info;
3082 g_tmp = g_string_new(NULL);
3084 /* Check to see if this is a dup */
3085 list = g_list_first(tapinfo->callsinfo_list);
3089 tmp_listinfo = list->data;
3091 if(tmp_listinfo->protocol == VOIP_UNISTIM){
3093 tmp_unistim_info = tmp_listinfo->prot_info;
3095 /* Search by termid if possible, otherwise use ni/it ip + port.. */
3096 if(pi->termid != 0){
3097 if(tmp_unistim_info->termid == pi->termid){
3098 /* If the call has ended, then we can reuse it.. */
3099 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
3102 callsinfo = (voip_calls_info_t*)(list->data);
3107 /* If no term id use ips / port to find entry */
3108 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)){
3109 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
3110 /* Do nothing previous call */
3112 callsinfo = (voip_calls_info_t*)(list->data);
3116 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)) {
3117 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
3118 /* Do nothing, it ain't our call.. */
3120 callsinfo = (voip_calls_info_t*)(list->data);
3127 /* Otherwise, go to the next one.. */
3128 list = g_list_next(list);
3131 if(pi->payload_type == 2 || pi->payload_type == 1){
3133 if(pi->key_state == 1 || pi->hook_state == 1){
3135 /* If the user hits a button,
3136 Session will be SETUP */
3138 /* If new add to list */
3139 if (callsinfo==NULL){
3141 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3142 callsinfo->call_active_state = VOIP_ACTIVE;
3143 callsinfo->call_state = VOIP_CALL_SETUP;
3144 callsinfo->from_identity=g_strdup_printf("%x",pi->termid);
3145 callsinfo->to_identity=g_strdup("UNKNOWN");
3146 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
3147 callsinfo->selected=FALSE;
3149 /* Set this on init of struct so in case the call doesn't complete, we'll have a ref. */
3150 /* Otherwise if the call is completed we'll have the open/close streams to ref actual call duration */
3151 /* Store frame data which holds time and frame number */
3152 callsinfo->start_fd=pinfo->fd;
3154 callsinfo->protocol=VOIP_UNISTIM;
3155 callsinfo->prot_info=g_malloc(sizeof(unistim_info_t));
3157 tmp_unistim_info = callsinfo->prot_info;
3159 /* Clear tap struct */
3160 tmp_unistim_info->rudp_type = 0;
3161 tmp_unistim_info->payload_type = 0;
3162 tmp_unistim_info->sequence = pi->sequence;
3163 tmp_unistim_info->termid = pi->termid;
3164 tmp_unistim_info->key_val = -1;
3165 tmp_unistim_info->key_state = -1;
3166 tmp_unistim_info->hook_state = -1;
3167 tmp_unistim_info->stream_connect = -1;
3168 tmp_unistim_info->trans_connect = -1;
3169 tmp_unistim_info->set_termid = -1;
3170 tmp_unistim_info->string_data = NULL;
3171 tmp_unistim_info->key_buffer = NULL;
3173 COPY_ADDRESS(&(tmp_unistim_info->it_ip),&(pi->it_ip));
3174 COPY_ADDRESS(&(tmp_unistim_info->ni_ip),&(pi->ni_ip));
3175 tmp_unistim_info->it_port = pi->it_port;
3177 callsinfo->free_prot_info = g_free;
3178 callsinfo->npackets = 0;
3179 callsinfo->call_num = tapinfo->ncalls++;
3180 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3184 /* Set up call wide info struct */
3185 tmp_unistim_info = callsinfo->prot_info;
3186 tmp_unistim_info->sequence = pi->sequence;
3189 /* Each packet COULD BE OUR LAST!!!! */
3190 /* Store frame data which holds time and frame number */
3191 callsinfo->stop_fd = pinfo->fd;
3193 /* This is a valid packet so increment counter */
3194 ++(callsinfo->npackets);
3196 /* increment the packets counter of all calls */
3197 ++(tapinfo->npackets);
3199 /* Key was depressed.. update key buffer.. */
3200 if(pi->key_val >= 0 && pi->key_val <= 11){
3202 if(tmp_unistim_info->key_buffer != NULL){
3204 /* assign to temp variable */
3205 g_string_assign(g_tmp,tmp_unistim_info->key_buffer);
3207 /* Manipulate the data */
3208 if(pi->key_val == 10) {
3209 tmp_unistim_info->key_buffer = g_strdup_printf("%s*",g_tmp->str);
3210 } else if(pi->key_val == 11) {
3211 tmp_unistim_info->key_buffer = g_strdup_printf("%s#",g_tmp->str);
3213 tmp_unistim_info->key_buffer = g_strdup_printf("%s%d",g_tmp->str,pi->key_val);
3218 /* Create new string */
3219 if(pi->key_val == 10) {
3220 tmp_unistim_info->key_buffer = g_strdup("*");
3221 } else if(pi->key_val == 11) {
3222 tmp_unistim_info->key_buffer = g_strdup("#");
3224 tmp_unistim_info->key_buffer = g_strdup_printf("%d",pi->key_val);
3229 /* Select for non-digit characters */
3230 if(pi->key_val == 10) {
3231 comment = g_strdup_printf("Key Input Sent: * (%d)", pi->sequence);
3232 } else if(pi->key_val == 11) {
3233 comment = g_strdup_printf("Key Input Sent: # (%d)", pi->sequence);
3235 comment = g_strdup_printf("Key Input Sent: %d (%d)",pi->key_val, pi->sequence);
3237 } else if(pi->key_val == 12) {
3238 /* Set label and comment for graph */
3239 comment = g_strdup_printf("Key Input Sent: UP (%d)", pi->sequence);
3240 } else if(pi->key_val == 13) {
3241 /* Set label and comment for graph */
3242 comment = g_strdup_printf("Key Input Sent: DOWN (%d)", pi->sequence);
3243 } else if(pi->key_val == 14) {
3244 /* Set label and comment for graph */
3245 comment = g_strdup_printf("Key Input Sent: RIGHT (%d)", pi->sequence);
3246 } else if(pi->key_val == 15) {
3247 if(pi->key_buffer != NULL){
3249 g_string_assign(g_tmp,pi->key_buffer);
3251 /* Manipulate the data */
3252 g_string_truncate(g_tmp,g_tmp->len-1);
3254 /* Insert new data */
3255 tmp_unistim_info->key_buffer = g_strdup(g_tmp->str);
3258 /* Set label and comment for graph */
3259 comment = g_strdup_printf("Key Input Sent: LEFT (%d)", pi->sequence);
3260 } else if(pi->key_val == 20) {
3261 /* User pressed the soft key 0 probably dial */
3262 comment = g_strdup_printf("Key Input Sent: S0 (%d)", pi->sequence);
3263 } else if(pi->key_val == 21) {
3264 /* User pressed the soft key 1 */
3265 comment = g_strdup_printf("Key Input Sent: S1 (%d)", pi->sequence);
3266 } else if(pi->key_val == 22) {
3267 /* User pressed the soft key 2 */
3268 /* On cs2k phones, soft key 2 is backspace. */
3269 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 /* add label and comment */
3282 comment = g_strdup_printf("Key Input Sent: S2 (%d)", pi->sequence);
3283 } else if(pi->key_val == 28) {
3284 /* User pressed something */
3285 comment = g_strdup_printf("Key Input Sent: Release (%d)", pi->sequence);
3286 } else if(pi->key_val == 23) {
3287 /* User pressed the soft key 3 */
3288 /* Cancel on cs2k so clear buffer */
3289 /* On mcs its config which will clear the buffer too */
3290 tmp_unistim_info->key_buffer = g_strdup("\n");
3292 /* User pressed something, set labels*/
3293 comment = g_strdup_printf("Key Input Sent: S3 (%d)", pi->sequence);
3294 } else if(pi->key_val == 27) {
3295 /* User pressed something */
3296 comment = g_strdup_printf("Key Input Sent: Hold (%d)", pi->sequence);
3297 } else if(pi->key_val == 29) {
3298 /* User pressed something */
3299 comment = g_strdup_printf("Key Input Sent: Mute (%d)", pi->sequence);
3300 } else if(pi->key_val == 30) {
3301 /* User pressed something */
3302 comment = g_strdup_printf("Key Input Sent: Headset (%d)", pi->sequence);
3303 } else if(pi->key_val == 31) {
3304 /* Handsfree button */
3305 comment = g_strdup_printf("Key Input Sent: Handsfree (%d)", pi->sequence);
3306 } else if(pi->key_val >= 32 && pi->key_val <= 56) {
3308 comment = g_strdup_printf("Key Input Sent: Prog%d (%d)", (pi->key_val & 31), pi->sequence);
3311 if(pi->key_val != -1) {
3313 frame_label = "KEY INPUT";
3315 if (comment == NULL)
3316 /* Ouch! What do you do!? */
3317 /* User pressed something */
3318 comment = g_strdup_printf("Key Input Sent: UNKNOWN - %d (%d)", pi->key_val, pi->sequence);
3320 /* add to the graph */
3321 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3326 if(pi->hook_state == 1) {
3328 /* Phone is off hook */
3329 frame_label = "OFF HOOK";
3330 comment = g_strdup_printf("Off Hook (%d)", pi->sequence);
3332 /* add to the graph */
3333 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3336 } else if(pi->hook_state == 0) {
3338 /* Phone is on hook */
3339 frame_label = "ON HOOK";
3340 comment = g_strdup_printf("On Hook (%d)", pi->sequence);
3342 /* add to the graph */
3343 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3349 /* Open stream was sent from server */
3350 if(pi->stream_connect == 1 && callsinfo != NULL) {
3353 /* Signifies the start of the call so set start_sec & start_usec */
3354 /* Frame data holds the time info */
3355 callsinfo->start_fd=pinfo->fd;
3357 /* Local packets too */
3358 ++(callsinfo->npackets);
3360 /* increment the packets counter of all calls */
3361 ++(tapinfo->npackets);
3363 /* ?? means we're not quite sure if this is accurate. Since Unistim isn't a true
3364 Call control protocol, we can only guess at the destination by messing with
3366 if(tmp_unistim_info->key_buffer != NULL){
3367 callsinfo->to_identity = g_strdup_printf("?? %s",tmp_unistim_info->key_buffer);
3370 /* change sequence number for ACK detection */
3371 tmp_unistim_info->sequence = pi->sequence;
3373 /* State changes too */
3374 callsinfo->call_active_state = VOIP_ACTIVE;
3375 callsinfo->call_state = VOIP_IN_CALL;
3377 /* Add graph data */
3378 frame_label = "STREAM OPENED";
3379 comment = g_strdup_printf("Stream Opened (%d)",pi->sequence);
3381 /* add to the graph */
3382 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3384 } else if(pi->stream_connect == 1 && callsinfo == NULL) {
3386 /* Research indicates some nortel products initiate stream first
3387 * without keypresses. therefore creating this solely on a keypress is
3389 * Sometimes calls start immediately with open stream.
3391 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3392 callsinfo->call_active_state = VOIP_ACTIVE;
3393 callsinfo->call_state = VOIP_CALL_SETUP;
3394 callsinfo->from_identity=g_strdup("UNKNOWN");
3395 callsinfo->to_identity=g_strdup("UNKNOWN");
3396 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
3397 callsinfo->selected=FALSE;
3399 /* Set this on init of struct so in case the call doesn't complete, we'll have a ref. */
3400 /* Otherwise if the call is completed we'll have the open/close streams to ref actual call duration */
3401 callsinfo->start_fd=pinfo->fd;
3403 callsinfo->protocol=VOIP_UNISTIM;
3404 callsinfo->prot_info=g_malloc(sizeof(unistim_info_t));
3406 tmp_unistim_info = callsinfo->prot_info;
3408 /* Clear tap struct */
3409 tmp_unistim_info->rudp_type = 0;
3410 tmp_unistim_info->payload_type = 0;
3411 tmp_unistim_info->sequence = pi->sequence;
3412 tmp_unistim_info->termid = 0;
3413 tmp_unistim_info->key_val = -1;
3414 tmp_unistim_info->key_state = -1;
3415 tmp_unistim_info->hook_state = -1;
3416 tmp_unistim_info->stream_connect = -1;
3417 tmp_unistim_info->trans_connect = -1;
3418 tmp_unistim_info->set_termid = -1;
3419 tmp_unistim_info->string_data = NULL;
3420 tmp_unistim_info->key_buffer = NULL;
3422 COPY_ADDRESS(&(tmp_unistim_info->it_ip),&(pi->it_ip));
3423 COPY_ADDRESS(&(tmp_unistim_info->ni_ip),&(pi->ni_ip));
3424 tmp_unistim_info->it_port = pi->it_port;
3426 callsinfo->free_prot_info = g_free;
3427 callsinfo->npackets = 0;
3428 callsinfo->call_num = tapinfo->ncalls++;
3429 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3432 /* Signifies the start of the call so set start_sec & start_usec */
3433 /* frame_data holds the time info */
3434 callsinfo->start_fd=pinfo->fd;
3436 /* Local packets too */
3437 ++(callsinfo->npackets);
3439 /* increment the packets counter of all calls */
3440 ++(tapinfo->npackets);
3442 /* ?? means we're not quite sure if this is accurate. Since Unistim isn't a true
3443 Call control protocol, we can only guess at the destination by messing with
3445 if(tmp_unistim_info->key_buffer != NULL){
3446 callsinfo->to_identity = g_strdup_printf("?? %s",tmp_unistim_info->key_buffer);
3449 /* change sequence number for ACK detection */
3450 tmp_unistim_info->sequence = pi->sequence;
3452 /* State changes too */
3453 callsinfo->call_active_state = VOIP_ACTIVE;
3454 callsinfo->call_state = VOIP_IN_CALL;
3456 /* Add graph data */
3457 frame_label = "STREAM OPENED";
3458 comment = g_strdup_printf("Stream Opened (%d)",pi->sequence);
3460 /* add to the graph */
3461 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3463 } else if(pi->stream_connect == 0 && callsinfo != NULL) {
3466 /* Set stop seconds + usec */
3467 /* frame_data holds the time info */
3468 callsinfo->stop_fd = pinfo->fd;
3470 tmp_unistim_info->sequence = pi->sequence;
3472 if(callsinfo->call_state == VOIP_IN_CALL){
3473 callsinfo->call_active_state = VOIP_INACTIVE;
3474 callsinfo->call_state = VOIP_COMPLETED;
3476 callsinfo->call_state = VOIP_UNKNOWN;
3477 callsinfo->call_active_state = VOIP_INACTIVE;
3480 frame_label = "STREAM CLOSED";
3481 comment = g_strdup_printf("Stream Closed (%d)",pi->sequence);
3483 /* add to the graph */
3484 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3489 } else if(pi->rudp_type == 1 && callsinfo != NULL) {
3491 /* Only show acks for processed seq #s */
3492 if(tmp_unistim_info->sequence == pi->sequence) {
3494 frame_label = "ACK";
3495 comment = g_strdup_printf("ACK for sequence %d",pi->sequence);
3497 /* add to the graph */
3498 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3502 } else if(pi->rudp_type == 0 && callsinfo != NULL) {
3505 frame_label = "NAK";
3506 comment = g_strdup_printf("NAK for sequence %d",pi->sequence);
3508 /* add to the graph */
3509 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3516 tapinfo->redraw = TRUE;
3521 /****************************************************************************/
3523 /****************************************************************************/
3524 static gboolean have_unistim_tap_listener=FALSE;
3525 /****************************************************************************/
3527 unistim_calls_init_tap(void){
3529 GString *error_string;
3531 if(have_unistim_tap_listener==FALSE) {
3533 error_string = register_tap_listener("unistim", &(the_tapinfo_struct.unistim_dummy),
3536 voip_calls_dlg_reset,
3537 unistim_calls_packet,
3541 if (error_string != NULL) {
3542 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3543 "%s", error_string->str);
3544 g_string_free(error_string, TRUE);
3548 have_unistim_tap_listener=TRUE;
3552 /****************************************************************************/
3554 remove_tap_listener_unistim_calls(void)
3556 protect_thread_critical_region();
3557 remove_tap_listener(&(the_tapinfo_struct.unistim_dummy));
3558 unprotect_thread_critical_region();
3560 have_unistim_tap_listener=FALSE;
3563 /****************************************************************************/
3564 /* ***************************TAP for SKINNY **********************************/
3565 /****************************************************************************/
3567 /* Telecaster to tap-voip call state mapping */
3568 static const voip_call_state skinny_tap_voip_state[] = {
3587 skinny_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *skinny_info)
3589 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3591 voip_calls_info_t *callsinfo = NULL;
3593 const skinny_info_t *si = skinny_info;
3594 skinny_calls_info_t *tmp_skinnyinfo;
3597 if (si == NULL || (si->callId == 0 && si->passThruId == 0))
3599 /* check whether we already have this context in the list */
3600 list = g_list_first(tapinfo->callsinfo_list);
3603 voip_calls_info_t* tmp_listinfo = list->data;
3604 if (tmp_listinfo->protocol == VOIP_SKINNY){
3605 tmp_skinnyinfo = tmp_listinfo->prot_info;
3606 if (tmp_skinnyinfo->callId == si->callId ||
3607 tmp_skinnyinfo->callId == si->passThruId){
3608 callsinfo = (voip_calls_info_t*)(list->data);
3612 list = g_list_next (list);
3615 if (si->messId >= 256)
3616 phone = &(pinfo->dst);
3618 phone = &(pinfo->src);
3620 if (callsinfo==NULL){
3621 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3622 callsinfo->call_state = VOIP_NO_STATE;
3623 callsinfo->call_active_state = VOIP_ACTIVE;
3624 /* callsinfo->from_identity = g_strdup_printf("%s : %.8x", "Skinny", 1); */
3625 callsinfo->from_identity = g_strdup("");
3626 callsinfo->to_identity = g_strdup("");
3627 callsinfo->prot_info = g_malloc(sizeof(skinny_calls_info_t));
3628 callsinfo->free_prot_info = g_free;
3629 tmp_skinnyinfo = callsinfo->prot_info;
3630 tmp_skinnyinfo->callId = si->callId ? si->callId : si->passThruId;
3631 callsinfo->npackets = 1;
3633 COPY_ADDRESS(&(callsinfo->initial_speaker), phone);
3635 callsinfo->protocol = VOIP_SKINNY;
3636 callsinfo->call_num = tapinfo->ncalls++;
3637 callsinfo->start_fd = pinfo->fd;
3638 callsinfo->stop_fd = pinfo->fd;
3640 callsinfo->selected = FALSE;
3641 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3643 if (si->callingParty) {
3644 g_free(callsinfo->from_identity);
3645 callsinfo->from_identity = g_strdup(si->callingParty);
3647 if (si->calledParty) {
3648 g_free(callsinfo->to_identity);
3649 callsinfo->to_identity = g_strdup(si->calledParty);
3651 if ((si->callState > 0) && (si->callState < (sizeof(skinny_tap_voip_state)/sizeof(skinny_tap_voip_state[0]))))
3652 callsinfo->call_state = skinny_tap_voip_state[si->callState];
3654 callsinfo->stop_fd = pinfo->fd;
3655 ++(callsinfo->npackets);
3660 comment = g_strdup_printf("CallId = %u, PTId = %u", si->callId, si->passThruId);
3662 comment = g_strdup_printf("CallId = %u, LineId = %u", si->callId, si->lineId);
3665 comment = g_strdup_printf("PTId = %u", si->passThruId);
3670 add_to_graph(tapinfo, pinfo, si->messageName, comment,
3671 callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3678 /****************************************************************************/
3680 /****************************************************************************/
3681 static gboolean have_skinny_tap_listener=FALSE;
3682 /****************************************************************************/
3684 skinny_calls_init_tap(void)
3686 GString *error_string;
3688 if(have_skinny_tap_listener==FALSE)
3691 * Don't register the tap listener if we have it already.
3692 * We set TL_REQUIRES_PROTO_TREE to force a non-null "tree"
3693 * in the SKINNY dissector; otherwise, the dissector
3694 * doesn't fill in the info passed to the tap's packet
3697 error_string = register_tap_listener("skinny",
3698 &(the_tapinfo_struct.skinny_dummy),
3700 TL_REQUIRES_PROTO_TREE,
3701 voip_calls_dlg_reset,
3702 skinny_calls_packet,
3705 if (error_string != NULL) {
3706 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3707 "%s", error_string->str);
3708 g_string_free(error_string, TRUE);
3711 have_skinny_tap_listener=TRUE;
3715 /****************************************************************************/
3717 remove_tap_listener_skinny_calls(void)
3719 protect_thread_critical_region();
3720 remove_tap_listener(&(the_tapinfo_struct.skinny_dummy));
3721 unprotect_thread_critical_region();
3723 have_skinny_tap_listener=FALSE;
3726 /****************************************************************************/
3727 /* ***************************TAP for IAX2 **********************************/
3728 /****************************************************************************/
3730 /* IAX2 to tap-voip call state mapping */
3731 static const voip_call_state tap_iax_voip_state[] = {
3733 VOIP_CALL_SETUP, /*NEW*/
3736 VOIP_COMPLETED, /*HANGUP*/
3737 VOIP_REJECTED, /*REJECT*/
3738 VOIP_RINGING, /*ACCEPT*/
3753 VOIP_CALL_SETUP, /*DIAL*/
3772 static void free_iax2_info(gpointer p) {
3773 iax2_info_t *ii = p;
3779 /****************************************************************************/
3780 /* whenever a IAX2 packet is seen by the tap listener */
3782 iax2_calls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *iax2_info)
3784 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3786 voip_calls_info_t *callsinfo = NULL;
3788 const iax2_info_t *ii = iax2_info;
3789 iax2_info_t *tmp_iax2info;
3792 if (ii == NULL || ii->ptype != IAX2_FULL_PACKET || (ii->scallno == 0 && ii->dcallno == 0))
3794 /* check whether we already have this context in the list */
3795 list = g_list_first(tapinfo->callsinfo_list);
3798 voip_calls_info_t* tmp_listinfo = list->data;
3799 if (tmp_listinfo->protocol == VOIP_IAX2){
3800 tmp_iax2info = tmp_listinfo->prot_info;
3801 if (tmp_iax2info->scallno == ii->scallno ||
3802 tmp_iax2info->scallno == ii->dcallno){
3803 callsinfo = (voip_calls_info_t*)(list->data);
3807 list = g_list_next (list);
3809 phone = &(pinfo->src);
3812 if (callsinfo==NULL){
3813 /* We only care about real calls, i.e., no registration stuff */
3814 if (ii->ftype != AST_FRAME_IAX || ii->csub != IAX_COMMAND_NEW)
3816 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3817 callsinfo->call_state = VOIP_NO_STATE;
3818 callsinfo->call_active_state = VOIP_ACTIVE;
3819 callsinfo->prot_info=g_malloc(sizeof(iax2_info_t));
3820 callsinfo->free_prot_info = free_iax2_info;
3821 tmp_iax2info = callsinfo->prot_info;
3823 tmp_iax2info->scallno = ii->scallno;
3824 if (tmp_iax2info->scallno == 0) tmp_iax2info->scallno = ii->dcallno;
3825 tmp_iax2info->callState = tap_iax_voip_state[ii->callState];
3827 callsinfo->npackets = 1;
3829 COPY_ADDRESS(&(callsinfo->initial_speaker), phone);
3830 callsinfo->from_identity = g_strdup(ii->callingParty);
3831 callsinfo->to_identity = g_strdup(ii->calledParty);
3833 callsinfo->protocol = VOIP_IAX2;
3834 callsinfo->call_num = tapinfo->ncalls++;
3835 callsinfo->start_fd=pinfo->fd;
3836 callsinfo->stop_fd = pinfo->fd;
3838 callsinfo->selected = FALSE;
3839 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3842 if ((ii->callState > 0) && (ii->callState < (sizeof(tap_iax_voip_state)/sizeof(tap_iax_voip_state[0]))))
3843 callsinfo->call_state = tap_iax_voip_state[ii->callState];
3845 callsinfo->stop_fd = pinfo->fd;
3846 ++(callsinfo->npackets);
3851 add_to_graph(tapinfo, pinfo, ii->messageName, comment,
3852 callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3859 /****************************************************************************/
3861 /****************************************************************************/
3862 static gboolean have_iax2_tap_listener=FALSE;
3863 /****************************************************************************/
3865 iax2_calls_init_tap(void)
3867 GString *error_string;
3869 if(have_iax2_tap_listener==FALSE)
3872 * Don't register the tap listener if we have it already.
3873 * We set TL_REQUIRES_PROTO_TREE to force a non-null "tree"
3874 * in the IAX2 dissector; otherwise, the dissector
3875 * doesn't fill in the info passed to the tap's packet
3877 * XXX - that appears to be true of the MGCP and SKINNY
3878 * dissectors, but, unless I've missed something, it doesn't
3879 * appear to be true of the IAX2 dissector.
3881 error_string = register_tap_listener("IAX2",
3882 &(the_tapinfo_struct.iax2_dummy),
3884 TL_REQUIRES_PROTO_TREE,
3885 voip_calls_dlg_reset,
3889 if (error_string != NULL) {
3890 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s",
3892 g_string_free(error_string, TRUE);
3895 have_iax2_tap_listener=TRUE;
3899 /****************************************************************************/
3901 remove_tap_listener_iax2_calls(void)
3903 protect_thread_critical_region();
3904 remove_tap_listener(&(the_tapinfo_struct.iax2_dummy));
3905 unprotect_thread_critical_region();
3907 have_iax2_tap_listener=FALSE;
3910 /****************************************************************************/
3911 /* ***************************TAP for OTHER PROTOCOL **********************************/
3912 /****************************************************************************/
3915 VoIPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *VoIPinfo)
3917 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3918 voip_calls_info_t *callsinfo = NULL;
3919 voip_calls_info_t *tmp_listinfo;
3921 const voip_packet_info_t *pi = VoIPinfo;
3924 list = g_list_first(tapinfo->callsinfo_list);
3926 tmp_listinfo = list->data;
3927 if ( tmp_listinfo->protocol == VOIP_COMMON ) {
3928 if (!strcmp(pi->call_id, tmp_listinfo->call_id)) {
3929 callsinfo = (voip_calls_info_t*)(list->data);
3933 list = g_list_next(list);
3936 if (callsinfo == NULL) {
3937 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3938 callsinfo->call_active_state = pi->call_active_state;
3939 callsinfo->call_state = pi->call_state;
3940 callsinfo->call_id=g_strdup((pi->call_id)?pi->call_id:"");
3941 callsinfo->from_identity = g_strdup((pi->from_identity)?pi->from_identity:"");
3942 callsinfo->to_identity = g_strdup((pi->to_identity)?pi->to_identity:"");
3943 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
3944 callsinfo->selected=FALSE;
3945 callsinfo->start_fd=pinfo->fd;
3946 callsinfo->protocol=VOIP_COMMON;
3947 callsinfo->protocol_name=g_strdup((pi->protocol_name)?pi->protocol_name:"");
3948 callsinfo->call_comment=g_strdup((pi->call_comment)?pi->call_comment:"");
3949 callsinfo->prot_info=NULL;
3950 callsinfo->free_prot_info = NULL;
3952 callsinfo->call_num = tapinfo->ncalls++;
3953 callsinfo->npackets = 0;
3955 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3958 if (callsinfo != NULL) {
3959 callsinfo->call_active_state = pi->call_active_state;
3960 if ((callsinfo->call_state != VOIP_COMPLETED) && (pi->call_state == VOIP_COMPLETED))
3961 tapinfo->completed_calls++;
3962 if (pi->call_state != VOIP_NO_STATE)
3963 callsinfo->call_state = pi->call_state;
3964 if (pi->call_comment) {
3965 g_free(callsinfo->call_comment);
3966 callsinfo->call_comment=g_strdup(pi->call_comment);
3968 callsinfo->stop_fd = pinfo->fd;
3969 ++(callsinfo->npackets);
3970 ++(tapinfo->npackets);
3973 /* add to the graph */
3974 add_to_graph(tapinfo, pinfo, (pi->frame_label)?pi->frame_label:"VoIP msg", pi->frame_comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3976 tapinfo->redraw = TRUE;
3980 /****************************************************************************/
3981 static gboolean have_voip_tap_listener=FALSE;
3984 VoIPcalls_init_tap(void)
3986 GString *error_string;
3988 if(have_voip_tap_listener==FALSE)
3990 error_string = register_tap_listener("voip", &(the_tapinfo_struct.voip_dummy),
3993 voip_calls_dlg_reset,
3998 if (error_string != NULL) {
3999 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4000 "%s", error_string->str);
4001 g_string_free(error_string, TRUE);
4004 have_voip_tap_listener=TRUE;
4007 /****************************************************************************/
4009 remove_tap_listener_voip_calls(void)
4011 protect_thread_critical_region();
4012 remove_tap_listener(&(the_tapinfo_struct.voip_dummy));
4013 unprotect_thread_critical_region();
4015 have_voip_tap_listener=FALSE;
4019 /****************************************************************************/
4020 /* ***************************TAP for OTHER PROTOCOL **********************************/
4021 /****************************************************************************/
4023 /****************************************************************************/
4024 /* whenever a prot_ packet is seen by the tap listener */
4027 prot_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info _U_)
4029 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
4030 if (callsinfo!=NULL){
4031 callsinfo->stop_abs = pinfo->fd->abs_ts;
4032 callsinfo->stop_rel = pinfo->fd->rel_ts;
4033 callsinfo->last_frame_num=pinfo->fd->num;
4034 ++(callsinfo->npackets);
4035 ++(tapinfo->npackets);
4038 tapinfo->redraw = TRUE;
4043 /****************************************************************************/
4045 static gboolean have_prot__tap_listener=FALSE;
4048 prot_calls_init_tap(void)
4050 GString *error_string;
4052 if(have_prot__tap_listener==FALSE)
4054 error_string = register_tap_listener("prot_", &(the_tapinfo_struct.prot__dummy),
4057 voip_calls_dlg_reset,
4062 if (error_string != NULL) {
4063 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4064 "%s", error_string->str);
4065 g_string_free(error_string, TRUE);
4068 have_prot__tap_listener=TRUE;
4072 /****************************************************************************/
4075 remove_tap_listener_prot__calls(void)
4077 protect_thread_critical_region();
4078 remove_tap_listener(&(the_tapinfo_struct.prot__dummy));
4079 unprotect_thread_critical_region();
4081 have_prot__tap_listener=FALSE;