2 * VoIP calls summary addition for Wireshark
6 * Copyright 2004, Ericsson, Spain
7 * By Francisco Alcoba <francisco.alcoba@ericsson.com>
9 * based on h323_calls.c
10 * Copyright 2004, Iskratel, Ltd, Kranj
11 * By Miha Jemec <m.jemec@iskratel.si>
13 * H323, RTP, RTP Event, MGCP, AudioCodes (ISDN PRI and CAS), T38 and Graph Support
14 * By Alejandro Vaquero, alejandro.vaquero@verso.com
15 * Copyright 2005, Verso Technologies Inc.
17 * Wireshark - Network traffic analyzer
18 * By Gerald Combs <gerald@wireshark.org>
19 * Copyright 1998 Gerald Combs
21 * This program is free software; you can redistribute it and/or
22 * modify it under the terms of the GNU General Public License
23 * as published by the Free Software Foundation; either version 2
24 * of the License, or (at your option) any later version.
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
42 #include "graph_analysis.h"
43 #include "voip_calls.h"
44 #include "voip_calls_dlg.h"
50 #include <epan/dissectors/packet-sip.h>
51 #include <epan/dissectors/packet-mtp3.h>
52 #include <epan/dissectors/packet-isup.h>
53 #include <epan/dissectors/packet-h225.h>
54 #include <epan/dissectors/packet-h245.h>
55 #include <epan/dissectors/packet-q931.h>
56 #include <epan/dissectors/packet-sdp.h>
57 #include <plugins/mgcp/packet-mgcp.h>
58 #include <epan/dissectors/packet-actrace.h>
59 #include <epan/dissectors/packet-rtp.h>
60 #include <epan/dissectors/packet-rtp-events.h>
61 #include <epan/dissectors/packet-t38.h>
62 #include <epan/conversation.h>
63 #include <epan/rtp_pt.h>
65 #include "alert_box.h"
66 #include "simple_dialog.h"
68 #ifdef HAVE_LIBPORTAUDIO
69 #if GTK_MAJOR_VERSION >= 2
70 #include "rtp_player.h"
71 #endif /* GTK_MAJOR_VERSION >= 2 */
72 #endif /* HAVE_LIBPORTAUDIO */
74 const char *voip_call_state_name[7]={
84 /* defines whether we can consider the call active */
85 const char *voip_protocol_name[7]={
105 graph_str labels[H245_MAX];
108 static h245_labels_t h245_labels;
110 /****************************************************************************/
111 /* the one and only global voip_calls_tapinfo_t structure */
112 static voip_calls_tapinfo_t the_tapinfo_struct =
113 {0, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
115 /* the one and only global voip_rtp_tapinfo_t structure */
116 static voip_rtp_tapinfo_t the_tapinfo_rtp_struct =
119 /****************************************************************************/
120 /* when there is a [re]reading of packet's */
121 void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
123 voip_calls_info_t *strinfo;
124 sip_calls_info_t *tmp_sipinfo;
125 h323_calls_info_t *tmp_h323info;
126 h245_address_t *h245_add;
128 graph_analysis_item_t *graph_item;
133 #ifdef HAVE_LIBPORTAUDIO
134 #if GTK_MAJOR_VERSION >= 2
135 /* reset the RTP player */
140 /* free the data items first */
141 list = g_list_first(tapinfo->strinfo_list);
144 strinfo = list->data;
145 g_free(strinfo->from_identity);
146 g_free(strinfo->to_identity);
147 g_free((void *)(strinfo->initial_speaker.data));
148 if (strinfo->protocol == VOIP_SIP){
149 tmp_sipinfo = strinfo->prot_info;
150 g_free(tmp_sipinfo->call_identifier);
152 if (strinfo->protocol == VOIP_H323){
153 tmp_h323info = strinfo->prot_info;
154 g_free(tmp_h323info->guid);
155 /* free the H245 list address */
156 list2 = g_list_first(tmp_h323info->h245_list);
159 h245_add=list2->data;
160 g_free((void *)h245_add->h245_address.data);
162 list2 = g_list_next(list2);
164 g_list_free(tmp_h323info->h245_list);
165 tmp_h323info->h245_list = NULL;
167 g_free(strinfo->prot_info);
170 list = g_list_next(list);
172 g_list_free(tapinfo->strinfo_list);
173 tapinfo->strinfo_list = NULL;
175 tapinfo->npackets = 0;
176 tapinfo->start_packets = 0;
177 tapinfo->completed_calls = 0;
178 tapinfo->rejected_calls = 0;
180 /* free the graph data items first */
181 list = g_list_first(tapinfo->graph_analysis->list);
184 graph_item = list->data;
185 g_free(graph_item->frame_label);
186 g_free(graph_item->comment);
187 g_free((void *)graph_item->src_addr.data);
188 g_free((void *)graph_item->dst_addr.data);
190 list = g_list_next(list);
192 g_list_free(tapinfo->graph_analysis->list);
193 tapinfo->graph_analysis->nconv = 0;
194 tapinfo->graph_analysis->list = NULL;
196 ++(tapinfo->launch_count);
201 /****************************************************************************/
202 void graph_analysis_data_init(void){
203 the_tapinfo_struct.graph_analysis = g_malloc(sizeof(graph_analysis_info_t));
204 the_tapinfo_struct.graph_analysis->nconv = 0;
205 the_tapinfo_struct.graph_analysis->list = NULL;
208 /****************************************************************************/
209 /* Add a new item into the graph */
210 static int add_to_graph(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, const gchar *frame_label, gchar *comment, guint16 call_num, address *src_addr, address *dst_addr, guint16 line_style)
212 graph_analysis_item_t *gai;
214 gai = g_malloc(sizeof(graph_analysis_item_t));
215 gai->frame_num = pinfo->fd->num;
216 gai->time= nstime_to_sec(&pinfo->fd->rel_ts);
217 COPY_ADDRESS(&(gai->src_addr),src_addr);
218 COPY_ADDRESS(&(gai->dst_addr),dst_addr);
220 gai->port_src=pinfo->srcport;
221 gai->port_dst=pinfo->destport;
222 if (frame_label != NULL)
223 gai->frame_label = g_strdup(frame_label);
225 gai->frame_label = g_strdup("");
228 gai->comment = g_strdup(comment);
230 gai->comment = g_strdup("");
231 gai->conv_num=call_num;
232 gai->line_style=line_style;
235 tapinfo->graph_analysis->list = g_list_append(tapinfo->graph_analysis->list, gai);
241 /****************************************************************************/
242 /* Append str to frame_label and comment in a graph item */
243 /* return 0 if the frame_num is not in the graph list */
244 static int append_to_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
246 graph_analysis_item_t *gai;
248 gchar *tmp_str = NULL;
249 gchar *tmp_str2 = NULL;
251 list = g_list_first(tapinfo->graph_analysis->list);
255 if (gai->frame_num == frame_num){
256 tmp_str = gai->frame_label;
257 tmp_str2 = gai->comment;
259 if (new_frame_label != NULL){
260 gai->frame_label = g_strdup_printf("%s %s", gai->frame_label, new_frame_label);
265 if (new_comment != NULL){
266 gai->comment = g_strdup_printf("%s %s", gai->comment, new_comment);
271 list = g_list_next (list);
273 if (tmp_str == NULL) return 0; /* it is not in the list */
278 /****************************************************************************/
279 /* Change the frame_label and comment in a graph item if not NULL*/
280 /* return 0 if the frame_num is not in the graph list */
281 static int change_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
283 graph_analysis_item_t *gai;
285 gchar *tmp_str = NULL;
286 gchar *tmp_str2 = NULL;
288 list = g_list_first(tapinfo->graph_analysis->list);
292 if (gai->frame_num == frame_num){
293 tmp_str = gai->frame_label;
294 tmp_str2 = gai->comment;
296 if (new_frame_label != NULL){
297 gai->frame_label = g_strdup(new_frame_label);
301 if (new_comment != NULL){
302 gai->comment = g_strdup(new_comment);
307 list = g_list_next (list);
309 if (tmp_str == NULL) return 0; /* it is not in the list */
314 /****************************************************************************/
315 /* Change all the graph items with call_num to new_call_num */
316 static guint change_call_num_graph(voip_calls_tapinfo_t *tapinfo _U_, guint16 call_num, guint16 new_call_num)
318 graph_analysis_item_t *gai;
323 list = g_list_first(tapinfo->graph_analysis->list);
327 if (gai->conv_num == call_num){
328 gai->conv_num = new_call_num;
331 list = g_list_next (list);
333 return items_changed;
339 /****************************************************************************/
340 /* Insert the item in the graph list */
341 void insert_to_graph(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, const gchar *frame_label, gchar *comment, guint16 call_num, address *src_addr, address *dst_addr, guint16 line_style, double time, guint32 frame_num)
343 graph_analysis_item_t *gai, *new_gai;
348 new_gai = g_malloc(sizeof(graph_analysis_item_t));
349 new_gai->frame_num = frame_num;
351 COPY_ADDRESS(&(new_gai->src_addr),src_addr);
352 COPY_ADDRESS(&(new_gai->dst_addr),dst_addr);
354 new_gai->port_src=pinfo->srcport;
355 new_gai->port_dst=pinfo->destport;
356 if (frame_label != NULL)
357 new_gai->frame_label = g_strdup(frame_label);
359 new_gai->frame_label = g_strdup("");
362 new_gai->comment = g_strdup(comment);
364 new_gai->comment = g_strdup("");
365 new_gai->conv_num=call_num;
366 new_gai->line_style=line_style;
367 new_gai->display=FALSE;
371 list = g_list_first(tapinfo->graph_analysis->list);
375 if (gai->frame_num > frame_num){
376 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item_num);
380 list = g_list_next (list);
384 if ( !inserted) tapinfo->graph_analysis->list = g_list_append(tapinfo->graph_analysis->list, new_gai);
387 /****************************************************************************/
388 /* ***************************TAP for RTP Events*****************************/
389 /****************************************************************************/
391 static guint32 rtp_evt_frame_num = 0;
392 static guint8 rtp_evt = 0;
393 static gboolean rtp_evt_end = FALSE;
394 /*static guint32 rtp_evt_setup_frame_num = 0;*/
396 /****************************************************************************/
397 /* whenever a rtp event packet is seen by the tap listener */
399 rtp_event_packet(void *ptr _U_, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *rtp_event_info)
401 const struct _rtp_event_info *pi = rtp_event_info;
403 /* do not consider RTP events packets without a setup frame */
404 if (pi->info_setup_frame_num == 0){
408 rtp_evt_frame_num = pinfo->fd->num;
409 rtp_evt = pi->info_rtp_evt;
410 rtp_evt_end = pi->info_end;
415 /****************************************************************************/
416 static gboolean have_rtp_event_tap_listener=FALSE;
419 rtp_event_init_tap(void)
421 GString *error_string;
424 if(have_rtp_event_tap_listener==FALSE)
426 error_string = register_tap_listener("rtpevent", &(the_tapinfo_rtp_struct.rtp_event_dummy),
433 if (error_string != NULL) {
434 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
436 g_string_free(error_string, TRUE);
439 have_rtp_event_tap_listener=TRUE;
443 /****************************************************************************/
446 remove_tap_listener_rtp_event(void)
448 protect_thread_critical_region();
449 remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_event_dummy));
450 unprotect_thread_critical_region();
452 have_rtp_event_tap_listener=FALSE;
455 /****************************************************************************/
456 /* ***************************TAP for RTP **********************************/
457 /****************************************************************************/
459 /****************************************************************************/
460 /* when there is a [re]reading of RTP packet's */
461 static void voip_rtp_reset(void *ptr _U_)
463 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
465 /* free the data items first */
466 list = g_list_first(tapinfo->list);
470 list = g_list_next(list);
472 g_list_free(tapinfo->list);
473 tapinfo->list = NULL;
474 tapinfo->nstreams = 0;
478 /****************************************************************************/
479 /* whenever a RTP packet is seen by the tap listener */
481 RTP_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void const *RTPinfo)
483 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
484 voip_rtp_stream_info_t *tmp_listinfo;
485 voip_rtp_stream_info_t *strinfo = NULL;
487 struct _rtp_conversation_info *p_conv_data = NULL;
489 const struct _rtp_info *pi = RTPinfo;
491 /* do not consider RTP packets without a setup frame */
492 if (pi->info_setup_frame_num == 0){
496 /* add this RTP for future listening using the RTP Player*/
497 #if GTK_MAJOR_VERSION >= 2
498 #ifdef HAVE_LIBPORTAUDIO
499 add_rtp_packet(pi, pinfo);
503 /* check wether we already have a RTP stream with this setup frame and ssrc in the list */
504 list = g_list_first(tapinfo->list);
507 tmp_listinfo=list->data;
508 if ( (tmp_listinfo->setup_frame_number == pi->info_setup_frame_num)
509 && (tmp_listinfo->ssrc == pi->info_sync_src) && (tmp_listinfo->end_stream == FALSE)){
510 /* if the payload type has changed, we mark the stream as finished to create a new one
511 this is to show multiple payload changes in the Graph for example for DTMF RFC2833 */
512 if ( tmp_listinfo->pt != pi->info_payload_type ) {
513 tmp_listinfo->end_stream = TRUE;
515 strinfo = (voip_rtp_stream_info_t*)(list->data);
519 list = g_list_next (list);
522 /* if this is a duplicated RTP Event End, just return */
523 if ((rtp_evt_frame_num == pinfo->fd->num) && !strinfo && (rtp_evt_end == TRUE)) {
527 /* not in the list? then create a new entry */
529 strinfo = g_malloc(sizeof(voip_rtp_stream_info_t));
530 COPY_ADDRESS(&(strinfo->src_addr), &(pinfo->src));
531 strinfo->src_port = pinfo->srcport;
532 COPY_ADDRESS(&(strinfo->dest_addr), &(pinfo->dst));
533 strinfo->dest_port = pinfo->destport;
534 strinfo->ssrc = pi->info_sync_src;
535 strinfo->end_stream = FALSE;
536 strinfo->pt = pi->info_payload_type;
537 strinfo->pt_str = NULL;
538 /* if it is dynamic payload, let use the conv data to see if it is defined */
539 if ( (strinfo->pt>95) && (strinfo->pt<128) ) {
540 /* Use existing packet info if available */
541 p_conv_data = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name("rtp"));
543 strinfo->pt_str = g_strdup(g_hash_table_lookup(p_conv_data->rtp_dyn_payload, &strinfo->pt));
545 if (!strinfo->pt_str) strinfo->pt_str = g_strdup(val_to_str(strinfo->pt, rtp_payload_type_short_vals, "%u"));
546 strinfo->npackets = 0;
547 strinfo->first_frame_num = pinfo->fd->num;
548 strinfo->start_rel_sec = pinfo->fd->rel_ts.secs;
549 strinfo->start_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
550 strinfo->setup_frame_number = pi->info_setup_frame_num;
551 strinfo->rtp_event = -1;
552 tapinfo->list = g_list_append(tapinfo->list, strinfo);
556 /* Add the info to the existing RTP stream */
558 strinfo->stop_rel_sec = pinfo->fd->rel_ts.secs;
559 strinfo->stop_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
561 /* process RTP Event */
562 if (rtp_evt_frame_num == pinfo->fd->num) {
563 strinfo->rtp_event = rtp_evt;
564 if (rtp_evt_end == TRUE) {
565 strinfo->end_stream = TRUE;
570 the_tapinfo_struct.redraw = TRUE;
575 /****************************************************************************/
576 /* whenever a redraw in the RTP tap listener */
577 static void RTP_packet_draw(void *prs _U_)
579 voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
580 GList* rtp_streams_list;
581 voip_rtp_stream_info_t *rtp_listinfo;
582 GList* voip_calls_graph_list;
584 graph_analysis_item_t *gai;
585 graph_analysis_item_t *new_gai;
589 /* add each rtp stream to the graph */
590 rtp_streams_list = g_list_first(rtp_tapinfo->list);
591 while (rtp_streams_list)
593 rtp_listinfo = rtp_streams_list->data;
595 /* using the setup frame number of the RTP stream, we get the call number that it belongs */
596 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
597 while (voip_calls_graph_list)
599 gai = voip_calls_graph_list->data;
600 conv_num = gai->conv_num;
601 /* if we get the setup frame number, then get the time position to graph the RTP arrow */
602 if (rtp_listinfo->setup_frame_number == gai->frame_num){
603 /* look again from the begining because there are cases where the Setup frame is after the RTP */
604 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
606 while(voip_calls_graph_list){
607 gai = voip_calls_graph_list->data;
608 /* if RTP was already in the Graph, just update the comment information */
609 if (rtp_listinfo->first_frame_num == gai->frame_num){
610 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
611 g_free(gai->comment);
612 gai->comment = g_strdup_printf("RTP Num packets:%u Duration:%u.%03us ssrc:%u", rtp_listinfo->npackets, duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
616 /* 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 */
617 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
618 if (!voip_calls_graph_list) item++;
620 /* add the RTP item to the graph if was not there*/
621 if (rtp_listinfo->first_frame_num<gai->frame_num || !voip_calls_graph_list){
622 new_gai = g_malloc(sizeof(graph_analysis_item_t));
623 new_gai->frame_num = rtp_listinfo->first_frame_num;
624 new_gai->time = (double)rtp_listinfo->start_rel_sec + (double)rtp_listinfo->start_rel_usec/1000000;
625 COPY_ADDRESS(&(new_gai->src_addr),&(rtp_listinfo->src_addr));
626 COPY_ADDRESS(&(new_gai->dst_addr),&(rtp_listinfo->dest_addr));
627 new_gai->port_src = rtp_listinfo->src_port;
628 new_gai->port_dst = rtp_listinfo->dest_port;
629 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
630 new_gai->frame_label = g_strdup_printf("RTP (%s) %s", rtp_listinfo->pt_str, (rtp_listinfo->rtp_event == -1)?"":val_to_str(rtp_listinfo->rtp_event, rtp_event_type_values, "Unknown RTP Event"));
631 g_free(rtp_listinfo->pt_str);
632 new_gai->comment = g_strdup_printf("RTP Num packets:%u Duration:%u.%03us ssrc:%u", rtp_listinfo->npackets, duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
633 new_gai->conv_num = conv_num;
634 new_gai->display=FALSE;
635 new_gai->line_style = 2; /* the arrow line will be 2 pixels width */
636 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item);
639 if (voip_calls_graph_list) item++;
643 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
645 rtp_streams_list = g_list_next(rtp_streams_list);
649 static gboolean have_RTP_tap_listener=FALSE;
650 /****************************************************************************/
654 GString *error_string;
656 if(have_RTP_tap_listener==FALSE)
658 /* don't register tap listener, if we have it already */
659 error_string = register_tap_listener("rtp", &(the_tapinfo_rtp_struct.rtp_dummy), NULL,
664 if (error_string != NULL) {
665 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
667 g_string_free(error_string, TRUE);
670 have_RTP_tap_listener=TRUE;
674 /****************************************************************************/
676 remove_tap_listener_rtp(void)
678 protect_thread_critical_region();
679 remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_dummy));
680 unprotect_thread_critical_region();
682 have_RTP_tap_listener=FALSE;
685 /* XXX just copied from gtk/rpc_stat.c */
686 void protect_thread_critical_region(void);
687 void unprotect_thread_critical_region(void);
689 /****************************************************************************/
690 /******************************TAP for T38 **********************************/
691 /****************************************************************************/
693 /****************************************************************************/
694 /* whenever a T38 packet is seen by the tap listener */
696 T38_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *T38info)
698 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
700 voip_calls_info_t *strinfo = NULL;
701 voip_calls_info_t *tmp_listinfo;
702 GList* voip_calls_graph_list;
704 gchar *frame_label = NULL;
705 gchar *comment = NULL;
706 graph_analysis_item_t *tmp_gai, *gai = NULL;
707 guint16 line_style = 2;
711 const t38_packet_info *pi = T38info;
713 if (pi->setup_frame_number != 0) {
714 /* using the setup frame number of the T38 packet, we get the call number that it belongs */
715 voip_calls_graph_list = g_list_first(tapinfo->graph_analysis->list);
716 while (voip_calls_graph_list)
718 tmp_gai = voip_calls_graph_list->data;
719 if (pi->setup_frame_number == tmp_gai->frame_num){
723 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
725 if (gai) conv_num = (int) gai->conv_num;
728 /* 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
729 * have the associated Voip calls. It probably means the the packet was decoded using the default t38 port, or using "Decode as.."
730 * in this case we create a "voip" call that only have t38 media (no signaling)
731 * OR if we have not found the Setup message in the graph.
733 if ( (pi->setup_frame_number == 0) || (gai == NULL) ){
734 /* check whether we already have a call with these parameters in the list */
735 list = g_list_first(tapinfo->strinfo_list);
738 tmp_listinfo=list->data;
739 if (tmp_listinfo->protocol == MEDIA_T38){
740 strinfo = (voip_calls_info_t*)(list->data);
743 list = g_list_next (list);
746 /* not in the list? then create a new entry */
748 strinfo = g_malloc(sizeof(voip_calls_info_t));
749 strinfo->call_active_state = VOIP_ACTIVE;
750 strinfo->call_state = VOIP_UNKNOWN;
751 strinfo->from_identity=g_strdup("T38 Media only");
752 strinfo->to_identity=g_strdup("T38 Media only");
753 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
754 strinfo->first_frame_num=pinfo->fd->num;
755 strinfo->selected=FALSE;
756 strinfo->start_sec=pinfo->fd->rel_ts.secs;
757 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
758 strinfo->protocol=MEDIA_T38;
759 strinfo->prot_info=NULL;
760 strinfo->npackets = 0;
761 strinfo->call_num = tapinfo->ncalls++;
762 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
764 ++(strinfo->npackets);
765 /* increment the packets counter of all calls */
766 ++(tapinfo->npackets);
768 conv_num = (int) strinfo->call_num;
771 /* at this point we should have found the call num for this t38 packets belong */
772 if (conv_num == -1) {
776 /* add the item to the graph list */
777 if (pi->type_msg == 0) { /* 0=t30-indicator */
778 frame_label = g_strdup(val_to_str(pi->t30ind_value, t30_indicator_vals, "Ukn (0x%02X)") );
779 comment = g_strdup_printf("t38:t30 Ind:%s",val_to_str(pi->t30ind_value, t30_indicator_vals, "Ukn (0x%02X)") );
781 } else if (pi->type_msg == 1) { /* 1=data */
782 switch(pi->Data_Field_field_type_value){
783 case 0: /* hdlc-data */
785 case 2: /* hdlc-fcs-OK */
786 case 4: /* hdlc-fcs-OK-sig-end */
787 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);
788 comment = g_strdup_printf("t38:%s:HDLC:%s",val_to_str(pi->data_value, t30_data_vals, "Ukn (0x%02X)"), val_to_str(pi->t30_Facsimile_Control & 0x7F, t30_facsimile_control_field_vals, "Ukn (0x%02X)"));
790 case 3: /* hdlc-fcs-BAD */
791 case 5: /* hdlc-fcs-BAD-sig-end */
792 frame_label = g_strdup(pi->Data_Field_field_type_value == 3 ? "fcs-BAD" : "fcs-BAD-sig-end");
793 comment = g_strdup_printf("WARNING: received t38:%s:HDLC:%s", val_to_str(pi->data_value, t30_data_vals, "Ukn (0x%02X)"), pi->Data_Field_field_type_value == 3 ? "fcs-BAD" : "fcs-BAD-sig-end");
795 case 7: /* t4-non-ecm-sig-end */
796 duration = nstime_to_sec(&pinfo->fd->rel_ts) - pi->time_first_t4_data;
797 frame_label = g_strdup_printf("t4-non-ecm-data:%s",val_to_str(pi->data_value, t30_data_vals, "Ukn (0x%02X)") );
798 comment = g_strdup_printf("t38:t4-non-ecm-data:%s Duration: %.2fs %s",val_to_str(pi->data_value, t30_data_vals, "Ukn (0x%02X)"), duration, pi->desc_comment );
799 insert_to_graph(tapinfo, pinfo, frame_label, comment, (guint16)conv_num, &(pinfo->src), &(pinfo->dst), line_style, pi->time_first_t4_data, pi->frame_num_first_t4_data);
804 if (frame_label && !(pi->Data_Field_field_type_value == 7 && pi->type_msg == 1)) {
805 add_to_graph(tapinfo, pinfo, frame_label, comment, (guint16)conv_num, &(pinfo->src), &(pinfo->dst), line_style);
811 tapinfo->redraw = TRUE;
813 return 1; /* refresh output */
816 static gboolean have_T38_tap_listener=FALSE;
817 /****************************************************************************/
821 GString *error_string;
823 if(have_T38_tap_listener==FALSE)
825 /* don't register tap listener, if we have it already */
826 error_string = register_tap_listener("t38", &(the_tapinfo_struct.t38_dummy), NULL,
827 voip_calls_dlg_reset,
831 if (error_string != NULL) {
832 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
834 g_string_free(error_string, TRUE);
837 have_T38_tap_listener=TRUE;
841 /****************************************************************************/
843 remove_tap_listener_t38(void)
845 protect_thread_critical_region();
846 remove_tap_listener(&(the_tapinfo_struct.t38_dummy));
847 unprotect_thread_critical_region();
849 have_T38_tap_listener=FALSE;
853 /****************************************************************************/
854 static gchar *sdp_summary = NULL;
855 static guint32 sdp_frame_num = 0;
857 /****************************************************************************/
858 /* ***************************TAP for SIP **********************************/
859 /****************************************************************************/
861 /****************************************************************************/
862 /* whenever a SIP packet is seen by the tap listener */
864 SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SIPinfo)
866 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
867 /* we just take note of the ISUP data here; when we receive the MTP3 part everything will
868 be compared with existing calls */
870 voip_calls_info_t *tmp_listinfo;
871 voip_calls_info_t *strinfo = NULL;
872 sip_calls_info_t *tmp_sipinfo = NULL;
874 address tmp_src, tmp_dst;
875 gchar *frame_label = NULL;
876 gchar *comment = NULL;
878 const sip_info_value_t *pi = SIPinfo;
880 /* do not consider packets without call_id */
881 if (pi->tap_call_id ==NULL){
885 /* check whether we already have a call with these parameters in the list */
886 list = g_list_first(tapinfo->strinfo_list);
889 tmp_listinfo=list->data;
890 if (tmp_listinfo->protocol == VOIP_SIP){
891 tmp_sipinfo = tmp_listinfo->prot_info;
892 if (strcmp(tmp_sipinfo->call_identifier,pi->tap_call_id)==0){
893 strinfo = (voip_calls_info_t*)(list->data);
897 list = g_list_next (list);
900 /* not in the list? then create a new entry if the message is INVITE -i.e. if this session is a call*/
901 if ((strinfo==NULL) &&(pi->request_method!=NULL)){
902 if (strcmp(pi->request_method,"INVITE")==0){
903 strinfo = g_malloc(sizeof(voip_calls_info_t));
904 strinfo->call_active_state = VOIP_ACTIVE;
905 strinfo->call_state = VOIP_CALL_SETUP;
906 strinfo->from_identity=g_strdup(pi->tap_from_addr);
907 strinfo->to_identity=g_strdup(pi->tap_to_addr);
908 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
909 strinfo->first_frame_num=pinfo->fd->num;
910 strinfo->selected=FALSE;
911 strinfo->start_sec=pinfo->fd->rel_ts.secs;
912 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
913 strinfo->protocol=VOIP_SIP;
914 strinfo->prot_info=g_malloc(sizeof(sip_calls_info_t));
915 tmp_sipinfo=strinfo->prot_info;
916 tmp_sipinfo->call_identifier=strdup(pi->tap_call_id);
917 tmp_sipinfo->sip_state=SIP_INVITE_SENT;
918 tmp_sipinfo->invite_cseq=pi->tap_cseq_number;
919 strinfo->npackets = 0;
920 strinfo->call_num = tapinfo->ncalls++;
921 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
927 /* let's analyze the call state */
929 COPY_ADDRESS(&(tmp_src), &(pinfo->src));
930 COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
932 if (pi->request_method == NULL){
933 frame_label = g_strdup_printf("%u %s", pi->response_code, pi->reason_phrase );
934 comment = g_strdup_printf("SIP Status");
936 if ((tmp_sipinfo && pi->tap_cseq_number == tmp_sipinfo->invite_cseq)&&(ADDRESSES_EQUAL(&tmp_dst,&(strinfo->initial_speaker)))){
937 if ((pi->response_code > 199) && (pi->response_code<300) && (tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
938 tmp_sipinfo->sip_state = SIP_200_REC;
940 else if ((pi->response_code>299)&&(tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
941 strinfo->call_state = VOIP_REJECTED;
942 tapinfo->rejected_calls++;
948 frame_label = g_strdup(pi->request_method);
950 if ((strcmp(pi->request_method,"INVITE")==0)&&(ADDRESSES_EQUAL(&tmp_src,&(strinfo->initial_speaker)))){
951 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
952 strinfo->call_state = VOIP_CALL_SETUP;
953 comment = g_strdup_printf("SIP From: %s To:%s", strinfo->from_identity, strinfo->to_identity);
955 else if ((strcmp(pi->request_method,"ACK")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
956 &&(ADDRESSES_EQUAL(&tmp_src,&(strinfo->initial_speaker)))&&(tmp_sipinfo->sip_state==SIP_200_REC)
957 &&(strinfo->call_state == VOIP_CALL_SETUP)){
958 strinfo->call_state = VOIP_IN_CALL;
959 comment = g_strdup_printf("SIP Request");
961 else if (strcmp(pi->request_method,"BYE")==0){
962 strinfo->call_state = VOIP_COMPLETED;
963 tapinfo->completed_calls++;
964 comment = g_strdup_printf("SIP Request");
966 else if ((strcmp(pi->request_method,"CANCEL")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
967 &&(ADDRESSES_EQUAL(&tmp_src,&(strinfo->initial_speaker)))&&(strinfo->call_state==VOIP_CALL_SETUP)){
968 strinfo->call_state = VOIP_CANCELLED;
969 tmp_sipinfo->sip_state = SIP_CANCEL_SENT;
970 comment = g_strdup_printf("SIP Request");
972 comment = g_strdup_printf("SIP Request");
976 strinfo->stop_sec=pinfo->fd->rel_ts.secs;
977 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
978 strinfo->last_frame_num=pinfo->fd->num;
979 ++(strinfo->npackets);
980 /* increment the packets counter of all calls */
981 ++(tapinfo->npackets);
983 /* add to the graph */
984 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
987 g_free((void *)tmp_src.data);
988 g_free((void *)tmp_dst.data);
990 /* add SDP info if apply */
991 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
992 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
998 tapinfo->redraw = TRUE;
1000 return 1; /* refresh output */
1004 /****************************************************************************/
1005 voip_calls_tapinfo_t* voip_calls_get_info(void)
1007 return &the_tapinfo_struct;
1011 /****************************************************************************/
1013 /****************************************************************************/
1014 static gboolean have_SIP_tap_listener=FALSE;
1015 /****************************************************************************/
1017 sip_calls_init_tap(void)
1019 GString *error_string;
1021 if(have_SIP_tap_listener==FALSE)
1023 /* don't register tap listener, if we have it already */
1024 error_string = register_tap_listener("sip", &(the_tapinfo_struct.sip_dummy), NULL,
1025 voip_calls_dlg_reset,
1029 if (error_string != NULL) {
1030 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1032 g_string_free(error_string, TRUE);
1035 have_SIP_tap_listener=TRUE;
1039 /****************************************************************************/
1041 remove_tap_listener_sip_calls(void)
1043 protect_thread_critical_region();
1044 remove_tap_listener(&(the_tapinfo_struct.sip_dummy));
1045 unprotect_thread_critical_region();
1047 have_SIP_tap_listener=FALSE;
1050 /****************************************************************************/
1051 /* ***************************TAP for ISUP **********************************/
1052 /****************************************************************************/
1054 static guint32 mtp3_opc, mtp3_dpc;
1055 static guint8 mtp3_ni;
1056 static guint32 mtp3_frame_num;
1059 /****************************************************************************/
1060 /* whenever a isup_ packet is seen by the tap listener */
1062 isup_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *isup_info _U_)
1064 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1065 voip_calls_info_t *tmp_listinfo;
1066 voip_calls_info_t *strinfo = NULL;
1067 isup_calls_info_t *tmp_isupinfo;
1068 gboolean found = FALSE;
1069 gboolean forward = FALSE;
1070 gboolean right_pair;
1072 gchar *frame_label = NULL;
1073 gchar *comment = NULL;
1076 /*voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct; unused */
1077 const isup_tap_rec_t *pi = isup_info;
1080 /* check if the lower layer is MTP matching the frame number */
1081 if (mtp3_frame_num != pinfo->fd->num) return 0;
1083 /* check whether we already have a call with these parameters in the list */
1084 list = g_list_first(tapinfo->strinfo_list);
1088 tmp_listinfo=list->data;
1089 if ((tmp_listinfo->protocol == VOIP_ISUP)&&(tmp_listinfo->call_active_state==VOIP_ACTIVE)){
1090 tmp_isupinfo = tmp_listinfo->prot_info;
1091 if ((tmp_isupinfo->cic == pinfo->circuit_id)&&(tmp_isupinfo->ni == mtp3_ni)) {
1092 if ((tmp_isupinfo->opc == mtp3_opc)&&(tmp_isupinfo->dpc == mtp3_dpc)){
1095 else if ((tmp_isupinfo->dpc == mtp3_opc)&&(tmp_isupinfo->opc == mtp3_dpc)){
1102 /* if there is an IAM for a call that is not in setup state, that means the previous call in the same
1103 cic is no longer active */
1104 if (tmp_listinfo->call_state == VOIP_CALL_SETUP){
1107 else if (pi->message_type != 1){
1111 tmp_listinfo->call_active_state=VOIP_INACTIVE;
1115 strinfo = (voip_calls_info_t*)(list->data);
1120 list = g_list_next (list);
1123 /* not in the list? then create a new entry if the message is IAM
1124 -i.e. if this session is a call*/
1127 if ((strinfo==NULL) &&(pi->message_type==1)){
1129 strinfo = g_malloc(sizeof(voip_calls_info_t));
1130 strinfo->call_active_state = VOIP_ACTIVE;
1131 strinfo->call_state = VOIP_UNKNOWN;
1132 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
1133 strinfo->selected=FALSE;
1134 strinfo->first_frame_num=pinfo->fd->num;
1135 strinfo->start_sec=pinfo->fd->rel_ts.secs;
1136 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1137 strinfo->protocol=VOIP_ISUP;
1138 if (pi->calling_number!=NULL){
1139 strinfo->from_identity=g_strdup(pi->calling_number);
1141 if (pi->called_number!=NULL){
1142 strinfo->to_identity=g_strdup(pi->called_number);
1144 strinfo->prot_info=g_malloc(sizeof(isup_calls_info_t));
1145 tmp_isupinfo=strinfo->prot_info;
1146 tmp_isupinfo->opc = mtp3_opc;
1147 tmp_isupinfo->dpc = mtp3_dpc;
1148 tmp_isupinfo->ni = mtp3_ni;
1149 tmp_isupinfo->cic = pinfo->circuit_id;
1150 strinfo->npackets = 0;
1151 strinfo->call_num = tapinfo->ncalls++;
1152 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
1156 strinfo->stop_sec=pinfo->fd->rel_ts.secs;
1157 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1158 strinfo->last_frame_num=pinfo->fd->num;
1159 ++(strinfo->npackets);
1161 /* Let's analyze the call state */
1164 for (i=0;(isup_message_type_value[i].strptr!=NULL)&& (isup_message_type_value[i].value!=pi->message_type);i++);
1166 if (isup_message_type_value[i].value==pi->message_type){
1167 frame_label = g_strdup(isup_message_type_value_acro[i].strptr);
1170 frame_label = g_strdup_printf("Unknown");
1173 if (strinfo->npackets == 1){ /* this is the first packet, that must be an IAM */
1174 if ((pi->calling_number!=NULL)&&(pi->called_number !=NULL)){
1175 comment = g_strdup_printf("Call from %s to %s",
1176 pi->calling_number, pi->called_number);
1179 else if (strinfo->npackets == 2){ /* in the second packet we show the SPs */
1181 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
1183 mtp3_ni, mtp3_dpc, pinfo->circuit_id);
1187 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
1189 mtp3_ni, mtp3_opc, pinfo->circuit_id);
1194 switch(pi->message_type){
1196 strinfo->call_state=VOIP_CALL_SETUP;
1198 case 7: /* CONNECT */
1199 case 9: /* ANSWER */
1200 strinfo->call_state=VOIP_IN_CALL;
1202 case 12: /* RELEASE */
1203 if (strinfo->call_state==VOIP_CALL_SETUP){
1205 strinfo->call_state=VOIP_CANCELLED;
1208 strinfo->call_state=VOIP_REJECTED;
1209 tapinfo->rejected_calls++;
1212 else if (strinfo->call_state == VOIP_IN_CALL){
1213 strinfo->call_state = VOIP_COMPLETED;
1214 tapinfo->completed_calls++;
1216 for (i=0;(q931_cause_code_vals[i].strptr!=NULL)&& (q931_cause_code_vals[i].value!=pi->cause_value);i++);
1217 if (q931_cause_code_vals[i].value==pi->cause_value){
1218 comment = g_strdup_printf("Cause %i - %s",pi->cause_value, q931_cause_code_vals[i].strptr);
1221 comment = g_strdup_printf("Cause %i",pi->cause_value);
1226 /* increment the packets counter of all calls */
1227 ++(tapinfo->npackets);
1229 /* add to the graph */
1230 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1232 g_free(frame_label);
1235 tapinfo->redraw = TRUE;
1237 return 1; /* refresh output */
1240 /****************************************************************************/
1242 static gboolean have_isup_tap_listener=FALSE;
1245 isup_calls_init_tap(void)
1247 GString *error_string;
1250 if(have_isup_tap_listener==FALSE)
1252 error_string = register_tap_listener("isup", &(the_tapinfo_struct.isup_dummy),
1254 voip_calls_dlg_reset,
1259 if (error_string != NULL) {
1260 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1262 g_string_free(error_string, TRUE);
1265 have_isup_tap_listener=TRUE;
1269 /****************************************************************************/
1272 remove_tap_listener_isup_calls(void)
1274 protect_thread_critical_region();
1275 remove_tap_listener(&(the_tapinfo_struct.isup_dummy));
1276 unprotect_thread_critical_region();
1278 have_isup_tap_listener=FALSE;
1282 /****************************************************************************/
1283 /* ***************************TAP for MTP3 **********************************/
1284 /****************************************************************************/
1287 /****************************************************************************/
1288 /* whenever a mtp3_ packet is seen by the tap listener */
1290 mtp3_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *mtp3_info _U_)
1292 const mtp3_tap_rec_t *pi = mtp3_info;
1294 /* keep the data in memory to use when the ISUP information arrives */
1296 mtp3_opc = pi->addr_opc.pc;
1297 mtp3_dpc = pi->addr_dpc.pc;
1298 mtp3_ni = pi->addr_opc.ni;
1299 mtp3_frame_num = pinfo->fd->num;
1304 /****************************************************************************/
1306 static gboolean have_mtp3_tap_listener=FALSE;
1309 mtp3_calls_init_tap(void)
1311 GString *error_string;
1314 if(have_mtp3_tap_listener==FALSE)
1316 error_string = register_tap_listener("mtp3", &(the_tapinfo_struct.mtp3_dummy),
1318 voip_calls_dlg_reset,
1323 if (error_string != NULL) {
1324 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1326 g_string_free(error_string, TRUE);
1329 have_mtp3_tap_listener=TRUE;
1333 /****************************************************************************/
1336 remove_tap_listener_mtp3_calls(void)
1338 protect_thread_critical_region();
1339 remove_tap_listener(&(the_tapinfo_struct.mtp3_dummy));
1340 unprotect_thread_critical_region();
1342 have_mtp3_tap_listener=FALSE;
1345 /****************************************************************************/
1346 /* ***************************TAP for Q931 **********************************/
1347 /****************************************************************************/
1348 void h245_add_to_graph(guint32 new_frame_num);
1349 static const e_guid_t guid_allzero = {0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };
1350 /* defines specific H323 data */
1352 static gchar *q931_calling_number;
1353 static gchar *q931_called_number;
1354 static guint8 q931_cause_value;
1355 static gint32 q931_crv;
1356 static guint32 q931_frame_num;
1358 static guint32 h225_frame_num = 0;
1359 static guint16 h225_call_num = 0;
1360 static h225_cs_type h225_cstype = H225_OTHER;
1361 static gboolean h225_is_faststart;
1363 static guint32 actrace_frame_num = 0;
1364 static gint32 actrace_trunk = 0;
1365 static gint32 actrace_direction = 0;
1368 /****************************************************************************/
1369 /* whenever a q931_ packet is seen by the tap listener */
1371 q931_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *q931_info _U_)
1374 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1375 h323_calls_info_t *tmp_h323info,*tmp2_h323info;
1376 actrace_isdn_calls_info_t *tmp_actrace_isdn_info;
1377 voip_calls_info_t *tmp_listinfo;
1378 voip_calls_info_t *strinfo = NULL;
1379 h245_address_t *h245_add = NULL;
1382 const q931_packet_info *pi = q931_info;
1384 /* free previously allocated q931_calling/ed_number */
1385 g_free(q931_calling_number);
1386 g_free(q931_called_number);
1388 if (pi->calling_number!=NULL)
1389 q931_calling_number = g_strdup(pi->calling_number);
1391 q931_calling_number = g_strdup("");
1393 if (pi->called_number!=NULL)
1394 q931_called_number = g_strdup(pi->called_number);
1396 q931_called_number = g_strdup("");
1397 q931_cause_value = pi->cause_value;
1398 q931_frame_num = pinfo->fd->num;
1402 /* add staff to H323 calls */
1403 if (h225_frame_num == q931_frame_num) {
1404 tmp_h323info = NULL;
1405 list = g_list_first(tapinfo->strinfo_list);
1408 tmp_listinfo=list->data;
1409 if ( (tmp_listinfo->protocol == VOIP_H323) && (tmp_listinfo->call_num == h225_call_num) ){
1410 tmp_h323info = tmp_listinfo->prot_info;
1411 strinfo = (voip_calls_info_t*)(list->data);
1413 /* Add the CRV to the h323 call */
1414 if (tmp_h323info->q931_crv == -1) {
1415 tmp_h323info->q931_crv = q931_crv;
1416 } else if (tmp_h323info->q931_crv != q931_crv) {
1417 tmp_h323info->q931_crv2 = q931_crv;
1421 list = g_list_next (list);
1424 if (strinfo != NULL) {
1426 if (h225_cstype == H225_SETUP) {
1427 /* set te calling and called number from the Q931 packet */
1428 if (q931_calling_number != NULL){
1429 g_free(strinfo->from_identity);
1430 strinfo->from_identity=g_strdup(q931_calling_number);
1432 if (q931_called_number != NULL){
1433 g_free(strinfo->to_identity);
1434 strinfo->to_identity=g_strdup(q931_called_number);
1437 /* check if there is an LRQ/LCF that match this Setup */
1438 /* TODO: we are just checking the DialedNumer in LRQ/LCF agains the Setup
1439 we should also check if the h225 signaling IP and port match the destination
1440 Setup ip and port */
1441 list = g_list_first(tapinfo->strinfo_list);
1444 tmp_listinfo=list->data;
1445 if (tmp_listinfo->protocol == VOIP_H323){
1446 tmp2_h323info = tmp_listinfo->prot_info;
1448 /* check if the called number match a LRQ/LCF */
1449 if ( (strcmp(strinfo->to_identity, tmp_listinfo->to_identity)==0)
1450 && (memcmp(&tmp2_h323info->guid, &guid_allzero, GUID_LEN) == 0) ){
1451 /* change the call graph to the LRQ/LCF to belong to this call */
1452 strinfo->npackets += change_call_num_graph(tapinfo, tmp_listinfo->call_num, strinfo->call_num);
1454 /* remove this LRQ/LCF call entry because we have found the Setup that match them */
1455 g_free(tmp_listinfo->from_identity);
1456 g_free(tmp_listinfo->to_identity);
1457 g_free(tmp2_h323info->guid);
1459 list2 = g_list_first(tmp2_h323info->h245_list);
1462 h245_add=list2->data;
1463 g_free((void *)h245_add->h245_address.data);
1464 g_free(list2->data);
1465 list2 = g_list_next(list2);
1467 g_list_free(tmp_h323info->h245_list);
1468 tmp_h323info->h245_list = NULL;
1469 g_free(tmp_listinfo->prot_info);
1470 tapinfo->strinfo_list = g_list_remove(tapinfo->strinfo_list, tmp_listinfo);
1474 list = g_list_next (list);
1477 comment = g_strdup_printf("H225 From: %s To:%s TunnH245:%s FS:%s", strinfo->from_identity, strinfo->to_identity, (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1478 (h225_is_faststart==TRUE?"on":"off"));
1479 } else if (h225_cstype == H225_RELEASE_COMPLET) {
1480 /* get the Q931 Release cause code */
1481 if (q931_cause_value != 0xFF){
1482 comment = g_strdup_printf("H225 Q931 Rel Cause (%i):%s", q931_cause_value, val_to_str(q931_cause_value, q931_cause_code_vals, "<unknown>"));
1483 } else { /* Cause not set */
1484 comment = g_strdup("H225 No Q931 Rel Cause");
1487 /* change the graph comment for this new one */
1488 if (comment != NULL) {
1489 change_frame_graph(tapinfo, h225_frame_num, NULL, comment);
1493 /* we reset the h225_frame_num to 0 because there could be empty h225 in the same frame
1494 as non empty h225 (e.g connect), so we don't have to be here twice */
1497 /* add staff to H245 */
1498 } else if (h245_labels.frame_num == q931_frame_num) {
1499 /* there are empty H225 frames that don't have guid (guaid=0) but they have h245 info,
1500 so the only way to match those frames is with the Q931 CRV number */
1501 list = g_list_first(tapinfo->strinfo_list);
1504 tmp_listinfo=list->data;
1505 if (tmp_listinfo->protocol == VOIP_H323){
1506 tmp_h323info = tmp_listinfo->prot_info;
1507 if ( ((tmp_h323info->q931_crv == q931_crv) || (tmp_h323info->q931_crv2 == q931_crv)) && (q931_crv!=-1)){
1509 comment = g_strdup("");
1511 /* if the frame number exists in graph, append to it*/
1512 if (!append_to_frame_graph(tapinfo, q931_frame_num, "", comment)) {
1513 /* if not exist, add to the graph */
1514 add_to_graph(tapinfo, pinfo, "", comment, tmp_listinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1515 ++(tmp_listinfo->npackets);
1516 /* increment the packets counter of all calls */
1517 ++(tapinfo->npackets);
1520 /* Add the H245 info if exists to the Graph */
1521 h245_add_to_graph(pinfo->fd->num);
1526 list = g_list_next (list);
1529 /* add staff to ACTRACE */
1530 } else if (actrace_frame_num == q931_frame_num) {
1532 gchar *comment = NULL;
1535 list = g_list_first(tapinfo->strinfo_list);
1538 tmp_listinfo=list->data;
1539 if ( tmp_listinfo->protocol == VOIP_AC_ISDN ){
1540 tmp_actrace_isdn_info = tmp_listinfo->prot_info;
1541 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
1542 if ( (tmp_actrace_isdn_info->crv == q931_crv) && (tmp_actrace_isdn_info->trunk == actrace_trunk) ) {
1543 strinfo = (voip_calls_info_t*)(list->data);
1547 list = g_list_next (list);
1550 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, g_strdup("PSTN"));
1552 /* if it is a new call, add it to the list */
1554 strinfo = g_malloc(sizeof(voip_calls_info_t));
1555 strinfo->call_active_state = VOIP_ACTIVE;
1556 strinfo->call_state = VOIP_CALL_SETUP;
1557 strinfo->from_identity=g_strdup(q931_calling_number);
1558 strinfo->to_identity=g_strdup(q931_called_number);
1559 COPY_ADDRESS(&(strinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
1560 strinfo->first_frame_num=pinfo->fd->num;
1561 strinfo->selected=FALSE;
1562 strinfo->start_sec=pinfo->fd->rel_ts.secs;
1563 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1564 strinfo->protocol=VOIP_AC_ISDN;
1565 strinfo->prot_info=g_malloc(sizeof(actrace_isdn_calls_info_t));
1566 tmp_actrace_isdn_info=strinfo->prot_info;
1567 tmp_actrace_isdn_info->crv=q931_crv;
1568 tmp_actrace_isdn_info->trunk=actrace_trunk;
1569 strinfo->npackets = 0;
1570 strinfo->call_num = tapinfo->ncalls++;
1571 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
1574 strinfo->stop_sec=pinfo->fd->rel_ts.secs;
1575 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1576 strinfo->last_frame_num=pinfo->fd->num;
1577 ++(strinfo->npackets);
1578 /* increment the packets counter of all calls */
1579 ++(tapinfo->npackets);
1581 switch(pi->message_type){
1583 comment = g_strdup_printf("AC_ISDN trunk:%u Calling: %s Called:%s", actrace_trunk, q931_calling_number, q931_called_number);
1584 strinfo->call_state=VOIP_CALL_SETUP;
1587 strinfo->call_state=VOIP_IN_CALL;
1589 case Q931_RELEASE_COMPLETE:
1591 case Q931_DISCONNECT:
1592 if (strinfo->call_state==VOIP_CALL_SETUP){
1593 if (ADDRESSES_EQUAL(&(strinfo->initial_speaker), actrace_direction?&pstn_add:&(pinfo->src) )){ /* forward direction */
1594 strinfo->call_state=VOIP_CANCELLED;
1597 strinfo->call_state=VOIP_REJECTED;
1598 tapinfo->rejected_calls++;
1600 } else if ( (strinfo->call_state!=VOIP_CANCELLED) && (strinfo->call_state!=VOIP_REJECTED) ){
1601 strinfo->call_state=VOIP_COMPLETED;
1602 tapinfo->completed_calls++;
1604 if (q931_cause_value != 0xFF){
1605 comment = g_strdup_printf("AC_ISDN trunk:%u Q931 Rel Cause (%i):%s", actrace_trunk, q931_cause_value, val_to_str(q931_cause_value, q931_cause_code_vals, "<unknown>"));
1606 } else { /* Cause not set */
1607 comment = g_strdup("AC_ISDN No Q931 Rel Cause");
1613 comment = g_strdup_printf("AC_ISDN trunk:%u", actrace_trunk );
1615 add_to_graph(tapinfo, pinfo, val_to_str(pi->message_type, q931_message_type_vals, "<unknown>") , comment, strinfo->call_num,
1616 actrace_direction?&pstn_add:&(pinfo->src),
1617 actrace_direction?&(pinfo->src):&pstn_add,
1621 g_free((char *)pstn_add.data);
1624 tapinfo->redraw = TRUE;
1626 return 1; /* refresh output */
1629 /****************************************************************************/
1630 static gboolean have_q931_tap_listener=FALSE;
1633 q931_calls_init_tap(void)
1635 GString *error_string;
1638 if(have_q931_tap_listener==FALSE)
1640 error_string = register_tap_listener("q931", &(the_tapinfo_struct.q931_dummy),
1642 voip_calls_dlg_reset,
1647 if (error_string != NULL) {
1648 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1650 g_string_free(error_string, TRUE);
1653 have_q931_tap_listener=TRUE;
1657 /****************************************************************************/
1660 remove_tap_listener_q931_calls(void)
1662 protect_thread_critical_region();
1663 remove_tap_listener(&(the_tapinfo_struct.q931_dummy));
1664 unprotect_thread_critical_region();
1666 have_q931_tap_listener=FALSE;
1669 /****************************************************************************/
1670 /****************************TAP for H323 ***********************************/
1671 /****************************************************************************/
1673 static void add_h245_Address(h323_calls_info_t *h323info, h245_address_t *h245_address)
1675 h323info->h245_list = g_list_append(h323info->h245_list, h245_address);
1678 /****************************************************************************/
1679 /* whenever a H225 packet is seen by the tap listener */
1681 H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H225info)
1683 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1684 voip_calls_info_t *tmp_listinfo;
1685 voip_calls_info_t *strinfo = NULL;
1686 h323_calls_info_t *tmp_h323info = NULL;
1690 address tmp_src, tmp_dst;
1691 h245_address_t *h245_add = NULL;
1693 const h225_packet_info *pi = H225info;
1695 /* if not guid and RAS and not LRQ, LCF or LRJ return because did not belong to a call */
1696 /* OR, if not guid and is H225 return because doesn't belong to a call */
1697 if ((memcmp(&pi->guid, &guid_allzero, GUID_LEN) == 0))
1698 if ( ((pi->msg_type == H225_RAS) && ((pi->msg_tag < 18) || (pi->msg_tag > 20))) || (pi->msg_type != H225_RAS) )
1701 /* if it is RAS LCF or LRJ*/
1702 if ( (pi->msg_type == H225_RAS) && ((pi->msg_tag == 19) || (pi->msg_tag == 20))) {
1703 /* if the LCF/LRJ doesn't match to a LRQ, just return */
1704 if (!pi->request_available) return 0;
1706 /* check whether we already have a call with this request SeqNum */
1707 list = g_list_first(tapinfo->strinfo_list);
1710 tmp_listinfo=list->data;
1711 g_assert(tmp_listinfo != NULL);
1712 if (tmp_listinfo->protocol == VOIP_H323){
1713 tmp_h323info = tmp_listinfo->prot_info;
1714 if (tmp_h323info->requestSeqNum == pi->requestSeqNum) {
1715 strinfo = (voip_calls_info_t*)(list->data);
1719 list = g_list_next (list);
1722 /* check whether we already have a call with this guid in the list */
1723 list = g_list_first(tapinfo->strinfo_list);
1726 tmp_listinfo=list->data;
1727 if (tmp_listinfo->protocol == VOIP_H323){
1728 tmp_h323info = tmp_listinfo->prot_info;
1729 g_assert(tmp_h323info != NULL);
1730 if ( (memcmp(tmp_h323info->guid, &guid_allzero, GUID_LEN) != 0) && (memcmp(tmp_h323info->guid, &pi->guid,GUID_LEN)==0) ){
1731 strinfo = (voip_calls_info_t*)(list->data);
1735 list = g_list_next (list);
1739 h225_cstype = pi->cs_type;
1740 h225_is_faststart = pi->is_faststart;
1742 /* not in the list? then create a new entry */
1743 if ((strinfo==NULL)){
1744 strinfo = g_malloc(sizeof(voip_calls_info_t));
1745 strinfo->call_active_state = VOIP_ACTIVE;
1746 strinfo->call_state = VOIP_UNKNOWN;
1747 strinfo->from_identity=g_strdup("");
1748 strinfo->to_identity=g_strdup("");
1749 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
1750 strinfo->selected=FALSE;
1751 strinfo->first_frame_num=pinfo->fd->num;
1752 strinfo->start_sec=pinfo->fd->rel_ts.secs;
1753 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1754 strinfo->protocol=VOIP_H323;
1755 strinfo->prot_info=g_malloc(sizeof(h323_calls_info_t));
1756 tmp_h323info = strinfo->prot_info;
1757 g_assert(tmp_h323info != NULL);
1758 tmp_h323info->guid = g_memdup(&pi->guid, sizeof pi->guid);
1759 tmp_h323info->h225SetupAddr.type = AT_NONE;
1760 tmp_h323info->h225SetupAddr.len = 0;
1761 tmp_h323info->h245_list = NULL;
1762 tmp_h323info->is_faststart_Setup = FALSE;
1763 tmp_h323info->is_faststart_Proc = FALSE;
1764 tmp_h323info->is_h245Tunneling = FALSE;
1765 tmp_h323info->is_h245 = FALSE;
1766 tmp_h323info->q931_crv = -1;
1767 tmp_h323info->q931_crv2 = -1;
1768 tmp_h323info->requestSeqNum = 0;
1769 strinfo->call_num = tapinfo->ncalls++;
1770 strinfo->npackets = 0;
1772 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
1777 h225_frame_num = pinfo->fd->num;
1778 h225_call_num = strinfo->call_num;
1780 /* let's analyze the call state */
1782 COPY_ADDRESS(&(tmp_src),&(pinfo->src));
1783 COPY_ADDRESS(&(tmp_dst),&(pinfo->dst));
1785 strinfo->stop_sec=pinfo->fd->rel_ts.secs;
1786 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1787 strinfo->last_frame_num=pinfo->fd->num;
1788 ++(strinfo->npackets);
1789 /* increment the packets counter of all calls */
1790 ++(tapinfo->npackets);
1793 /* XXX: it is supposed to be initialized isn't it? */
1794 g_assert(tmp_h323info != NULL);
1796 /* change the status */
1797 if (pi->msg_type == H225_CS){
1799 /* this is still IPv4 only, because the dissector is */
1800 if (pi->is_h245 == TRUE){
1801 h245_add = g_malloc(sizeof (h245_address_t));
1802 h245_add->h245_address.type=AT_IPv4;
1803 h245_add->h245_address.len=4;
1804 h245_add->h245_address.data = g_malloc(sizeof(pi->h245_address));
1805 g_memmove((void *)(h245_add->h245_address.data), &(pi->h245_address), 4);
1806 h245_add->h245_port = pi->h245_port;
1807 add_h245_Address(tmp_h323info, h245_add);
1810 if (pi->cs_type != H225_RELEASE_COMPLET) tmp_h323info->is_h245Tunneling = pi->is_h245Tunneling;
1812 frame_label = g_strdup(pi->frame_label);
1814 switch(pi->cs_type){
1816 tmp_h323info->is_faststart_Setup = pi->is_faststart;
1818 /* Set the Setup address if it was not set */
1819 if (tmp_h323info->h225SetupAddr.type == AT_NONE)
1820 COPY_ADDRESS(&(tmp_h323info->h225SetupAddr), &(pinfo->src));
1821 strinfo->call_state=VOIP_CALL_SETUP;
1822 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1823 (pi->is_faststart==TRUE?"on":"off"));
1826 strinfo->call_state=VOIP_IN_CALL;
1827 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1828 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1829 (pi->is_faststart==TRUE?"on":"off"));
1831 case H225_RELEASE_COMPLET:
1832 COPY_ADDRESS(&tmp_src,&(pinfo->src));
1833 if (strinfo->call_state==VOIP_CALL_SETUP){
1834 if (ADDRESSES_EQUAL(&(tmp_h323info->h225SetupAddr),&tmp_src)){ /* forward direction */
1835 strinfo->call_state=VOIP_CANCELLED;
1838 strinfo->call_state=VOIP_REJECTED;
1839 tapinfo->rejected_calls++;
1842 strinfo->call_state=VOIP_COMPLETED;
1843 tapinfo->completed_calls++;
1845 comment = g_strdup("H225 No Q931 Rel Cause");
1849 case H225_CALL_PROCEDING:
1850 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1851 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1852 (pi->is_faststart==TRUE?"on":"off"));
1855 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1856 (pi->is_faststart==TRUE?"on":"off"));
1860 else if (pi->msg_type == H225_RAS){
1861 switch(pi->msg_tag){
1863 if (!pi->is_duplicate){
1864 g_free(strinfo->to_identity);
1865 strinfo->to_identity=g_strdup(pi->dialedDigits);
1866 tmp_h323info->requestSeqNum = pi->requestSeqNum;
1869 if (strlen(pi->dialedDigits))
1870 comment = g_strdup_printf("H225 RAS dialedDigits: %s", pi->dialedDigits);
1872 comment = g_strdup("H225 RAS");
1875 comment = g_strdup("H225 RAS");
1877 frame_label = g_strdup_printf("%s", val_to_str(pi->msg_tag, RasMessage_vals, "<unknown>"));
1879 frame_label = g_strdup("H225: Unknown");
1880 comment = g_strdup("");
1883 /* add to graph analysis */
1885 /* if the frame number exists in graph, append to it*/
1886 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, comment)) {
1887 /* if not exist, add to the graph */
1888 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1889 g_free((void *)tmp_src.data);
1890 g_free((void *)tmp_dst.data);
1893 /* Add the H245 info if exists to the Graph */
1894 h245_add_to_graph(pinfo->fd->num);
1896 g_free(frame_label);
1901 tapinfo->redraw = TRUE;
1903 return 1; /* refresh output */
1907 /****************************************************************************/
1909 /****************************************************************************/
1910 static gboolean have_H225_tap_listener=FALSE;
1911 /****************************************************************************/
1913 h225_calls_init_tap(void)
1915 GString *error_string;
1917 if(have_H225_tap_listener==FALSE)
1919 /* don't register tap listener, if we have it already */
1920 error_string = register_tap_listener("h225", &(the_tapinfo_struct.h225_dummy), NULL,
1921 voip_calls_dlg_reset,
1926 if (error_string != NULL) {
1927 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1929 g_string_free(error_string, TRUE);
1932 have_H225_tap_listener=TRUE;
1936 /****************************************************************************/
1938 remove_tap_listener_h225_calls(void)
1940 protect_thread_critical_region();
1941 remove_tap_listener(&(the_tapinfo_struct.h225_dummy));
1942 unprotect_thread_critical_region();
1944 have_H225_tap_listener=FALSE;
1947 /* Add the h245 label info to the graph */
1948 void h245_add_to_graph(guint32 new_frame_num)
1952 if (new_frame_num != h245_labels.frame_num) return;
1954 for (n=0; n<h245_labels.labels_count; n++) {
1955 append_to_frame_graph(&the_tapinfo_struct, new_frame_num, h245_labels.labels[n].frame_label, h245_labels.labels[n].comment);
1956 g_free(h245_labels.labels[n].frame_label);
1957 h245_labels.labels[n].frame_label = NULL;
1958 g_free(h245_labels.labels[n].comment);
1959 h245_labels.labels[n].comment = NULL;
1961 h245_labels.frame_num = 0;
1962 h245_labels.labels_count = 0;
1965 /* free the h245_labels if the frame number is different */
1966 static void h245_free_labels(guint32 new_frame_num)
1970 if (new_frame_num == h245_labels.frame_num) return;
1972 for (n=0; n<h245_labels.labels_count; n++) {
1973 g_free(h245_labels.labels[n].frame_label);
1974 h245_labels.labels[n].frame_label = NULL;
1975 g_free(h245_labels.labels[n].comment);
1976 h245_labels.labels[n].comment = NULL;
1978 h245_labels.frame_num = 0;
1979 h245_labels.labels_count = 0;
1982 /* add the frame_label and comment to h245_labels and free the actual one if it is different frame num */
1983 static void h245_add_label(guint32 new_frame_num, gchar *frame_label, gchar *comment)
1985 h245_free_labels(new_frame_num);
1987 h245_labels.frame_num = new_frame_num;
1988 h245_labels.labels[h245_labels.labels_count].frame_label = g_strdup(frame_label);
1989 h245_labels.labels[h245_labels.labels_count].comment = g_strdup(comment);
1991 if (h245_labels.labels_count < (H245_MAX-1))
1992 h245_labels.labels_count++;
1996 /****************************************************************************/
1997 /* whenever a H245dg packet is seen by the tap listener (when H245 tunneling is ON) */
1999 H245dgcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H245info)
2001 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2002 voip_calls_info_t *tmp_listinfo;
2003 voip_calls_info_t *strinfo = NULL;
2004 h323_calls_info_t *tmp_h323info;
2009 address tmp_src, tmp_dst;
2010 h245_address_t *h245_add = NULL;
2012 const h245_packet_info *pi = H245info;
2014 /* check if Tunneling is OFF and we have a call with this H245 add */
2015 list = g_list_first(tapinfo->strinfo_list);
2018 tmp_listinfo=list->data;
2019 if (tmp_listinfo->protocol == VOIP_H323){
2020 tmp_h323info = tmp_listinfo->prot_info;
2022 COPY_ADDRESS(&(tmp_src), &(pinfo->src));
2023 COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
2024 list2 = g_list_first(tmp_h323info->h245_list);
2027 h245_add=list2->data;
2028 if ( (ADDRESSES_EQUAL(&(h245_add->h245_address),&tmp_src) && (h245_add->h245_port == pinfo->srcport))
2029 || (ADDRESSES_EQUAL(&(h245_add->h245_address),&tmp_dst) && (h245_add->h245_port == pinfo->destport)) ){
2030 strinfo = (voip_calls_info_t*)(list->data);
2032 ++(strinfo->npackets);
2033 /* increment the packets counter of all calls */
2034 ++(tapinfo->npackets);
2038 list2 = g_list_next(list2);
2040 if (strinfo!=NULL) break;
2041 g_free((void *)tmp_src.data);
2042 g_free((void *)tmp_dst.data);
2044 list = g_list_next(list);
2047 /* Tunnel is OFF, and we matched the h245 add so we add it to graph */
2049 ++(strinfo->npackets);
2050 /* increment the packets counter of all calls */
2051 ++(tapinfo->npackets);
2052 frame_label = g_strdup(pi->frame_label);
2053 comment = g_strdup(pi->comment);
2054 /* if the frame number exists in graph, append to it*/
2055 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, frame_label, comment)) {
2056 /* if not exist, add to the graph */
2057 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2059 g_free(frame_label);
2062 /* Tunnel is ON, so we save the label info to use it into h225 or q931 tap. OR may be
2063 tunnel OFF but we did not matched the h245 add, in this case nobady will set this label
2064 since the frame_num will not match */
2066 h245_add_label(pinfo->fd->num, (gchar *) pi->frame_label, (gchar *) pi->comment);
2069 tapinfo->redraw = TRUE;
2071 return 1; /* refresh output */
2075 /****************************************************************************/
2077 /****************************************************************************/
2078 static gboolean have_H245dg_tap_listener=FALSE;
2079 /****************************************************************************/
2081 h245dg_calls_init_tap(void)
2083 GString *error_string;
2085 if(have_H245dg_tap_listener==FALSE)
2087 /* don't register tap listener, if we have it already */
2088 error_string = register_tap_listener("h245dg", &(the_tapinfo_struct.h245dg_dummy), NULL,
2089 voip_calls_dlg_reset,
2094 if (error_string != NULL) {
2095 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2097 g_string_free(error_string, TRUE);
2100 have_H245dg_tap_listener=TRUE;
2104 /****************************************************************************/
2106 remove_tap_listener_h245dg_calls(void)
2108 protect_thread_critical_region();
2109 remove_tap_listener(&(the_tapinfo_struct.h245dg_dummy));
2110 unprotect_thread_critical_region();
2112 have_H245dg_tap_listener=FALSE;
2115 /****************************************************************************/
2116 /****************************TAP for SDP PROTOCOL ***************************/
2117 /****************************************************************************/
2118 /* whenever a SDP packet is seen by the tap listener */
2120 SDPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SDPinfo)
2122 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2123 const sdp_packet_info *pi = SDPinfo;
2125 /* There are protocols like MGCP/SIP where the SDP is called before the tap for the
2126 MGCP/SIP packet, in those cases we assign the SPD summary to global lastSDPsummary
2129 g_free(sdp_summary);
2130 sdp_frame_num = pinfo->fd->num;
2131 /* Append to graph the SDP summary if the packet exists */
2132 sdp_summary = g_strdup_printf("SDP (%s)", pi->summary_str);
2133 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2135 tapinfo->redraw = TRUE;
2137 return 1; /* refresh output */
2141 /****************************************************************************/
2143 /****************************************************************************/
2144 static gboolean have_sdp_tap_listener=FALSE;
2145 /****************************************************************************/
2147 sdp_calls_init_tap(void)
2149 GString *error_string;
2151 if(have_sdp_tap_listener==FALSE)
2153 /* don't register tap listener, if we have it already */
2154 error_string = register_tap_listener("sdp", &(the_tapinfo_struct.sdp_dummy), NULL,
2155 voip_calls_dlg_reset,
2160 if (error_string != NULL) {
2161 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2163 g_string_free(error_string, TRUE);
2166 have_sdp_tap_listener=TRUE;
2170 /****************************************************************************/
2172 remove_tap_listener_sdp_calls(void)
2174 protect_thread_critical_region();
2175 remove_tap_listener(&(the_tapinfo_struct.sdp_dummy));
2176 unprotect_thread_critical_region();
2178 have_sdp_tap_listener=FALSE;
2183 /****************************************************************************/
2184 /* ***************************TAP for MGCP **********************************/
2185 /****************************************************************************/
2188 This function will look for a signal/event in the SignalReq/ObsEvent string
2189 and return true if it is found
2191 static gboolean isSignal(const gchar *signal, const gchar *signalStr)
2194 gchar **resultArray;
2196 /* if there is no signalStr, just return false */
2197 if (signalStr == NULL) return FALSE;
2199 /* if are both "blank" return true */
2200 if ( (*signal == '\0') && (*signalStr == '\0') ) return TRUE;
2202 /* look for signal in signalSre */
2203 resultArray = g_strsplit(signalStr, ",", 10);
2205 for (i = 0; resultArray[i]; i++) {
2206 g_strstrip(resultArray[i]);
2207 if (strcmp(resultArray[i], signal) == 0) return TRUE;
2210 g_strfreev(resultArray);
2216 This function will get the Caller ID info and replace the current string
2217 This is how it looks the caller Id: rg, ci(02/16/08/29, "3035550002","Ale Sipura 2")
2219 static void mgcpCallerID(gchar *signalStr, gchar **callerId)
2223 /* if there is no signalStr, just return false */
2224 if (signalStr == NULL) return;
2226 arrayStr = g_strsplit(signalStr, "\"", 10);
2228 if (arrayStr[0] == NULL) return;
2230 /* look for the ci signal */
2231 if (strstr(arrayStr[0], "ci(") && (arrayStr[1] != NULL) ) {
2232 /* free the previous "From" field of the call, and assign the new */
2234 *callerId = g_strdup(arrayStr[1]);
2236 g_strfreev(arrayStr);
2243 This function will get the Dialed Digits and replace the current string
2244 This is how it looks the dialed digits 5,5,5,0,0,0,2,#,*
2246 static void mgcpDialedDigits(gchar *signalStr, gchar **dialedDigits)
2249 gchar resultStr[50];
2252 /* if there is no signalStr, just return false */
2253 if (signalStr == NULL) return;
2255 tmpStr = g_strdup(signalStr);
2257 for ( i = 0 ; tmpStr[i] ; i++) {
2258 switch (tmpStr[i]) {
2259 case '0' : case '1' : case '2' : case '3' : case '4' :
2260 case '5' : case '6' : case '7' : case '8' : case '9' :
2261 case '#' : case '*' :
2269 for (i = 0, j = 0; tmpStr[i] && i<50; i++) {
2270 if (tmpStr[i] != '?')
2271 resultStr[j++] = tmpStr[i];
2273 resultStr[j] = '\0';
2275 if (*resultStr == '\0') return;
2277 g_free(*dialedDigits);
2278 *dialedDigits = g_strdup(resultStr);
2286 /****************************************************************************/
2287 /* whenever a MGCP packet is seen by the tap listener */
2289 MGCPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *MGCPinfo)
2291 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2293 voip_calls_info_t *tmp_listinfo;
2294 voip_calls_info_t *strinfo = NULL;
2295 mgcp_calls_info_t *tmp_mgcpinfo = NULL;
2298 gchar *frame_label = NULL;
2299 gchar *comment = NULL;
2300 graph_analysis_item_t *gai;
2301 gboolean new = FALSE;
2302 gboolean fromEndpoint = FALSE; /* true for calls originated in Endpoints, false for calls from MGC */
2305 const mgcp_info_t *pi = MGCPinfo;
2308 if ((pi->mgcp_type == MGCP_REQUEST) && !pi->is_duplicate ){
2309 /* check whether we already have a call with this Endpoint and it is active*/
2310 list = g_list_first(tapinfo->strinfo_list);
2313 tmp_listinfo=list->data;
2314 if ((tmp_listinfo->protocol == VOIP_MGCP) && (tmp_listinfo->call_active_state == VOIP_ACTIVE)){
2315 tmp_mgcpinfo = tmp_listinfo->prot_info;
2316 if (pi->endpointId != NULL){
2317 if (g_strcasecmp(tmp_mgcpinfo->endpointId,pi->endpointId) == 0){
2319 check first if it is an ended call. We can still match packets to this Endpoint 2 seconds
2320 after the call has been released
2322 diff_time = nstime_to_sec(&pinfo->fd->rel_ts) - tmp_listinfo->stop_sec - (double)tmp_listinfo->stop_usec/1000000;
2323 if ( ((tmp_listinfo->call_state == VOIP_CANCELLED) ||
2324 (tmp_listinfo->call_state == VOIP_COMPLETED) ||
2325 (tmp_listinfo->call_state == VOIP_REJECTED)) &&
2328 tmp_listinfo->call_active_state = VOIP_INACTIVE;
2330 strinfo = (voip_calls_info_t*)(list->data);
2336 list = g_list_next (list);
2339 /* there is no call with this Endpoint, lets see if this a new call or not */
2340 if (strinfo == NULL){
2341 if ( (strcmp(pi->code, "NTFY") == 0) && isSignal("hd", pi->observedEvents) ){ /* off hook transition */
2342 /* this is a new call from the Endpoint */
2343 fromEndpoint = TRUE;
2345 } else if (strcmp(pi->code, "CRCX") == 0){
2346 /* this is a new call from the MGC */
2347 fromEndpoint = FALSE;
2352 } else if ( ((pi->mgcp_type == MGCP_RESPONSE) && pi->request_available) ||
2353 ((pi->mgcp_type == MGCP_REQUEST) && pi->is_duplicate) ) {
2354 /* if it is a response OR if it is a duplicated Request, lets look in the Graph to see
2355 if there is a request that matches */
2356 listGraph = g_list_first(tapinfo->graph_analysis->list);
2359 gai = listGraph->data;
2360 if (gai->frame_num == pi->req_num){
2361 /* there is a request that match, so look the associated call with this call_num */
2362 list = g_list_first(tapinfo->strinfo_list);
2365 tmp_listinfo=list->data;
2366 if (tmp_listinfo->protocol == VOIP_MGCP){
2367 if (tmp_listinfo->call_num == gai->conv_num){
2368 tmp_mgcpinfo = tmp_listinfo->prot_info;
2369 strinfo = (voip_calls_info_t*)(list->data);
2373 list = g_list_next (list);
2375 if (strinfo != NULL) break;
2377 listGraph = g_list_next(listGraph);
2379 /* if there is not a matching request, just return */
2380 if (strinfo == NULL) return 0;
2383 /* not in the list? then create a new entry */
2385 strinfo = g_malloc(sizeof(voip_calls_info_t));
2386 strinfo->call_active_state = VOIP_ACTIVE;
2387 strinfo->call_state = VOIP_CALL_SETUP;
2389 strinfo->from_identity=g_strdup(pi->endpointId);
2390 strinfo->to_identity=g_strdup("");
2392 strinfo->from_identity=g_strdup("");
2393 strinfo->to_identity=g_strdup(pi->endpointId);
2395 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
2396 strinfo->first_frame_num=pinfo->fd->num;
2397 strinfo->selected=FALSE;
2398 strinfo->start_sec=pinfo->fd->rel_ts.secs;
2399 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
2400 strinfo->protocol=VOIP_MGCP;
2401 strinfo->prot_info=g_malloc(sizeof(mgcp_calls_info_t));
2402 tmp_mgcpinfo=strinfo->prot_info;
2403 tmp_mgcpinfo->endpointId = g_strdup(pi->endpointId);
2404 tmp_mgcpinfo->fromEndpoint = fromEndpoint;
2405 strinfo->npackets = 0;
2406 strinfo->call_num = tapinfo->ncalls++;
2407 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
2410 g_assert(tmp_mgcpinfo != NULL);
2412 /* change call state and add to graph */
2413 switch (pi->mgcp_type)
2416 if ( (strcmp(pi->code, "NTFY") == 0) && (pi->observedEvents != NULL) ){
2417 frame_label = g_strdup_printf("%s ObsEvt:%s",pi->code, pi->observedEvents);
2419 if (tmp_mgcpinfo->fromEndpoint){
2420 /* use the Dialed digits to fill the "To" for the call, but use the first NTFY */
2421 if (strinfo->to_identity[0] == '\0') mgcpDialedDigits(pi->observedEvents, &(strinfo->to_identity));
2423 /* from MGC and the user picked up, the call is connected */
2424 } else if (isSignal("hd", pi->observedEvents))
2425 strinfo->call_state=VOIP_IN_CALL;
2427 /* hung up signal */
2428 if (isSignal("hu", pi->observedEvents)) {
2429 if ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state == VOIP_RINGING)){
2430 strinfo->call_state = VOIP_CANCELLED;
2432 strinfo->call_state = VOIP_COMPLETED;
2436 } else if (strcmp(pi->code, "RQNT") == 0) {
2437 /* for calls from Endpoint: if there is a "no signal" RQNT and the call was RINGING, we assume this is the CONNECT */
2438 if ( tmp_mgcpinfo->fromEndpoint && isSignal("", pi->signalReq) && (strinfo->call_state == VOIP_RINGING) ) {
2439 strinfo->call_state = VOIP_IN_CALL;
2442 /* if there is ringback or ring tone, change state to ringing */
2443 if ( isSignal("rg", pi->signalReq) || isSignal("rt", pi->signalReq) ) {
2444 strinfo->call_state = VOIP_RINGING;
2447 /* if there is a Busy or ReorderTone, and the call was Ringing or Setup the call is Rejected */
2448 if ( (isSignal("ro", pi->signalReq) || isSignal("bz", pi->signalReq)) && ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state = VOIP_RINGING)) ) {
2449 strinfo->call_state = VOIP_REJECTED;
2452 if (pi->signalReq != NULL)
2453 frame_label = g_strdup_printf("%s%sSigReq:%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"", pi->signalReq);
2455 frame_label = g_strdup_printf("%s%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"");
2457 /* use the CallerID info to fill the "From" for the call */
2458 if (!tmp_mgcpinfo->fromEndpoint) mgcpCallerID(pi->signalReq, &(strinfo->from_identity));
2460 } else if (strcmp(pi->code, "DLCX") == 0) {
2462 if there is a DLCX in a call To an Endpoint and the call was not connected, we use
2463 the DLCX as the end of the call
2465 if (!tmp_mgcpinfo->fromEndpoint){
2466 if ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state == VOIP_RINGING)){
2467 strinfo->call_state = VOIP_CANCELLED;
2472 if (frame_label == NULL) frame_label = g_strdup_printf("%s",pi->code);
2475 frame_label = g_strdup_printf("%u (%s)",pi->rspcode, pi->code);
2478 /* XXX what to do? */
2483 comment = g_strdup_printf("MGCP %s %s%s", tmp_mgcpinfo->endpointId, (pi->mgcp_type == MGCP_REQUEST)?"Request":"Response", pi->is_duplicate?" Duplicate":"");
2485 strinfo->stop_sec=pinfo->fd->rel_ts.secs;
2486 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
2487 strinfo->last_frame_num=pinfo->fd->num;
2488 ++(strinfo->npackets);
2489 /* increment the packets counter of all calls */
2490 ++(tapinfo->npackets);
2492 /* add to the graph */
2493 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2495 g_free(frame_label);
2497 /* add SDP info if apply */
2498 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
2499 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2500 g_free(sdp_summary);
2504 tapinfo->redraw = TRUE;
2506 return 1; /* refresh output */
2510 /****************************************************************************/
2512 /****************************************************************************/
2513 static gboolean have_MGCP_tap_listener=FALSE;
2514 /****************************************************************************/
2516 mgcp_calls_init_tap(void)
2518 GString *error_string;
2520 if(have_MGCP_tap_listener==FALSE)
2522 /* don't register tap listener, if we have it already */
2523 /* we send an empty filter, to force a non null "tree" in the mgcp dissector */
2524 error_string = register_tap_listener("mgcp", &(the_tapinfo_struct.mgcp_dummy), strdup(""),
2525 voip_calls_dlg_reset,
2529 if (error_string != NULL) {
2530 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2532 g_string_free(error_string, TRUE);
2535 have_MGCP_tap_listener=TRUE;
2539 /****************************************************************************/
2541 remove_tap_listener_mgcp_calls(void)
2543 protect_thread_critical_region();
2544 remove_tap_listener(&(the_tapinfo_struct.mgcp_dummy));
2545 unprotect_thread_critical_region();
2547 have_MGCP_tap_listener=FALSE;
2551 /****************************************************************************/
2552 /****************************TAP for ACTRACE (AudioCodes trace)**************/
2553 /****************************************************************************/
2555 /* whenever a ACTRACE packet is seen by the tap listener */
2557 ACTRACEcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *ACTRACEinfo)
2559 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2560 const actrace_info_t *pi = ACTRACEinfo;
2562 actrace_cas_calls_info_t *tmp_actrace_cas_info;
2563 voip_calls_info_t *tmp_listinfo;
2564 voip_calls_info_t *strinfo = NULL;
2567 actrace_frame_num = pinfo->fd->num;
2568 actrace_trunk = pi->trunk;
2569 actrace_direction = pi->direction;
2571 if (pi->type == 1){ /* is CAS protocol */
2573 gchar *comment = NULL;
2576 list = g_list_first(tapinfo->strinfo_list);
2579 tmp_listinfo=list->data;
2580 if ( tmp_listinfo->protocol == VOIP_AC_CAS ){
2581 tmp_actrace_cas_info = tmp_listinfo->prot_info;
2582 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
2583 if ( (tmp_actrace_cas_info->bchannel == pi->cas_bchannel) && (tmp_actrace_cas_info->trunk == actrace_trunk) ) {
2584 strinfo = (voip_calls_info_t*)(list->data);
2588 list = g_list_next (list);
2591 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, g_strdup("PSTN"));
2593 /* if it is a new call, add it to the list */
2595 strinfo = g_malloc(sizeof(voip_calls_info_t));
2596 strinfo->call_active_state = VOIP_ACTIVE;
2597 strinfo->call_state = VOIP_CALL_SETUP;
2598 strinfo->from_identity=g_strdup("N/A");
2599 strinfo->to_identity=g_strdup("N/A");
2600 COPY_ADDRESS(&(strinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
2601 strinfo->first_frame_num=pinfo->fd->num;
2602 strinfo->selected=FALSE;
2603 strinfo->start_sec=pinfo->fd->rel_ts.secs;
2604 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
2605 strinfo->protocol=VOIP_AC_CAS;
2606 strinfo->prot_info=g_malloc(sizeof(actrace_cas_calls_info_t));
2607 tmp_actrace_cas_info=strinfo->prot_info;
2608 tmp_actrace_cas_info->bchannel=pi->cas_bchannel;
2609 tmp_actrace_cas_info->trunk=actrace_trunk;
2610 strinfo->npackets = 0;
2611 strinfo->call_num = tapinfo->ncalls++;
2612 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
2615 strinfo->stop_sec=pinfo->fd->rel_ts.secs;
2616 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
2617 strinfo->last_frame_num=pinfo->fd->num;
2618 ++(strinfo->npackets);
2619 /* increment the packets counter of all calls */
2620 ++(tapinfo->npackets);
2623 comment = g_strdup_printf("AC_CAS trunk:%u", actrace_trunk );
2625 add_to_graph(tapinfo, pinfo, pi->cas_frame_label , comment, strinfo->call_num,
2626 actrace_direction?&pstn_add:&(pinfo->src),
2627 actrace_direction?&(pinfo->src):&pstn_add,
2631 g_free((char *)pstn_add.data);
2634 tapinfo->redraw = TRUE;
2636 return 1; /* refresh output */
2640 /****************************************************************************/
2642 /****************************************************************************/
2643 static gboolean have_actrace_tap_listener=FALSE;
2644 /****************************************************************************/
2646 actrace_calls_init_tap(void)
2648 GString *error_string;
2650 if(have_actrace_tap_listener==FALSE)
2652 /* don't register tap listener, if we have it already */
2653 error_string = register_tap_listener("actrace", &(the_tapinfo_struct.actrace_dummy), NULL,
2654 voip_calls_dlg_reset,
2655 ACTRACEcalls_packet,
2659 if (error_string != NULL) {
2660 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2662 g_string_free(error_string, TRUE);
2665 have_actrace_tap_listener=TRUE;
2669 /****************************************************************************/
2671 remove_tap_listener_actrace_calls(void)
2673 protect_thread_critical_region();
2674 remove_tap_listener(&(the_tapinfo_struct.actrace_dummy));
2675 unprotect_thread_critical_region();
2677 have_actrace_tap_listener=FALSE;
2680 /****************************************************************************/
2681 /* ***************************TAP for OTHER PROTOCOL **********************************/
2682 /****************************************************************************/
2684 /****************************************************************************/
2685 /* whenever a prot_ packet is seen by the tap listener */
2688 prot_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info _U_)
2690 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2692 strinfo->stop_sec=pinfo->fd->rel_secs;
2693 strinfo->stop_usec=pinfo->fd->rel_usecs;
2694 strinfo->last_frame_num=pinfo->fd->num;
2695 ++(strinfo->npackets);
2696 ++(tapinfo->npackets);
2699 tapinfo->redraw = TRUE;
2704 /****************************************************************************/
2706 static gboolean have_prot__tap_listener=FALSE;
2709 prot_calls_init_tap(void)
2711 GString *error_string;
2713 if(have_prot__tap_listener==FALSE)
2715 error_string = register_tap_listener("prot_", &(the_tapinfo_struct.prot__dummy),
2717 voip_calls_dlg_reset,
2722 if (error_string != NULL) {
2723 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2725 g_string_free(error_string, TRUE);
2728 have_prot__tap_listener=TRUE;
2732 /****************************************************************************/
2735 remove_tap_listener_prot__calls(void)
2737 protect_thread_critical_region();
2738 remove_tap_listener(&(the_tapinfo_struct.prot__dummy));
2739 unprotect_thread_critical_region();
2741 have_prot__tap_listener=FALSE;