2 * VoIP calls summary addition for Wireshark
6 * Copyright 2004, Ericsson, Spain
7 * By Francisco Alcoba <francisco.alcoba@ericsson.com>
9 * based on h323_calls.c
10 * Copyright 2004, Iskratel, Ltd, Kranj
11 * By Miha Jemec <m.jemec@iskratel.si>
13 * H323, RTP, RTP Event, MGCP, AudioCodes (ISDN PRI and CAS), T38 and Graph Support
14 * By Alejandro Vaquero, alejandro.vaquero@verso.com
15 * Copyright 2005, Verso Technologies Inc.
17 * Wireshark - Network traffic analyzer
18 * By Gerald Combs <gerald@wireshark.org>
19 * Copyright 1998 Gerald Combs
21 * This program is free software; you can redistribute it and/or
22 * modify it under the terms of the GNU General Public License
23 * as published by the Free Software Foundation; either version 2
24 * of the License, or (at your option) any later version.
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
41 #include <epan/epan.h>
42 #include <epan/packet.h>
44 #include <epan/tap-voip.h>
45 #include <epan/dissectors/packet-sip.h>
46 #include <epan/dissectors/packet-mtp3.h>
47 #include <epan/dissectors/packet-isup.h>
48 #include <epan/dissectors/packet-h225.h>
49 #include <epan/dissectors/packet-h245.h>
50 #include <epan/dissectors/packet-q931.h>
51 #include <epan/dissectors/packet-sdp.h>
52 #include <epan/dissectors/packet-mgcp.h>
53 #include <epan/dissectors/packet-actrace.h>
54 #include <epan/dissectors/packet-rtp.h>
55 #include <epan/dissectors/packet-rtp-events.h>
56 #include <epan/dissectors/packet-t38.h>
57 #include <epan/dissectors/packet-t30.h>
58 #include <epan/dissectors/packet-h248.h>
59 #include <epan/dissectors/packet-sccp.h>
60 #include <plugins/unistim/packet-unistim.h>
61 #include <epan/dissectors/packet-skinny.h>
62 #include <epan/dissectors/packet-iax2.h>
63 #include <epan/rtp_pt.h>
65 #include "../globals.h"
66 #include "../alert_box.h"
67 #include "../simple_dialog.h"
69 #include "gtk/graph_analysis.h"
70 #include "gtk/voip_calls.h"
71 #include "gtk/voip_calls_dlg.h"
74 #ifdef HAVE_LIBPORTAUDIO
75 #include "gtk/rtp_player.h"
76 #endif /* HAVE_LIBPORTAUDIO */
79 const char *voip_call_state_name[8]={
90 /* defines whether we can consider the call active */
91 const char *voip_protocol_name[]={
119 graph_str labels[H245_MAX];
122 static h245_labels_t h245_labels;
124 /****************************************************************************/
125 /* the one and only global voip_calls_tapinfo_t structure */
126 static voip_calls_tapinfo_t the_tapinfo_struct =
127 {0, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
129 /* the one and only global voip_rtp_tapinfo_t structure */
130 static voip_rtp_tapinfo_t the_tapinfo_rtp_struct =
133 /****************************************************************************/
134 /* when there is a [re]reading of packet's */
135 void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
137 voip_calls_info_t *callsinfo;
138 voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
139 voip_rtp_stream_info_t *strinfo;
140 graph_analysis_item_t *graph_item;
143 #ifdef HAVE_LIBPORTAUDIO
144 /* reset the RTP player */
148 /* free the data items first */
149 list = g_list_first(tapinfo->callsinfo_list);
152 callsinfo = list->data;
153 g_free(callsinfo->call_id);
154 g_free(callsinfo->from_identity);
155 g_free(callsinfo->to_identity);
156 g_free((void *)(callsinfo->initial_speaker.data));
157 g_free(callsinfo->protocol_name);
158 g_free(callsinfo->call_comment);
160 if (callsinfo->free_prot_info && callsinfo->prot_info)
161 callsinfo->free_prot_info(callsinfo->prot_info);
164 list = g_list_next(list);
166 g_list_free(tapinfo->callsinfo_list);
167 tapinfo->callsinfo_list = NULL;
169 tapinfo->npackets = 0;
170 tapinfo->start_packets = 0;
171 tapinfo->completed_calls = 0;
172 tapinfo->rejected_calls = 0;
174 /* free the graph data items first */
175 list = g_list_first(tapinfo->graph_analysis->list);
178 graph_item = list->data;
179 g_free(graph_item->frame_label);
180 g_free(graph_item->comment);
181 g_free((void *)graph_item->src_addr.data);
182 g_free((void *)graph_item->dst_addr.data);
184 list = g_list_next(list);
186 g_list_free(tapinfo->graph_analysis->list);
187 tapinfo->graph_analysis->nconv = 0;
188 tapinfo->graph_analysis->list = NULL;
190 ++(tapinfo->launch_count);
192 /* free the strinfo data items first */
193 list = g_list_first(rtp_tapinfo->list);
196 strinfo = list->data;
197 g_free(strinfo->pt_str);
198 list = g_list_next(list);
201 g_list_free(rtp_tapinfo->list);
202 rtp_tapinfo->list = NULL;
207 /****************************************************************************/
208 void graph_analysis_data_init(void){
209 the_tapinfo_struct.graph_analysis = g_malloc(sizeof(graph_analysis_info_t));
210 the_tapinfo_struct.graph_analysis->nconv = 0;
211 the_tapinfo_struct.graph_analysis->list = NULL;
214 /****************************************************************************/
215 /* Add a new item into the graph */
216 static void add_to_graph(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, const gchar *frame_label, const gchar *comment, guint16 call_num, address *src_addr, address *dst_addr, guint16 line_style)
218 graph_analysis_item_t *gai;
220 gai = g_malloc(sizeof(graph_analysis_item_t));
221 gai->frame_num = pinfo->fd->num;
222 gai->time= nstime_to_sec(&pinfo->fd->rel_ts);
223 COPY_ADDRESS(&(gai->src_addr),src_addr);
224 COPY_ADDRESS(&(gai->dst_addr),dst_addr);
226 gai->port_src=pinfo->srcport;
227 gai->port_dst=pinfo->destport;
228 if (frame_label != NULL)
229 gai->frame_label = g_strdup(frame_label);
231 gai->frame_label = g_strdup("");
234 gai->comment = g_strdup(comment);
236 gai->comment = g_strdup("");
237 gai->conv_num=call_num;
238 gai->line_style=line_style;
241 tapinfo->graph_analysis->list = g_list_append(tapinfo->graph_analysis->list, gai);
245 /****************************************************************************/
246 /* Append str to frame_label and comment in a graph item */
247 /* return 0 if the frame_num is not in the graph list */
248 static int append_to_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
250 graph_analysis_item_t *gai;
252 gchar *frame_label = NULL;
253 gchar *comment = NULL;
255 list = g_list_first(tapinfo->graph_analysis->list);
259 if (gai->frame_num == frame_num){
260 frame_label = gai->frame_label;
261 comment = gai->comment;
263 if (new_frame_label != NULL){
264 gai->frame_label = g_strdup_printf("%s %s", frame_label, new_frame_label);
268 if (new_comment != NULL){
269 gai->comment = g_strdup_printf("%s %s", comment, new_comment);
274 list = g_list_next(list);
281 /****************************************************************************/
282 /* Change the frame_label and comment in a graph item if not NULL*/
283 /* return 0 if the frame_num is not in the graph list */
284 static int change_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
286 graph_analysis_item_t *gai;
288 gchar *frame_label = NULL;
289 gchar *comment = NULL;
291 list = g_list_first(tapinfo->graph_analysis->list);
295 if (gai->frame_num == frame_num){
296 frame_label = gai->frame_label;
297 comment = gai->comment;
299 if (new_frame_label != NULL){
300 gai->frame_label = g_strdup(new_frame_label);
304 if (new_comment != NULL){
305 gai->comment = g_strdup(new_comment);
310 list = g_list_next(list);
317 /****************************************************************************/
318 /* Change all the graph items with call_num to new_call_num */
319 static guint change_call_num_graph(voip_calls_tapinfo_t *tapinfo _U_, guint16 call_num, guint16 new_call_num)
321 graph_analysis_item_t *gai;
326 list = g_list_first(tapinfo->graph_analysis->list);
330 if (gai->conv_num == call_num){
331 gai->conv_num = new_call_num;
334 list = g_list_next(list);
336 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, const 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, 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),
434 if (error_string != NULL) {
435 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
436 "%s", error_string->str);
437 g_string_free(error_string, TRUE);
440 have_rtp_event_tap_listener=TRUE;
444 /****************************************************************************/
447 remove_tap_listener_rtp_event(void)
449 protect_thread_critical_region();
450 remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_event_dummy));
451 unprotect_thread_critical_region();
453 have_rtp_event_tap_listener=FALSE;
456 /****************************************************************************/
457 /* ***************************TAP for RTP **********************************/
458 /****************************************************************************/
460 /****************************************************************************/
461 /* when there is a [re]reading of RTP packet's */
462 static void voip_rtp_reset(void *ptr _U_)
464 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
466 /* free the data items first */
467 list = g_list_first(tapinfo->list);
471 list = g_list_next(list);
473 g_list_free(tapinfo->list);
474 tapinfo->list = NULL;
475 tapinfo->nstreams = 0;
479 /****************************************************************************/
480 /* whenever a RTP packet is seen by the tap listener */
482 RTP_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void const *RTPinfo)
484 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
485 voip_rtp_stream_info_t *tmp_listinfo;
486 voip_rtp_stream_info_t *strinfo = NULL;
488 struct _rtp_conversation_info *p_conv_data = NULL;
490 const struct _rtp_info *pi = RTPinfo;
492 /* do not consider RTP packets without a setup frame */
493 if (pi->info_setup_frame_num == 0){
497 /* add this RTP for future listening using the RTP Player*/
498 #ifdef HAVE_LIBPORTAUDIO
499 add_rtp_packet(pi, pinfo);
502 /* check whether we already have a RTP stream with this setup frame and ssrc in the list */
503 list = g_list_first(tapinfo->list);
506 tmp_listinfo=list->data;
507 if ( (tmp_listinfo->setup_frame_number == pi->info_setup_frame_num)
508 && (tmp_listinfo->ssrc == pi->info_sync_src) && (tmp_listinfo->end_stream == FALSE)){
509 /* if the payload type has changed, we mark the stream as finished to create a new one
510 this is to show multiple payload changes in the Graph for example for DTMF RFC2833 */
511 if ( tmp_listinfo->pt != pi->info_payload_type ) {
512 tmp_listinfo->end_stream = TRUE;
514 strinfo = (voip_rtp_stream_info_t*)(list->data);
518 list = g_list_next(list);
521 /* if this is a duplicated RTP Event End, just return */
522 if ((rtp_evt_frame_num == pinfo->fd->num) && !strinfo && (rtp_evt_end == TRUE)) {
526 /* not in the list? then create a new entry */
528 strinfo = g_malloc(sizeof(voip_rtp_stream_info_t));
529 COPY_ADDRESS(&(strinfo->src_addr), &(pinfo->src));
530 strinfo->src_port = pinfo->srcport;
531 COPY_ADDRESS(&(strinfo->dest_addr), &(pinfo->dst));
532 strinfo->dest_port = pinfo->destport;
533 strinfo->ssrc = pi->info_sync_src;
534 strinfo->end_stream = FALSE;
535 strinfo->pt = pi->info_payload_type;
536 strinfo->pt_str = NULL;
537 strinfo->is_srtp = pi->info_is_srtp;
538 /* if it is dynamic payload, let use the conv data to see if it is defined */
539 if ( (strinfo->pt>95) && (strinfo->pt<128) ) {
540 /* Use existing packet info if available */
541 p_conv_data = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name("rtp"));
542 if (p_conv_data && p_conv_data->rtp_dyn_payload)
543 strinfo->pt_str = g_strdup(g_hash_table_lookup(p_conv_data->rtp_dyn_payload, &strinfo->pt));
545 if (!strinfo->pt_str) strinfo->pt_str = g_strdup(val_to_str(strinfo->pt, rtp_payload_type_short_vals, "%u"));
546 strinfo->npackets = 0;
547 strinfo->first_frame_num = pinfo->fd->num;
548 strinfo->start_rel_sec = (guint32) (pinfo->fd->rel_ts.secs);
549 strinfo->start_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
550 strinfo->setup_frame_number = pi->info_setup_frame_num;
551 strinfo->rtp_event = -1;
552 tapinfo->list = g_list_append(tapinfo->list, strinfo);
556 /* Add the info to the existing RTP stream */
558 strinfo->stop_rel_sec = (guint32) (pinfo->fd->rel_ts.secs);
559 strinfo->stop_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
561 /* process RTP Event */
562 if (rtp_evt_frame_num == pinfo->fd->num) {
563 strinfo->rtp_event = rtp_evt;
564 if (rtp_evt_end == TRUE) {
565 strinfo->end_stream = TRUE;
570 the_tapinfo_struct.redraw = TRUE;
575 /****************************************************************************/
576 /* whenever a redraw in the RTP tap listener */
577 static void RTP_packet_draw(void *prs _U_)
579 voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
580 GList *rtp_streams_list;
581 voip_rtp_stream_info_t *rtp_listinfo;
582 GList *voip_calls_graph_list;
584 graph_analysis_item_t *gai;
585 graph_analysis_item_t *new_gai;
589 /* add each rtp stream to the graph */
590 rtp_streams_list = g_list_first(rtp_tapinfo->list);
591 while (rtp_streams_list)
593 rtp_listinfo = rtp_streams_list->data;
595 /* using the setup frame number of the RTP stream, we get the call number that it belongs */
596 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
597 while (voip_calls_graph_list)
599 gai = voip_calls_graph_list->data;
600 conv_num = gai->conv_num;
601 /* if we get the setup frame number, then get the time position to graph the RTP arrow */
602 if (rtp_listinfo->setup_frame_number == gai->frame_num){
603 /* look again from the begining because there are cases where the Setup frame is after the RTP */
604 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
606 while(voip_calls_graph_list){
607 gai = voip_calls_graph_list->data;
608 /* if RTP was already in the Graph, just update the comment information */
609 if (rtp_listinfo->first_frame_num == gai->frame_num){
610 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
611 g_free(gai->comment);
612 gai->comment = g_strdup_printf("%s Num packets:%u Duration:%u.%03us SSRC:0x%X",
613 (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->npackets,
614 duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
618 /* 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 */
619 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
620 if (!voip_calls_graph_list) item++;
622 /* add the RTP item to the graph if was not there*/
623 if (rtp_listinfo->first_frame_num<gai->frame_num || !voip_calls_graph_list){
624 new_gai = g_malloc(sizeof(graph_analysis_item_t));
625 new_gai->frame_num = rtp_listinfo->first_frame_num;
626 new_gai->time = (double)rtp_listinfo->start_rel_sec + (double)rtp_listinfo->start_rel_usec/1000000;
627 COPY_ADDRESS(&(new_gai->src_addr),&(rtp_listinfo->src_addr));
628 COPY_ADDRESS(&(new_gai->dst_addr),&(rtp_listinfo->dest_addr));
629 new_gai->port_src = rtp_listinfo->src_port;
630 new_gai->port_dst = rtp_listinfo->dest_port;
631 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
632 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"));
633 new_gai->comment = g_strdup_printf("%s Num packets:%u Duration:%u.%03us SSRC:0x%X",
634 (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->npackets,
635 duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
636 new_gai->conv_num = conv_num;
637 new_gai->display=FALSE;
638 new_gai->line_style = 2; /* the arrow line will be 2 pixels width */
639 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item);
642 if (voip_calls_graph_list) item++;
646 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
648 rtp_streams_list = g_list_next(rtp_streams_list);
652 static gboolean have_RTP_tap_listener=FALSE;
653 /****************************************************************************/
657 GString *error_string;
659 if(have_RTP_tap_listener==FALSE)
661 /* don't register tap listener, if we have it already */
662 error_string = register_tap_listener("rtp", &(the_tapinfo_rtp_struct.rtp_dummy), NULL,
668 if (error_string != NULL) {
669 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
670 "%s", error_string->str);
671 g_string_free(error_string, TRUE);
674 have_RTP_tap_listener=TRUE;
678 /****************************************************************************/
680 remove_tap_listener_rtp(void)
682 protect_thread_critical_region();
683 remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_dummy));
684 unprotect_thread_critical_region();
686 have_RTP_tap_listener=FALSE;
689 /****************************************************************************/
690 /******************************TAP for T38 **********************************/
691 /****************************************************************************/
693 /****************************************************************************/
694 /* whenever a T38 packet is seen by the tap listener */
696 T38_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *T38info)
698 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
700 voip_calls_info_t *callsinfo = NULL;
701 voip_calls_info_t *tmp_listinfo;
702 GList *voip_calls_graph_list;
704 gchar *frame_label = NULL;
705 gchar *comment = NULL;
706 graph_analysis_item_t *tmp_gai, *gai = NULL;
707 guint16 line_style = 2;
711 const t38_packet_info *pi = T38info;
713 if (pi->setup_frame_number != 0) {
714 /* using the setup frame number of the T38 packet, we get the call number that it belongs */
715 voip_calls_graph_list = g_list_first(tapinfo->graph_analysis->list);
716 while (voip_calls_graph_list)
718 tmp_gai = voip_calls_graph_list->data;
719 if (pi->setup_frame_number == tmp_gai->frame_num){
723 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
725 if (gai) conv_num = (int) gai->conv_num;
728 /* if setup_frame_number in the t38 packet is 0, it means it was not set using an SDP or H245 sesion, which means we don't
729 * have the associated Voip calls. It probably means the the packet was decoded using the default t38 port, or using "Decode as.."
730 * in this case we create a "voip" call that only have t38 media (no signaling)
731 * OR if we have not found the Setup message in the graph.
733 if ( (pi->setup_frame_number == 0) || (gai == NULL) ){
734 /* check whether we already have a call with these parameters in the list */
735 list = g_list_first(tapinfo->callsinfo_list);
738 tmp_listinfo=list->data;
739 if (tmp_listinfo->protocol == MEDIA_T38){
740 callsinfo = (voip_calls_info_t*)(list->data);
743 list = g_list_next (list);
746 /* not in the list? then create a new entry */
747 if (callsinfo==NULL){
748 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
749 callsinfo->call_active_state = VOIP_ACTIVE;
750 callsinfo->call_state = VOIP_UNKNOWN;
751 callsinfo->from_identity=g_strdup("T38 Media only");
752 callsinfo->to_identity=g_strdup("T38 Media only");
753 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
754 callsinfo->first_frame_num=pinfo->fd->num;
755 callsinfo->selected=FALSE;
756 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
757 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
758 callsinfo->protocol=MEDIA_T38;
759 callsinfo->prot_info=NULL;
760 callsinfo->free_prot_info = NULL;
761 callsinfo->npackets = 0;
762 callsinfo->call_num = tapinfo->ncalls++;
763 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
765 ++(callsinfo->npackets);
766 /* increment the packets counter of all calls */
767 ++(tapinfo->npackets);
769 conv_num = (int) callsinfo->call_num;
772 /* at this point we should have found the call num for this t38 packets belong */
773 if (conv_num == -1) {
777 /* add the item to the graph list */
778 if (pi->type_msg == 0) { /* 0=t30-indicator */
779 frame_label = g_strdup(val_to_str(pi->t30ind_value, t38_T30_indicator_vals, "Ukn (0x%02X)") );
780 comment = g_strdup_printf("t38:t30 Ind:%s",val_to_str(pi->t30ind_value, t38_T30_indicator_vals, "Ukn (0x%02X)") );
782 } else if (pi->type_msg == 1) { /* 1=data */
783 switch(pi->Data_Field_field_type_value){
784 case 0: /* hdlc-data */
786 case 2: /* hdlc-fcs-OK */
787 case 4: /* hdlc-fcs-OK-sig-end */
788 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);
789 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)"));
791 case 3: /* hdlc-fcs-BAD */
792 case 5: /* hdlc-fcs-BAD-sig-end */
793 frame_label = g_strdup(pi->Data_Field_field_type_value == 3 ? "fcs-BAD" : "fcs-BAD-sig-end");
794 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");
796 case 7: /* t4-non-ecm-sig-end */
797 duration = nstime_to_sec(&pinfo->fd->rel_ts) - pi->time_first_t4_data;
798 frame_label = g_strdup_printf("t4-non-ecm-data:%s",val_to_str(pi->data_value, t38_T30_data_vals, "Ukn (0x%02X)") );
799 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 );
800 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);
805 if (frame_label && !(pi->Data_Field_field_type_value == 7 && pi->type_msg == 1)) {
806 add_to_graph(tapinfo, pinfo, frame_label, comment, (guint16)conv_num, &(pinfo->src), &(pinfo->dst), line_style);
812 tapinfo->redraw = TRUE;
814 return 1; /* refresh output */
817 static gboolean have_T38_tap_listener=FALSE;
818 /****************************************************************************/
822 GString *error_string;
824 if(have_T38_tap_listener==FALSE)
826 /* don't register tap listener, if we have it already */
827 error_string = register_tap_listener("t38", &(the_tapinfo_struct.t38_dummy), NULL,
829 voip_calls_dlg_reset,
833 if (error_string != NULL) {
834 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
835 "%s", error_string->str);
836 g_string_free(error_string, TRUE);
839 have_T38_tap_listener=TRUE;
843 /****************************************************************************/
845 remove_tap_listener_t38(void)
847 protect_thread_critical_region();
848 remove_tap_listener(&(the_tapinfo_struct.t38_dummy));
849 unprotect_thread_critical_region();
851 have_T38_tap_listener=FALSE;
855 /****************************************************************************/
856 static gchar *sdp_summary = NULL;
857 static guint32 sdp_frame_num = 0;
859 /****************************************************************************/
860 /* ***************************TAP for SIP **********************************/
861 /****************************************************************************/
864 static void free_sip_info(gpointer p) {
865 sip_calls_info_t *si = p;
867 g_free(si->call_identifier);
871 /****************************************************************************/
872 /* whenever a SIP packet is seen by the tap listener */
874 SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SIPinfo)
876 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
877 /* we just take note of the ISUP data here; when we receive the MTP3 part everything will
878 be compared with existing calls */
880 voip_calls_info_t *tmp_listinfo;
881 voip_calls_info_t *callsinfo = NULL;
882 sip_calls_info_t *tmp_sipinfo = NULL;
884 address tmp_src, tmp_dst;
885 gchar *frame_label = NULL;
886 gchar *comment = NULL;
888 const sip_info_value_t *pi = SIPinfo;
890 /* do not consider packets without call_id */
891 if (pi->tap_call_id ==NULL){
895 /* check whether we already have a call with these parameters in the list */
896 list = g_list_first(tapinfo->callsinfo_list);
899 tmp_listinfo=list->data;
900 if (tmp_listinfo->protocol == VOIP_SIP){
901 tmp_sipinfo = tmp_listinfo->prot_info;
902 if (strcmp(tmp_sipinfo->call_identifier,pi->tap_call_id)==0){
903 callsinfo = (voip_calls_info_t*)(list->data);
907 list = g_list_next (list);
910 /* not in the list? then create a new entry if the message is INVITE -i.e. if this session is a call*/
911 if ((callsinfo==NULL) &&(pi->request_method!=NULL)){
912 if (strcmp(pi->request_method,"INVITE")==0){
913 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
914 callsinfo->call_active_state = VOIP_ACTIVE;
915 callsinfo->call_state = VOIP_CALL_SETUP;
916 callsinfo->from_identity=g_strdup(pi->tap_from_addr);
917 callsinfo->to_identity=g_strdup(pi->tap_to_addr);
918 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
919 callsinfo->first_frame_num=pinfo->fd->num;
920 callsinfo->selected=FALSE;
921 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
922 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
923 callsinfo->protocol=VOIP_SIP;
924 callsinfo->prot_info=g_malloc(sizeof(sip_calls_info_t));
925 callsinfo->free_prot_info = free_sip_info;
926 tmp_sipinfo = callsinfo->prot_info;
927 tmp_sipinfo->call_identifier = g_strdup(pi->tap_call_id);
928 tmp_sipinfo->sip_state = SIP_INVITE_SENT;
929 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
930 callsinfo->npackets = 0;
931 callsinfo->call_num = tapinfo->ncalls++;
932 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
936 if (callsinfo!=NULL){
938 /* let's analyze the call state */
940 COPY_ADDRESS(&(tmp_src), &(pinfo->src));
941 COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
943 if (pi->request_method == NULL){
944 frame_label = g_strdup_printf("%u %s", pi->response_code, pi->reason_phrase );
945 comment = g_strdup("SIP Status");
947 if ((tmp_sipinfo && pi->tap_cseq_number == tmp_sipinfo->invite_cseq)&&(ADDRESSES_EQUAL(&tmp_dst,&(callsinfo->initial_speaker)))){
948 if ((pi->response_code > 199) && (pi->response_code<300) && (tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
949 tmp_sipinfo->sip_state = SIP_200_REC;
951 else if ((pi->response_code>299)&&(tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
952 callsinfo->call_state = VOIP_REJECTED;
953 tapinfo->rejected_calls++;
959 frame_label = g_strdup(pi->request_method);
961 if ((strcmp(pi->request_method,"INVITE")==0)&&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))){
962 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
963 callsinfo->call_state = VOIP_CALL_SETUP;
964 comment = g_strdup_printf("SIP From: %s To:%s", callsinfo->from_identity, callsinfo->to_identity);
966 else if ((strcmp(pi->request_method,"ACK")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
967 &&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))&&(tmp_sipinfo->sip_state==SIP_200_REC)
968 &&(callsinfo->call_state == VOIP_CALL_SETUP)){
969 callsinfo->call_state = VOIP_IN_CALL;
970 comment = g_strdup("SIP Request");
972 else if (strcmp(pi->request_method,"BYE")==0){
973 callsinfo->call_state = VOIP_COMPLETED;
974 tapinfo->completed_calls++;
975 comment = g_strdup("SIP Request");
977 else if ((strcmp(pi->request_method,"CANCEL")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
978 &&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))&&(callsinfo->call_state==VOIP_CALL_SETUP)){
979 callsinfo->call_state = VOIP_CANCELLED;
980 tmp_sipinfo->sip_state = SIP_CANCEL_SENT;
981 comment = g_strdup("SIP Request");
983 comment = g_strdup("SIP Request");
987 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
988 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
989 callsinfo->last_frame_num=pinfo->fd->num;
990 ++(callsinfo->npackets);
991 /* increment the packets counter of all calls */
992 ++(tapinfo->npackets);
994 /* add to the graph */
995 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
998 g_free((void *)tmp_src.data);
999 g_free((void *)tmp_dst.data);
1001 /* add SDP info if apply */
1002 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
1003 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
1004 g_free(sdp_summary);
1009 tapinfo->redraw = TRUE;
1011 return 1; /* refresh output */
1015 /****************************************************************************/
1016 voip_calls_tapinfo_t* voip_calls_get_info(void)
1018 return &the_tapinfo_struct;
1022 /****************************************************************************/
1024 /****************************************************************************/
1025 static gboolean have_SIP_tap_listener=FALSE;
1026 /****************************************************************************/
1028 sip_calls_init_tap(void)
1030 GString *error_string;
1032 if(have_SIP_tap_listener==FALSE)
1034 /* don't register tap listener, if we have it already */
1035 error_string = register_tap_listener("sip", &(the_tapinfo_struct.sip_dummy), NULL,
1037 voip_calls_dlg_reset,
1041 if (error_string != NULL) {
1042 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1043 "%s", error_string->str);
1044 g_string_free(error_string, TRUE);
1047 have_SIP_tap_listener=TRUE;
1051 /****************************************************************************/
1053 remove_tap_listener_sip_calls(void)
1055 protect_thread_critical_region();
1056 remove_tap_listener(&(the_tapinfo_struct.sip_dummy));
1057 unprotect_thread_critical_region();
1059 have_SIP_tap_listener=FALSE;
1062 /****************************************************************************/
1063 /* ***************************TAP for ISUP **********************************/
1064 /****************************************************************************/
1066 static guint32 mtp3_opc, mtp3_dpc;
1067 static guint8 mtp3_ni;
1068 static guint32 mtp3_frame_num;
1071 /****************************************************************************/
1072 /* whenever a isup_ packet is seen by the tap listener */
1074 isup_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *isup_info _U_)
1076 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1077 voip_calls_info_t *tmp_listinfo;
1078 voip_calls_info_t *callsinfo = NULL;
1079 isup_calls_info_t *tmp_isupinfo;
1080 gboolean found = FALSE;
1081 gboolean forward = FALSE;
1082 gboolean right_pair;
1084 gchar *frame_label = NULL;
1085 gchar *comment = NULL;
1088 /*voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct; unused */
1089 const isup_tap_rec_t *pi = isup_info;
1091 /* check if the lower layer is MTP matching the frame number */
1092 if (mtp3_frame_num != pinfo->fd->num) return 0;
1094 /* check whether we already have a call with these parameters in the list */
1095 list = g_list_first(tapinfo->callsinfo_list);
1099 tmp_listinfo=list->data;
1100 if ((tmp_listinfo->protocol == VOIP_ISUP)&&(tmp_listinfo->call_active_state==VOIP_ACTIVE)){
1101 tmp_isupinfo = tmp_listinfo->prot_info;
1102 if ((tmp_isupinfo->cic == pinfo->circuit_id)&&(tmp_isupinfo->ni == mtp3_ni)) {
1103 if ((tmp_isupinfo->opc == mtp3_opc)&&(tmp_isupinfo->dpc == mtp3_dpc)){
1105 } else if ((tmp_isupinfo->dpc == mtp3_opc)&&(tmp_isupinfo->opc == mtp3_dpc)){
1112 /* if there is an IAM for a call that is not in setup state, that means the previous call in the same
1113 cic is no longer active */
1114 if (tmp_listinfo->call_state == VOIP_CALL_SETUP){
1116 } else if (pi->message_type != 1){
1119 tmp_listinfo->call_active_state=VOIP_INACTIVE;
1124 callsinfo = (voip_calls_info_t*)(list->data);
1129 list = g_list_next (list);
1132 /* not in the list? then create a new entry if the message is IAM
1133 -i.e. if this session is a call*/
1136 if ((callsinfo==NULL) &&(pi->message_type==1)){
1137 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
1138 callsinfo->call_active_state = VOIP_ACTIVE;
1139 callsinfo->call_state = VOIP_UNKNOWN;
1140 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
1141 callsinfo->selected=FALSE;
1142 callsinfo->first_frame_num=pinfo->fd->num;
1143 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
1144 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1145 callsinfo->protocol=VOIP_ISUP;
1146 if (pi->calling_number!=NULL){
1147 callsinfo->from_identity=g_strdup(pi->calling_number);
1149 if (pi->called_number!=NULL){
1150 callsinfo->to_identity=g_strdup(pi->called_number);
1152 callsinfo->prot_info=g_malloc(sizeof(isup_calls_info_t));
1153 callsinfo->free_prot_info = g_free;
1154 tmp_isupinfo=callsinfo->prot_info;
1155 tmp_isupinfo->opc = mtp3_opc;
1156 tmp_isupinfo->dpc = mtp3_dpc;
1157 tmp_isupinfo->ni = mtp3_ni;
1158 tmp_isupinfo->cic = pinfo->circuit_id;
1159 callsinfo->npackets = 0;
1160 callsinfo->call_num = tapinfo->ncalls++;
1161 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
1165 if (callsinfo!=NULL){
1166 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
1167 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1168 callsinfo->last_frame_num=pinfo->fd->num;
1169 ++(callsinfo->npackets);
1171 /* Let's analyze the call state */
1174 for (i=0;(isup_message_type_value[i].strptr!=NULL)&& (isup_message_type_value[i].value!=pi->message_type);i++);
1176 if (isup_message_type_value[i].value==pi->message_type){
1177 frame_label = g_strdup(isup_message_type_value_acro[i].strptr);
1180 frame_label = g_strdup("Unknown");
1183 if (callsinfo->npackets == 1){ /* this is the first packet, that must be an IAM */
1185 if ((pi->calling_number!=NULL)&&(pi->called_number !=NULL)){
1186 comment = g_strdup_printf("Call from %s to %s",
1187 pi->calling_number, pi->called_number);
1189 } else if (callsinfo->npackets == 2){ /* in the second packet we show the SPs */
1191 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
1193 mtp3_ni, mtp3_dpc, pinfo->circuit_id);
1195 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
1197 mtp3_ni, mtp3_opc, pinfo->circuit_id);
1202 switch(pi->message_type){
1204 callsinfo->call_state=VOIP_CALL_SETUP;
1206 case 7: /* CONNECT */
1207 case 9: /* ANSWER */
1208 callsinfo->call_state=VOIP_IN_CALL;
1210 case 12: /* RELEASE */
1211 if (callsinfo->call_state==VOIP_CALL_SETUP){
1213 callsinfo->call_state=VOIP_CANCELLED;
1216 callsinfo->call_state=VOIP_REJECTED;
1217 tapinfo->rejected_calls++;
1220 else if (callsinfo->call_state == VOIP_IN_CALL){
1221 callsinfo->call_state = VOIP_COMPLETED;
1222 tapinfo->completed_calls++;
1224 for (i=0;(q931_cause_code_vals[i].strptr!=NULL)&& (q931_cause_code_vals[i].value!=pi->cause_value);i++);
1225 if (q931_cause_code_vals[i].value==pi->cause_value){
1226 comment = g_strdup_printf("Cause %i - %s",pi->cause_value, q931_cause_code_vals[i].strptr);
1229 comment = g_strdup_printf("Cause %i",pi->cause_value);
1234 /* increment the packets counter of all calls */
1235 ++(tapinfo->npackets);
1237 /* add to the graph */
1238 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1240 g_free(frame_label);
1243 tapinfo->redraw = TRUE;
1245 return 1; /* refresh output */
1248 /****************************************************************************/
1250 static gboolean have_isup_tap_listener=FALSE;
1253 isup_calls_init_tap(void)
1255 GString *error_string;
1258 if(have_isup_tap_listener==FALSE)
1260 error_string = register_tap_listener("isup", &(the_tapinfo_struct.isup_dummy),
1263 voip_calls_dlg_reset,
1268 if (error_string != NULL) {
1269 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1270 "%s", error_string->str);
1271 g_string_free(error_string, TRUE);
1274 have_isup_tap_listener=TRUE;
1278 /****************************************************************************/
1281 remove_tap_listener_isup_calls(void)
1283 protect_thread_critical_region();
1284 remove_tap_listener(&(the_tapinfo_struct.isup_dummy));
1285 unprotect_thread_critical_region();
1287 have_isup_tap_listener=FALSE;
1291 /****************************************************************************/
1292 /* ***************************TAP for MTP3 **********************************/
1293 /****************************************************************************/
1296 /****************************************************************************/
1297 /* whenever a mtp3_ packet is seen by the tap listener */
1299 mtp3_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *mtp3_info _U_)
1301 const mtp3_tap_rec_t *pi = mtp3_info;
1303 /* keep the data in memory to use when the ISUP information arrives */
1305 mtp3_opc = pi->addr_opc.pc;
1306 mtp3_dpc = pi->addr_dpc.pc;
1307 mtp3_ni = pi->addr_opc.ni;
1308 mtp3_frame_num = pinfo->fd->num;
1313 /****************************************************************************/
1315 static gboolean have_mtp3_tap_listener=FALSE;
1316 static gboolean have_m3ua_tap_listener=FALSE;
1319 mtp3_calls_init_tap(void)
1321 GString *error_string;
1324 if(have_mtp3_tap_listener==FALSE)
1326 error_string = register_tap_listener("mtp3", &(the_tapinfo_struct.mtp3_dummy),
1329 voip_calls_dlg_reset,
1334 if (error_string != NULL) {
1335 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1336 "%s", error_string->str);
1337 g_string_free(error_string, TRUE);
1340 have_mtp3_tap_listener=TRUE;
1343 if(have_m3ua_tap_listener==FALSE)
1345 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,
1355 "%s", error_string->str);
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 *callsinfo = 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->callsinfo_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 callsinfo = (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 (callsinfo != 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(callsinfo->from_identity);
1463 callsinfo->from_identity=g_strdup(q931_calling_number);
1465 if (q931_called_number != NULL){
1466 g_free(callsinfo->to_identity);
1467 callsinfo->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->callsinfo_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(callsinfo->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 callsinfo->npackets += change_call_num_graph(tapinfo, tmp_listinfo->call_num, callsinfo->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->callsinfo_list = g_list_remove(tapinfo->callsinfo_list, tmp_listinfo);
1507 list = g_list_next (list);
1510 comment = g_strdup_printf("H225 From: %s To:%s TunnH245:%s FS:%s", callsinfo->from_identity, callsinfo->to_identity, (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
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->callsinfo_list);
1537 tmp_listinfo=list->data;
1538 if (tmp_listinfo->protocol == VOIP_H323){
1539 tmp_h323info = tmp_listinfo->prot_info;
1540 if ( ((tmp_h323info->q931_crv == q931_crv) || (tmp_h323info->q931_crv2 == q931_crv)) && (q931_crv!=-1)){
1541 /* if the frame number exists in graph, append to it*/
1542 if (!append_to_frame_graph(tapinfo, q931_frame_num, NULL, NULL)) {
1543 /* if not exist, add to the graph */
1544 add_to_graph(tapinfo, pinfo, NULL, NULL, tmp_listinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1545 ++(tmp_listinfo->npackets);
1546 /* increment the packets counter of all calls */
1547 ++(tapinfo->npackets);
1550 /* Add the H245 info if exists to the Graph */
1551 h245_add_to_graph(pinfo->fd->num);
1555 list = g_list_next (list);
1558 /* add staff to ACTRACE */
1559 } else if (actrace_frame_num == q931_frame_num) {
1564 list = g_list_first(tapinfo->callsinfo_list);
1567 tmp_listinfo=list->data;
1568 if ( tmp_listinfo->protocol == VOIP_AC_ISDN ){
1569 tmp_actrace_isdn_info = tmp_listinfo->prot_info;
1570 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
1571 if ( (tmp_actrace_isdn_info->crv == q931_crv) && (tmp_actrace_isdn_info->trunk == actrace_trunk) ) {
1572 callsinfo = (voip_calls_info_t*)(list->data);
1576 list = g_list_next (list);
1579 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, g_strdup("PSTN"));
1581 /* if it is a new call, add it to the list */
1583 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
1584 callsinfo->call_active_state = VOIP_ACTIVE;
1585 callsinfo->call_state = VOIP_CALL_SETUP;
1586 callsinfo->from_identity=g_strdup(q931_calling_number);
1587 callsinfo->to_identity=g_strdup(q931_called_number);
1588 COPY_ADDRESS(&(callsinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
1589 callsinfo->first_frame_num=pinfo->fd->num;
1590 callsinfo->selected=FALSE;
1591 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
1592 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1593 callsinfo->protocol=VOIP_AC_ISDN;
1594 callsinfo->prot_info=g_malloc(sizeof(actrace_isdn_calls_info_t));
1595 callsinfo->free_prot_info = g_free;
1596 tmp_actrace_isdn_info=callsinfo->prot_info;
1597 tmp_actrace_isdn_info->crv=q931_crv;
1598 tmp_actrace_isdn_info->trunk=actrace_trunk;
1599 callsinfo->npackets = 0;
1600 callsinfo->call_num = tapinfo->ncalls++;
1601 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
1604 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
1605 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1606 callsinfo->last_frame_num=pinfo->fd->num;
1607 ++(callsinfo->npackets);
1608 /* increment the packets counter of all calls */
1609 ++(tapinfo->npackets);
1611 switch(pi->message_type){
1613 comment = g_strdup_printf("AC_ISDN trunk:%u Calling: %s Called:%s", actrace_trunk, q931_calling_number, q931_called_number);
1614 callsinfo->call_state=VOIP_CALL_SETUP;
1617 callsinfo->call_state=VOIP_IN_CALL;
1619 case Q931_RELEASE_COMPLETE:
1621 case Q931_DISCONNECT:
1622 if (callsinfo->call_state==VOIP_CALL_SETUP){
1623 if (ADDRESSES_EQUAL(&(callsinfo->initial_speaker), actrace_direction?&pstn_add:&(pinfo->src) )){ /* forward direction */
1624 callsinfo->call_state=VOIP_CANCELLED;
1627 callsinfo->call_state=VOIP_REJECTED;
1628 tapinfo->rejected_calls++;
1630 } else if ( (callsinfo->call_state!=VOIP_CANCELLED) && (callsinfo->call_state!=VOIP_REJECTED) ){
1631 callsinfo->call_state=VOIP_COMPLETED;
1632 tapinfo->completed_calls++;
1634 if (q931_cause_value != 0xFF){
1635 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>"));
1636 } else { /* Cause not set */
1637 comment = g_strdup("AC_ISDN No Q931 Rel Cause");
1643 comment = g_strdup_printf("AC_ISDN trunk:%u", actrace_trunk );
1645 add_to_graph(tapinfo, pinfo, val_to_str(pi->message_type, q931_message_type_vals, "<unknown>") , comment, callsinfo->call_num,
1646 actrace_direction?&pstn_add:&(pinfo->src),
1647 actrace_direction?&(pinfo->src):&pstn_add,
1651 g_free((char *)pstn_add.data);
1654 tapinfo->redraw = TRUE;
1656 return 1; /* refresh output */
1659 /****************************************************************************/
1660 static gboolean have_q931_tap_listener=FALSE;
1663 q931_calls_init_tap(void)
1665 GString *error_string;
1668 if(have_q931_tap_listener==FALSE)
1670 error_string = register_tap_listener("q931", &(the_tapinfo_struct.q931_dummy),
1673 voip_calls_dlg_reset,
1678 if (error_string != NULL) {
1679 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1680 "%s", error_string->str);
1681 g_string_free(error_string, TRUE);
1684 have_q931_tap_listener=TRUE;
1688 /****************************************************************************/
1691 remove_tap_listener_q931_calls(void)
1693 protect_thread_critical_region();
1694 remove_tap_listener(&(the_tapinfo_struct.q931_dummy));
1695 unprotect_thread_critical_region();
1697 have_q931_tap_listener=FALSE;
1700 /****************************************************************************/
1701 /****************************TAP for H323 ***********************************/
1702 /****************************************************************************/
1704 static void add_h245_Address(h323_calls_info_t *h323info, h245_address_t *h245_address)
1706 h323info->h245_list = g_list_append(h323info->h245_list, h245_address);
1710 static void free_h225_info(gpointer p) {
1711 h323_calls_info_t *tmp_h323info = p;
1713 g_free(tmp_h323info->guid);
1715 if (tmp_h323info->h245_list) {
1716 GList *list2 = g_list_first(tmp_h323info->h245_list);
1719 h245_address_t *h245_add=list2->data;
1720 g_free((void *)h245_add->h245_address.data);
1721 g_free(list2->data);
1722 list2 = g_list_next(list2);
1725 g_list_free(tmp_h323info->h245_list);
1731 /****************************************************************************/
1732 /* whenever a H225 packet is seen by the tap listener */
1734 H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H225info)
1736 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1737 voip_calls_info_t *tmp_listinfo;
1738 voip_calls_info_t *callsinfo = NULL;
1739 h323_calls_info_t *tmp_h323info = NULL;
1743 h245_address_t *h245_add = NULL;
1745 const h225_packet_info *pi = H225info;
1747 /* if not guid and RAS and not LRQ, LCF or LRJ return because did not belong to a call */
1748 /* OR, if not guid and is H225 return because doesn't belong to a call */
1749 if ((memcmp(&pi->guid, &guid_allzero, GUID_LEN) == 0))
1750 if ( ((pi->msg_type == H225_RAS) && ((pi->msg_tag < 18) || (pi->msg_tag > 20))) || (pi->msg_type != H225_RAS) )
1753 /* if it is RAS LCF or LRJ*/
1754 if ( (pi->msg_type == H225_RAS) && ((pi->msg_tag == 19) || (pi->msg_tag == 20))) {
1755 /* if the LCF/LRJ doesn't match to a LRQ, just return */
1756 if (!pi->request_available) return 0;
1758 /* check whether we already have a call with this request SeqNum */
1759 list = g_list_first(tapinfo->callsinfo_list);
1762 tmp_listinfo=list->data;
1763 g_assert(tmp_listinfo != NULL);
1764 if (tmp_listinfo->protocol == VOIP_H323){
1765 tmp_h323info = tmp_listinfo->prot_info;
1766 if (tmp_h323info->requestSeqNum == pi->requestSeqNum) {
1767 callsinfo = (voip_calls_info_t*)(list->data);
1771 list = g_list_next (list);
1774 /* check whether we already have a call with this guid in the list */
1775 list = g_list_first(tapinfo->callsinfo_list);
1778 tmp_listinfo=list->data;
1779 if (tmp_listinfo->protocol == VOIP_H323){
1780 tmp_h323info = tmp_listinfo->prot_info;
1781 g_assert(tmp_h323info != NULL);
1782 if ( (memcmp(tmp_h323info->guid, &guid_allzero, GUID_LEN) != 0) && (memcmp(tmp_h323info->guid, &pi->guid,GUID_LEN)==0) ){
1783 callsinfo = (voip_calls_info_t*)(list->data);
1787 list = g_list_next (list);
1791 h225_cstype = pi->cs_type;
1792 h225_is_faststart = pi->is_faststart;
1794 /* not in the list? then create a new entry */
1795 if ((callsinfo==NULL)){
1796 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
1797 callsinfo->call_active_state = VOIP_ACTIVE;
1798 callsinfo->call_state = VOIP_UNKNOWN;
1799 callsinfo->from_identity=g_strdup("");
1800 callsinfo->to_identity=g_strdup("");
1801 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
1802 callsinfo->selected=FALSE;
1803 callsinfo->first_frame_num=pinfo->fd->num;
1804 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
1805 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1806 callsinfo->protocol=VOIP_H323;
1807 callsinfo->prot_info=g_malloc(sizeof(h323_calls_info_t));
1808 callsinfo->free_prot_info = free_h225_info;
1810 tmp_h323info = callsinfo->prot_info;
1811 g_assert(tmp_h323info != NULL);
1812 tmp_h323info->guid = g_memdup(&pi->guid, sizeof pi->guid);
1813 tmp_h323info->h225SetupAddr.type = AT_NONE;
1814 tmp_h323info->h225SetupAddr.len = 0;
1815 tmp_h323info->h245_list = NULL;
1816 tmp_h323info->is_faststart_Setup = FALSE;
1817 tmp_h323info->is_faststart_Proc = FALSE;
1818 tmp_h323info->is_h245Tunneling = FALSE;
1819 tmp_h323info->is_h245 = FALSE;
1820 tmp_h323info->q931_crv = -1;
1821 tmp_h323info->q931_crv2 = -1;
1822 tmp_h323info->requestSeqNum = 0;
1823 callsinfo->call_num = tapinfo->ncalls++;
1824 callsinfo->npackets = 0;
1826 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
1829 if (callsinfo!=NULL){
1831 h225_frame_num = pinfo->fd->num;
1832 h225_call_num = callsinfo->call_num;
1834 /* let's analyze the call state */
1836 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
1837 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1838 callsinfo->last_frame_num=pinfo->fd->num;
1839 ++(callsinfo->npackets);
1840 /* increment the packets counter of all calls */
1841 ++(tapinfo->npackets);
1844 /* XXX: it is supposed to be initialized isn't it? */
1845 g_assert(tmp_h323info != NULL);
1847 /* change the status */
1848 if (pi->msg_type == H225_CS){
1850 /* this is still IPv4 only, because the dissector is */
1851 if (pi->is_h245 == TRUE){
1852 h245_add = g_malloc(sizeof (h245_address_t));
1853 h245_add->h245_address.type=AT_IPv4;
1854 h245_add->h245_address.len=4;
1855 h245_add->h245_address.data = g_malloc(sizeof(pi->h245_address));
1856 memcpy((void *)(h245_add->h245_address.data), &(pi->h245_address), 4);
1857 h245_add->h245_port = pi->h245_port;
1858 add_h245_Address(tmp_h323info, h245_add);
1861 if (pi->cs_type != H225_RELEASE_COMPLET) tmp_h323info->is_h245Tunneling = pi->is_h245Tunneling;
1863 frame_label = g_strdup(pi->frame_label);
1865 switch(pi->cs_type){
1867 tmp_h323info->is_faststart_Setup = pi->is_faststart;
1869 /* Set the Setup address if it was not set */
1870 if (tmp_h323info->h225SetupAddr.type == AT_NONE)
1871 COPY_ADDRESS(&(tmp_h323info->h225SetupAddr), &(pinfo->src));
1872 callsinfo->call_state=VOIP_CALL_SETUP;
1873 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1874 (pi->is_faststart==TRUE?"on":"off"));
1877 callsinfo->call_state=VOIP_IN_CALL;
1878 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1879 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1880 (pi->is_faststart==TRUE?"on":"off"));
1882 case H225_RELEASE_COMPLET:
1883 if (callsinfo->call_state==VOIP_CALL_SETUP){
1884 if (ADDRESSES_EQUAL(&(tmp_h323info->h225SetupAddr),&(pinfo->src))){ /* forward direction */
1885 callsinfo->call_state=VOIP_CANCELLED;
1888 callsinfo->call_state=VOIP_REJECTED;
1889 tapinfo->rejected_calls++;
1892 callsinfo->call_state=VOIP_COMPLETED;
1893 tapinfo->completed_calls++;
1895 comment = g_strdup("H225 No Q931 Rel Cause");
1899 case H225_CALL_PROCEDING:
1900 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1901 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1902 (pi->is_faststart==TRUE?"on":"off"));
1905 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1906 (pi->is_faststart==TRUE?"on":"off"));
1910 else if (pi->msg_type == H225_RAS){
1911 switch(pi->msg_tag){
1913 if (!pi->is_duplicate){
1914 g_free(callsinfo->to_identity);
1915 callsinfo->to_identity=g_strdup(pi->dialedDigits);
1916 tmp_h323info->requestSeqNum = pi->requestSeqNum;
1919 if (strlen(pi->dialedDigits))
1920 comment = g_strdup_printf("H225 RAS dialedDigits: %s", pi->dialedDigits);
1922 comment = g_strdup("H225 RAS");
1925 comment = g_strdup("H225 RAS");
1927 frame_label = g_strdup(val_to_str(pi->msg_tag, h225_RasMessage_vals, "<unknown>"));
1929 frame_label = g_strdup("H225: Unknown");
1933 /* add to graph analysis */
1935 /* if the frame number exists in graph, append to it*/
1936 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, comment)) {
1937 /* if not exist, add to the graph */
1938 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1941 /* Add the H245 info if exists to the Graph */
1942 h245_add_to_graph(pinfo->fd->num);
1944 g_free(frame_label);
1948 tapinfo->redraw = TRUE;
1950 return 1; /* refresh output */
1954 /****************************************************************************/
1956 /****************************************************************************/
1957 static gboolean have_H225_tap_listener=FALSE;
1958 /****************************************************************************/
1960 h225_calls_init_tap(void)
1962 GString *error_string;
1964 if(have_H225_tap_listener==FALSE)
1966 /* don't register tap listener, if we have it already */
1967 error_string = register_tap_listener("h225", &(the_tapinfo_struct.h225_dummy), NULL,
1969 voip_calls_dlg_reset,
1974 if (error_string != NULL) {
1975 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1976 "%s", error_string->str);
1977 g_string_free(error_string, TRUE);
1980 have_H225_tap_listener=TRUE;
1984 /****************************************************************************/
1986 remove_tap_listener_h225_calls(void)
1988 protect_thread_critical_region();
1989 remove_tap_listener(&(the_tapinfo_struct.h225_dummy));
1990 unprotect_thread_critical_region();
1992 have_H225_tap_listener=FALSE;
1995 /* Add the h245 label info to the graph */
1996 void h245_add_to_graph(guint32 new_frame_num)
2000 if (new_frame_num != h245_labels.frame_num) return;
2002 for (n=0; n<h245_labels.labels_count; n++) {
2003 append_to_frame_graph(&the_tapinfo_struct, new_frame_num, h245_labels.labels[n].frame_label, h245_labels.labels[n].comment);
2004 g_free(h245_labels.labels[n].frame_label);
2005 h245_labels.labels[n].frame_label = NULL;
2006 g_free(h245_labels.labels[n].comment);
2007 h245_labels.labels[n].comment = NULL;
2009 h245_labels.frame_num = 0;
2010 h245_labels.labels_count = 0;
2013 /* free the h245_labels if the frame number is different */
2014 static void h245_free_labels(guint32 new_frame_num)
2018 if (new_frame_num == h245_labels.frame_num) return;
2020 for (n=0; n<h245_labels.labels_count; n++) {
2021 g_free(h245_labels.labels[n].frame_label);
2022 h245_labels.labels[n].frame_label = NULL;
2023 g_free(h245_labels.labels[n].comment);
2024 h245_labels.labels[n].comment = NULL;
2026 h245_labels.frame_num = 0;
2027 h245_labels.labels_count = 0;
2030 /* add the frame_label and comment to h245_labels and free the actual one if it is different frame num */
2031 static void h245_add_label(guint32 new_frame_num, const gchar *frame_label, const gchar *comment)
2033 h245_free_labels(new_frame_num);
2035 h245_labels.frame_num = new_frame_num;
2036 h245_labels.labels[h245_labels.labels_count].frame_label = g_strdup(frame_label);
2037 h245_labels.labels[h245_labels.labels_count].comment = g_strdup(comment);
2039 if (h245_labels.labels_count < (H245_MAX-1))
2040 h245_labels.labels_count++;
2044 /****************************************************************************/
2045 /* whenever a H245dg packet is seen by the tap listener (when H245 tunneling is ON) */
2047 H245dgcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H245info)
2049 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2050 voip_calls_info_t *tmp_listinfo;
2051 voip_calls_info_t *callsinfo = NULL;
2052 h323_calls_info_t *tmp_h323info;
2055 h245_address_t *h245_add = NULL;
2057 const h245_packet_info *pi = H245info;
2059 /* check if Tunneling is OFF and we have a call with this H245 add */
2060 list = g_list_first(tapinfo->callsinfo_list);
2063 tmp_listinfo=list->data;
2064 if (tmp_listinfo->protocol == VOIP_H323){
2065 tmp_h323info = tmp_listinfo->prot_info;
2067 list2 = g_list_first(tmp_h323info->h245_list);
2070 h245_add=list2->data;
2071 if ( (ADDRESSES_EQUAL(&(h245_add->h245_address),&(pinfo->src)) && (h245_add->h245_port == pinfo->srcport))
2072 || (ADDRESSES_EQUAL(&(h245_add->h245_address),&(pinfo->dst)) && (h245_add->h245_port == pinfo->destport)) ){
2073 callsinfo = (voip_calls_info_t*)(list->data);
2075 ++(callsinfo->npackets);
2076 /* increment the packets counter of all calls */
2077 ++(tapinfo->npackets);
2081 list2 = g_list_next(list2);
2083 if (callsinfo!=NULL) break;
2085 list = g_list_next(list);
2088 /* Tunnel is OFF, and we matched the h245 add so we add it to graph */
2089 if (callsinfo!=NULL){
2090 ++(callsinfo->npackets);
2091 /* increment the packets counter of all calls */
2092 ++(tapinfo->npackets);
2093 /* if the frame number exists in graph, append to it*/
2094 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, pi->comment)) {
2095 /* if not exist, add to the graph */
2096 add_to_graph(tapinfo, pinfo, pi->frame_label, pi->comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2099 /* Tunnel is ON, so we save the label info to use it into h225 or q931 tap. OR may be
2100 tunnel OFF but we did not matched the h245 add, in this case nobady will set this label
2101 since the frame_num will not match */
2103 h245_add_label(pinfo->fd->num, (gchar *) pi->frame_label, (gchar *) pi->comment);
2106 tapinfo->redraw = TRUE;
2108 return 1; /* refresh output */
2112 /****************************************************************************/
2114 /****************************************************************************/
2115 static gboolean have_H245dg_tap_listener=FALSE;
2116 /****************************************************************************/
2118 h245dg_calls_init_tap(void)
2120 GString *error_string;
2122 if(have_H245dg_tap_listener==FALSE)
2124 /* don't register tap listener, if we have it already */
2125 error_string = register_tap_listener("h245dg", &(the_tapinfo_struct.h245dg_dummy), NULL,
2127 voip_calls_dlg_reset,
2132 if (error_string != NULL) {
2133 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2134 "%s", error_string->str);
2135 g_string_free(error_string, TRUE);
2138 have_H245dg_tap_listener=TRUE;
2142 /****************************************************************************/
2144 remove_tap_listener_h245dg_calls(void)
2146 protect_thread_critical_region();
2147 remove_tap_listener(&(the_tapinfo_struct.h245dg_dummy));
2148 unprotect_thread_critical_region();
2150 have_H245dg_tap_listener=FALSE;
2153 /****************************************************************************/
2154 /****************************TAP for SDP PROTOCOL ***************************/
2155 /****************************************************************************/
2156 /* whenever a SDP packet is seen by the tap listener */
2158 SDPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SDPinfo)
2160 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2161 const sdp_packet_info *pi = SDPinfo;
2163 /* There are protocols like MGCP/SIP where the SDP is called before the tap for the
2164 MGCP/SIP packet, in those cases we assign the SPD summary to global lastSDPsummary
2167 g_free(sdp_summary);
2168 sdp_frame_num = pinfo->fd->num;
2169 /* Append to graph the SDP summary if the packet exists */
2170 sdp_summary = g_strdup_printf("SDP (%s)", pi->summary_str);
2171 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2173 tapinfo->redraw = TRUE;
2175 return 1; /* refresh output */
2179 /****************************************************************************/
2181 /****************************************************************************/
2182 static gboolean have_sdp_tap_listener=FALSE;
2183 /****************************************************************************/
2185 sdp_calls_init_tap(void)
2187 GString *error_string;
2189 if(have_sdp_tap_listener==FALSE)
2191 /* don't register tap listener, if we have it already */
2192 error_string = register_tap_listener("sdp", &(the_tapinfo_struct.sdp_dummy), NULL,
2194 voip_calls_dlg_reset,
2199 if (error_string != NULL) {
2200 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2201 "%s", error_string->str);
2202 g_string_free(error_string, TRUE);
2205 have_sdp_tap_listener=TRUE;
2209 /****************************************************************************/
2211 remove_tap_listener_sdp_calls(void)
2213 protect_thread_critical_region();
2214 remove_tap_listener(&(the_tapinfo_struct.sdp_dummy));
2215 unprotect_thread_critical_region();
2217 have_sdp_tap_listener=FALSE;
2222 /****************************************************************************/
2223 /* ***************************TAP for MGCP **********************************/
2224 /****************************************************************************/
2227 This function will look for a signal/event in the SignalReq/ObsEvent string
2228 and return true if it is found
2230 static gboolean isSignal(const gchar *signal, const gchar *signalStr)
2233 gchar **resultArray;
2235 /* if there is no signalStr, just return false */
2236 if (signalStr == NULL) return FALSE;
2238 /* if are both "blank" return true */
2239 if ( (*signal == '\0') && (*signalStr == '\0') ) return TRUE;
2241 /* look for signal in signalSre */
2242 resultArray = g_strsplit(signalStr, ",", 10);
2244 for (i = 0; resultArray[i]; i++) {
2245 g_strstrip(resultArray[i]);
2246 if (strcmp(resultArray[i], signal) == 0) return TRUE;
2249 g_strfreev(resultArray);
2255 This function will get the Caller ID info and replace the current string
2256 This is how it looks the caller Id: rg, ci(02/16/08/29, "3035550002","Ale Sipura 2")
2258 static void mgcpCallerID(gchar *signalStr, gchar **callerId)
2262 /* if there is no signalStr, just return false */
2263 if (signalStr == NULL) return;
2265 arrayStr = g_strsplit(signalStr, "\"", 10);
2267 if (arrayStr[0] == NULL) return;
2269 /* look for the ci signal */
2270 if (strstr(arrayStr[0], "ci(") && (arrayStr[1] != NULL) ) {
2271 /* free the previous "From" field of the call, and assign the new */
2273 *callerId = g_strdup(arrayStr[1]);
2275 g_strfreev(arrayStr);
2282 This function will get the Dialed Digits and replace the current string
2283 This is how it looks the dialed digits 5,5,5,0,0,0,2,#,*
2285 static void mgcpDialedDigits(gchar *signalStr, gchar **dialedDigits)
2288 gchar resultStr[50];
2291 /* if there is no signalStr, just return false */
2292 if (signalStr == NULL) return;
2294 tmpStr = g_strdup(signalStr);
2296 for ( i = 0 ; tmpStr[i] ; i++) {
2297 switch (tmpStr[i]) {
2298 case '0' : case '1' : case '2' : case '3' : case '4' :
2299 case '5' : case '6' : case '7' : case '8' : case '9' :
2300 case '#' : case '*' :
2308 for (i = 0, j = 0; tmpStr[i] && i<50; i++) {
2309 if (tmpStr[i] != '?')
2310 resultStr[j++] = tmpStr[i];
2312 resultStr[j] = '\0';
2314 if (*resultStr == '\0') return;
2316 g_free(*dialedDigits);
2317 *dialedDigits = g_strdup(resultStr);
2325 /****************************************************************************/
2326 /* whenever a MGCP packet is seen by the tap listener */
2328 MGCPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *MGCPinfo)
2330 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2332 voip_calls_info_t *tmp_listinfo;
2333 voip_calls_info_t *callsinfo = NULL;
2334 mgcp_calls_info_t *tmp_mgcpinfo = NULL;
2337 gchar *frame_label = NULL;
2338 gchar *comment = NULL;
2339 graph_analysis_item_t *gai;
2340 gboolean new = FALSE;
2341 gboolean fromEndpoint = FALSE; /* true for calls originated in Endpoints, false for calls from MGC */
2344 const mgcp_info_t *pi = MGCPinfo;
2347 if ((pi->mgcp_type == MGCP_REQUEST) && !pi->is_duplicate ){
2348 /* check whether we already have a call with this Endpoint and it is active*/
2349 list = g_list_first(tapinfo->callsinfo_list);
2352 tmp_listinfo=list->data;
2353 if ((tmp_listinfo->protocol == VOIP_MGCP) && (tmp_listinfo->call_active_state == VOIP_ACTIVE)){
2354 tmp_mgcpinfo = tmp_listinfo->prot_info;
2355 if (pi->endpointId != NULL){
2356 if (g_ascii_strcasecmp(tmp_mgcpinfo->endpointId,pi->endpointId) == 0){
2358 check first if it is an ended call. We can still match packets to this Endpoint 2 seconds
2359 after the call has been released
2361 diff_time = nstime_to_sec(&pinfo->fd->rel_ts) - tmp_listinfo->stop_sec - (double)tmp_listinfo->stop_usec/1000000;
2362 if ( ((tmp_listinfo->call_state == VOIP_CANCELLED) ||
2363 (tmp_listinfo->call_state == VOIP_COMPLETED) ||
2364 (tmp_listinfo->call_state == VOIP_REJECTED)) &&
2367 tmp_listinfo->call_active_state = VOIP_INACTIVE;
2369 callsinfo = (voip_calls_info_t*)(list->data);
2375 list = g_list_next (list);
2378 /* there is no call with this Endpoint, lets see if this a new call or not */
2379 if (callsinfo == NULL){
2380 if ( (strcmp(pi->code, "NTFY") == 0) && isSignal("hd", pi->observedEvents) ){ /* off hook transition */
2381 /* this is a new call from the Endpoint */
2382 fromEndpoint = TRUE;
2384 } else if (strcmp(pi->code, "CRCX") == 0){
2385 /* this is a new call from the MGC */
2386 fromEndpoint = FALSE;
2391 } else if ( ((pi->mgcp_type == MGCP_RESPONSE) && pi->request_available) ||
2392 ((pi->mgcp_type == MGCP_REQUEST) && pi->is_duplicate) ) {
2393 /* if it is a response OR if it is a duplicated Request, lets look in the Graph to see
2394 if there is a request that matches */
2395 listGraph = g_list_first(tapinfo->graph_analysis->list);
2398 gai = listGraph->data;
2399 if (gai->frame_num == pi->req_num){
2400 /* there is a request that match, so look the associated call with this call_num */
2401 list = g_list_first(tapinfo->callsinfo_list);
2404 tmp_listinfo=list->data;
2405 if (tmp_listinfo->protocol == VOIP_MGCP){
2406 if (tmp_listinfo->call_num == gai->conv_num){
2407 tmp_mgcpinfo = tmp_listinfo->prot_info;
2408 callsinfo = (voip_calls_info_t*)(list->data);
2412 list = g_list_next (list);
2414 if (callsinfo != NULL) break;
2416 listGraph = g_list_next(listGraph);
2418 /* if there is not a matching request, just return */
2419 if (callsinfo == NULL) return 0;
2422 /* not in the list? then create a new entry */
2423 if (callsinfo==NULL){
2424 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2425 callsinfo->call_active_state = VOIP_ACTIVE;
2426 callsinfo->call_state = VOIP_CALL_SETUP;
2428 callsinfo->from_identity=g_strdup(pi->endpointId);
2429 callsinfo->to_identity=g_strdup("");
2431 callsinfo->from_identity=g_strdup("");
2432 callsinfo->to_identity=g_strdup(pi->endpointId);
2434 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
2435 callsinfo->first_frame_num=pinfo->fd->num;
2436 callsinfo->selected=FALSE;
2437 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
2438 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
2439 callsinfo->protocol=VOIP_MGCP;
2440 callsinfo->prot_info=g_malloc(sizeof(mgcp_calls_info_t));
2441 callsinfo->free_prot_info = g_free;
2442 tmp_mgcpinfo=callsinfo->prot_info;
2443 tmp_mgcpinfo->endpointId = g_strdup(pi->endpointId);
2444 tmp_mgcpinfo->fromEndpoint = fromEndpoint;
2445 callsinfo->npackets = 0;
2446 callsinfo->call_num = tapinfo->ncalls++;
2447 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2450 g_assert(tmp_mgcpinfo != NULL);
2452 /* change call state and add to graph */
2453 switch (pi->mgcp_type)
2456 if ( (strcmp(pi->code, "NTFY") == 0) && (pi->observedEvents != NULL) ){
2457 frame_label = g_strdup_printf("%s ObsEvt:%s",pi->code, pi->observedEvents);
2459 if (tmp_mgcpinfo->fromEndpoint){
2460 /* use the Dialed digits to fill the "To" for the call, but use the first NTFY */
2461 if (callsinfo->to_identity[0] == '\0') mgcpDialedDigits(pi->observedEvents, &(callsinfo->to_identity));
2463 /* from MGC and the user picked up, the call is connected */
2464 } else if (isSignal("hd", pi->observedEvents))
2465 callsinfo->call_state=VOIP_IN_CALL;
2467 /* hung up signal */
2468 if (isSignal("hu", pi->observedEvents)) {
2469 if ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state == VOIP_RINGING)){
2470 callsinfo->call_state = VOIP_CANCELLED;
2472 callsinfo->call_state = VOIP_COMPLETED;
2476 } else if (strcmp(pi->code, "RQNT") == 0) {
2477 /* for calls from Endpoint: if there is a "no signal" RQNT and the call was RINGING, we assume this is the CONNECT */
2478 if ( tmp_mgcpinfo->fromEndpoint && isSignal("", pi->signalReq) && (callsinfo->call_state == VOIP_RINGING) ) {
2479 callsinfo->call_state = VOIP_IN_CALL;
2482 /* if there is ringback or ring tone, change state to ringing */
2483 if ( isSignal("rg", pi->signalReq) || isSignal("rt", pi->signalReq) ) {
2484 callsinfo->call_state = VOIP_RINGING;
2487 /* if there is a Busy or ReorderTone, and the call was Ringing or Setup the call is Rejected */
2488 if ( (isSignal("ro", pi->signalReq) || isSignal("bz", pi->signalReq)) && ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state = VOIP_RINGING)) ) {
2489 callsinfo->call_state = VOIP_REJECTED;
2492 if (pi->signalReq != NULL)
2493 frame_label = g_strdup_printf("%s%sSigReq:%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"", pi->signalReq);
2495 frame_label = g_strdup_printf("%s%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"");
2497 /* use the CallerID info to fill the "From" for the call */
2498 if (!tmp_mgcpinfo->fromEndpoint) mgcpCallerID(pi->signalReq, &(callsinfo->from_identity));
2500 } else if (strcmp(pi->code, "DLCX") == 0) {
2502 if there is a DLCX in a call To an Endpoint and the call was not connected, we use
2503 the DLCX as the end of the call
2505 if (!tmp_mgcpinfo->fromEndpoint){
2506 if ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state == VOIP_RINGING)){
2507 callsinfo->call_state = VOIP_CANCELLED;
2512 if (frame_label == NULL) frame_label = g_strdup(pi->code);
2515 frame_label = g_strdup_printf("%u (%s)",pi->rspcode, pi->code);
2518 /* XXX what to do? */
2523 comment = g_strdup_printf("MGCP %s %s%s", tmp_mgcpinfo->endpointId, (pi->mgcp_type == MGCP_REQUEST)?"Request":"Response", pi->is_duplicate?" Duplicate":"");
2525 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
2526 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
2527 callsinfo->last_frame_num=pinfo->fd->num;
2528 ++(callsinfo->npackets);
2529 /* increment the packets counter of all calls */
2530 ++(tapinfo->npackets);
2532 /* add to the graph */
2533 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2535 g_free(frame_label);
2537 /* add SDP info if apply */
2538 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
2539 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2540 g_free(sdp_summary);
2544 tapinfo->redraw = TRUE;
2546 return 1; /* refresh output */
2550 /****************************************************************************/
2552 /****************************************************************************/
2553 static gboolean have_MGCP_tap_listener=FALSE;
2554 /****************************************************************************/
2556 mgcp_calls_init_tap(void)
2558 GString *error_string;
2560 if(have_MGCP_tap_listener==FALSE)
2562 /* don't register tap listener, if we have it already */
2563 /* we send an empty filter, to force a non null "tree" in the mgcp dissector */
2564 error_string = register_tap_listener("mgcp", &(the_tapinfo_struct.mgcp_dummy), g_strdup(""),
2566 voip_calls_dlg_reset,
2570 if (error_string != NULL) {
2571 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2572 "%s", error_string->str);
2573 g_string_free(error_string, TRUE);
2576 have_MGCP_tap_listener=TRUE;
2580 /****************************************************************************/
2582 remove_tap_listener_mgcp_calls(void)
2584 protect_thread_critical_region();
2585 remove_tap_listener(&(the_tapinfo_struct.mgcp_dummy));
2586 unprotect_thread_critical_region();
2588 have_MGCP_tap_listener=FALSE;
2592 /****************************************************************************/
2593 /****************************TAP for ACTRACE (AudioCodes trace)**************/
2594 /****************************************************************************/
2596 /* whenever a ACTRACE packet is seen by the tap listener */
2598 ACTRACEcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *ACTRACEinfo)
2600 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2601 const actrace_info_t *pi = ACTRACEinfo;
2603 actrace_cas_calls_info_t *tmp_actrace_cas_info;
2604 voip_calls_info_t *tmp_listinfo;
2605 voip_calls_info_t *callsinfo = NULL;
2608 actrace_frame_num = pinfo->fd->num;
2609 actrace_trunk = pi->trunk;
2610 actrace_direction = pi->direction;
2612 if (pi->type == 1){ /* is CAS protocol */
2614 gchar *comment = NULL;
2617 list = g_list_first(tapinfo->callsinfo_list);
2620 tmp_listinfo=list->data;
2621 if ( tmp_listinfo->protocol == VOIP_AC_CAS ){
2622 tmp_actrace_cas_info = tmp_listinfo->prot_info;
2623 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
2624 if ( (tmp_actrace_cas_info->bchannel == pi->cas_bchannel) && (tmp_actrace_cas_info->trunk == actrace_trunk) ) {
2625 callsinfo = (voip_calls_info_t*)(list->data);
2629 list = g_list_next (list);
2632 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, "PSTN");
2634 /* if it is a new call, add it to the list */
2636 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2637 callsinfo->call_active_state = VOIP_ACTIVE;
2638 callsinfo->call_state = VOIP_CALL_SETUP;
2639 callsinfo->from_identity=g_strdup("N/A");
2640 callsinfo->to_identity=g_strdup("N/A");
2641 COPY_ADDRESS(&(callsinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
2642 callsinfo->first_frame_num=pinfo->fd->num;
2643 callsinfo->selected=FALSE;
2644 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
2645 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
2646 callsinfo->protocol=VOIP_AC_CAS;
2647 callsinfo->prot_info=g_malloc(sizeof(actrace_cas_calls_info_t));
2648 callsinfo->free_prot_info = g_free;
2650 tmp_actrace_cas_info=callsinfo->prot_info;
2651 tmp_actrace_cas_info->bchannel=pi->cas_bchannel;
2652 tmp_actrace_cas_info->trunk=actrace_trunk;
2653 callsinfo->npackets = 0;
2654 callsinfo->call_num = tapinfo->ncalls++;
2655 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2658 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
2659 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
2660 callsinfo->last_frame_num=pinfo->fd->num;
2661 ++(callsinfo->npackets);
2662 /* increment the packets counter of all calls */
2663 ++(tapinfo->npackets);
2665 comment = g_strdup_printf("AC_CAS trunk:%u", actrace_trunk);
2667 add_to_graph(tapinfo, pinfo, pi->cas_frame_label, comment, callsinfo->call_num,
2668 actrace_direction?&pstn_add:&(pinfo->src),
2669 actrace_direction?&(pinfo->src):&pstn_add,
2675 tapinfo->redraw = TRUE;
2677 return 1; /* refresh output */
2681 /****************************************************************************/
2683 /****************************************************************************/
2684 static gboolean have_actrace_tap_listener=FALSE;
2685 /****************************************************************************/
2687 actrace_calls_init_tap(void)
2689 GString *error_string;
2691 if(have_actrace_tap_listener==FALSE)
2693 /* don't register tap listener, if we have it already */
2694 error_string = register_tap_listener("actrace", &(the_tapinfo_struct.actrace_dummy), NULL,
2696 voip_calls_dlg_reset,
2697 ACTRACEcalls_packet,
2701 if (error_string != NULL) {
2702 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2703 "%s", error_string->str);
2704 g_string_free(error_string, TRUE);
2707 have_actrace_tap_listener=TRUE;
2711 /****************************************************************************/
2713 remove_tap_listener_actrace_calls(void)
2715 protect_thread_critical_region();
2716 remove_tap_listener(&(the_tapinfo_struct.actrace_dummy));
2717 unprotect_thread_critical_region();
2719 have_actrace_tap_listener=FALSE;
2723 /****************************************************************************/
2724 /**************************** TAP for H248/MEGACO **********************************/
2725 /****************************************************************************/
2726 static gboolean have_h248_tap_listener = FALSE;
2727 static gboolean have_megaco_tap_listener = FALSE;
2729 #define gcp_is_req(type) ( type == GCP_CMD_ADD_REQ || type == GCP_CMD_MOVE_REQ || type == GCP_CMD_MOD_REQ || \
2730 type == GCP_CMD_SUB_REQ || type == GCP_CMD_AUDITCAP_REQ || type == GCP_CMD_AUDITVAL_REQ || \
2731 type == GCP_CMD_NOTIFY_REQ || type == GCP_CMD_SVCCHG_REQ || type == GCP_CMD_TOPOLOGY_REQ || \
2732 type == GCP_CMD_CTX_ATTR_AUDIT_REQ )
2734 static int h248_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
2735 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2736 const gcp_cmd_t *cmd = prot_info;
2738 voip_calls_info_t *callsinfo = NULL;
2741 gchar mgw_addr[128];
2743 if (cmd->ctx->id == NULL_CONTEXT || cmd->ctx->id == ALL_CONTEXTS ) {
2747 if ( gcp_is_req(cmd->type) ) {
2748 mgw = &(pinfo->dst);
2749 mgc = &(pinfo->src);
2751 mgc = &(pinfo->dst);
2752 mgw = &(pinfo->src);
2755 address_to_str_buf(mgw, mgw_addr, 128);
2757 /* check whether we already have this context in the list */
2758 list = g_list_first(tapinfo->callsinfo_list);
2761 voip_calls_info_t* tmp_listinfo = list->data;
2763 if (tmp_listinfo->protocol == TEL_H248){
2764 if (tmp_listinfo->prot_info == cmd->ctx){
2765 callsinfo = (voip_calls_info_t*)(list->data);
2769 list = g_list_next (list);
2772 if (callsinfo==NULL){
2774 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2775 callsinfo->call_state = VOIP_NO_STATE;
2776 callsinfo->call_active_state = VOIP_ACTIVE;
2777 callsinfo->from_identity = g_strdup_printf("%s : %.8x", mgw_addr, cmd->ctx->id);
2778 callsinfo->to_identity = g_strdup("");
2779 callsinfo->prot_info = cmd->ctx;
2780 callsinfo->free_prot_info = NULL;
2782 callsinfo->npackets = 1;
2783 callsinfo->first_frame_num=pinfo->fd->num;
2784 callsinfo->last_frame_num=pinfo->fd->num;
2786 COPY_ADDRESS(&(callsinfo->initial_speaker), mgc);
2788 callsinfo->protocol = TEL_H248;
2789 callsinfo->call_num = tapinfo->ncalls++;
2790 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
2791 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs;
2792 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
2793 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
2795 callsinfo->selected = FALSE;
2797 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2800 GString *s = g_string_new("");
2801 gcp_terms_t *ctx_term;
2803 g_free(callsinfo->from_identity);
2804 callsinfo->from_identity = g_strdup_printf("%s : %.8x", mgw_addr, ((gcp_ctx_t*)callsinfo->prot_info)->id);
2806 g_free(callsinfo->to_identity);
2808 for (ctx_term = ((gcp_ctx_t*)callsinfo->prot_info)->terms.next;
2810 ctx_term = ctx_term->next ) {
2811 if ( ctx_term->term && ctx_term->term->str) {
2812 g_string_append_printf(s," %s",ctx_term->term->str);
2816 callsinfo->to_identity = s->str;
2817 g_string_free(s,FALSE);
2819 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
2820 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
2821 callsinfo->last_frame_num=pinfo->fd->num;
2822 ++(callsinfo->npackets);
2825 add_to_graph(tapinfo, pinfo, cmd->str ? cmd->str : "unknown Msg",
2826 ep_strdup_printf("TrxId = %u, CtxId = %.8x",cmd->trx->id,cmd->ctx->id),
2827 callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2829 ++(tapinfo->npackets);
2831 tapinfo->redraw = TRUE;
2836 void h248_calls_init_tap(void)
2838 GString *error_string;
2841 if(have_megaco_tap_listener==FALSE)
2843 error_string = register_tap_listener("megaco", &(the_tapinfo_struct.megaco_dummy),
2846 voip_calls_dlg_reset,
2848 voip_calls_dlg_draw);
2850 if (error_string != NULL) {
2851 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2852 "%s", error_string->str);
2853 g_string_free(error_string, TRUE);
2857 have_megaco_tap_listener=TRUE;
2860 if(have_h248_tap_listener==FALSE)
2862 error_string = register_tap_listener("h248", &(the_tapinfo_struct.h248_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,
2871 "%s", error_string->str);
2872 g_string_free(error_string, TRUE);
2876 have_h248_tap_listener=TRUE;
2881 remove_tap_listener_h248_calls(void)
2883 protect_thread_critical_region();
2884 remove_tap_listener(&(the_tapinfo_struct.h248_dummy));
2885 remove_tap_listener(&(the_tapinfo_struct.megaco_dummy));
2886 unprotect_thread_critical_region();
2888 have_megaco_tap_listener=FALSE;
2889 have_h248_tap_listener=FALSE;
2892 /****************************************************************************/
2893 /**************************** TAP for SCCP and SUA **********************************/
2894 /**************************** ( RANAP and BSSAP ) **********************************/
2895 /****************************************************************************/
2897 static gboolean have_sccp_tap_listener = FALSE;
2898 static gboolean have_sua_tap_listener = FALSE;
2900 static const voip_protocol sccp_proto_map[] = {
2905 #define SP2VP(ap) ((ap) < SCCP_PLOAD_NUM_PLOADS ? sccp_proto_map[(ap)] : TEL_SCCP)
2906 const value_string* sccp_payload_values;
2908 static int sccp_calls(packet_info *pinfo, const void *prot_info) {
2909 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2910 const sccp_msg_info_t* msg = prot_info;
2911 sccp_assoc_info_t* assoc = msg->data.co.assoc;
2913 voip_calls_info_t *callsinfo = NULL;
2914 const gchar *label = NULL;
2915 const gchar *comment = NULL;
2916 /* check whether we already have this assoc in the list */
2918 for(list = g_list_first(tapinfo->callsinfo_list) ; list ; list = g_list_next (list) ) {
2919 if ( ((voip_calls_info_t*)(list->data))->prot_info == assoc ){
2920 callsinfo = (voip_calls_info_t*)(list->data);
2925 if (callsinfo==NULL){
2926 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2927 callsinfo->call_state = VOIP_CALL_SETUP;
2928 callsinfo->call_active_state = VOIP_ACTIVE;
2929 if ( assoc->calling_party ) {
2930 callsinfo->from_identity = g_strdup(assoc->calling_party);
2932 callsinfo->from_identity = g_strdup("Unknown");
2935 if ( assoc->called_party ) {
2936 callsinfo->to_identity = g_strdup(assoc->called_party);
2938 callsinfo->to_identity = g_strdup("Unknown");
2941 callsinfo->prot_info = (void*)assoc;
2942 callsinfo->free_prot_info = NULL;
2944 callsinfo->npackets = 1;
2945 callsinfo->first_frame_num=pinfo->fd->num;
2946 callsinfo->last_frame_num=pinfo->fd->num;
2948 COPY_ADDRESS(&(callsinfo->initial_speaker), &(pinfo->src));
2950 callsinfo->protocol = SP2VP(assoc->payload);
2951 callsinfo->start_sec=(gint32) pinfo->fd->rel_ts.secs;
2952 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs;
2953 callsinfo->stop_sec=(gint32) pinfo->fd->rel_ts.secs;
2954 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
2956 callsinfo->selected = FALSE;
2957 callsinfo->call_num = tapinfo->ncalls++;
2959 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2962 if ( assoc->calling_party ) {
2963 g_free(callsinfo->from_identity);
2964 callsinfo->from_identity = g_strdup(assoc->calling_party);
2967 if ( assoc->called_party ) {
2968 g_free(callsinfo->to_identity);
2969 callsinfo->to_identity = g_strdup(assoc->called_party);
2972 callsinfo->protocol = SP2VP(assoc->payload);
2973 callsinfo->stop_sec=(gint32) pinfo->fd->rel_ts.secs;
2974 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
2975 callsinfo->last_frame_num=pinfo->fd->num;
2976 ++(callsinfo->npackets);
2978 switch (msg->type) {
2979 case SCCP_MSG_TYPE_CC:
2980 callsinfo->call_state = VOIP_IN_CALL;
2982 case SCCP_MSG_TYPE_RLC:
2983 callsinfo->call_state = VOIP_COMPLETED;
2984 callsinfo->call_active_state = VOIP_INACTIVE;
2991 if (msg->data.co.label) {
2992 label = msg->data.co.label;
2994 label = val_to_str(msg->type, sccp_payload_values, "Unknown(%d)");
2997 if (msg->data.co.comment) {
2998 comment = msg->data.co.comment;
3003 add_to_graph(tapinfo, pinfo, label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3005 ++(tapinfo->npackets);
3007 tapinfo->redraw = TRUE;
3012 static int sccp_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
3013 sccp_payload_values = sccp_message_type_acro_values;
3014 return sccp_calls(pinfo, prot_info);
3018 static int sua_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
3019 sccp_payload_values = sua_co_class_type_acro_values;
3020 return sccp_calls(pinfo, prot_info);
3024 void sccp_calls_init_tap(void)
3026 GString *error_string;
3028 if(have_sccp_tap_listener==FALSE)
3030 error_string = register_tap_listener("sccp", &(the_tapinfo_struct.sccp_dummy),
3033 voip_calls_dlg_reset,
3035 voip_calls_dlg_draw);
3037 if (error_string != NULL) {
3038 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3039 "%s", error_string->str);
3040 g_string_free(error_string, TRUE);
3044 have_sccp_tap_listener=TRUE;
3047 if(have_sua_tap_listener==FALSE)
3049 error_string = register_tap_listener("sua", &(the_tapinfo_struct.sua_dummy),
3052 voip_calls_dlg_reset,
3054 voip_calls_dlg_draw);
3056 if (error_string != NULL) {
3057 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3058 "%s", error_string->str);
3059 g_string_free(error_string, TRUE);
3063 have_sua_tap_listener=TRUE;
3069 remove_tap_listener_sccp_calls(void)
3071 protect_thread_critical_region();
3072 remove_tap_listener(&(the_tapinfo_struct.sccp_dummy));
3073 unprotect_thread_critical_region();
3075 have_sccp_tap_listener=FALSE;
3076 have_sua_tap_listener=FALSE;
3080 /****************************************************************************/
3081 /****************************TAP for UNISTIM ********************************/
3082 /****************************************************************************/
3085 unistim_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *unistim_info)
3087 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3088 voip_calls_info_t *tmp_listinfo;
3089 voip_calls_info_t *callsinfo = NULL;
3090 unistim_info_t *tmp_unistim_info = NULL;
3092 GString *g_tmp = NULL;
3093 gchar *frame_label = NULL;
3094 gchar *comment = NULL;
3096 /* Fetch specific packet infos */
3097 const unistim_info_t *pi = unistim_info;
3100 g_tmp = g_string_new(NULL);
3102 /* Check to see if this is a dup */
3103 list = g_list_first(tapinfo->callsinfo_list);
3107 tmp_listinfo = list->data;
3109 if(tmp_listinfo->protocol == VOIP_UNISTIM){
3111 tmp_unistim_info = tmp_listinfo->prot_info;
3113 /* Search by termid if possible, otherwise use ni/it ip + port.. */
3114 if(pi->termid != 0){
3115 if(tmp_unistim_info->termid == pi->termid){
3116 /* If the call has ended, then we can reuse it.. */
3117 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
3120 callsinfo = (voip_calls_info_t*)(list->data);
3125 /* If no term id use ips / port to find entry */
3126 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)){
3127 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
3128 /* Do nothing previous call */
3130 callsinfo = (voip_calls_info_t*)(list->data);
3134 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)) {
3135 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
3136 /* Do nothing, it ain't our call.. */
3138 callsinfo = (voip_calls_info_t*)(list->data);
3145 /* Otherwise, go to the next one.. */
3146 list = g_list_next(list);
3149 if(pi->payload_type == 2 || pi->payload_type == 1){
3151 if(pi->key_state == 1 || pi->hook_state == 1){
3153 /* If the user hits a button,
3154 Session will be SETUP */
3156 /* If new add to list */
3157 if (callsinfo==NULL){
3159 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3160 callsinfo->call_active_state = VOIP_ACTIVE;
3161 callsinfo->call_state = VOIP_CALL_SETUP;
3162 callsinfo->from_identity=g_strdup_printf("%x",pi->termid);
3163 callsinfo->to_identity=g_strdup("UNKNOWN");
3164 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
3165 callsinfo->first_frame_num=pinfo->fd->num;
3166 callsinfo->selected=FALSE;
3168 /* Set this on init of struct so in case the call doesn't complete, we'll have a ref. */
3169 /* Otherwise if the call is completed we'll have the open/close streams to ref actual call duration */
3170 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3171 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3173 callsinfo->protocol=VOIP_UNISTIM;
3174 callsinfo->prot_info=g_malloc(sizeof(unistim_info_t));
3176 tmp_unistim_info = callsinfo->prot_info;
3178 /* Clear tap struct */
3179 tmp_unistim_info->rudp_type = 0;
3180 tmp_unistim_info->payload_type = 0;
3181 tmp_unistim_info->sequence = pi->sequence;
3182 tmp_unistim_info->termid = pi->termid;
3183 tmp_unistim_info->key_val = -1;
3184 tmp_unistim_info->key_state = -1;
3185 tmp_unistim_info->hook_state = -1;
3186 tmp_unistim_info->stream_connect = -1;
3187 tmp_unistim_info->trans_connect = -1;
3188 tmp_unistim_info->set_termid = -1;
3189 tmp_unistim_info->string_data = NULL;
3190 tmp_unistim_info->key_buffer = NULL;
3192 COPY_ADDRESS(&(tmp_unistim_info->it_ip),&(pi->it_ip));
3193 COPY_ADDRESS(&(tmp_unistim_info->ni_ip),&(pi->ni_ip));
3194 tmp_unistim_info->it_port = pi->it_port;
3196 callsinfo->free_prot_info = g_free;
3197 callsinfo->npackets = 0;
3198 callsinfo->call_num = tapinfo->ncalls++;
3199 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3203 /* Set up call wide info struct */
3204 tmp_unistim_info = callsinfo->prot_info;
3205 tmp_unistim_info->sequence = pi->sequence;
3208 /* Each packet COULD BE OUR LAST!!!! */
3209 callsinfo->stop_sec=(gint32)(pinfo->fd->rel_ts.secs);
3210 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
3211 callsinfo->last_frame_num=pinfo->fd->num;
3213 /* This is a valid packet so increment counter */
3214 ++(callsinfo->npackets);
3216 /* increment the packets counter of all calls */
3217 ++(tapinfo->npackets);
3219 /* Key was depressed.. update key buffer.. */
3220 if(pi->key_val >= 0 && pi->key_val <= 11){
3222 if(tmp_unistim_info->key_buffer != NULL){
3224 /* assign to temp variable */
3225 g_string_assign(g_tmp,tmp_unistim_info->key_buffer);
3227 /* Manipulate the data */
3228 if(pi->key_val == 10) {
3229 tmp_unistim_info->key_buffer = g_strdup_printf("%s*",g_tmp->str);
3230 } else if(pi->key_val == 11) {
3231 tmp_unistim_info->key_buffer = g_strdup_printf("%s#",g_tmp->str);
3233 tmp_unistim_info->key_buffer = g_strdup_printf("%s%d",g_tmp->str,pi->key_val);
3238 /* Create new string */
3239 if(pi->key_val == 10) {
3240 tmp_unistim_info->key_buffer = g_strdup("*");
3241 } else if(pi->key_val == 11) {
3242 tmp_unistim_info->key_buffer = g_strdup("#");
3244 tmp_unistim_info->key_buffer = g_strdup_printf("%d",pi->key_val);
3249 /* Select for non-digit characters */
3250 if(pi->key_val == 10) {
3251 comment = g_strdup_printf("Key Input Sent: * (%d)", pi->sequence);
3252 } else if(pi->key_val == 11) {
3253 comment = g_strdup_printf("Key Input Sent: # (%d)", pi->sequence);
3255 comment = g_strdup_printf("Key Input Sent: %d (%d)",pi->key_val, pi->sequence);
3257 } else if(pi->key_val == 12) {
3258 /* Set label and comment for graph */
3259 comment = g_strdup_printf("Key Input Sent: UP (%d)", pi->sequence);
3260 } else if(pi->key_val == 13) {
3261 /* Set label and comment for graph */
3262 comment = g_strdup_printf("Key Input Sent: DOWN (%d)", pi->sequence);
3263 } else if(pi->key_val == 14) {
3264 /* Set label and comment for graph */
3265 comment = g_strdup_printf("Key Input Sent: RIGHT (%d)", pi->sequence);
3266 } else if(pi->key_val == 15) {
3267 if(pi->key_buffer != NULL){
3269 g_string_assign(g_tmp,pi->key_buffer);
3271 /* Manipulate the data */
3272 g_string_truncate(g_tmp,g_tmp->len-1);
3274 /* Insert new data */
3275 tmp_unistim_info->key_buffer = g_strdup(g_tmp->str);
3278 /* Set label and comment for graph */
3279 comment = g_strdup_printf("Key Input Sent: LEFT (%d)", pi->sequence);
3280 } else if(pi->key_val == 20) {
3281 /* User pressed the soft key 0 probably dial */
3282 comment = g_strdup_printf("Key Input Sent: S0 (%d)", pi->sequence);
3283 } else if(pi->key_val == 21) {
3284 /* User pressed the soft key 1 */
3285 comment = g_strdup_printf("Key Input Sent: S1 (%d)", pi->sequence);
3286 } else if(pi->key_val == 22) {
3287 /* User pressed the soft key 2 */
3288 /* On cs2k phones, soft key 2 is backspace. */
3289 if(pi->key_buffer != NULL) {
3292 g_string_assign(g_tmp,pi->key_buffer);
3294 /* Manipulate the data */
3295 g_string_truncate(g_tmp,g_tmp->len-1);
3297 /* Insert new data */
3298 tmp_unistim_info->key_buffer = g_strdup(g_tmp->str);
3301 /* add label and comment */
3302 comment = g_strdup_printf("Key Input Sent: S2 (%d)", pi->sequence);
3303 } else if(pi->key_val == 28) {
3304 /* User pressed something */
3305 comment = g_strdup_printf("Key Input Sent: Release (%d)", pi->sequence);
3306 } else if(pi->key_val == 23) {
3307 /* User pressed the soft key 3 */
3308 /* Cancel on cs2k so clear buffer */
3309 /* On mcs its config which will clear the buffer too */
3310 tmp_unistim_info->key_buffer = g_strdup("\n");
3312 /* User pressed something, set labels*/
3313 comment = g_strdup_printf("Key Input Sent: S3 (%d)", pi->sequence);
3314 } else if(pi->key_val == 27) {
3315 /* User pressed something */
3316 comment = g_strdup_printf("Key Input Sent: Hold (%d)", pi->sequence);
3317 } else if(pi->key_val == 29) {
3318 /* User pressed something */
3319 comment = g_strdup_printf("Key Input Sent: Mute (%d)", pi->sequence);
3320 } else if(pi->key_val == 30) {
3321 /* User pressed something */
3322 comment = g_strdup_printf("Key Input Sent: Headset (%d)", pi->sequence);
3323 } else if(pi->key_val == 31) {
3324 /* Handsfree button */
3325 comment = g_strdup_printf("Key Input Sent: Handsfree (%d)", pi->sequence);
3326 } else if(pi->key_val >= 32 && pi->key_val <= 56) {
3328 comment = g_strdup_printf("Key Input Sent: Prog%d (%d)", (pi->key_val & 31), pi->sequence);
3331 if(pi->key_val != -1) {
3333 frame_label = "KEY INPUT";
3335 if (comment == NULL)
3336 /* Ouch! What do you do!? */
3337 /* User pressed something */
3338 comment = g_strdup_printf("Key Input Sent: UNKNOWN - %d (%d)", pi->key_val, pi->sequence);
3340 /* add to the graph */
3341 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3346 if(pi->hook_state == 1) {
3348 /* Phone is off hook */
3349 frame_label = "OFF HOOK";
3350 comment = g_strdup_printf("Off Hook (%d)", pi->sequence);
3352 /* add to the graph */
3353 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3356 } else if(pi->hook_state == 0) {
3358 /* Phone is on hook */
3359 frame_label = "ON HOOK";
3360 comment = g_strdup_printf("On Hook (%d)", pi->sequence);
3362 /* add to the graph */
3363 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3369 /* Open stream was sent from server */
3370 if(pi->stream_connect == 1 && callsinfo != NULL) {
3373 /* Signifies the start of the call so set start_sec & start_usec */
3374 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3375 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3377 /* Local packets too */
3378 ++(callsinfo->npackets);
3380 /* increment the packets counter of all calls */
3381 ++(tapinfo->npackets);
3383 /* ?? means we're not quite sure if this is accurate. Since Unistim isn't a true
3384 Call control protocol, we can only guess at the destination by messing with
3386 if(tmp_unistim_info->key_buffer != NULL){
3387 callsinfo->to_identity = g_strdup_printf("?? %s",tmp_unistim_info->key_buffer);
3390 /* change sequence number for ACK detection */
3391 tmp_unistim_info->sequence = pi->sequence;
3393 /* State changes too */
3394 callsinfo->call_active_state = VOIP_ACTIVE;
3395 callsinfo->call_state = VOIP_IN_CALL;
3397 /* Add graph data */
3398 frame_label = "STREAM OPENED";
3399 comment = g_strdup_printf("Stream Opened (%d)",pi->sequence);
3401 /* add to the graph */
3402 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3404 } else if(pi->stream_connect == 1 && callsinfo == NULL) {
3406 /* Research indicates some nortel products initiate stream first
3407 * without keypresses. therefore creating this solely on a keypress is
3409 * Sometimes calls start immediately with open stream.
3411 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3412 callsinfo->call_active_state = VOIP_ACTIVE;
3413 callsinfo->call_state = VOIP_CALL_SETUP;
3414 callsinfo->from_identity=g_strdup("UNKNOWN");
3415 callsinfo->to_identity=g_strdup("UNKNOWN");
3416 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
3417 callsinfo->first_frame_num=pinfo->fd->num;
3418 callsinfo->selected=FALSE;
3420 /* Set this on init of struct so in case the call doesn't complete, we'll have a ref. */
3421 /* Otherwise if the call is completed we'll have the open/close streams to ref actual call duration */
3422 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3423 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3425 callsinfo->protocol=VOIP_UNISTIM;
3426 callsinfo->prot_info=g_malloc(sizeof(unistim_info_t));
3428 tmp_unistim_info = callsinfo->prot_info;
3430 /* Clear tap struct */
3431 tmp_unistim_info->rudp_type = 0;
3432 tmp_unistim_info->payload_type = 0;
3433 tmp_unistim_info->sequence = pi->sequence;
3434 tmp_unistim_info->termid = 0;
3435 tmp_unistim_info->key_val = -1;
3436 tmp_unistim_info->key_state = -1;
3437 tmp_unistim_info->hook_state = -1;
3438 tmp_unistim_info->stream_connect = -1;
3439 tmp_unistim_info->trans_connect = -1;
3440 tmp_unistim_info->set_termid = -1;
3441 tmp_unistim_info->string_data = NULL;
3442 tmp_unistim_info->key_buffer = NULL;
3444 COPY_ADDRESS(&(tmp_unistim_info->it_ip),&(pi->it_ip));
3445 COPY_ADDRESS(&(tmp_unistim_info->ni_ip),&(pi->ni_ip));
3446 tmp_unistim_info->it_port = pi->it_port;
3448 callsinfo->free_prot_info = g_free;
3449 callsinfo->npackets = 0;
3450 callsinfo->call_num = tapinfo->ncalls++;
3451 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3454 /* Signifies the start of the call so set start_sec & start_usec */
3455 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3456 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3458 /* Local packets too */
3459 ++(callsinfo->npackets);
3461 /* increment the packets counter of all calls */
3462 ++(tapinfo->npackets);
3464 /* ?? means we're not quite sure if this is accurate. Since Unistim isn't a true
3465 Call control protocol, we can only guess at the destination by messing with
3467 if(tmp_unistim_info->key_buffer != NULL){
3468 callsinfo->to_identity = g_strdup_printf("?? %s",tmp_unistim_info->key_buffer);
3471 /* change sequence number for ACK detection */
3472 tmp_unistim_info->sequence = pi->sequence;
3474 /* State changes too */
3475 callsinfo->call_active_state = VOIP_ACTIVE;
3476 callsinfo->call_state = VOIP_IN_CALL;
3478 /* Add graph data */
3479 frame_label = "STREAM OPENED";
3480 comment = g_strdup_printf("Stream Opened (%d)",pi->sequence);
3482 /* add to the graph */
3483 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3485 } else if(pi->stream_connect == 0 && callsinfo != NULL) {
3488 /* Set stop seconds + usec */
3489 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
3490 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
3491 callsinfo->last_frame_num=pinfo->fd->num;
3493 tmp_unistim_info->sequence = pi->sequence;
3495 if(callsinfo->call_state == VOIP_IN_CALL){
3496 callsinfo->call_active_state = VOIP_INACTIVE;
3497 callsinfo->call_state = VOIP_COMPLETED;
3499 callsinfo->call_state = VOIP_UNKNOWN;
3500 callsinfo->call_active_state = VOIP_INACTIVE;
3503 frame_label = "STREAM CLOSED";
3504 comment = g_strdup_printf("Stream Closed (%d)",pi->sequence);
3506 /* add to the graph */
3507 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3512 } else if(pi->rudp_type == 1 && callsinfo != NULL) {
3514 /* Only show acks for processed seq #s */
3515 if(tmp_unistim_info->sequence == pi->sequence) {
3517 frame_label = "ACK";
3518 comment = g_strdup_printf("ACK for sequence %d",pi->sequence);
3520 /* add to the graph */
3521 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3525 } else if(pi->rudp_type == 0 && callsinfo != NULL) {
3528 frame_label = "NAK";
3529 comment = g_strdup_printf("NAK for sequence %d",pi->sequence);
3531 /* add to the graph */
3532 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3539 tapinfo->redraw = TRUE;
3544 /****************************************************************************/
3546 /****************************************************************************/
3547 static gboolean have_unistim_tap_listener=FALSE;
3548 /****************************************************************************/
3550 unistim_calls_init_tap(void){
3552 GString *error_string;
3554 if(have_unistim_tap_listener==FALSE) {
3556 error_string = register_tap_listener("unistim", &(the_tapinfo_struct.unistim_dummy),
3559 voip_calls_dlg_reset,
3560 unistim_calls_packet,
3564 if (error_string != NULL) {
3565 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3566 "%s", error_string->str);
3567 g_string_free(error_string, TRUE);
3571 have_unistim_tap_listener=TRUE;
3575 /****************************************************************************/
3577 remove_tap_listener_unistim_calls(void)
3579 protect_thread_critical_region();
3580 remove_tap_listener(&(the_tapinfo_struct.unistim_dummy));
3581 unprotect_thread_critical_region();
3583 have_unistim_tap_listener=FALSE;
3586 /****************************************************************************/
3587 /* ***************************TAP for SKINNY **********************************/
3588 /****************************************************************************/
3590 /* Telecaster to tap-voip call state mapping */
3591 static const voip_call_state skinny_tap_voip_state[] = {
3610 skinny_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *skinny_info)
3612 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3614 voip_calls_info_t *callsinfo = NULL;
3616 const skinny_info_t *si = skinny_info;
3617 skinny_calls_info_t *tmp_skinnyinfo;
3620 if (si == NULL || (si->callId == 0 && si->passThruId == 0))
3622 /* check whether we already have this context in the list */
3623 list = g_list_first(tapinfo->callsinfo_list);
3626 voip_calls_info_t* tmp_listinfo = list->data;
3627 if (tmp_listinfo->protocol == VOIP_SKINNY){
3628 tmp_skinnyinfo = tmp_listinfo->prot_info;
3629 if (tmp_skinnyinfo->callId == si->callId ||
3630 tmp_skinnyinfo->callId == si->passThruId){
3631 callsinfo = (voip_calls_info_t*)(list->data);
3635 list = g_list_next (list);
3638 if (si->messId >= 256)
3639 phone = &(pinfo->dst);
3641 phone = &(pinfo->src);
3643 if (callsinfo==NULL){
3644 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3645 callsinfo->call_state = VOIP_NO_STATE;
3646 callsinfo->call_active_state = VOIP_ACTIVE;
3647 /* callsinfo->from_identity = g_strdup_printf("%s : %.8x", "Skinny", 1); */
3648 callsinfo->from_identity = g_strdup("");
3649 callsinfo->to_identity = g_strdup("");
3650 callsinfo->prot_info = g_malloc(sizeof(skinny_calls_info_t));
3651 callsinfo->free_prot_info = g_free;
3652 tmp_skinnyinfo = callsinfo->prot_info;
3653 tmp_skinnyinfo->callId = si->callId ? si->callId : si->passThruId;
3654 callsinfo->npackets = 1;
3655 callsinfo->first_frame_num=pinfo->fd->num;
3656 callsinfo->last_frame_num=pinfo->fd->num;
3658 COPY_ADDRESS(&(callsinfo->initial_speaker), phone);
3660 callsinfo->protocol = VOIP_SKINNY;
3661 callsinfo->call_num = tapinfo->ncalls++;
3662 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3663 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs;
3664 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
3665 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
3667 callsinfo->selected = FALSE;
3668 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3670 if (si->callingParty) {
3671 g_free(callsinfo->from_identity);
3672 callsinfo->from_identity = g_strdup(si->callingParty);
3674 if (si->calledParty) {
3675 g_free(callsinfo->to_identity);
3676 callsinfo->to_identity = g_strdup(si->calledParty);
3678 if ((si->callState > 0) && (si->callState < (sizeof(skinny_tap_voip_state)/sizeof(skinny_tap_voip_state[0]))))
3679 callsinfo->call_state = skinny_tap_voip_state[si->callState];
3681 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
3682 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
3683 callsinfo->last_frame_num=pinfo->fd->num;
3684 ++(callsinfo->npackets);
3689 comment = g_strdup_printf("CallId = %u, PTId = %u", si->callId, si->passThruId);
3691 comment = g_strdup_printf("CallId = %u, LineId = %u", si->callId, si->lineId);
3694 comment = g_strdup_printf("PTId = %u", si->passThruId);
3699 add_to_graph(tapinfo, pinfo, si->messageName, comment,
3700 callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3707 /****************************************************************************/
3709 /****************************************************************************/
3710 static gboolean have_skinny_tap_listener=FALSE;
3711 /****************************************************************************/
3713 skinny_calls_init_tap(void)
3715 GString *error_string;
3717 if(have_skinny_tap_listener==FALSE)
3719 /* don't register tap listener, if we have it already */
3720 /* we send an empty filter, to force a non null "tree" in the SKINNY dissector */
3721 error_string = register_tap_listener("skinny", &(the_tapinfo_struct.skinny_dummy), g_strdup(""),
3723 voip_calls_dlg_reset,
3724 skinny_calls_packet,
3727 if (error_string != NULL) {
3728 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3729 "%s", error_string->str);
3730 g_string_free(error_string, TRUE);
3733 have_skinny_tap_listener=TRUE;
3737 /****************************************************************************/
3739 remove_tap_listener_skinny_calls(void)
3741 protect_thread_critical_region();
3742 remove_tap_listener(&(the_tapinfo_struct.skinny_dummy));
3743 unprotect_thread_critical_region();
3745 have_skinny_tap_listener=FALSE;
3748 /****************************************************************************/
3749 /* ***************************TAP for IAX2 **********************************/
3750 /****************************************************************************/
3752 /* IAX2 to tap-voip call state mapping */
3753 static const voip_call_state tap_iax_voip_state[] = {
3755 VOIP_CALL_SETUP, /*NEW*/
3758 VOIP_COMPLETED, /*HANGUP*/
3759 VOIP_REJECTED, /*REJECT*/
3760 VOIP_RINGING, /*ACCEPT*/
3775 VOIP_CALL_SETUP, /*DIAL*/
3794 static void free_iax2_info(gpointer p) {
3795 iax2_info_t *ii = p;
3801 /****************************************************************************/
3802 /* whenever a IAX2 packet is seen by the tap listener */
3804 iax2_calls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *iax2_info)
3806 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3808 voip_calls_info_t *callsinfo = NULL;
3810 const iax2_info_t *ii = iax2_info;
3811 iax2_info_t *tmp_iax2info;
3814 if (ii == NULL || ii->ptype != IAX2_FULL_PACKET || (ii->scallno == 0 && ii->dcallno == 0))
3816 /* check whether we already have this context in the list */
3817 list = g_list_first(tapinfo->callsinfo_list);
3820 voip_calls_info_t* tmp_listinfo = list->data;
3821 if (tmp_listinfo->protocol == VOIP_IAX2){
3822 tmp_iax2info = tmp_listinfo->prot_info;
3823 if (tmp_iax2info->scallno == ii->scallno ||
3824 tmp_iax2info->scallno == ii->dcallno){
3825 callsinfo = (voip_calls_info_t*)(list->data);
3829 list = g_list_next (list);
3831 phone = &(pinfo->src);
3834 if (callsinfo==NULL){
3835 /* We only care about real calls, i.e., no registration stuff */
3836 if (ii->ftype != AST_FRAME_IAX || ii->csub != IAX_COMMAND_NEW)
3838 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3839 callsinfo->call_state = VOIP_NO_STATE;
3840 callsinfo->call_active_state = VOIP_ACTIVE;
3841 callsinfo->prot_info=g_malloc(sizeof(iax2_info_t));
3842 callsinfo->free_prot_info = free_iax2_info;
3843 tmp_iax2info = callsinfo->prot_info;
3845 tmp_iax2info->scallno = ii->scallno;
3846 if (tmp_iax2info->scallno == 0) tmp_iax2info->scallno = ii->dcallno;
3847 tmp_iax2info->callState = tap_iax_voip_state[ii->callState];
3849 callsinfo->npackets = 1;
3850 callsinfo->first_frame_num=pinfo->fd->num;
3851 callsinfo->last_frame_num=pinfo->fd->num;
3853 COPY_ADDRESS(&(callsinfo->initial_speaker), phone);
3854 callsinfo->from_identity = g_strdup(ii->callingParty);
3855 callsinfo->to_identity = g_strdup(ii->calledParty);
3857 callsinfo->protocol = VOIP_IAX2;
3858 callsinfo->call_num = tapinfo->ncalls++;
3859 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3860 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs;
3861 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
3862 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
3864 callsinfo->selected = FALSE;
3865 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3868 if ((ii->callState > 0) && (ii->callState < (sizeof(tap_iax_voip_state)/sizeof(tap_iax_voip_state[0]))))
3869 callsinfo->call_state = tap_iax_voip_state[ii->callState];
3871 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
3872 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
3873 callsinfo->last_frame_num=pinfo->fd->num;
3874 ++(callsinfo->npackets);
3879 add_to_graph(tapinfo, pinfo, ii->messageName, comment,
3880 callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3887 /****************************************************************************/
3889 /****************************************************************************/
3890 static gboolean have_iax2_tap_listener=FALSE;
3891 /****************************************************************************/
3893 iax2_calls_init_tap(void)
3895 GString *error_string;
3897 if(have_iax2_tap_listener==FALSE)
3899 /* don't register tap listener, if we have it already */
3900 /* we send an empty filter, to force a non null "tree" in the IAX2 dissector */
3901 error_string = register_tap_listener("IAX2", &(the_tapinfo_struct.iax2_dummy), g_strdup(""),
3903 voip_calls_dlg_reset,
3907 if (error_string != NULL) {
3908 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s",
3910 g_string_free(error_string, TRUE);
3913 have_iax2_tap_listener=TRUE;
3917 /****************************************************************************/
3919 remove_tap_listener_iax2_calls(void)
3921 protect_thread_critical_region();
3922 remove_tap_listener(&(the_tapinfo_struct.iax2_dummy));
3923 unprotect_thread_critical_region();
3925 have_iax2_tap_listener=FALSE;
3928 /****************************************************************************/
3929 /* ***************************TAP for OTHER PROTOCOL **********************************/
3930 /****************************************************************************/
3933 VoIPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *VoIPinfo)
3935 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3936 voip_calls_info_t *callsinfo = NULL;
3937 voip_calls_info_t *tmp_listinfo;
3939 const voip_packet_info_t *pi = VoIPinfo;
3942 list = g_list_first(tapinfo->callsinfo_list);
3944 tmp_listinfo = list->data;
3945 if ( tmp_listinfo->protocol == VOIP_COMMON ) {
3946 if (!strcmp(pi->call_id, tmp_listinfo->call_id)) {
3947 callsinfo = (voip_calls_info_t*)(list->data);
3951 list = g_list_next(list);
3954 if (callsinfo == NULL) {
3955 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3956 callsinfo->call_active_state = pi->call_active_state;
3957 callsinfo->call_state = pi->call_state;
3958 callsinfo->call_id=g_strdup((pi->call_id)?pi->call_id:"");
3959 callsinfo->from_identity = g_strdup((pi->from_identity)?pi->from_identity:"");
3960 callsinfo->to_identity = g_strdup((pi->to_identity)?pi->to_identity:"");
3961 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
3962 callsinfo->selected=FALSE;
3963 callsinfo->first_frame_num=pinfo->fd->num;
3964 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3965 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3966 callsinfo->protocol=VOIP_COMMON;
3967 callsinfo->protocol_name=g_strdup((pi->protocol_name)?pi->protocol_name:"");
3968 callsinfo->call_comment=g_strdup((pi->call_comment)?pi->call_comment:"");
3969 callsinfo->prot_info=NULL;
3970 callsinfo->free_prot_info = NULL;
3972 callsinfo->call_num = tapinfo->ncalls++;
3973 callsinfo->npackets = 0;
3975 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3978 if (callsinfo != NULL) {
3979 callsinfo->call_active_state = pi->call_active_state;
3980 if ((callsinfo->call_state != VOIP_COMPLETED) && (pi->call_state == VOIP_COMPLETED))
3981 tapinfo->completed_calls++;
3982 if (pi->call_state != VOIP_NO_STATE)
3983 callsinfo->call_state = pi->call_state;
3984 if (pi->call_comment) {
3985 g_free(callsinfo->call_comment);
3986 callsinfo->call_comment=g_strdup(pi->call_comment);
3988 callsinfo->stop_sec=(gint32)(pinfo->fd->rel_ts.secs);
3989 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
3990 callsinfo->last_frame_num=pinfo->fd->num;
3991 ++(callsinfo->npackets);
3992 ++(tapinfo->npackets);
3995 /* add to the graph */
3996 add_to_graph(tapinfo, pinfo, (pi->frame_label)?pi->frame_label:"VoIP msg", pi->frame_comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3998 tapinfo->redraw = TRUE;
4002 /****************************************************************************/
4003 static gboolean have_voip_tap_listener=FALSE;
4006 VoIPcalls_init_tap(void)
4008 GString *error_string;
4010 if(have_voip_tap_listener==FALSE)
4012 error_string = register_tap_listener("voip", &(the_tapinfo_struct.voip_dummy),
4015 voip_calls_dlg_reset,
4020 if (error_string != NULL) {
4021 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4022 "%s", error_string->str);
4023 g_string_free(error_string, TRUE);
4026 have_voip_tap_listener=TRUE;
4029 /****************************************************************************/
4031 remove_tap_listener_voip_calls(void)
4033 protect_thread_critical_region();
4034 remove_tap_listener(&(the_tapinfo_struct.voip_dummy));
4035 unprotect_thread_critical_region();
4037 have_voip_tap_listener=FALSE;
4041 /****************************************************************************/
4042 /* ***************************TAP for OTHER PROTOCOL **********************************/
4043 /****************************************************************************/
4045 /****************************************************************************/
4046 /* whenever a prot_ packet is seen by the tap listener */
4049 prot_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info _U_)
4051 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
4052 if (callsinfo!=NULL){
4053 callsinfo->stop_sec=pinfo->fd->rel_secs;
4054 callsinfo->stop_usec=pinfo->fd->rel_usecs;
4055 callsinfo->last_frame_num=pinfo->fd->num;
4056 ++(callsinfo->npackets);
4057 ++(tapinfo->npackets);
4060 tapinfo->redraw = TRUE;
4065 /****************************************************************************/
4067 static gboolean have_prot__tap_listener=FALSE;
4070 prot_calls_init_tap(void)
4072 GString *error_string;
4074 if(have_prot__tap_listener==FALSE)
4076 error_string = register_tap_listener("prot_", &(the_tapinfo_struct.prot__dummy),
4079 voip_calls_dlg_reset,
4084 if (error_string != NULL) {
4085 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4086 "%s", error_string->str);
4087 g_string_free(error_string, TRUE);
4090 have_prot__tap_listener=TRUE;
4094 /****************************************************************************/
4097 remove_tap_listener_prot__calls(void)
4099 protect_thread_critical_region();
4100 remove_tap_listener(&(the_tapinfo_struct.prot__dummy));
4101 unprotect_thread_critical_region();
4103 have_prot__tap_listener=FALSE;