2 * VoIP calls summary addition for Wireshark
6 * Copyright 2004, Ericsson, Spain
7 * By Francisco Alcoba <francisco.alcoba@ericsson.com>
9 * based on h323_calls.c
10 * Copyright 2004, Iskratel, Ltd, Kranj
11 * By Miha Jemec <m.jemec@iskratel.si>
13 * H323, RTP, RTP Event, MGCP, AudioCodes (ISDN PRI and CAS), T38 and Graph Support
14 * By Alejandro Vaquero, alejandro.vaquero@verso.com
15 * Copyright 2005, Verso Technologies Inc.
17 * Wireshark - Network traffic analyzer
18 * By Gerald Combs <gerald@wireshark.org>
19 * Copyright 1998 Gerald Combs
21 * This program is free software; you can redistribute it and/or
22 * modify it under the terms of the GNU General Public License
23 * as published by the Free Software Foundation; either version 2
24 * of the License, or (at your option) any later version.
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
42 #include "graph_analysis.h"
43 #include "voip_calls.h"
44 #include "voip_calls_dlg.h"
50 #include <epan/tap-voip.h>
51 #include <epan/dissectors/packet-sip.h>
52 #include <epan/dissectors/packet-mtp3.h>
53 #include <epan/dissectors/packet-isup.h>
54 #include <epan/dissectors/packet-h225.h>
55 #include <epan/dissectors/packet-h245.h>
56 #include <epan/dissectors/packet-q931.h>
57 #include <epan/dissectors/packet-sdp.h>
58 #include <epan/dissectors/packet-mgcp.h>
59 #include <epan/dissectors/packet-actrace.h>
60 #include <epan/dissectors/packet-rtp.h>
61 #include <epan/dissectors/packet-rtp-events.h>
62 #include <epan/dissectors/packet-t38.h>
63 #include <epan/dissectors/packet-t30.h>
64 #include <epan/dissectors/packet-h248.h>
65 #include <epan/dissectors/packet-sccp.h>
66 #include <plugins/unistim/packet-unistim.h>
67 #include <epan/conversation.h>
68 #include <epan/rtp_pt.h>
69 #include <epan/ws_strsplit.h>
71 #include "alert_box.h"
72 #include "simple_dialog.h"
74 #ifdef HAVE_LIBPORTAUDIO
75 #if GTK_MAJOR_VERSION >= 2
76 #include "rtp_player.h"
77 #endif /* GTK_MAJOR_VERSION >= 2 */
78 #endif /* HAVE_LIBPORTAUDIO */
80 #ifdef NEED_G_ASCII_STRCASECMP_H
81 #include "../epan/g_ascii_strcasecmp.h"
84 const char *voip_call_state_name[8]={
95 /* defines whether we can consider the call active */
96 const char *voip_protocol_name[]={
122 graph_str labels[H245_MAX];
125 static h245_labels_t h245_labels;
127 /****************************************************************************/
128 /* the one and only global voip_calls_tapinfo_t structure */
129 static voip_calls_tapinfo_t the_tapinfo_struct =
130 {0, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
132 /* the one and only global voip_rtp_tapinfo_t structure */
133 static voip_rtp_tapinfo_t the_tapinfo_rtp_struct =
136 /****************************************************************************/
137 /* when there is a [re]reading of packet's */
138 void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
140 voip_calls_info_t *strinfo;
141 graph_analysis_item_t *graph_item;
144 #ifdef HAVE_LIBPORTAUDIO
145 #if GTK_MAJOR_VERSION >= 2
146 /* reset the RTP player */
151 /* free the data items first */
152 list = g_list_first(tapinfo->strinfo_list);
155 strinfo = list->data;
156 if (strinfo->call_id)
157 g_free(strinfo->call_id);
158 g_free(strinfo->from_identity);
159 g_free(strinfo->to_identity);
160 g_free((void *)(strinfo->initial_speaker.data));
161 if (strinfo->protocol_name)
162 g_free(strinfo->protocol_name);
163 if (strinfo->call_comment)
164 g_free(strinfo->call_comment);
166 if (strinfo->free_prot_info && strinfo->prot_info)
167 strinfo->free_prot_info(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 strinfo->is_srtp = pi->info_is_srtp;
539 /* if it is dynamic payload, let use the conv data to see if it is defined */
540 if ( (strinfo->pt>95) && (strinfo->pt<128) ) {
541 /* Use existing packet info if available */
542 p_conv_data = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name("rtp"));
544 strinfo->pt_str = g_strdup(g_hash_table_lookup(p_conv_data->rtp_dyn_payload, &strinfo->pt));
546 if (!strinfo->pt_str) strinfo->pt_str = g_strdup(val_to_str(strinfo->pt, rtp_payload_type_short_vals, "%u"));
547 strinfo->npackets = 0;
548 strinfo->first_frame_num = pinfo->fd->num;
549 strinfo->start_rel_sec = (guint32) (pinfo->fd->rel_ts.secs);
550 strinfo->start_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
551 strinfo->setup_frame_number = pi->info_setup_frame_num;
552 strinfo->rtp_event = -1;
553 tapinfo->list = g_list_append(tapinfo->list, strinfo);
557 /* Add the info to the existing RTP stream */
559 strinfo->stop_rel_sec = (guint32) (pinfo->fd->rel_ts.secs);
560 strinfo->stop_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
562 /* process RTP Event */
563 if (rtp_evt_frame_num == pinfo->fd->num) {
564 strinfo->rtp_event = rtp_evt;
565 if (rtp_evt_end == TRUE) {
566 strinfo->end_stream = TRUE;
571 the_tapinfo_struct.redraw = TRUE;
576 /****************************************************************************/
577 /* whenever a redraw in the RTP tap listener */
578 static void RTP_packet_draw(void *prs _U_)
580 voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
581 GList* rtp_streams_list;
582 voip_rtp_stream_info_t *rtp_listinfo;
583 GList* voip_calls_graph_list;
585 graph_analysis_item_t *gai;
586 graph_analysis_item_t *new_gai;
590 /* add each rtp stream to the graph */
591 rtp_streams_list = g_list_first(rtp_tapinfo->list);
592 while (rtp_streams_list)
594 rtp_listinfo = rtp_streams_list->data;
596 /* using the setup frame number of the RTP stream, we get the call number that it belongs */
597 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
598 while (voip_calls_graph_list)
600 gai = voip_calls_graph_list->data;
601 conv_num = gai->conv_num;
602 /* if we get the setup frame number, then get the time position to graph the RTP arrow */
603 if (rtp_listinfo->setup_frame_number == gai->frame_num){
604 /* look again from the begining because there are cases where the Setup frame is after the RTP */
605 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
607 while(voip_calls_graph_list){
608 gai = voip_calls_graph_list->data;
609 /* if RTP was already in the Graph, just update the comment information */
610 if (rtp_listinfo->first_frame_num == gai->frame_num){
611 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
612 g_free(gai->comment);
613 gai->comment = g_strdup_printf("%s Num packets:%u Duration:%u.%03us SSRC:0x%X",
614 (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->npackets,
615 duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
619 /* 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 */
620 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
621 if (!voip_calls_graph_list) item++;
623 /* add the RTP item to the graph if was not there*/
624 if (rtp_listinfo->first_frame_num<gai->frame_num || !voip_calls_graph_list){
625 new_gai = g_malloc(sizeof(graph_analysis_item_t));
626 new_gai->frame_num = rtp_listinfo->first_frame_num;
627 new_gai->time = (double)rtp_listinfo->start_rel_sec + (double)rtp_listinfo->start_rel_usec/1000000;
628 COPY_ADDRESS(&(new_gai->src_addr),&(rtp_listinfo->src_addr));
629 COPY_ADDRESS(&(new_gai->dst_addr),&(rtp_listinfo->dest_addr));
630 new_gai->port_src = rtp_listinfo->src_port;
631 new_gai->port_dst = rtp_listinfo->dest_port;
632 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
633 new_gai->frame_label = g_strdup_printf("%s (%s) %s", (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->pt_str, (rtp_listinfo->rtp_event == -1)?"":val_to_str(rtp_listinfo->rtp_event, rtp_event_type_values, "Unknown RTP Event"));
634 g_free(rtp_listinfo->pt_str);
635 new_gai->comment = g_strdup_printf("%s Num packets:%u Duration:%u.%03us SSRC:0x%X",
636 (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->npackets,
637 duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
638 new_gai->conv_num = conv_num;
639 new_gai->display=FALSE;
640 new_gai->line_style = 2; /* the arrow line will be 2 pixels width */
641 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item);
644 if (voip_calls_graph_list) item++;
648 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
650 rtp_streams_list = g_list_next(rtp_streams_list);
654 static gboolean have_RTP_tap_listener=FALSE;
655 /****************************************************************************/
659 GString *error_string;
661 if(have_RTP_tap_listener==FALSE)
663 /* don't register tap listener, if we have it already */
664 error_string = register_tap_listener("rtp", &(the_tapinfo_rtp_struct.rtp_dummy), NULL,
669 if (error_string != NULL) {
670 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
672 g_string_free(error_string, TRUE);
675 have_RTP_tap_listener=TRUE;
679 /****************************************************************************/
681 remove_tap_listener_rtp(void)
683 protect_thread_critical_region();
684 remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_dummy));
685 unprotect_thread_critical_region();
687 have_RTP_tap_listener=FALSE;
690 /* XXX just copied from gtk/rpc_stat.c */
691 void protect_thread_critical_region(void);
692 void unprotect_thread_critical_region(void);
694 /****************************************************************************/
695 /******************************TAP for T38 **********************************/
696 /****************************************************************************/
698 /****************************************************************************/
699 /* whenever a T38 packet is seen by the tap listener */
701 T38_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *T38info)
703 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
705 voip_calls_info_t *strinfo = NULL;
706 voip_calls_info_t *tmp_listinfo;
707 GList* voip_calls_graph_list;
709 gchar *frame_label = NULL;
710 gchar *comment = NULL;
711 graph_analysis_item_t *tmp_gai, *gai = NULL;
712 guint16 line_style = 2;
716 const t38_packet_info *pi = T38info;
718 if (pi->setup_frame_number != 0) {
719 /* using the setup frame number of the T38 packet, we get the call number that it belongs */
720 voip_calls_graph_list = g_list_first(tapinfo->graph_analysis->list);
721 while (voip_calls_graph_list)
723 tmp_gai = voip_calls_graph_list->data;
724 if (pi->setup_frame_number == tmp_gai->frame_num){
728 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
730 if (gai) conv_num = (int) gai->conv_num;
733 /* 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
734 * have the associated Voip calls. It probably means the the packet was decoded using the default t38 port, or using "Decode as.."
735 * in this case we create a "voip" call that only have t38 media (no signaling)
736 * OR if we have not found the Setup message in the graph.
738 if ( (pi->setup_frame_number == 0) || (gai == NULL) ){
739 /* check whether we already have a call with these parameters in the list */
740 list = g_list_first(tapinfo->strinfo_list);
743 tmp_listinfo=list->data;
744 if (tmp_listinfo->protocol == MEDIA_T38){
745 strinfo = (voip_calls_info_t*)(list->data);
748 list = g_list_next (list);
751 /* not in the list? then create a new entry */
753 strinfo = g_malloc0(sizeof(voip_calls_info_t));
754 strinfo->call_active_state = VOIP_ACTIVE;
755 strinfo->call_state = VOIP_UNKNOWN;
756 strinfo->from_identity=g_strdup("T38 Media only");
757 strinfo->to_identity=g_strdup("T38 Media only");
758 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
759 strinfo->first_frame_num=pinfo->fd->num;
760 strinfo->selected=FALSE;
761 strinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
762 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
763 strinfo->protocol=MEDIA_T38;
764 strinfo->prot_info=NULL;
765 strinfo->free_prot_info = NULL;
766 strinfo->npackets = 0;
767 strinfo->call_num = tapinfo->ncalls++;
768 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
770 ++(strinfo->npackets);
771 /* increment the packets counter of all calls */
772 ++(tapinfo->npackets);
774 conv_num = (int) strinfo->call_num;
777 /* at this point we should have found the call num for this t38 packets belong */
778 if (conv_num == -1) {
782 /* add the item to the graph list */
783 if (pi->type_msg == 0) { /* 0=t30-indicator */
784 frame_label = g_strdup(val_to_str(pi->t30ind_value, t38_T30_indicator_vals, "Ukn (0x%02X)") );
785 comment = g_strdup_printf("t38:t30 Ind:%s",val_to_str(pi->t30ind_value, t38_T30_indicator_vals, "Ukn (0x%02X)") );
787 } else if (pi->type_msg == 1) { /* 1=data */
788 switch(pi->Data_Field_field_type_value){
789 case 0: /* hdlc-data */
791 case 2: /* hdlc-fcs-OK */
792 case 4: /* hdlc-fcs-OK-sig-end */
793 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);
794 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)"));
796 case 3: /* hdlc-fcs-BAD */
797 case 5: /* hdlc-fcs-BAD-sig-end */
798 frame_label = g_strdup(pi->Data_Field_field_type_value == 3 ? "fcs-BAD" : "fcs-BAD-sig-end");
799 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");
801 case 7: /* t4-non-ecm-sig-end */
802 duration = nstime_to_sec(&pinfo->fd->rel_ts) - pi->time_first_t4_data;
803 frame_label = g_strdup_printf("t4-non-ecm-data:%s",val_to_str(pi->data_value, t38_T30_data_vals, "Ukn (0x%02X)") );
804 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 );
805 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);
810 if (frame_label && !(pi->Data_Field_field_type_value == 7 && pi->type_msg == 1)) {
811 add_to_graph(tapinfo, pinfo, frame_label, comment, (guint16)conv_num, &(pinfo->src), &(pinfo->dst), line_style);
817 tapinfo->redraw = TRUE;
819 return 1; /* refresh output */
822 static gboolean have_T38_tap_listener=FALSE;
823 /****************************************************************************/
827 GString *error_string;
829 if(have_T38_tap_listener==FALSE)
831 /* don't register tap listener, if we have it already */
832 error_string = register_tap_listener("t38", &(the_tapinfo_struct.t38_dummy), NULL,
833 voip_calls_dlg_reset,
837 if (error_string != NULL) {
838 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
840 g_string_free(error_string, TRUE);
843 have_T38_tap_listener=TRUE;
847 /****************************************************************************/
849 remove_tap_listener_t38(void)
851 protect_thread_critical_region();
852 remove_tap_listener(&(the_tapinfo_struct.t38_dummy));
853 unprotect_thread_critical_region();
855 have_T38_tap_listener=FALSE;
859 /****************************************************************************/
860 static gchar *sdp_summary = NULL;
861 static guint32 sdp_frame_num = 0;
863 /****************************************************************************/
864 /* ***************************TAP for SIP **********************************/
865 /****************************************************************************/
868 static void free_sip_info(gpointer p) {
869 sip_calls_info_t *si = p;
871 if (si->call_identifier) g_free(si->call_identifier);
875 /****************************************************************************/
876 /* whenever a SIP packet is seen by the tap listener */
878 SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SIPinfo)
880 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
881 /* we just take note of the ISUP data here; when we receive the MTP3 part everything will
882 be compared with existing calls */
884 voip_calls_info_t *tmp_listinfo;
885 voip_calls_info_t *strinfo = NULL;
886 sip_calls_info_t *tmp_sipinfo = NULL;
888 address tmp_src, tmp_dst;
889 gchar *frame_label = NULL;
890 gchar *comment = NULL;
892 const sip_info_value_t *pi = SIPinfo;
894 /* do not consider packets without call_id */
895 if (pi->tap_call_id ==NULL){
899 /* check whether we already have a call with these parameters in the list */
900 list = g_list_first(tapinfo->strinfo_list);
903 tmp_listinfo=list->data;
904 if (tmp_listinfo->protocol == VOIP_SIP){
905 tmp_sipinfo = tmp_listinfo->prot_info;
906 if (strcmp(tmp_sipinfo->call_identifier,pi->tap_call_id)==0){
907 strinfo = (voip_calls_info_t*)(list->data);
911 list = g_list_next (list);
914 /* not in the list? then create a new entry if the message is INVITE -i.e. if this session is a call*/
915 if ((strinfo==NULL) &&(pi->request_method!=NULL)){
916 if (strcmp(pi->request_method,"INVITE")==0){
917 strinfo = g_malloc0(sizeof(voip_calls_info_t));
918 strinfo->call_active_state = VOIP_ACTIVE;
919 strinfo->call_state = VOIP_CALL_SETUP;
920 strinfo->from_identity=g_strdup(pi->tap_from_addr);
921 strinfo->to_identity=g_strdup(pi->tap_to_addr);
922 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
923 strinfo->first_frame_num=pinfo->fd->num;
924 strinfo->selected=FALSE;
925 strinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
926 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
927 strinfo->protocol=VOIP_SIP;
928 strinfo->prot_info=g_malloc(sizeof(sip_calls_info_t));
929 strinfo->free_prot_info = free_sip_info;
930 tmp_sipinfo = strinfo->prot_info;
931 tmp_sipinfo->call_identifier = g_strdup(pi->tap_call_id);
932 tmp_sipinfo->sip_state = SIP_INVITE_SENT;
933 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
934 strinfo->npackets = 0;
935 strinfo->call_num = tapinfo->ncalls++;
936 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
942 /* let's analyze the call state */
944 COPY_ADDRESS(&(tmp_src), &(pinfo->src));
945 COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
947 if (pi->request_method == NULL){
948 frame_label = g_strdup_printf("%u %s", pi->response_code, pi->reason_phrase );
949 comment = g_strdup_printf("SIP Status");
951 if ((tmp_sipinfo && pi->tap_cseq_number == tmp_sipinfo->invite_cseq)&&(ADDRESSES_EQUAL(&tmp_dst,&(strinfo->initial_speaker)))){
952 if ((pi->response_code > 199) && (pi->response_code<300) && (tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
953 tmp_sipinfo->sip_state = SIP_200_REC;
955 else if ((pi->response_code>299)&&(tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
956 strinfo->call_state = VOIP_REJECTED;
957 tapinfo->rejected_calls++;
963 frame_label = g_strdup(pi->request_method);
965 if ((strcmp(pi->request_method,"INVITE")==0)&&(ADDRESSES_EQUAL(&tmp_src,&(strinfo->initial_speaker)))){
966 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
967 strinfo->call_state = VOIP_CALL_SETUP;
968 comment = g_strdup_printf("SIP From: %s To:%s", strinfo->from_identity, strinfo->to_identity);
970 else if ((strcmp(pi->request_method,"ACK")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
971 &&(ADDRESSES_EQUAL(&tmp_src,&(strinfo->initial_speaker)))&&(tmp_sipinfo->sip_state==SIP_200_REC)
972 &&(strinfo->call_state == VOIP_CALL_SETUP)){
973 strinfo->call_state = VOIP_IN_CALL;
974 comment = g_strdup_printf("SIP Request");
976 else if (strcmp(pi->request_method,"BYE")==0){
977 strinfo->call_state = VOIP_COMPLETED;
978 tapinfo->completed_calls++;
979 comment = g_strdup_printf("SIP Request");
981 else if ((strcmp(pi->request_method,"CANCEL")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
982 &&(ADDRESSES_EQUAL(&tmp_src,&(strinfo->initial_speaker)))&&(strinfo->call_state==VOIP_CALL_SETUP)){
983 strinfo->call_state = VOIP_CANCELLED;
984 tmp_sipinfo->sip_state = SIP_CANCEL_SENT;
985 comment = g_strdup_printf("SIP Request");
987 comment = g_strdup_printf("SIP Request");
991 strinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
992 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
993 strinfo->last_frame_num=pinfo->fd->num;
994 ++(strinfo->npackets);
995 /* increment the packets counter of all calls */
996 ++(tapinfo->npackets);
998 /* add to the graph */
999 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1001 g_free(frame_label);
1002 g_free((void *)tmp_src.data);
1003 g_free((void *)tmp_dst.data);
1005 /* add SDP info if apply */
1006 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
1007 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
1008 g_free(sdp_summary);
1013 tapinfo->redraw = TRUE;
1015 return 1; /* refresh output */
1019 /****************************************************************************/
1020 voip_calls_tapinfo_t* voip_calls_get_info(void)
1022 return &the_tapinfo_struct;
1026 /****************************************************************************/
1028 /****************************************************************************/
1029 static gboolean have_SIP_tap_listener=FALSE;
1030 /****************************************************************************/
1032 sip_calls_init_tap(void)
1034 GString *error_string;
1036 if(have_SIP_tap_listener==FALSE)
1038 /* don't register tap listener, if we have it already */
1039 error_string = register_tap_listener("sip", &(the_tapinfo_struct.sip_dummy), NULL,
1040 voip_calls_dlg_reset,
1044 if (error_string != NULL) {
1045 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1047 g_string_free(error_string, TRUE);
1050 have_SIP_tap_listener=TRUE;
1054 /****************************************************************************/
1056 remove_tap_listener_sip_calls(void)
1058 protect_thread_critical_region();
1059 remove_tap_listener(&(the_tapinfo_struct.sip_dummy));
1060 unprotect_thread_critical_region();
1062 have_SIP_tap_listener=FALSE;
1065 /****************************************************************************/
1066 /* ***************************TAP for ISUP **********************************/
1067 /****************************************************************************/
1069 static guint32 mtp3_opc, mtp3_dpc;
1070 static guint8 mtp3_ni;
1071 static guint32 mtp3_frame_num;
1074 /****************************************************************************/
1075 /* whenever a isup_ packet is seen by the tap listener */
1077 isup_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *isup_info _U_)
1079 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1080 voip_calls_info_t *tmp_listinfo;
1081 voip_calls_info_t *strinfo = NULL;
1082 isup_calls_info_t *tmp_isupinfo;
1083 gboolean found = FALSE;
1084 gboolean forward = FALSE;
1085 gboolean right_pair;
1087 gchar *frame_label = NULL;
1088 gchar *comment = NULL;
1091 /*voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct; unused */
1092 const isup_tap_rec_t *pi = isup_info;
1094 /* check if the lower layer is MTP matching the frame number */
1095 if (mtp3_frame_num != pinfo->fd->num) return 0;
1097 /* check whether we already have a call with these parameters in the list */
1098 list = g_list_first(tapinfo->strinfo_list);
1102 tmp_listinfo=list->data;
1103 if ((tmp_listinfo->protocol == VOIP_ISUP)&&(tmp_listinfo->call_active_state==VOIP_ACTIVE)){
1104 tmp_isupinfo = tmp_listinfo->prot_info;
1105 if ((tmp_isupinfo->cic == pinfo->circuit_id)&&(tmp_isupinfo->ni == mtp3_ni)) {
1106 if ((tmp_isupinfo->opc == mtp3_opc)&&(tmp_isupinfo->dpc == mtp3_dpc)){
1108 } else if ((tmp_isupinfo->dpc == mtp3_opc)&&(tmp_isupinfo->opc == mtp3_dpc)){
1115 /* if there is an IAM for a call that is not in setup state, that means the previous call in the same
1116 cic is no longer active */
1117 if (tmp_listinfo->call_state == VOIP_CALL_SETUP){
1119 } else if (pi->message_type != 1){
1122 tmp_listinfo->call_active_state=VOIP_INACTIVE;
1127 strinfo = (voip_calls_info_t*)(list->data);
1132 list = g_list_next (list);
1135 /* not in the list? then create a new entry if the message is IAM
1136 -i.e. if this session is a call*/
1139 if ((strinfo==NULL) &&(pi->message_type==1)){
1140 strinfo = g_malloc0(sizeof(voip_calls_info_t));
1141 strinfo->call_active_state = VOIP_ACTIVE;
1142 strinfo->call_state = VOIP_UNKNOWN;
1143 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
1144 strinfo->selected=FALSE;
1145 strinfo->first_frame_num=pinfo->fd->num;
1146 strinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
1147 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1148 strinfo->protocol=VOIP_ISUP;
1149 if (pi->calling_number!=NULL){
1150 strinfo->from_identity=g_strdup(pi->calling_number);
1152 if (pi->called_number!=NULL){
1153 strinfo->to_identity=g_strdup(pi->called_number);
1155 strinfo->prot_info=g_malloc(sizeof(isup_calls_info_t));
1156 strinfo->free_prot_info = g_free;
1157 tmp_isupinfo=strinfo->prot_info;
1158 tmp_isupinfo->opc = mtp3_opc;
1159 tmp_isupinfo->dpc = mtp3_dpc;
1160 tmp_isupinfo->ni = mtp3_ni;
1161 tmp_isupinfo->cic = pinfo->circuit_id;
1162 strinfo->npackets = 0;
1163 strinfo->call_num = tapinfo->ncalls++;
1164 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
1169 strinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
1170 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1171 strinfo->last_frame_num=pinfo->fd->num;
1172 ++(strinfo->npackets);
1174 /* Let's analyze the call state */
1177 for (i=0;(isup_message_type_value[i].strptr!=NULL)&& (isup_message_type_value[i].value!=pi->message_type);i++);
1179 if (isup_message_type_value[i].value==pi->message_type){
1180 frame_label = g_strdup(isup_message_type_value_acro[i].strptr);
1183 frame_label = g_strdup_printf("Unknown");
1186 if (strinfo->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 (strinfo->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 strinfo->call_state=VOIP_CALL_SETUP;
1209 case 7: /* CONNECT */
1210 case 9: /* ANSWER */
1211 strinfo->call_state=VOIP_IN_CALL;
1213 case 12: /* RELEASE */
1214 if (strinfo->call_state==VOIP_CALL_SETUP){
1216 strinfo->call_state=VOIP_CANCELLED;
1219 strinfo->call_state=VOIP_REJECTED;
1220 tapinfo->rejected_calls++;
1223 else if (strinfo->call_state == VOIP_IN_CALL){
1224 strinfo->call_state = VOIP_COMPLETED;
1225 tapinfo->completed_calls++;
1227 for (i=0;(q931_cause_code_vals[i].strptr!=NULL)&& (q931_cause_code_vals[i].value!=pi->cause_value);i++);
1228 if (q931_cause_code_vals[i].value==pi->cause_value){
1229 comment = g_strdup_printf("Cause %i - %s",pi->cause_value, q931_cause_code_vals[i].strptr);
1232 comment = g_strdup_printf("Cause %i",pi->cause_value);
1237 /* increment the packets counter of all calls */
1238 ++(tapinfo->npackets);
1240 /* add to the graph */
1241 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1243 g_free(frame_label);
1246 tapinfo->redraw = TRUE;
1248 return 1; /* refresh output */
1251 /****************************************************************************/
1253 static gboolean have_isup_tap_listener=FALSE;
1256 isup_calls_init_tap(void)
1258 GString *error_string;
1261 if(have_isup_tap_listener==FALSE)
1263 error_string = register_tap_listener("isup", &(the_tapinfo_struct.isup_dummy),
1265 voip_calls_dlg_reset,
1270 if (error_string != NULL) {
1271 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1273 g_string_free(error_string, TRUE);
1276 have_isup_tap_listener=TRUE;
1280 /****************************************************************************/
1283 remove_tap_listener_isup_calls(void)
1285 protect_thread_critical_region();
1286 remove_tap_listener(&(the_tapinfo_struct.isup_dummy));
1287 unprotect_thread_critical_region();
1289 have_isup_tap_listener=FALSE;
1293 /****************************************************************************/
1294 /* ***************************TAP for MTP3 **********************************/
1295 /****************************************************************************/
1298 /****************************************************************************/
1299 /* whenever a mtp3_ packet is seen by the tap listener */
1301 mtp3_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *mtp3_info _U_)
1303 const mtp3_tap_rec_t *pi = mtp3_info;
1305 /* keep the data in memory to use when the ISUP information arrives */
1307 mtp3_opc = pi->addr_opc.pc;
1308 mtp3_dpc = pi->addr_dpc.pc;
1309 mtp3_ni = pi->addr_opc.ni;
1310 mtp3_frame_num = pinfo->fd->num;
1315 /****************************************************************************/
1317 static gboolean have_mtp3_tap_listener=FALSE;
1318 static gboolean have_m3ua_tap_listener=FALSE;
1321 mtp3_calls_init_tap(void)
1323 GString *error_string;
1326 if(have_mtp3_tap_listener==FALSE)
1328 error_string = register_tap_listener("mtp3", &(the_tapinfo_struct.mtp3_dummy),
1330 voip_calls_dlg_reset,
1335 if (error_string != NULL) {
1336 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1338 g_string_free(error_string, TRUE);
1341 have_mtp3_tap_listener=TRUE;
1344 if(have_m3ua_tap_listener==FALSE)
1346 error_string = register_tap_listener("m3ua", &(the_tapinfo_struct.mtp3_dummy),
1348 voip_calls_dlg_reset,
1353 if (error_string != NULL) {
1354 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1356 g_string_free(error_string, TRUE);
1359 have_m3ua_tap_listener=TRUE;
1364 /****************************************************************************/
1367 remove_tap_listener_mtp3_calls(void)
1369 protect_thread_critical_region();
1370 remove_tap_listener(&(the_tapinfo_struct.mtp3_dummy));
1371 remove_tap_listener(&(the_tapinfo_struct.m3ua_dummy));
1372 unprotect_thread_critical_region();
1374 have_mtp3_tap_listener=FALSE;
1375 have_m3ua_tap_listener=FALSE;
1378 /****************************************************************************/
1379 /* ***************************TAP for Q931 **********************************/
1380 /****************************************************************************/
1381 void h245_add_to_graph(guint32 new_frame_num);
1382 static const e_guid_t guid_allzero = {0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };
1383 /* defines specific H323 data */
1385 static gchar *q931_calling_number;
1386 static gchar *q931_called_number;
1387 static guint8 q931_cause_value;
1388 static gint32 q931_crv;
1389 static guint32 q931_frame_num;
1391 static guint32 h225_frame_num = 0;
1392 static guint16 h225_call_num = 0;
1393 static h225_cs_type h225_cstype = H225_OTHER;
1394 static gboolean h225_is_faststart;
1396 static guint32 actrace_frame_num = 0;
1397 static gint32 actrace_trunk = 0;
1398 static gint32 actrace_direction = 0;
1401 /****************************************************************************/
1402 /* whenever a q931_ packet is seen by the tap listener */
1404 q931_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *q931_info _U_)
1407 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1408 h323_calls_info_t *tmp_h323info,*tmp2_h323info;
1409 actrace_isdn_calls_info_t *tmp_actrace_isdn_info;
1410 voip_calls_info_t *tmp_listinfo;
1411 voip_calls_info_t *strinfo = NULL;
1412 h245_address_t *h245_add = NULL;
1415 const q931_packet_info *pi = q931_info;
1417 /* free previously allocated q931_calling/ed_number */
1418 g_free(q931_calling_number);
1419 g_free(q931_called_number);
1421 if (pi->calling_number!=NULL)
1422 q931_calling_number = g_strdup(pi->calling_number);
1424 q931_calling_number = g_strdup("");
1426 if (pi->called_number!=NULL)
1427 q931_called_number = g_strdup(pi->called_number);
1429 q931_called_number = g_strdup("");
1430 q931_cause_value = pi->cause_value;
1431 q931_frame_num = pinfo->fd->num;
1435 /* add staff to H323 calls */
1436 if (h225_frame_num == q931_frame_num) {
1437 tmp_h323info = NULL;
1438 list = g_list_first(tapinfo->strinfo_list);
1441 tmp_listinfo=list->data;
1442 if ( (tmp_listinfo->protocol == VOIP_H323) && (tmp_listinfo->call_num == h225_call_num) ){
1443 tmp_h323info = tmp_listinfo->prot_info;
1444 strinfo = (voip_calls_info_t*)(list->data);
1446 /* Add the CRV to the h323 call */
1447 if (tmp_h323info->q931_crv == -1) {
1448 tmp_h323info->q931_crv = q931_crv;
1449 } else if (tmp_h323info->q931_crv != q931_crv) {
1450 tmp_h323info->q931_crv2 = q931_crv;
1454 list = g_list_next (list);
1457 if (strinfo != NULL) {
1459 if (h225_cstype == H225_SETUP) {
1460 /* set te calling and called number from the Q931 packet */
1461 if (q931_calling_number != NULL){
1462 g_free(strinfo->from_identity);
1463 strinfo->from_identity=g_strdup(q931_calling_number);
1465 if (q931_called_number != NULL){
1466 g_free(strinfo->to_identity);
1467 strinfo->to_identity=g_strdup(q931_called_number);
1470 /* check if there is an LRQ/LCF that match this Setup */
1471 /* TODO: we are just checking the DialedNumer in LRQ/LCF agains the Setup
1472 we should also check if the h225 signaling IP and port match the destination
1473 Setup ip and port */
1474 list = g_list_first(tapinfo->strinfo_list);
1477 tmp_listinfo=list->data;
1478 if (tmp_listinfo->protocol == VOIP_H323){
1479 tmp2_h323info = tmp_listinfo->prot_info;
1481 /* check if the called number match a LRQ/LCF */
1482 if ( (strcmp(strinfo->to_identity, tmp_listinfo->to_identity)==0)
1483 && (memcmp(&tmp2_h323info->guid, &guid_allzero, GUID_LEN) == 0) ){
1484 /* change the call graph to the LRQ/LCF to belong to this call */
1485 strinfo->npackets += change_call_num_graph(tapinfo, tmp_listinfo->call_num, strinfo->call_num);
1487 /* remove this LRQ/LCF call entry because we have found the Setup that match them */
1488 g_free(tmp_listinfo->from_identity);
1489 g_free(tmp_listinfo->to_identity);
1490 g_free(tmp2_h323info->guid);
1492 list2 = g_list_first(tmp2_h323info->h245_list);
1495 h245_add=list2->data;
1496 g_free((void *)h245_add->h245_address.data);
1497 g_free(list2->data);
1498 list2 = g_list_next(list2);
1500 g_list_free(tmp_h323info->h245_list);
1501 tmp_h323info->h245_list = NULL;
1502 g_free(tmp_listinfo->prot_info);
1503 tapinfo->strinfo_list = g_list_remove(tapinfo->strinfo_list, tmp_listinfo);
1507 list = g_list_next (list);
1510 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"),
1511 (h225_is_faststart==TRUE?"on":"off"));
1512 } else if (h225_cstype == H225_RELEASE_COMPLET) {
1513 /* get the Q931 Release cause code */
1514 if (q931_cause_value != 0xFF){
1515 comment = g_strdup_printf("H225 Q931 Rel Cause (%i):%s", q931_cause_value, val_to_str(q931_cause_value, q931_cause_code_vals, "<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->strinfo_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)){
1542 comment = g_strdup("");
1544 /* if the frame number exists in graph, append to it*/
1545 if (!append_to_frame_graph(tapinfo, q931_frame_num, "", comment)) {
1546 /* if not exist, add to the graph */
1547 add_to_graph(tapinfo, pinfo, "", comment, tmp_listinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1548 ++(tmp_listinfo->npackets);
1549 /* increment the packets counter of all calls */
1550 ++(tapinfo->npackets);
1553 /* Add the H245 info if exists to the Graph */
1554 h245_add_to_graph(pinfo->fd->num);
1559 list = g_list_next (list);
1562 /* add staff to ACTRACE */
1563 } else if (actrace_frame_num == q931_frame_num) {
1565 gchar *comment = NULL;
1568 list = g_list_first(tapinfo->strinfo_list);
1571 tmp_listinfo=list->data;
1572 if ( tmp_listinfo->protocol == VOIP_AC_ISDN ){
1573 tmp_actrace_isdn_info = tmp_listinfo->prot_info;
1574 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
1575 if ( (tmp_actrace_isdn_info->crv == q931_crv) && (tmp_actrace_isdn_info->trunk == actrace_trunk) ) {
1576 strinfo = (voip_calls_info_t*)(list->data);
1580 list = g_list_next (list);
1583 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, g_strdup("PSTN"));
1585 /* if it is a new call, add it to the list */
1587 strinfo = g_malloc0(sizeof(voip_calls_info_t));
1588 strinfo->call_active_state = VOIP_ACTIVE;
1589 strinfo->call_state = VOIP_CALL_SETUP;
1590 strinfo->from_identity=g_strdup(q931_calling_number);
1591 strinfo->to_identity=g_strdup(q931_called_number);
1592 COPY_ADDRESS(&(strinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
1593 strinfo->first_frame_num=pinfo->fd->num;
1594 strinfo->selected=FALSE;
1595 strinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
1596 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1597 strinfo->protocol=VOIP_AC_ISDN;
1598 strinfo->prot_info=g_malloc(sizeof(actrace_isdn_calls_info_t));
1599 strinfo->free_prot_info = g_free;
1600 tmp_actrace_isdn_info=strinfo->prot_info;
1601 tmp_actrace_isdn_info->crv=q931_crv;
1602 tmp_actrace_isdn_info->trunk=actrace_trunk;
1603 strinfo->npackets = 0;
1604 strinfo->call_num = tapinfo->ncalls++;
1605 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
1608 strinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
1609 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1610 strinfo->last_frame_num=pinfo->fd->num;
1611 ++(strinfo->npackets);
1612 /* increment the packets counter of all calls */
1613 ++(tapinfo->npackets);
1615 switch(pi->message_type){
1617 comment = g_strdup_printf("AC_ISDN trunk:%u Calling: %s Called:%s", actrace_trunk, q931_calling_number, q931_called_number);
1618 strinfo->call_state=VOIP_CALL_SETUP;
1621 strinfo->call_state=VOIP_IN_CALL;
1623 case Q931_RELEASE_COMPLETE:
1625 case Q931_DISCONNECT:
1626 if (strinfo->call_state==VOIP_CALL_SETUP){
1627 if (ADDRESSES_EQUAL(&(strinfo->initial_speaker), actrace_direction?&pstn_add:&(pinfo->src) )){ /* forward direction */
1628 strinfo->call_state=VOIP_CANCELLED;
1631 strinfo->call_state=VOIP_REJECTED;
1632 tapinfo->rejected_calls++;
1634 } else if ( (strinfo->call_state!=VOIP_CANCELLED) && (strinfo->call_state!=VOIP_REJECTED) ){
1635 strinfo->call_state=VOIP_COMPLETED;
1636 tapinfo->completed_calls++;
1638 if (q931_cause_value != 0xFF){
1639 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>"));
1640 } else { /* Cause not set */
1641 comment = g_strdup("AC_ISDN No Q931 Rel Cause");
1647 comment = g_strdup_printf("AC_ISDN trunk:%u", actrace_trunk );
1649 add_to_graph(tapinfo, pinfo, val_to_str(pi->message_type, q931_message_type_vals, "<unknown>") , comment, strinfo->call_num,
1650 actrace_direction?&pstn_add:&(pinfo->src),
1651 actrace_direction?&(pinfo->src):&pstn_add,
1655 g_free((char *)pstn_add.data);
1658 tapinfo->redraw = TRUE;
1660 return 1; /* refresh output */
1663 /****************************************************************************/
1664 static gboolean have_q931_tap_listener=FALSE;
1667 q931_calls_init_tap(void)
1669 GString *error_string;
1672 if(have_q931_tap_listener==FALSE)
1674 error_string = register_tap_listener("q931", &(the_tapinfo_struct.q931_dummy),
1676 voip_calls_dlg_reset,
1681 if (error_string != NULL) {
1682 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1684 g_string_free(error_string, TRUE);
1687 have_q931_tap_listener=TRUE;
1691 /****************************************************************************/
1694 remove_tap_listener_q931_calls(void)
1696 protect_thread_critical_region();
1697 remove_tap_listener(&(the_tapinfo_struct.q931_dummy));
1698 unprotect_thread_critical_region();
1700 have_q931_tap_listener=FALSE;
1703 /****************************************************************************/
1704 /****************************TAP for H323 ***********************************/
1705 /****************************************************************************/
1707 static void add_h245_Address(h323_calls_info_t *h323info, h245_address_t *h245_address)
1709 h323info->h245_list = g_list_append(h323info->h245_list, h245_address);
1713 static void free_h225_info(gpointer p) {
1714 h323_calls_info_t *tmp_h323info = p;
1716 if (tmp_h323info->guid) g_free(tmp_h323info->guid);
1718 if (tmp_h323info->h245_list) {
1719 GList* list2 = g_list_first(tmp_h323info->h245_list);
1722 h245_address_t *h245_add=list2->data;
1723 g_free((void *)h245_add->h245_address.data);
1724 g_free(list2->data);
1725 list2 = g_list_next(list2);
1728 g_list_free(tmp_h323info->h245_list);
1734 /****************************************************************************/
1735 /* whenever a H225 packet is seen by the tap listener */
1737 H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H225info)
1739 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1740 voip_calls_info_t *tmp_listinfo;
1741 voip_calls_info_t *strinfo = NULL;
1742 h323_calls_info_t *tmp_h323info = NULL;
1746 address tmp_src, tmp_dst;
1747 h245_address_t *h245_add = NULL;
1749 const h225_packet_info *pi = H225info;
1751 /* if not guid and RAS and not LRQ, LCF or LRJ return because did not belong to a call */
1752 /* OR, if not guid and is H225 return because doesn't belong to a call */
1753 if ((memcmp(&pi->guid, &guid_allzero, GUID_LEN) == 0))
1754 if ( ((pi->msg_type == H225_RAS) && ((pi->msg_tag < 18) || (pi->msg_tag > 20))) || (pi->msg_type != H225_RAS) )
1757 /* if it is RAS LCF or LRJ*/
1758 if ( (pi->msg_type == H225_RAS) && ((pi->msg_tag == 19) || (pi->msg_tag == 20))) {
1759 /* if the LCF/LRJ doesn't match to a LRQ, just return */
1760 if (!pi->request_available) return 0;
1762 /* check whether we already have a call with this request SeqNum */
1763 list = g_list_first(tapinfo->strinfo_list);
1766 tmp_listinfo=list->data;
1767 g_assert(tmp_listinfo != NULL);
1768 if (tmp_listinfo->protocol == VOIP_H323){
1769 tmp_h323info = tmp_listinfo->prot_info;
1770 if (tmp_h323info->requestSeqNum == pi->requestSeqNum) {
1771 strinfo = (voip_calls_info_t*)(list->data);
1775 list = g_list_next (list);
1778 /* check whether we already have a call with this guid in the list */
1779 list = g_list_first(tapinfo->strinfo_list);
1782 tmp_listinfo=list->data;
1783 if (tmp_listinfo->protocol == VOIP_H323){
1784 tmp_h323info = tmp_listinfo->prot_info;
1785 g_assert(tmp_h323info != NULL);
1786 if ( (memcmp(tmp_h323info->guid, &guid_allzero, GUID_LEN) != 0) && (memcmp(tmp_h323info->guid, &pi->guid,GUID_LEN)==0) ){
1787 strinfo = (voip_calls_info_t*)(list->data);
1791 list = g_list_next (list);
1795 h225_cstype = pi->cs_type;
1796 h225_is_faststart = pi->is_faststart;
1798 /* not in the list? then create a new entry */
1799 if ((strinfo==NULL)){
1800 strinfo = g_malloc0(sizeof(voip_calls_info_t));
1801 strinfo->call_active_state = VOIP_ACTIVE;
1802 strinfo->call_state = VOIP_UNKNOWN;
1803 strinfo->from_identity=g_strdup("");
1804 strinfo->to_identity=g_strdup("");
1805 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
1806 strinfo->selected=FALSE;
1807 strinfo->first_frame_num=pinfo->fd->num;
1808 strinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
1809 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1810 strinfo->protocol=VOIP_H323;
1811 strinfo->prot_info=g_malloc(sizeof(h323_calls_info_t));
1812 strinfo->free_prot_info = free_h225_info;
1814 tmp_h323info = strinfo->prot_info;
1815 g_assert(tmp_h323info != NULL);
1816 tmp_h323info->guid = g_memdup(&pi->guid, sizeof pi->guid);
1817 tmp_h323info->h225SetupAddr.type = AT_NONE;
1818 tmp_h323info->h225SetupAddr.len = 0;
1819 tmp_h323info->h245_list = NULL;
1820 tmp_h323info->is_faststart_Setup = FALSE;
1821 tmp_h323info->is_faststart_Proc = FALSE;
1822 tmp_h323info->is_h245Tunneling = FALSE;
1823 tmp_h323info->is_h245 = FALSE;
1824 tmp_h323info->q931_crv = -1;
1825 tmp_h323info->q931_crv2 = -1;
1826 tmp_h323info->requestSeqNum = 0;
1827 strinfo->call_num = tapinfo->ncalls++;
1828 strinfo->npackets = 0;
1830 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
1835 h225_frame_num = pinfo->fd->num;
1836 h225_call_num = strinfo->call_num;
1838 /* let's analyze the call state */
1840 COPY_ADDRESS(&(tmp_src),&(pinfo->src));
1841 COPY_ADDRESS(&(tmp_dst),&(pinfo->dst));
1843 strinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
1844 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1845 strinfo->last_frame_num=pinfo->fd->num;
1846 ++(strinfo->npackets);
1847 /* increment the packets counter of all calls */
1848 ++(tapinfo->npackets);
1851 /* XXX: it is supposed to be initialized isn't it? */
1852 g_assert(tmp_h323info != NULL);
1854 /* change the status */
1855 if (pi->msg_type == H225_CS){
1857 /* this is still IPv4 only, because the dissector is */
1858 if (pi->is_h245 == TRUE){
1859 h245_add = g_malloc(sizeof (h245_address_t));
1860 h245_add->h245_address.type=AT_IPv4;
1861 h245_add->h245_address.len=4;
1862 h245_add->h245_address.data = g_malloc(sizeof(pi->h245_address));
1863 memcpy((void *)(h245_add->h245_address.data), &(pi->h245_address), 4);
1864 h245_add->h245_port = pi->h245_port;
1865 add_h245_Address(tmp_h323info, h245_add);
1868 if (pi->cs_type != H225_RELEASE_COMPLET) tmp_h323info->is_h245Tunneling = pi->is_h245Tunneling;
1870 frame_label = g_strdup(pi->frame_label);
1872 switch(pi->cs_type){
1874 tmp_h323info->is_faststart_Setup = pi->is_faststart;
1876 /* Set the Setup address if it was not set */
1877 if (tmp_h323info->h225SetupAddr.type == AT_NONE)
1878 COPY_ADDRESS(&(tmp_h323info->h225SetupAddr), &(pinfo->src));
1879 strinfo->call_state=VOIP_CALL_SETUP;
1880 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1881 (pi->is_faststart==TRUE?"on":"off"));
1884 strinfo->call_state=VOIP_IN_CALL;
1885 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1886 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1887 (pi->is_faststart==TRUE?"on":"off"));
1889 case H225_RELEASE_COMPLET:
1890 COPY_ADDRESS(&tmp_src,&(pinfo->src));
1891 if (strinfo->call_state==VOIP_CALL_SETUP){
1892 if (ADDRESSES_EQUAL(&(tmp_h323info->h225SetupAddr),&tmp_src)){ /* forward direction */
1893 strinfo->call_state=VOIP_CANCELLED;
1896 strinfo->call_state=VOIP_REJECTED;
1897 tapinfo->rejected_calls++;
1900 strinfo->call_state=VOIP_COMPLETED;
1901 tapinfo->completed_calls++;
1903 comment = g_strdup("H225 No Q931 Rel Cause");
1907 case H225_CALL_PROCEDING:
1908 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1909 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1910 (pi->is_faststart==TRUE?"on":"off"));
1913 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1914 (pi->is_faststart==TRUE?"on":"off"));
1918 else if (pi->msg_type == H225_RAS){
1919 switch(pi->msg_tag){
1921 if (!pi->is_duplicate){
1922 g_free(strinfo->to_identity);
1923 strinfo->to_identity=g_strdup(pi->dialedDigits);
1924 tmp_h323info->requestSeqNum = pi->requestSeqNum;
1927 if (strlen(pi->dialedDigits))
1928 comment = g_strdup_printf("H225 RAS dialedDigits: %s", pi->dialedDigits);
1930 comment = g_strdup("H225 RAS");
1933 comment = g_strdup("H225 RAS");
1935 frame_label = g_strdup_printf("%s", val_to_str(pi->msg_tag, h225_RasMessage_vals, "<unknown>"));
1937 frame_label = g_strdup("H225: Unknown");
1938 comment = g_strdup("");
1941 /* add to graph analysis */
1943 /* if the frame number exists in graph, append to it*/
1944 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, comment)) {
1945 /* if not exist, add to the graph */
1946 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1947 g_free((void *)tmp_src.data);
1948 g_free((void *)tmp_dst.data);
1951 /* Add the H245 info if exists to the Graph */
1952 h245_add_to_graph(pinfo->fd->num);
1954 g_free(frame_label);
1959 tapinfo->redraw = TRUE;
1961 return 1; /* refresh output */
1965 /****************************************************************************/
1967 /****************************************************************************/
1968 static gboolean have_H225_tap_listener=FALSE;
1969 /****************************************************************************/
1971 h225_calls_init_tap(void)
1973 GString *error_string;
1975 if(have_H225_tap_listener==FALSE)
1977 /* don't register tap listener, if we have it already */
1978 error_string = register_tap_listener("h225", &(the_tapinfo_struct.h225_dummy), NULL,
1979 voip_calls_dlg_reset,
1984 if (error_string != NULL) {
1985 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1987 g_string_free(error_string, TRUE);
1990 have_H225_tap_listener=TRUE;
1994 /****************************************************************************/
1996 remove_tap_listener_h225_calls(void)
1998 protect_thread_critical_region();
1999 remove_tap_listener(&(the_tapinfo_struct.h225_dummy));
2000 unprotect_thread_critical_region();
2002 have_H225_tap_listener=FALSE;
2005 /* Add the h245 label info to the graph */
2006 void h245_add_to_graph(guint32 new_frame_num)
2010 if (new_frame_num != h245_labels.frame_num) return;
2012 for (n=0; n<h245_labels.labels_count; n++) {
2013 append_to_frame_graph(&the_tapinfo_struct, new_frame_num, h245_labels.labels[n].frame_label, h245_labels.labels[n].comment);
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 /* free the h245_labels if the frame number is different */
2024 static void h245_free_labels(guint32 new_frame_num)
2028 if (new_frame_num == h245_labels.frame_num) return;
2030 for (n=0; n<h245_labels.labels_count; n++) {
2031 g_free(h245_labels.labels[n].frame_label);
2032 h245_labels.labels[n].frame_label = NULL;
2033 g_free(h245_labels.labels[n].comment);
2034 h245_labels.labels[n].comment = NULL;
2036 h245_labels.frame_num = 0;
2037 h245_labels.labels_count = 0;
2040 /* add the frame_label and comment to h245_labels and free the actual one if it is different frame num */
2041 static void h245_add_label(guint32 new_frame_num, const gchar *frame_label, const gchar *comment)
2043 h245_free_labels(new_frame_num);
2045 h245_labels.frame_num = new_frame_num;
2046 h245_labels.labels[h245_labels.labels_count].frame_label = g_strdup(frame_label);
2047 h245_labels.labels[h245_labels.labels_count].comment = g_strdup(comment);
2049 if (h245_labels.labels_count < (H245_MAX-1))
2050 h245_labels.labels_count++;
2054 /****************************************************************************/
2055 /* whenever a H245dg packet is seen by the tap listener (when H245 tunneling is ON) */
2057 H245dgcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H245info)
2059 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2060 voip_calls_info_t *tmp_listinfo;
2061 voip_calls_info_t *strinfo = NULL;
2062 h323_calls_info_t *tmp_h323info;
2067 address tmp_src, tmp_dst;
2068 h245_address_t *h245_add = NULL;
2070 const h245_packet_info *pi = H245info;
2072 /* check if Tunneling is OFF and we have a call with this H245 add */
2073 list = g_list_first(tapinfo->strinfo_list);
2076 tmp_listinfo=list->data;
2077 if (tmp_listinfo->protocol == VOIP_H323){
2078 tmp_h323info = tmp_listinfo->prot_info;
2080 COPY_ADDRESS(&(tmp_src), &(pinfo->src));
2081 COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
2082 list2 = g_list_first(tmp_h323info->h245_list);
2085 h245_add=list2->data;
2086 if ( (ADDRESSES_EQUAL(&(h245_add->h245_address),&tmp_src) && (h245_add->h245_port == pinfo->srcport))
2087 || (ADDRESSES_EQUAL(&(h245_add->h245_address),&tmp_dst) && (h245_add->h245_port == pinfo->destport)) ){
2088 strinfo = (voip_calls_info_t*)(list->data);
2090 ++(strinfo->npackets);
2091 /* increment the packets counter of all calls */
2092 ++(tapinfo->npackets);
2096 list2 = g_list_next(list2);
2098 if (strinfo!=NULL) break;
2099 g_free((void *)tmp_src.data);
2100 g_free((void *)tmp_dst.data);
2102 list = g_list_next(list);
2105 /* Tunnel is OFF, and we matched the h245 add so we add it to graph */
2107 ++(strinfo->npackets);
2108 /* increment the packets counter of all calls */
2109 ++(tapinfo->npackets);
2110 frame_label = g_strdup(pi->frame_label);
2111 comment = g_strdup(pi->comment);
2112 /* if the frame number exists in graph, append to it*/
2113 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, frame_label, comment)) {
2114 /* if not exist, add to the graph */
2115 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2117 g_free(frame_label);
2120 /* Tunnel is ON, so we save the label info to use it into h225 or q931 tap. OR may be
2121 tunnel OFF but we did not matched the h245 add, in this case nobady will set this label
2122 since the frame_num will not match */
2124 h245_add_label(pinfo->fd->num, (gchar *) pi->frame_label, (gchar *) pi->comment);
2127 tapinfo->redraw = TRUE;
2129 return 1; /* refresh output */
2133 /****************************************************************************/
2135 /****************************************************************************/
2136 static gboolean have_H245dg_tap_listener=FALSE;
2137 /****************************************************************************/
2139 h245dg_calls_init_tap(void)
2141 GString *error_string;
2143 if(have_H245dg_tap_listener==FALSE)
2145 /* don't register tap listener, if we have it already */
2146 error_string = register_tap_listener("h245dg", &(the_tapinfo_struct.h245dg_dummy), NULL,
2147 voip_calls_dlg_reset,
2152 if (error_string != NULL) {
2153 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2155 g_string_free(error_string, TRUE);
2158 have_H245dg_tap_listener=TRUE;
2162 /****************************************************************************/
2164 remove_tap_listener_h245dg_calls(void)
2166 protect_thread_critical_region();
2167 remove_tap_listener(&(the_tapinfo_struct.h245dg_dummy));
2168 unprotect_thread_critical_region();
2170 have_H245dg_tap_listener=FALSE;
2173 /****************************************************************************/
2174 /****************************TAP for SDP PROTOCOL ***************************/
2175 /****************************************************************************/
2176 /* whenever a SDP packet is seen by the tap listener */
2178 SDPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SDPinfo)
2180 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2181 const sdp_packet_info *pi = SDPinfo;
2183 /* There are protocols like MGCP/SIP where the SDP is called before the tap for the
2184 MGCP/SIP packet, in those cases we assign the SPD summary to global lastSDPsummary
2187 g_free(sdp_summary);
2188 sdp_frame_num = pinfo->fd->num;
2189 /* Append to graph the SDP summary if the packet exists */
2190 sdp_summary = g_strdup_printf("SDP (%s)", pi->summary_str);
2191 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2193 tapinfo->redraw = TRUE;
2195 return 1; /* refresh output */
2199 /****************************************************************************/
2201 /****************************************************************************/
2202 static gboolean have_sdp_tap_listener=FALSE;
2203 /****************************************************************************/
2205 sdp_calls_init_tap(void)
2207 GString *error_string;
2209 if(have_sdp_tap_listener==FALSE)
2211 /* don't register tap listener, if we have it already */
2212 error_string = register_tap_listener("sdp", &(the_tapinfo_struct.sdp_dummy), NULL,
2213 voip_calls_dlg_reset,
2218 if (error_string != NULL) {
2219 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2221 g_string_free(error_string, TRUE);
2224 have_sdp_tap_listener=TRUE;
2228 /****************************************************************************/
2230 remove_tap_listener_sdp_calls(void)
2232 protect_thread_critical_region();
2233 remove_tap_listener(&(the_tapinfo_struct.sdp_dummy));
2234 unprotect_thread_critical_region();
2236 have_sdp_tap_listener=FALSE;
2241 /****************************************************************************/
2242 /* ***************************TAP for MGCP **********************************/
2243 /****************************************************************************/
2246 This function will look for a signal/event in the SignalReq/ObsEvent string
2247 and return true if it is found
2249 static gboolean isSignal(const gchar *signal, const gchar *signalStr)
2252 gchar **resultArray;
2254 /* if there is no signalStr, just return false */
2255 if (signalStr == NULL) return FALSE;
2257 /* if are both "blank" return true */
2258 if ( (*signal == '\0') && (*signalStr == '\0') ) return TRUE;
2260 /* look for signal in signalSre */
2261 resultArray = g_strsplit(signalStr, ",", 10);
2263 for (i = 0; resultArray[i]; i++) {
2264 g_strstrip(resultArray[i]);
2265 if (strcmp(resultArray[i], signal) == 0) return TRUE;
2268 g_strfreev(resultArray);
2274 This function will get the Caller ID info and replace the current string
2275 This is how it looks the caller Id: rg, ci(02/16/08/29, "3035550002","Ale Sipura 2")
2277 static void mgcpCallerID(gchar *signalStr, gchar **callerId)
2281 /* if there is no signalStr, just return false */
2282 if (signalStr == NULL) return;
2284 arrayStr = g_strsplit(signalStr, "\"", 10);
2286 if (arrayStr[0] == NULL) return;
2288 /* look for the ci signal */
2289 if (strstr(arrayStr[0], "ci(") && (arrayStr[1] != NULL) ) {
2290 /* free the previous "From" field of the call, and assign the new */
2292 *callerId = g_strdup(arrayStr[1]);
2294 g_strfreev(arrayStr);
2301 This function will get the Dialed Digits and replace the current string
2302 This is how it looks the dialed digits 5,5,5,0,0,0,2,#,*
2304 static void mgcpDialedDigits(gchar *signalStr, gchar **dialedDigits)
2307 gchar resultStr[50];
2310 /* if there is no signalStr, just return false */
2311 if (signalStr == NULL) return;
2313 tmpStr = g_strdup(signalStr);
2315 for ( i = 0 ; tmpStr[i] ; i++) {
2316 switch (tmpStr[i]) {
2317 case '0' : case '1' : case '2' : case '3' : case '4' :
2318 case '5' : case '6' : case '7' : case '8' : case '9' :
2319 case '#' : case '*' :
2327 for (i = 0, j = 0; tmpStr[i] && i<50; i++) {
2328 if (tmpStr[i] != '?')
2329 resultStr[j++] = tmpStr[i];
2331 resultStr[j] = '\0';
2333 if (*resultStr == '\0') return;
2335 g_free(*dialedDigits);
2336 *dialedDigits = g_strdup(resultStr);
2344 /****************************************************************************/
2345 /* whenever a MGCP packet is seen by the tap listener */
2347 MGCPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *MGCPinfo)
2349 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2351 voip_calls_info_t *tmp_listinfo;
2352 voip_calls_info_t *strinfo = NULL;
2353 mgcp_calls_info_t *tmp_mgcpinfo = NULL;
2356 gchar *frame_label = NULL;
2357 gchar *comment = NULL;
2358 graph_analysis_item_t *gai;
2359 gboolean new = FALSE;
2360 gboolean fromEndpoint = FALSE; /* true for calls originated in Endpoints, false for calls from MGC */
2363 const mgcp_info_t *pi = MGCPinfo;
2366 if ((pi->mgcp_type == MGCP_REQUEST) && !pi->is_duplicate ){
2367 /* check whether we already have a call with this Endpoint and it is active*/
2368 list = g_list_first(tapinfo->strinfo_list);
2371 tmp_listinfo=list->data;
2372 if ((tmp_listinfo->protocol == VOIP_MGCP) && (tmp_listinfo->call_active_state == VOIP_ACTIVE)){
2373 tmp_mgcpinfo = tmp_listinfo->prot_info;
2374 if (pi->endpointId != NULL){
2375 if (g_ascii_strcasecmp(tmp_mgcpinfo->endpointId,pi->endpointId) == 0){
2377 check first if it is an ended call. We can still match packets to this Endpoint 2 seconds
2378 after the call has been released
2380 diff_time = nstime_to_sec(&pinfo->fd->rel_ts) - tmp_listinfo->stop_sec - (double)tmp_listinfo->stop_usec/1000000;
2381 if ( ((tmp_listinfo->call_state == VOIP_CANCELLED) ||
2382 (tmp_listinfo->call_state == VOIP_COMPLETED) ||
2383 (tmp_listinfo->call_state == VOIP_REJECTED)) &&
2386 tmp_listinfo->call_active_state = VOIP_INACTIVE;
2388 strinfo = (voip_calls_info_t*)(list->data);
2394 list = g_list_next (list);
2397 /* there is no call with this Endpoint, lets see if this a new call or not */
2398 if (strinfo == NULL){
2399 if ( (strcmp(pi->code, "NTFY") == 0) && isSignal("hd", pi->observedEvents) ){ /* off hook transition */
2400 /* this is a new call from the Endpoint */
2401 fromEndpoint = TRUE;
2403 } else if (strcmp(pi->code, "CRCX") == 0){
2404 /* this is a new call from the MGC */
2405 fromEndpoint = FALSE;
2410 } else if ( ((pi->mgcp_type == MGCP_RESPONSE) && pi->request_available) ||
2411 ((pi->mgcp_type == MGCP_REQUEST) && pi->is_duplicate) ) {
2412 /* if it is a response OR if it is a duplicated Request, lets look in the Graph to see
2413 if there is a request that matches */
2414 listGraph = g_list_first(tapinfo->graph_analysis->list);
2417 gai = listGraph->data;
2418 if (gai->frame_num == pi->req_num){
2419 /* there is a request that match, so look the associated call with this call_num */
2420 list = g_list_first(tapinfo->strinfo_list);
2423 tmp_listinfo=list->data;
2424 if (tmp_listinfo->protocol == VOIP_MGCP){
2425 if (tmp_listinfo->call_num == gai->conv_num){
2426 tmp_mgcpinfo = tmp_listinfo->prot_info;
2427 strinfo = (voip_calls_info_t*)(list->data);
2431 list = g_list_next (list);
2433 if (strinfo != NULL) break;
2435 listGraph = g_list_next(listGraph);
2437 /* if there is not a matching request, just return */
2438 if (strinfo == NULL) return 0;
2441 /* not in the list? then create a new entry */
2443 strinfo = g_malloc0(sizeof(voip_calls_info_t));
2444 strinfo->call_active_state = VOIP_ACTIVE;
2445 strinfo->call_state = VOIP_CALL_SETUP;
2447 strinfo->from_identity=g_strdup(pi->endpointId);
2448 strinfo->to_identity=g_strdup("");
2450 strinfo->from_identity=g_strdup("");
2451 strinfo->to_identity=g_strdup(pi->endpointId);
2453 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
2454 strinfo->first_frame_num=pinfo->fd->num;
2455 strinfo->selected=FALSE;
2456 strinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
2457 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
2458 strinfo->protocol=VOIP_MGCP;
2459 strinfo->prot_info=g_malloc(sizeof(mgcp_calls_info_t));
2460 strinfo->free_prot_info = g_free;
2461 tmp_mgcpinfo=strinfo->prot_info;
2462 tmp_mgcpinfo->endpointId = g_strdup(pi->endpointId);
2463 tmp_mgcpinfo->fromEndpoint = fromEndpoint;
2464 strinfo->npackets = 0;
2465 strinfo->call_num = tapinfo->ncalls++;
2466 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
2469 g_assert(tmp_mgcpinfo != NULL);
2471 /* change call state and add to graph */
2472 switch (pi->mgcp_type)
2475 if ( (strcmp(pi->code, "NTFY") == 0) && (pi->observedEvents != NULL) ){
2476 frame_label = g_strdup_printf("%s ObsEvt:%s",pi->code, pi->observedEvents);
2478 if (tmp_mgcpinfo->fromEndpoint){
2479 /* use the Dialed digits to fill the "To" for the call, but use the first NTFY */
2480 if (strinfo->to_identity[0] == '\0') mgcpDialedDigits(pi->observedEvents, &(strinfo->to_identity));
2482 /* from MGC and the user picked up, the call is connected */
2483 } else if (isSignal("hd", pi->observedEvents))
2484 strinfo->call_state=VOIP_IN_CALL;
2486 /* hung up signal */
2487 if (isSignal("hu", pi->observedEvents)) {
2488 if ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state == VOIP_RINGING)){
2489 strinfo->call_state = VOIP_CANCELLED;
2491 strinfo->call_state = VOIP_COMPLETED;
2495 } else if (strcmp(pi->code, "RQNT") == 0) {
2496 /* for calls from Endpoint: if there is a "no signal" RQNT and the call was RINGING, we assume this is the CONNECT */
2497 if ( tmp_mgcpinfo->fromEndpoint && isSignal("", pi->signalReq) && (strinfo->call_state == VOIP_RINGING) ) {
2498 strinfo->call_state = VOIP_IN_CALL;
2501 /* if there is ringback or ring tone, change state to ringing */
2502 if ( isSignal("rg", pi->signalReq) || isSignal("rt", pi->signalReq) ) {
2503 strinfo->call_state = VOIP_RINGING;
2506 /* if there is a Busy or ReorderTone, and the call was Ringing or Setup the call is Rejected */
2507 if ( (isSignal("ro", pi->signalReq) || isSignal("bz", pi->signalReq)) && ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state = VOIP_RINGING)) ) {
2508 strinfo->call_state = VOIP_REJECTED;
2511 if (pi->signalReq != NULL)
2512 frame_label = g_strdup_printf("%s%sSigReq:%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"", pi->signalReq);
2514 frame_label = g_strdup_printf("%s%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"");
2516 /* use the CallerID info to fill the "From" for the call */
2517 if (!tmp_mgcpinfo->fromEndpoint) mgcpCallerID(pi->signalReq, &(strinfo->from_identity));
2519 } else if (strcmp(pi->code, "DLCX") == 0) {
2521 if there is a DLCX in a call To an Endpoint and the call was not connected, we use
2522 the DLCX as the end of the call
2524 if (!tmp_mgcpinfo->fromEndpoint){
2525 if ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state == VOIP_RINGING)){
2526 strinfo->call_state = VOIP_CANCELLED;
2531 if (frame_label == NULL) frame_label = g_strdup_printf("%s",pi->code);
2534 frame_label = g_strdup_printf("%u (%s)",pi->rspcode, pi->code);
2537 /* XXX what to do? */
2542 comment = g_strdup_printf("MGCP %s %s%s", tmp_mgcpinfo->endpointId, (pi->mgcp_type == MGCP_REQUEST)?"Request":"Response", pi->is_duplicate?" Duplicate":"");
2544 strinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
2545 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
2546 strinfo->last_frame_num=pinfo->fd->num;
2547 ++(strinfo->npackets);
2548 /* increment the packets counter of all calls */
2549 ++(tapinfo->npackets);
2551 /* add to the graph */
2552 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2554 g_free(frame_label);
2556 /* add SDP info if apply */
2557 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
2558 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2559 g_free(sdp_summary);
2563 tapinfo->redraw = TRUE;
2565 return 1; /* refresh output */
2569 /****************************************************************************/
2571 /****************************************************************************/
2572 static gboolean have_MGCP_tap_listener=FALSE;
2573 /****************************************************************************/
2575 mgcp_calls_init_tap(void)
2577 GString *error_string;
2579 if(have_MGCP_tap_listener==FALSE)
2581 /* don't register tap listener, if we have it already */
2582 /* we send an empty filter, to force a non null "tree" in the mgcp dissector */
2583 error_string = register_tap_listener("mgcp", &(the_tapinfo_struct.mgcp_dummy), strdup(""),
2584 voip_calls_dlg_reset,
2588 if (error_string != NULL) {
2589 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2591 g_string_free(error_string, TRUE);
2594 have_MGCP_tap_listener=TRUE;
2598 /****************************************************************************/
2600 remove_tap_listener_mgcp_calls(void)
2602 protect_thread_critical_region();
2603 remove_tap_listener(&(the_tapinfo_struct.mgcp_dummy));
2604 unprotect_thread_critical_region();
2606 have_MGCP_tap_listener=FALSE;
2610 /****************************************************************************/
2611 /****************************TAP for ACTRACE (AudioCodes trace)**************/
2612 /****************************************************************************/
2614 /* whenever a ACTRACE packet is seen by the tap listener */
2616 ACTRACEcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *ACTRACEinfo)
2618 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2619 const actrace_info_t *pi = ACTRACEinfo;
2621 actrace_cas_calls_info_t *tmp_actrace_cas_info;
2622 voip_calls_info_t *tmp_listinfo;
2623 voip_calls_info_t *strinfo = NULL;
2626 actrace_frame_num = pinfo->fd->num;
2627 actrace_trunk = pi->trunk;
2628 actrace_direction = pi->direction;
2630 if (pi->type == 1){ /* is CAS protocol */
2632 gchar *comment = NULL;
2635 list = g_list_first(tapinfo->strinfo_list);
2638 tmp_listinfo=list->data;
2639 if ( tmp_listinfo->protocol == VOIP_AC_CAS ){
2640 tmp_actrace_cas_info = tmp_listinfo->prot_info;
2641 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
2642 if ( (tmp_actrace_cas_info->bchannel == pi->cas_bchannel) && (tmp_actrace_cas_info->trunk == actrace_trunk) ) {
2643 strinfo = (voip_calls_info_t*)(list->data);
2647 list = g_list_next (list);
2650 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, g_strdup("PSTN"));
2652 /* if it is a new call, add it to the list */
2654 strinfo = g_malloc0(sizeof(voip_calls_info_t));
2655 strinfo->call_active_state = VOIP_ACTIVE;
2656 strinfo->call_state = VOIP_CALL_SETUP;
2657 strinfo->from_identity=g_strdup("N/A");
2658 strinfo->to_identity=g_strdup("N/A");
2659 COPY_ADDRESS(&(strinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
2660 strinfo->first_frame_num=pinfo->fd->num;
2661 strinfo->selected=FALSE;
2662 strinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
2663 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
2664 strinfo->protocol=VOIP_AC_CAS;
2665 strinfo->prot_info=g_malloc(sizeof(actrace_cas_calls_info_t));
2666 strinfo->free_prot_info = g_free;
2668 tmp_actrace_cas_info=strinfo->prot_info;
2669 tmp_actrace_cas_info->bchannel=pi->cas_bchannel;
2670 tmp_actrace_cas_info->trunk=actrace_trunk;
2671 strinfo->npackets = 0;
2672 strinfo->call_num = tapinfo->ncalls++;
2673 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
2676 strinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
2677 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
2678 strinfo->last_frame_num=pinfo->fd->num;
2679 ++(strinfo->npackets);
2680 /* increment the packets counter of all calls */
2681 ++(tapinfo->npackets);
2684 comment = g_strdup_printf("AC_CAS trunk:%u", actrace_trunk );
2686 add_to_graph(tapinfo, pinfo, pi->cas_frame_label , comment, strinfo->call_num,
2687 actrace_direction?&pstn_add:&(pinfo->src),
2688 actrace_direction?&(pinfo->src):&pstn_add,
2692 g_free((char *)pstn_add.data);
2695 tapinfo->redraw = TRUE;
2697 return 1; /* refresh output */
2701 /****************************************************************************/
2703 /****************************************************************************/
2704 static gboolean have_actrace_tap_listener=FALSE;
2705 /****************************************************************************/
2707 actrace_calls_init_tap(void)
2709 GString *error_string;
2711 if(have_actrace_tap_listener==FALSE)
2713 /* don't register tap listener, if we have it already */
2714 error_string = register_tap_listener("actrace", &(the_tapinfo_struct.actrace_dummy), NULL,
2715 voip_calls_dlg_reset,
2716 ACTRACEcalls_packet,
2720 if (error_string != NULL) {
2721 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2723 g_string_free(error_string, TRUE);
2726 have_actrace_tap_listener=TRUE;
2730 /****************************************************************************/
2732 remove_tap_listener_actrace_calls(void)
2734 protect_thread_critical_region();
2735 remove_tap_listener(&(the_tapinfo_struct.actrace_dummy));
2736 unprotect_thread_critical_region();
2738 have_actrace_tap_listener=FALSE;
2745 /**************************** TAP for H248/MEGACO **********************************/
2746 static gboolean have_h248_tap_listener = FALSE;
2747 static gboolean have_megaco_tap_listener = FALSE;
2749 #define gcp_is_req(type) ( type == GCP_CMD_ADD_REQ || type == GCP_CMD_MOVE_REQ || type == GCP_CMD_MOD_REQ || \
2750 type == GCP_CMD_SUB_REQ || type == GCP_CMD_AUDITCAP_REQ || type == GCP_CMD_AUDITVAL_REQ || \
2751 type == GCP_CMD_NOTIFY_REQ || type == GCP_CMD_SVCCHG_REQ || type == GCP_CMD_TOPOLOGY_REQ || \
2752 type == GCP_CMD_CTX_ATTR_AUDIT_REQ )
2754 static int h248_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
2755 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2756 const gcp_cmd_t* cmd = prot_info;
2758 voip_calls_info_t *strinfo = NULL;
2761 gchar mgw_addr[128];
2763 if (cmd->ctx->id == NULL_CONTEXT || cmd->ctx->id == ALL_CONTEXTS ) {
2767 if ( gcp_is_req(cmd->type) ) {
2768 mgw = &(pinfo->dst);
2769 mgc = &(pinfo->src);
2771 mgc = &(pinfo->dst);
2772 mgw = &(pinfo->src);
2775 address_to_str_buf(mgw, mgw_addr, 128);
2777 /* check whether we already have this context in the list */
2778 list = g_list_first(tapinfo->strinfo_list);
2781 voip_calls_info_t* tmp_listinfo = list->data;
2783 if (tmp_listinfo->protocol == TEL_H248){
2784 if (tmp_listinfo->prot_info == cmd->ctx){
2785 strinfo = (voip_calls_info_t*)(list->data);
2789 list = g_list_next (list);
2794 strinfo = g_malloc0(sizeof(voip_calls_info_t));
2795 strinfo->call_state = VOIP_NO_STATE;
2796 strinfo->call_active_state = VOIP_ACTIVE;
2797 strinfo->from_identity = g_strdup_printf("%s : %.8x", mgw_addr, cmd->ctx->id);
2798 strinfo->to_identity = g_strdup("");
2799 strinfo->prot_info = cmd->ctx;
2800 strinfo->free_prot_info = NULL;
2802 strinfo->npackets = 1;
2803 strinfo->first_frame_num=pinfo->fd->num;
2804 strinfo->last_frame_num=pinfo->fd->num;
2806 COPY_ADDRESS(&(strinfo->initial_speaker), mgc);
2808 strinfo->protocol = TEL_H248;
2809 strinfo->call_num = tapinfo->ncalls++;
2810 strinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
2811 strinfo->start_usec=pinfo->fd->rel_ts.nsecs;
2812 strinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
2813 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
2815 strinfo->selected = FALSE;
2817 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
2820 GString* s = g_string_new("");
2821 gcp_terms_t *ctx_term;
2823 g_free(strinfo->from_identity);
2824 strinfo->from_identity = g_strdup_printf("%s : %.8x", mgw_addr, ((gcp_ctx_t*)strinfo->prot_info)->id);
2826 g_free(strinfo->to_identity);
2828 for (ctx_term = ((gcp_ctx_t*)strinfo->prot_info)->terms.next;
2830 ctx_term = ctx_term->next ) {
2831 if ( ctx_term->term && ctx_term->term->str) {
2832 g_string_sprintfa(s," %s",ctx_term->term->str);
2836 strinfo->to_identity = s->str;
2837 g_string_free(s,FALSE);
2839 strinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
2840 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
2841 strinfo->last_frame_num=pinfo->fd->num;
2842 ++(strinfo->npackets);
2845 add_to_graph(tapinfo, pinfo, cmd->str ? cmd->str : "unknown Msg",
2846 ep_strdup_printf("TrxId = %u, CtxId = %.8x",cmd->trx->id,cmd->ctx->id),
2847 strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2849 ++(tapinfo->npackets);
2851 tapinfo->redraw = TRUE;
2856 void h248_calls_init_tap(void)
2858 GString *error_string;
2861 if(have_megaco_tap_listener==FALSE)
2863 error_string = register_tap_listener("megaco", &(the_tapinfo_struct.megaco_dummy),
2865 voip_calls_dlg_reset,
2867 voip_calls_dlg_draw);
2869 if (error_string != NULL) {
2870 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2872 g_string_free(error_string, TRUE);
2876 have_megaco_tap_listener=TRUE;
2879 if(have_h248_tap_listener==FALSE)
2881 error_string = register_tap_listener("h248", &(the_tapinfo_struct.h248_dummy),
2883 voip_calls_dlg_reset,
2885 voip_calls_dlg_draw);
2887 if (error_string != NULL) {
2888 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2890 g_string_free(error_string, TRUE);
2894 have_h248_tap_listener=TRUE;
2899 remove_tap_listener_h248_calls(void)
2901 protect_thread_critical_region();
2902 remove_tap_listener(&(the_tapinfo_struct.h248_dummy));
2903 remove_tap_listener(&(the_tapinfo_struct.megaco_dummy));
2904 unprotect_thread_critical_region();
2906 have_megaco_tap_listener=FALSE;
2907 have_h248_tap_listener=FALSE;
2911 /**************************** TAP for SCCP and SUA **********************************/
2912 /**************************** ( RANAP and BSSAP ) **********************************/
2913 static gboolean have_sccp_tap_listener = FALSE;
2914 static gboolean have_sua_tap_listener = FALSE;
2916 static const voip_protocol sccp_proto_map[] = {
2921 #define SP2VP(ap) ((ap) < SCCP_PLOAD_NUM_PLOADS ? sccp_proto_map[(ap)] : TEL_SCCP)
2922 const value_string* sccp_payload_values;
2924 static int sccp_calls(packet_info *pinfo, const void *prot_info) {
2925 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2926 const sccp_msg_info_t* msg = prot_info;
2927 sccp_assoc_info_t* assoc = msg->data.co.assoc;
2929 voip_calls_info_t *strinfo = NULL;
2930 const gchar* label = NULL;
2931 const gchar* comment = NULL;
2932 /* check whether we already have this assoc in the list */
2934 for(list = g_list_first(tapinfo->strinfo_list) ; list ; list = g_list_next (list) ) {
2935 if ( ((voip_calls_info_t*)(list->data))->prot_info == assoc ){
2936 strinfo = (voip_calls_info_t*)(list->data);
2942 strinfo = g_malloc0(sizeof(voip_calls_info_t));
2943 strinfo->call_state = VOIP_CALL_SETUP;
2944 strinfo->call_active_state = VOIP_ACTIVE;
2945 if ( assoc->calling_party ) {
2946 strinfo->from_identity = g_strdup(assoc->calling_party);
2948 strinfo->from_identity = g_strdup("Unknown");
2951 if ( assoc->called_party ) {
2952 strinfo->to_identity = g_strdup(assoc->called_party);
2954 strinfo->to_identity = g_strdup("Unknown");
2957 strinfo->prot_info = (void*)assoc;
2958 strinfo->free_prot_info = NULL;
2960 strinfo->npackets = 1;
2961 strinfo->first_frame_num=pinfo->fd->num;
2962 strinfo->last_frame_num=pinfo->fd->num;
2964 COPY_ADDRESS(&(strinfo->initial_speaker), &(pinfo->src));
2966 strinfo->protocol = SP2VP(assoc->payload);
2967 strinfo->start_sec=(gint32) pinfo->fd->rel_ts.secs;
2968 strinfo->start_usec=pinfo->fd->rel_ts.nsecs;
2969 strinfo->stop_sec=(gint32) pinfo->fd->rel_ts.secs;
2970 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
2972 strinfo->selected = FALSE;
2973 strinfo->call_num = tapinfo->ncalls++;
2975 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
2978 if ( assoc->calling_party ) {
2979 if (strinfo->from_identity) g_free(strinfo->from_identity );
2980 strinfo->from_identity = g_strdup(assoc->calling_party);
2983 if ( assoc->called_party ) {
2984 if (strinfo->to_identity) g_free(strinfo->to_identity );
2985 strinfo->to_identity = g_strdup(assoc->called_party);
2988 strinfo->protocol = SP2VP(assoc->payload);
2989 strinfo->stop_sec=(gint32) pinfo->fd->rel_ts.secs;
2990 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
2991 strinfo->last_frame_num=pinfo->fd->num;
2992 ++(strinfo->npackets);
2994 switch (msg->type) {
2995 case SCCP_MSG_TYPE_CC:
2996 strinfo->call_state = VOIP_IN_CALL;
2998 case SCCP_MSG_TYPE_RLC:
2999 strinfo->call_state = VOIP_COMPLETED;
3000 strinfo->call_active_state = VOIP_INACTIVE;
3007 if (msg->data.co.label) {
3008 label = msg->data.co.label;
3010 label = val_to_str(msg->type, sccp_payload_values, "Unknown(%d)");
3013 if (msg->data.co.comment) {
3014 comment = msg->data.co.comment;
3019 add_to_graph(tapinfo, pinfo, label,(void*) comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3021 ++(tapinfo->npackets);
3023 tapinfo->redraw = TRUE;
3028 static int sccp_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
3029 sccp_payload_values = sccp_message_type_acro_values;
3030 return sccp_calls(pinfo, prot_info);
3034 static int sua_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
3035 sccp_payload_values = sua_co_class_type_acro_values;
3036 return sccp_calls(pinfo, prot_info);
3040 void sccp_calls_init_tap(void)
3042 GString *error_string;
3044 if(have_sccp_tap_listener==FALSE)
3046 error_string = register_tap_listener("sccp", &(the_tapinfo_struct.sccp_dummy),
3048 voip_calls_dlg_reset,
3050 voip_calls_dlg_draw);
3052 if (error_string != NULL) {
3053 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3055 g_string_free(error_string, TRUE);
3059 have_sccp_tap_listener=TRUE;
3062 if(have_sua_tap_listener==FALSE)
3064 error_string = register_tap_listener("sua", &(the_tapinfo_struct.sua_dummy),
3066 voip_calls_dlg_reset,
3068 voip_calls_dlg_draw);
3070 if (error_string != NULL) {
3071 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3073 g_string_free(error_string, TRUE);
3077 have_sua_tap_listener=TRUE;
3083 remove_tap_listener_sccp_calls(void)
3085 protect_thread_critical_region();
3086 remove_tap_listener(&(the_tapinfo_struct.sccp_dummy));
3087 unprotect_thread_critical_region();
3089 have_sccp_tap_listener=FALSE;
3090 have_sua_tap_listener=FALSE;
3094 /****************************************************************************/
3095 /****************************TAP for UNISTIM ********************************/
3096 /****************************************************************************/
3099 unistim_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *unistim_info)
3101 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3102 voip_calls_info_t *tmp_listinfo;
3103 voip_calls_info_t *strinfo = NULL;
3104 unistim_info_t *tmp_unistim_info = NULL;
3106 GString *g_tmp = NULL;
3107 gchar *frame_label = NULL;
3108 gchar *comment = NULL;
3110 /* Fetch specific packet infos */
3111 const unistim_info_t *pi = unistim_info;
3114 g_tmp = g_string_new(NULL);
3116 /* Check to see if this is a dup */
3117 list = g_list_first(tapinfo->strinfo_list);
3121 tmp_listinfo = list->data;
3123 if(tmp_listinfo->protocol == VOIP_UNISTIM){
3125 tmp_unistim_info = tmp_listinfo->prot_info;
3127 /* Search by termid if possible, otherwise use ni/it ip + port.. */
3128 if(pi->termid != 0){
3129 if(tmp_unistim_info->termid == pi->termid){
3130 /* If the call has ended, then we can reuse it.. */
3131 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
3134 strinfo = (voip_calls_info_t*)(list->data);
3139 /* If no term id use ips / port to find entry */
3140 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)){
3141 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
3142 /* Do nothing previous call */
3144 strinfo = (voip_calls_info_t*)(list->data);
3148 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)) {
3149 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
3150 /* Do nothing, it ain't our call.. */
3152 strinfo = (voip_calls_info_t*)(list->data);
3159 /* Otherwise, go to the next one.. */
3160 list = g_list_next(list);
3163 if(pi->payload_type == 2 || pi->payload_type == 1){
3165 if(pi->key_state == 1 || pi->hook_state == 1){
3167 /* If the user hits a button,
3168 Session will be SETUP */
3170 /* If new add to list */
3173 strinfo = g_malloc0(sizeof(voip_calls_info_t));
3174 strinfo->call_active_state = VOIP_ACTIVE;
3175 strinfo->call_state = VOIP_CALL_SETUP;
3176 strinfo->from_identity=g_strdup_printf("%x",pi->termid);
3177 strinfo->to_identity=g_strdup_printf("UNKNOWN");
3178 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
3179 strinfo->first_frame_num=pinfo->fd->num;
3180 strinfo->selected=FALSE;
3182 /* Set this on init of struct so in case the call doesn't complete, we'll have a ref. */
3183 /* Otherwise if the call is completed we'll have the open/close streams to ref actual call duration */
3184 strinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3185 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3187 strinfo->protocol=VOIP_UNISTIM;
3188 strinfo->prot_info=g_malloc(sizeof(unistim_info_t));
3190 tmp_unistim_info = strinfo->prot_info;
3192 /* Clear tap struct */
3193 tmp_unistim_info->rudp_type = 0;
3194 tmp_unistim_info->payload_type = 0;
3195 tmp_unistim_info->sequence = pi->sequence;
3196 tmp_unistim_info->termid = pi->termid;
3197 tmp_unistim_info->key_val = -1;
3198 tmp_unistim_info->key_state = -1;
3199 tmp_unistim_info->hook_state = -1;
3200 tmp_unistim_info->stream_connect = -1;
3201 tmp_unistim_info->trans_connect = -1;
3202 tmp_unistim_info->set_termid = -1;
3203 tmp_unistim_info->string_data = NULL;
3204 tmp_unistim_info->key_buffer = NULL;
3206 COPY_ADDRESS(&(tmp_unistim_info->it_ip),&(pi->it_ip));
3207 COPY_ADDRESS(&(tmp_unistim_info->ni_ip),&(pi->ni_ip));
3208 tmp_unistim_info->it_port = pi->it_port;
3210 strinfo->free_prot_info = g_free;
3211 strinfo->npackets = 0;
3212 strinfo->call_num = tapinfo->ncalls++;
3213 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
3217 /* Set up call wide info struct */
3218 tmp_unistim_info = strinfo->prot_info;
3219 tmp_unistim_info->sequence = pi->sequence;
3222 /* Each packet COULD BE OUR LAST!!!! */
3223 strinfo->stop_sec=(gint32)(pinfo->fd->rel_ts.secs);
3224 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
3225 strinfo->last_frame_num=pinfo->fd->num;
3227 /* This is a valid packet so increment counter */
3228 ++(strinfo->npackets);
3230 /* increment the packets counter of all calls */
3231 ++(tapinfo->npackets);
3233 /* Key was depressed.. update key buffer.. */
3234 if(pi->key_val >= 0 && pi->key_val <= 11){
3236 if(tmp_unistim_info->key_buffer != NULL){
3238 /* assign to temp variable */
3239 g_string_assign(g_tmp,tmp_unistim_info->key_buffer);
3241 /* Manipulate the data */
3242 if(pi->key_val == 10) {
3243 tmp_unistim_info->key_buffer = g_strdup_printf("%s*",g_tmp->str);
3244 } else if(pi->key_val == 11) {
3245 tmp_unistim_info->key_buffer = g_strdup_printf("%s#",g_tmp->str);
3247 tmp_unistim_info->key_buffer = g_strdup_printf("%s%d",g_tmp->str,pi->key_val);
3252 /* Create new string */
3253 if(pi->key_val == 10) {
3254 tmp_unistim_info->key_buffer = g_strdup_printf("*");
3255 } else if(pi->key_val == 11) {
3256 tmp_unistim_info->key_buffer = g_strdup_printf("#");
3258 tmp_unistim_info->key_buffer = g_strdup_printf("%d",pi->key_val);
3263 /* Select for non-digit characters */
3264 if(pi->key_val == 10) {
3265 comment = g_strdup_printf("Key Input Sent: * (%d)", pi->sequence);
3266 } else if(pi->key_val == 11) {
3267 comment = g_strdup_printf("Key Input Sent: # (%d)", pi->sequence);
3269 comment = g_strdup_printf("Key Input Sent: %d (%d)",pi->key_val, pi->sequence);
3271 } else if(pi->key_val == 12) {
3272 /* Set label and comment for graph */
3273 comment = g_strdup_printf("Key Input Sent: UP (%d)", pi->sequence);
3274 } else if(pi->key_val == 13) {
3275 /* Set label and comment for graph */
3276 comment = g_strdup_printf("Key Input Sent: DOWN (%d)", pi->sequence);
3277 } else if(pi->key_val == 14) {
3278 /* Set label and comment for graph */
3279 comment = g_strdup_printf("Key Input Sent: RIGHT (%d)", pi->sequence);
3280 } else if(pi->key_val == 15) {
3281 if(pi->key_buffer != NULL){
3283 g_string_assign(g_tmp,pi->key_buffer);
3285 /* Manipulate the data */
3286 g_string_truncate(g_tmp,g_tmp->len-1);
3288 /* Insert new data */
3289 tmp_unistim_info->key_buffer = g_strdup_printf("%s",g_tmp->str);
3292 /* Set label and comment for graph */
3293 comment = g_strdup_printf("Key Input Sent: LEFT (%d)", pi->sequence);
3294 } else if(pi->key_val == 20) {
3295 /* User pressed the soft key 0 probably dial */
3296 comment = g_strdup_printf("Key Input Sent: S0 (%d)", pi->sequence);
3297 } else if(pi->key_val == 21) {
3298 /* User pressed the soft key 1 */
3299 comment = g_strdup_printf("Key Input Sent: S1 (%d)", pi->sequence);
3300 } else if(pi->key_val == 22) {
3301 /* User pressed the soft key 2 */
3302 /* On cs2k phones, soft key 2 is backspace. */
3303 if(pi->key_buffer != NULL) {
3306 g_string_assign(g_tmp,pi->key_buffer);
3308 /* Manipulate the data */
3309 g_string_truncate(g_tmp,g_tmp->len-1);
3311 /* Insert new data */
3312 tmp_unistim_info->key_buffer = g_strdup_printf("%s",g_tmp->str);
3315 /* add label and comment */
3316 comment = g_strdup_printf("Key Input Sent: S2 (%d)", pi->sequence);
3317 } else if(pi->key_val == 28) {
3318 /* User pressed something */
3319 comment = g_strdup_printf("Key Input Sent: Release (%d)", pi->sequence);
3320 } else if(pi->key_val == 23) {
3321 /* User pressed the soft key 3 */
3322 /* Cancel on cs2k so clear buffer */
3323 /* On mcs its config which will clear the buffer too */
3324 tmp_unistim_info->key_buffer = g_strdup_printf("\n");
3326 /* User pressed something, set labels*/
3327 comment = g_strdup_printf("Key Input Sent: S3 (%d)", pi->sequence);
3328 } else if(pi->key_val == 27) {
3329 /* User pressed something */
3330 comment = g_strdup_printf("Key Input Sent: Hold (%d)", pi->sequence);
3331 } else if(pi->key_val == 29) {
3332 /* User pressed something */
3333 comment = g_strdup_printf("Key Input Sent: Mute (%d)", pi->sequence);
3334 } else if(pi->key_val == 30) {
3335 /* User pressed something */
3336 comment = g_strdup_printf("Key Input Sent: Headset (%d)", pi->sequence);
3337 } else if(pi->key_val == 31) {
3338 /* Handsfree button */
3339 comment = g_strdup_printf("Key Input Sent: Handsfree (%d)", pi->sequence);
3340 } else if(pi->key_val >= 32 && pi->key_val <= 56) {
3342 comment = g_strdup_printf("Key Input Sent: Prog%d (%d)", (pi->key_val & 31), pi->sequence);
3345 if(pi->key_val != -1) {
3347 frame_label = g_strdup_printf("KEY INPUT");
3349 if (comment == NULL)
3350 /* Ouch! What do you do!? */
3351 /* User pressed something */
3352 comment = g_strdup_printf("Key Input Sent: UNKNOWN - %d (%d)", pi->key_val, pi->sequence);
3354 /* add to the graph */
3355 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3359 if(pi->hook_state == 1) {
3361 /* Phone is off hook */
3362 frame_label = g_strdup_printf("OFF HOOK");
3363 comment = g_strdup_printf("Off Hook (%d)", pi->sequence);
3365 /* add to the graph */
3366 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3367 } else if(pi->hook_state == 0) {
3369 /* Phone is on hook */
3370 frame_label = g_strdup_printf("ON HOOK");
3371 comment = g_strdup_printf("On Hook (%d)", pi->sequence);
3373 /* add to the graph */
3374 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3379 /* Open stream was sent from server */
3380 if(pi->stream_connect == 1 && strinfo != NULL) {
3383 /* Signifies the start of the call so set start_sec & start_usec */
3384 strinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3385 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3387 /* Local packets too */
3388 ++(strinfo->npackets);
3390 /* increment the packets counter of all calls */
3391 ++(tapinfo->npackets);
3393 /* ?? means we're not quite sure if this is accurate. Since Unistim isn't a true
3394 Call control protocol, we can only guess at the destination by messing with
3396 if(tmp_unistim_info->key_buffer != NULL){
3397 strinfo->to_identity = g_strdup_printf("?? %s",tmp_unistim_info->key_buffer);
3400 /* change sequence number for ACK detection */
3401 tmp_unistim_info->sequence = pi->sequence;
3403 /* State changes too */
3404 strinfo->call_active_state = VOIP_ACTIVE;
3405 strinfo->call_state = VOIP_IN_CALL;
3407 /* Add graph data */
3408 frame_label = g_strdup_printf("STREAM OPENED");
3409 comment = g_strdup_printf("Stream Opened (%d)",pi->sequence);
3411 /* add to the graph */
3412 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3414 /* Redraw the scree */
3415 tapinfo->redraw = TRUE;
3418 } else if(pi->stream_connect == 1 && strinfo == NULL) {
3420 /* Research indicates some nortel products initiate stream first
3421 * without keypresses. therefore creating this solely on a keypress is
3423 * Sometimes calls start immediately with open stream.
3425 strinfo = g_malloc0(sizeof(voip_calls_info_t));
3426 strinfo->call_active_state = VOIP_ACTIVE;
3427 strinfo->call_state = VOIP_CALL_SETUP;
3428 strinfo->from_identity=g_strdup_printf("UNKNOWN");
3429 strinfo->to_identity=g_strdup_printf("UNKNOWN");
3430 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
3431 strinfo->first_frame_num=pinfo->fd->num;
3432 strinfo->selected=FALSE;
3434 /* Set this on init of struct so in case the call doesn't complete, we'll have a ref. */
3435 /* Otherwise if the call is completed we'll have the open/close streams to ref actual call duration */
3436 strinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3437 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3439 strinfo->protocol=VOIP_UNISTIM;
3440 strinfo->prot_info=g_malloc(sizeof(unistim_info_t));
3442 tmp_unistim_info = strinfo->prot_info;
3444 /* Clear tap struct */
3445 tmp_unistim_info->rudp_type = 0;
3446 tmp_unistim_info->payload_type = 0;
3447 tmp_unistim_info->sequence = pi->sequence;
3448 tmp_unistim_info->termid = 0;
3449 tmp_unistim_info->key_val = -1;
3450 tmp_unistim_info->key_state = -1;
3451 tmp_unistim_info->hook_state = -1;
3452 tmp_unistim_info->stream_connect = -1;
3453 tmp_unistim_info->trans_connect = -1;
3454 tmp_unistim_info->set_termid = -1;
3455 tmp_unistim_info->string_data = NULL;
3456 tmp_unistim_info->key_buffer = NULL;
3458 COPY_ADDRESS(&(tmp_unistim_info->it_ip),&(pi->it_ip));
3459 COPY_ADDRESS(&(tmp_unistim_info->ni_ip),&(pi->ni_ip));
3460 tmp_unistim_info->it_port = pi->it_port;
3462 strinfo->free_prot_info = g_free;
3463 strinfo->npackets = 0;
3464 strinfo->call_num = tapinfo->ncalls++;
3465 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
3468 /* Signifies the start of the call so set start_sec & start_usec */
3469 strinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3470 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3472 /* Local packets too */
3473 ++(strinfo->npackets);
3475 /* increment the packets counter of all calls */
3476 ++(tapinfo->npackets);
3478 /* ?? means we're not quite sure if this is accurate. Since Unistim isn't a true
3479 Call control protocol, we can only guess at the destination by messing with
3481 if(tmp_unistim_info->key_buffer != NULL){
3482 strinfo->to_identity = g_strdup_printf("?? %s",tmp_unistim_info->key_buffer);
3485 /* change sequence number for ACK detection */
3486 tmp_unistim_info->sequence = pi->sequence;
3488 /* State changes too */
3489 strinfo->call_active_state = VOIP_ACTIVE;
3490 strinfo->call_state = VOIP_IN_CALL;
3492 /* Add graph data */
3493 frame_label = g_strdup_printf("STREAM OPENED");
3494 comment = g_strdup_printf("Stream Opened (%d)",pi->sequence);
3496 /* add to the graph */
3497 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3499 /* Redraw the scree */
3500 tapinfo->redraw = TRUE;
3504 } else if(pi->stream_connect == 0 && strinfo != NULL) {
3507 /* Set stop seconds + usec */
3508 strinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
3509 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
3510 strinfo->last_frame_num=pinfo->fd->num;
3512 tmp_unistim_info->sequence = pi->sequence;
3514 if(strinfo->call_state == VOIP_IN_CALL){
3515 strinfo->call_active_state = VOIP_INACTIVE;
3516 strinfo->call_state = VOIP_COMPLETED;
3518 strinfo->call_state = VOIP_UNKNOWN;
3519 strinfo->call_active_state = VOIP_INACTIVE;
3522 frame_label = g_strdup_printf("STREAM CLOSED");
3523 comment = g_strdup_printf("Stream Closed (%d)",pi->sequence);
3525 /* add to the graph */
3526 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3530 } else if(pi->rudp_type == 1 && strinfo != NULL) {
3532 /* Only show acks for processed seq #s */
3533 if(tmp_unistim_info->sequence == pi->sequence) {
3535 frame_label = g_strdup_printf("ACK");
3536 comment = g_strdup_printf("ACK for sequence %d",pi->sequence);
3538 /* add to the graph */
3539 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3543 } else if(pi->rudp_type == 0 && strinfo != NULL) {
3546 frame_label = g_strdup_printf("NAK");
3547 comment = g_strdup_printf("NAK for sequence %d",pi->sequence);
3549 /* add to the graph */
3550 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3555 g_free(frame_label);
3558 tapinfo->redraw = TRUE;
3563 /****************************************************************************/
3565 /****************************************************************************/
3566 static gboolean have_unistim_tap_listener=FALSE;
3567 /****************************************************************************/
3569 unistim_calls_init_tap(void){
3571 GString *error_string;
3573 if(have_unistim_tap_listener==FALSE) {
3575 error_string = register_tap_listener("unistim", &(the_tapinfo_struct.unistim_dummy),
3577 voip_calls_dlg_reset,
3578 unistim_calls_packet,
3582 if (error_string != NULL) {
3583 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3585 g_string_free(error_string, TRUE);
3589 have_unistim_tap_listener=TRUE;
3593 /****************************************************************************/
3595 remove_tap_listener_unistim_calls(void)
3597 protect_thread_critical_region();
3598 remove_tap_listener(&(the_tapinfo_struct.unistim_dummy));
3599 unprotect_thread_critical_region();
3601 have_unistim_tap_listener=FALSE;
3604 /****************************************************************************/
3605 /* ***************************TAP for OTHER PROTOCOL **********************************/
3606 /****************************************************************************/
3609 VoIPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *VoIPinfo _U_)
3611 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3612 voip_calls_info_t *strinfo = NULL;
3613 voip_calls_info_t *tmp_listinfo;
3615 const voip_packet_info_t *pi = VoIPinfo;
3618 list = g_list_first(tapinfo->strinfo_list);
3620 tmp_listinfo = list->data;
3621 if ( tmp_listinfo->protocol == VOIP_COMMON ) {
3622 if (!strcmp(pi->call_id, tmp_listinfo->call_id)) {
3623 strinfo = (voip_calls_info_t*)(list->data);
3627 list = g_list_next(list);
3630 if (strinfo == NULL) {
3631 strinfo = g_malloc0(sizeof(voip_calls_info_t));
3632 strinfo->call_active_state = pi->call_active_state;
3633 strinfo->call_state = pi->call_state;
3634 strinfo->call_id=g_strdup((pi->call_id)?pi->call_id:"");
3635 strinfo->from_identity = g_strdup((pi->from_identity)?pi->from_identity:"");
3636 strinfo->to_identity = g_strdup((pi->to_identity)?pi->to_identity:"");
3637 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
3638 strinfo->selected=FALSE;
3639 strinfo->first_frame_num=pinfo->fd->num;
3640 strinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3641 strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3642 strinfo->protocol=VOIP_COMMON;
3643 strinfo->protocol_name=g_strdup((pi->protocol_name)?pi->protocol_name:"");
3644 strinfo->call_comment=g_strdup((pi->call_comment)?pi->call_comment:"");
3645 strinfo->prot_info=NULL;
3646 strinfo->free_prot_info = NULL;
3648 strinfo->call_num = tapinfo->ncalls++;
3649 strinfo->npackets = 0;
3651 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
3654 if (strinfo != NULL) {
3655 strinfo->call_active_state = pi->call_active_state;
3656 if ((strinfo->call_state != VOIP_COMPLETED) && (pi->call_state == VOIP_COMPLETED))
3657 tapinfo->completed_calls++;
3658 if (pi->call_state != VOIP_NO_STATE)
3659 strinfo->call_state = pi->call_state;
3660 strinfo->stop_sec=(gint32)(pinfo->fd->rel_ts.secs);
3661 strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
3662 strinfo->last_frame_num=pinfo->fd->num;
3663 ++(strinfo->npackets);
3664 ++(tapinfo->npackets);
3667 /* add to the graph */
3668 add_to_graph(tapinfo, pinfo, (pi->frame_label)?pi->frame_label:"VoIP msg", (pi->frame_comment)?pi->frame_comment:"", strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3670 tapinfo->redraw = TRUE;
3674 /****************************************************************************/
3675 static gboolean have_voip_tap_listener=FALSE;
3678 VoIPcalls_init_tap(void)
3680 GString *error_string;
3682 if(have_voip_tap_listener==FALSE)
3684 error_string = register_tap_listener("voip", &(the_tapinfo_struct.voip_dummy),
3686 voip_calls_dlg_reset,
3691 if (error_string != NULL) {
3692 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3694 g_string_free(error_string, TRUE);
3697 have_voip_tap_listener=TRUE;
3700 /****************************************************************************/
3702 remove_tap_listener_voip_calls(void)
3704 protect_thread_critical_region();
3705 remove_tap_listener(&(the_tapinfo_struct.voip_dummy));
3706 unprotect_thread_critical_region();
3708 have_voip_tap_listener=FALSE;
3712 /****************************************************************************/
3713 /* ***************************TAP for OTHER PROTOCOL **********************************/
3714 /****************************************************************************/
3716 /****************************************************************************/
3717 /* whenever a prot_ packet is seen by the tap listener */
3720 prot_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info _U_)
3722 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3724 strinfo->stop_sec=pinfo->fd->rel_secs;
3725 strinfo->stop_usec=pinfo->fd->rel_usecs;
3726 strinfo->last_frame_num=pinfo->fd->num;
3727 ++(strinfo->npackets);
3728 ++(tapinfo->npackets);
3731 tapinfo->redraw = TRUE;
3736 /****************************************************************************/
3738 static gboolean have_prot__tap_listener=FALSE;
3741 prot_calls_init_tap(void)
3743 GString *error_string;
3745 if(have_prot__tap_listener==FALSE)
3747 error_string = register_tap_listener("prot_", &(the_tapinfo_struct.prot__dummy),
3749 voip_calls_dlg_reset,
3754 if (error_string != NULL) {
3755 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3757 g_string_free(error_string, TRUE);
3760 have_prot__tap_listener=TRUE;
3764 /****************************************************************************/
3767 remove_tap_listener_prot__calls(void)
3769 protect_thread_critical_region();
3770 remove_tap_listener(&(the_tapinfo_struct.prot__dummy));
3771 unprotect_thread_critical_region();
3773 have_prot__tap_listener=FALSE;