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),
433 if (error_string != NULL) {
434 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
435 "%s", error_string->str);
436 g_string_free(error_string, TRUE);
439 have_rtp_event_tap_listener=TRUE;
443 /****************************************************************************/
446 remove_tap_listener_rtp_event(void)
448 protect_thread_critical_region();
449 remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_event_dummy));
450 unprotect_thread_critical_region();
452 have_rtp_event_tap_listener=FALSE;
455 /****************************************************************************/
456 /* ***************************TAP for RTP **********************************/
457 /****************************************************************************/
459 /****************************************************************************/
460 /* when there is a [re]reading of RTP packet's */
461 static void voip_rtp_reset(void *ptr _U_)
463 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
465 /* free the data items first */
466 list = g_list_first(tapinfo->list);
470 list = g_list_next(list);
472 g_list_free(tapinfo->list);
473 tapinfo->list = NULL;
474 tapinfo->nstreams = 0;
478 /****************************************************************************/
479 /* whenever a RTP packet is seen by the tap listener */
481 RTP_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void const *RTPinfo)
483 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
484 voip_rtp_stream_info_t *tmp_listinfo;
485 voip_rtp_stream_info_t *strinfo = NULL;
487 struct _rtp_conversation_info *p_conv_data = NULL;
489 const struct _rtp_info *pi = RTPinfo;
491 /* do not consider RTP packets without a setup frame */
492 if (pi->info_setup_frame_num == 0){
496 /* add this RTP for future listening using the RTP Player*/
497 #ifdef HAVE_LIBPORTAUDIO
498 add_rtp_packet(pi, pinfo);
501 /* check whether we already have a RTP stream with this setup frame and ssrc in the list */
502 list = g_list_first(tapinfo->list);
505 tmp_listinfo=list->data;
506 if ( (tmp_listinfo->setup_frame_number == pi->info_setup_frame_num)
507 && (tmp_listinfo->ssrc == pi->info_sync_src) && (tmp_listinfo->end_stream == FALSE)){
508 /* if the payload type has changed, we mark the stream as finished to create a new one
509 this is to show multiple payload changes in the Graph for example for DTMF RFC2833 */
510 if ( tmp_listinfo->pt != pi->info_payload_type ) {
511 tmp_listinfo->end_stream = TRUE;
513 strinfo = (voip_rtp_stream_info_t*)(list->data);
517 list = g_list_next(list);
520 /* if this is a duplicated RTP Event End, just return */
521 if ((rtp_evt_frame_num == pinfo->fd->num) && !strinfo && (rtp_evt_end == TRUE)) {
525 /* not in the list? then create a new entry */
527 strinfo = g_malloc(sizeof(voip_rtp_stream_info_t));
528 COPY_ADDRESS(&(strinfo->src_addr), &(pinfo->src));
529 strinfo->src_port = pinfo->srcport;
530 COPY_ADDRESS(&(strinfo->dest_addr), &(pinfo->dst));
531 strinfo->dest_port = pinfo->destport;
532 strinfo->ssrc = pi->info_sync_src;
533 strinfo->end_stream = FALSE;
534 strinfo->pt = pi->info_payload_type;
535 strinfo->pt_str = NULL;
536 strinfo->is_srtp = pi->info_is_srtp;
537 /* if it is dynamic payload, let use the conv data to see if it is defined */
538 if ( (strinfo->pt>95) && (strinfo->pt<128) ) {
539 /* Use existing packet info if available */
540 p_conv_data = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name("rtp"));
541 if (p_conv_data && p_conv_data->rtp_dyn_payload)
542 strinfo->pt_str = g_strdup(g_hash_table_lookup(p_conv_data->rtp_dyn_payload, &strinfo->pt));
544 if (!strinfo->pt_str) strinfo->pt_str = g_strdup(val_to_str(strinfo->pt, rtp_payload_type_short_vals, "%u"));
545 strinfo->npackets = 0;
546 strinfo->first_frame_num = pinfo->fd->num;
547 strinfo->start_rel_sec = (guint32) (pinfo->fd->rel_ts.secs);
548 strinfo->start_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
549 strinfo->setup_frame_number = pi->info_setup_frame_num;
550 strinfo->rtp_event = -1;
551 tapinfo->list = g_list_append(tapinfo->list, strinfo);
555 /* Add the info to the existing RTP stream */
557 strinfo->stop_rel_sec = (guint32) (pinfo->fd->rel_ts.secs);
558 strinfo->stop_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
560 /* process RTP Event */
561 if (rtp_evt_frame_num == pinfo->fd->num) {
562 strinfo->rtp_event = rtp_evt;
563 if (rtp_evt_end == TRUE) {
564 strinfo->end_stream = TRUE;
569 the_tapinfo_struct.redraw = TRUE;
574 /****************************************************************************/
575 /* whenever a redraw in the RTP tap listener */
576 static void RTP_packet_draw(void *prs _U_)
578 voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
579 GList *rtp_streams_list;
580 voip_rtp_stream_info_t *rtp_listinfo;
581 GList *voip_calls_graph_list;
583 graph_analysis_item_t *gai;
584 graph_analysis_item_t *new_gai;
588 /* add each rtp stream to the graph */
589 rtp_streams_list = g_list_first(rtp_tapinfo->list);
590 while (rtp_streams_list)
592 rtp_listinfo = rtp_streams_list->data;
594 /* using the setup frame number of the RTP stream, we get the call number that it belongs */
595 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
596 while (voip_calls_graph_list)
598 gai = voip_calls_graph_list->data;
599 conv_num = gai->conv_num;
600 /* if we get the setup frame number, then get the time position to graph the RTP arrow */
601 if (rtp_listinfo->setup_frame_number == gai->frame_num){
602 /* look again from the begining because there are cases where the Setup frame is after the RTP */
603 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
605 while(voip_calls_graph_list){
606 gai = voip_calls_graph_list->data;
607 /* if RTP was already in the Graph, just update the comment information */
608 if (rtp_listinfo->first_frame_num == gai->frame_num){
609 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
610 g_free(gai->comment);
611 gai->comment = g_strdup_printf("%s Num packets:%u Duration:%u.%03us SSRC:0x%X",
612 (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->npackets,
613 duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
617 /* 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 */
618 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
619 if (!voip_calls_graph_list) item++;
621 /* add the RTP item to the graph if was not there*/
622 if (rtp_listinfo->first_frame_num<gai->frame_num || !voip_calls_graph_list){
623 new_gai = g_malloc(sizeof(graph_analysis_item_t));
624 new_gai->frame_num = rtp_listinfo->first_frame_num;
625 new_gai->time = (double)rtp_listinfo->start_rel_sec + (double)rtp_listinfo->start_rel_usec/1000000;
626 COPY_ADDRESS(&(new_gai->src_addr),&(rtp_listinfo->src_addr));
627 COPY_ADDRESS(&(new_gai->dst_addr),&(rtp_listinfo->dest_addr));
628 new_gai->port_src = rtp_listinfo->src_port;
629 new_gai->port_dst = rtp_listinfo->dest_port;
630 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
631 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"));
632 new_gai->comment = g_strdup_printf("%s Num packets:%u Duration:%u.%03us SSRC:0x%X",
633 (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->npackets,
634 duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
635 new_gai->conv_num = conv_num;
636 new_gai->display=FALSE;
637 new_gai->line_style = 2; /* the arrow line will be 2 pixels width */
638 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item);
641 if (voip_calls_graph_list) item++;
645 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
647 rtp_streams_list = g_list_next(rtp_streams_list);
651 static gboolean have_RTP_tap_listener=FALSE;
652 /****************************************************************************/
656 GString *error_string;
658 if(have_RTP_tap_listener==FALSE)
660 /* don't register tap listener, if we have it already */
661 error_string = register_tap_listener("rtp", &(the_tapinfo_rtp_struct.rtp_dummy), NULL,
666 if (error_string != NULL) {
667 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
668 "%s", error_string->str);
669 g_string_free(error_string, TRUE);
672 have_RTP_tap_listener=TRUE;
676 /****************************************************************************/
678 remove_tap_listener_rtp(void)
680 protect_thread_critical_region();
681 remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_dummy));
682 unprotect_thread_critical_region();
684 have_RTP_tap_listener=FALSE;
687 /****************************************************************************/
688 /******************************TAP for T38 **********************************/
689 /****************************************************************************/
691 /****************************************************************************/
692 /* whenever a T38 packet is seen by the tap listener */
694 T38_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *T38info)
696 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
698 voip_calls_info_t *callsinfo = NULL;
699 voip_calls_info_t *tmp_listinfo;
700 GList *voip_calls_graph_list;
702 gchar *frame_label = NULL;
703 gchar *comment = NULL;
704 graph_analysis_item_t *tmp_gai, *gai = NULL;
705 guint16 line_style = 2;
709 const t38_packet_info *pi = T38info;
711 if (pi->setup_frame_number != 0) {
712 /* using the setup frame number of the T38 packet, we get the call number that it belongs */
713 voip_calls_graph_list = g_list_first(tapinfo->graph_analysis->list);
714 while (voip_calls_graph_list)
716 tmp_gai = voip_calls_graph_list->data;
717 if (pi->setup_frame_number == tmp_gai->frame_num){
721 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
723 if (gai) conv_num = (int) gai->conv_num;
726 /* 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
727 * have the associated Voip calls. It probably means the the packet was decoded using the default t38 port, or using "Decode as.."
728 * in this case we create a "voip" call that only have t38 media (no signaling)
729 * OR if we have not found the Setup message in the graph.
731 if ( (pi->setup_frame_number == 0) || (gai == NULL) ){
732 /* check whether we already have a call with these parameters in the list */
733 list = g_list_first(tapinfo->callsinfo_list);
736 tmp_listinfo=list->data;
737 if (tmp_listinfo->protocol == MEDIA_T38){
738 callsinfo = (voip_calls_info_t*)(list->data);
741 list = g_list_next (list);
744 /* not in the list? then create a new entry */
745 if (callsinfo==NULL){
746 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
747 callsinfo->call_active_state = VOIP_ACTIVE;
748 callsinfo->call_state = VOIP_UNKNOWN;
749 callsinfo->from_identity=g_strdup("T38 Media only");
750 callsinfo->to_identity=g_strdup("T38 Media only");
751 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
752 callsinfo->first_frame_num=pinfo->fd->num;
753 callsinfo->selected=FALSE;
754 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
755 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
756 callsinfo->protocol=MEDIA_T38;
757 callsinfo->prot_info=NULL;
758 callsinfo->free_prot_info = NULL;
759 callsinfo->npackets = 0;
760 callsinfo->call_num = tapinfo->ncalls++;
761 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
763 ++(callsinfo->npackets);
764 /* increment the packets counter of all calls */
765 ++(tapinfo->npackets);
767 conv_num = (int) callsinfo->call_num;
770 /* at this point we should have found the call num for this t38 packets belong */
771 if (conv_num == -1) {
775 /* add the item to the graph list */
776 if (pi->type_msg == 0) { /* 0=t30-indicator */
777 frame_label = g_strdup(val_to_str(pi->t30ind_value, t38_T30_indicator_vals, "Ukn (0x%02X)") );
778 comment = g_strdup_printf("t38:t30 Ind:%s",val_to_str(pi->t30ind_value, t38_T30_indicator_vals, "Ukn (0x%02X)") );
780 } else if (pi->type_msg == 1) { /* 1=data */
781 switch(pi->Data_Field_field_type_value){
782 case 0: /* hdlc-data */
784 case 2: /* hdlc-fcs-OK */
785 case 4: /* hdlc-fcs-OK-sig-end */
786 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);
787 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)"));
789 case 3: /* hdlc-fcs-BAD */
790 case 5: /* hdlc-fcs-BAD-sig-end */
791 frame_label = g_strdup(pi->Data_Field_field_type_value == 3 ? "fcs-BAD" : "fcs-BAD-sig-end");
792 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");
794 case 7: /* t4-non-ecm-sig-end */
795 duration = nstime_to_sec(&pinfo->fd->rel_ts) - pi->time_first_t4_data;
796 frame_label = g_strdup_printf("t4-non-ecm-data:%s",val_to_str(pi->data_value, t38_T30_data_vals, "Ukn (0x%02X)") );
797 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 );
798 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);
803 if (frame_label && !(pi->Data_Field_field_type_value == 7 && pi->type_msg == 1)) {
804 add_to_graph(tapinfo, pinfo, frame_label, comment, (guint16)conv_num, &(pinfo->src), &(pinfo->dst), line_style);
810 tapinfo->redraw = TRUE;
812 return 1; /* refresh output */
815 static gboolean have_T38_tap_listener=FALSE;
816 /****************************************************************************/
820 GString *error_string;
822 if(have_T38_tap_listener==FALSE)
824 /* don't register tap listener, if we have it already */
825 error_string = register_tap_listener("t38", &(the_tapinfo_struct.t38_dummy), NULL,
826 voip_calls_dlg_reset,
830 if (error_string != NULL) {
831 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
832 "%s", error_string->str);
833 g_string_free(error_string, TRUE);
836 have_T38_tap_listener=TRUE;
840 /****************************************************************************/
842 remove_tap_listener_t38(void)
844 protect_thread_critical_region();
845 remove_tap_listener(&(the_tapinfo_struct.t38_dummy));
846 unprotect_thread_critical_region();
848 have_T38_tap_listener=FALSE;
852 /****************************************************************************/
853 static gchar *sdp_summary = NULL;
854 static guint32 sdp_frame_num = 0;
856 /****************************************************************************/
857 /* ***************************TAP for SIP **********************************/
858 /****************************************************************************/
861 static void free_sip_info(gpointer p) {
862 sip_calls_info_t *si = p;
864 g_free(si->call_identifier);
868 /****************************************************************************/
869 /* whenever a SIP packet is seen by the tap listener */
871 SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SIPinfo)
873 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
874 /* we just take note of the ISUP data here; when we receive the MTP3 part everything will
875 be compared with existing calls */
877 voip_calls_info_t *tmp_listinfo;
878 voip_calls_info_t *callsinfo = NULL;
879 sip_calls_info_t *tmp_sipinfo = NULL;
881 address tmp_src, tmp_dst;
882 gchar *frame_label = NULL;
883 gchar *comment = NULL;
885 const sip_info_value_t *pi = SIPinfo;
887 /* do not consider packets without call_id */
888 if (pi->tap_call_id ==NULL){
892 /* check whether we already have a call with these parameters in the list */
893 list = g_list_first(tapinfo->callsinfo_list);
896 tmp_listinfo=list->data;
897 if (tmp_listinfo->protocol == VOIP_SIP){
898 tmp_sipinfo = tmp_listinfo->prot_info;
899 if (strcmp(tmp_sipinfo->call_identifier,pi->tap_call_id)==0){
900 callsinfo = (voip_calls_info_t*)(list->data);
904 list = g_list_next (list);
907 /* not in the list? then create a new entry if the message is INVITE -i.e. if this session is a call*/
908 if ((callsinfo==NULL) &&(pi->request_method!=NULL)){
909 if (strcmp(pi->request_method,"INVITE")==0){
910 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
911 callsinfo->call_active_state = VOIP_ACTIVE;
912 callsinfo->call_state = VOIP_CALL_SETUP;
913 callsinfo->from_identity=g_strdup(pi->tap_from_addr);
914 callsinfo->to_identity=g_strdup(pi->tap_to_addr);
915 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
916 callsinfo->first_frame_num=pinfo->fd->num;
917 callsinfo->selected=FALSE;
918 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
919 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
920 callsinfo->protocol=VOIP_SIP;
921 callsinfo->prot_info=g_malloc(sizeof(sip_calls_info_t));
922 callsinfo->free_prot_info = free_sip_info;
923 tmp_sipinfo = callsinfo->prot_info;
924 tmp_sipinfo->call_identifier = g_strdup(pi->tap_call_id);
925 tmp_sipinfo->sip_state = SIP_INVITE_SENT;
926 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
927 callsinfo->npackets = 0;
928 callsinfo->call_num = tapinfo->ncalls++;
929 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
933 if (callsinfo!=NULL){
935 /* let's analyze the call state */
937 COPY_ADDRESS(&(tmp_src), &(pinfo->src));
938 COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
940 if (pi->request_method == NULL){
941 frame_label = g_strdup_printf("%u %s", pi->response_code, pi->reason_phrase );
942 comment = g_strdup("SIP Status");
944 if ((tmp_sipinfo && pi->tap_cseq_number == tmp_sipinfo->invite_cseq)&&(ADDRESSES_EQUAL(&tmp_dst,&(callsinfo->initial_speaker)))){
945 if ((pi->response_code > 199) && (pi->response_code<300) && (tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
946 tmp_sipinfo->sip_state = SIP_200_REC;
948 else if ((pi->response_code>299)&&(tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
949 callsinfo->call_state = VOIP_REJECTED;
950 tapinfo->rejected_calls++;
956 frame_label = g_strdup(pi->request_method);
958 if ((strcmp(pi->request_method,"INVITE")==0)&&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))){
959 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
960 callsinfo->call_state = VOIP_CALL_SETUP;
961 comment = g_strdup_printf("SIP From: %s To:%s", callsinfo->from_identity, callsinfo->to_identity);
963 else if ((strcmp(pi->request_method,"ACK")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
964 &&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))&&(tmp_sipinfo->sip_state==SIP_200_REC)
965 &&(callsinfo->call_state == VOIP_CALL_SETUP)){
966 callsinfo->call_state = VOIP_IN_CALL;
967 comment = g_strdup("SIP Request");
969 else if (strcmp(pi->request_method,"BYE")==0){
970 callsinfo->call_state = VOIP_COMPLETED;
971 tapinfo->completed_calls++;
972 comment = g_strdup("SIP Request");
974 else if ((strcmp(pi->request_method,"CANCEL")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
975 &&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))&&(callsinfo->call_state==VOIP_CALL_SETUP)){
976 callsinfo->call_state = VOIP_CANCELLED;
977 tmp_sipinfo->sip_state = SIP_CANCEL_SENT;
978 comment = g_strdup("SIP Request");
980 comment = g_strdup("SIP Request");
984 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
985 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
986 callsinfo->last_frame_num=pinfo->fd->num;
987 ++(callsinfo->npackets);
988 /* increment the packets counter of all calls */
989 ++(tapinfo->npackets);
991 /* add to the graph */
992 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
995 g_free((void *)tmp_src.data);
996 g_free((void *)tmp_dst.data);
998 /* add SDP info if apply */
999 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
1000 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
1001 g_free(sdp_summary);
1006 tapinfo->redraw = TRUE;
1008 return 1; /* refresh output */
1012 /****************************************************************************/
1013 voip_calls_tapinfo_t* voip_calls_get_info(void)
1015 return &the_tapinfo_struct;
1019 /****************************************************************************/
1021 /****************************************************************************/
1022 static gboolean have_SIP_tap_listener=FALSE;
1023 /****************************************************************************/
1025 sip_calls_init_tap(void)
1027 GString *error_string;
1029 if(have_SIP_tap_listener==FALSE)
1031 /* don't register tap listener, if we have it already */
1032 error_string = register_tap_listener("sip", &(the_tapinfo_struct.sip_dummy), NULL,
1033 voip_calls_dlg_reset,
1037 if (error_string != NULL) {
1038 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1039 "%s", error_string->str);
1040 g_string_free(error_string, TRUE);
1043 have_SIP_tap_listener=TRUE;
1047 /****************************************************************************/
1049 remove_tap_listener_sip_calls(void)
1051 protect_thread_critical_region();
1052 remove_tap_listener(&(the_tapinfo_struct.sip_dummy));
1053 unprotect_thread_critical_region();
1055 have_SIP_tap_listener=FALSE;
1058 /****************************************************************************/
1059 /* ***************************TAP for ISUP **********************************/
1060 /****************************************************************************/
1062 static guint32 mtp3_opc, mtp3_dpc;
1063 static guint8 mtp3_ni;
1064 static guint32 mtp3_frame_num;
1067 /****************************************************************************/
1068 /* whenever a isup_ packet is seen by the tap listener */
1070 isup_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *isup_info _U_)
1072 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1073 voip_calls_info_t *tmp_listinfo;
1074 voip_calls_info_t *callsinfo = NULL;
1075 isup_calls_info_t *tmp_isupinfo;
1076 gboolean found = FALSE;
1077 gboolean forward = FALSE;
1078 gboolean right_pair;
1080 gchar *frame_label = NULL;
1081 gchar *comment = NULL;
1084 /*voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct; unused */
1085 const isup_tap_rec_t *pi = isup_info;
1087 /* check if the lower layer is MTP matching the frame number */
1088 if (mtp3_frame_num != pinfo->fd->num) return 0;
1090 /* check whether we already have a call with these parameters in the list */
1091 list = g_list_first(tapinfo->callsinfo_list);
1095 tmp_listinfo=list->data;
1096 if ((tmp_listinfo->protocol == VOIP_ISUP)&&(tmp_listinfo->call_active_state==VOIP_ACTIVE)){
1097 tmp_isupinfo = tmp_listinfo->prot_info;
1098 if ((tmp_isupinfo->cic == pinfo->circuit_id)&&(tmp_isupinfo->ni == mtp3_ni)) {
1099 if ((tmp_isupinfo->opc == mtp3_opc)&&(tmp_isupinfo->dpc == mtp3_dpc)){
1101 } else if ((tmp_isupinfo->dpc == mtp3_opc)&&(tmp_isupinfo->opc == mtp3_dpc)){
1108 /* if there is an IAM for a call that is not in setup state, that means the previous call in the same
1109 cic is no longer active */
1110 if (tmp_listinfo->call_state == VOIP_CALL_SETUP){
1112 } else if (pi->message_type != 1){
1115 tmp_listinfo->call_active_state=VOIP_INACTIVE;
1120 callsinfo = (voip_calls_info_t*)(list->data);
1125 list = g_list_next (list);
1128 /* not in the list? then create a new entry if the message is IAM
1129 -i.e. if this session is a call*/
1132 if ((callsinfo==NULL) &&(pi->message_type==1)){
1133 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
1134 callsinfo->call_active_state = VOIP_ACTIVE;
1135 callsinfo->call_state = VOIP_UNKNOWN;
1136 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
1137 callsinfo->selected=FALSE;
1138 callsinfo->first_frame_num=pinfo->fd->num;
1139 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
1140 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1141 callsinfo->protocol=VOIP_ISUP;
1142 if (pi->calling_number!=NULL){
1143 callsinfo->from_identity=g_strdup(pi->calling_number);
1145 if (pi->called_number!=NULL){
1146 callsinfo->to_identity=g_strdup(pi->called_number);
1148 callsinfo->prot_info=g_malloc(sizeof(isup_calls_info_t));
1149 callsinfo->free_prot_info = g_free;
1150 tmp_isupinfo=callsinfo->prot_info;
1151 tmp_isupinfo->opc = mtp3_opc;
1152 tmp_isupinfo->dpc = mtp3_dpc;
1153 tmp_isupinfo->ni = mtp3_ni;
1154 tmp_isupinfo->cic = pinfo->circuit_id;
1155 callsinfo->npackets = 0;
1156 callsinfo->call_num = tapinfo->ncalls++;
1157 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
1161 if (callsinfo!=NULL){
1162 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
1163 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1164 callsinfo->last_frame_num=pinfo->fd->num;
1165 ++(callsinfo->npackets);
1167 /* Let's analyze the call state */
1170 for (i=0;(isup_message_type_value[i].strptr!=NULL)&& (isup_message_type_value[i].value!=pi->message_type);i++);
1172 if (isup_message_type_value[i].value==pi->message_type){
1173 frame_label = g_strdup(isup_message_type_value_acro[i].strptr);
1176 frame_label = g_strdup("Unknown");
1179 if (callsinfo->npackets == 1){ /* this is the first packet, that must be an IAM */
1181 if ((pi->calling_number!=NULL)&&(pi->called_number !=NULL)){
1182 comment = g_strdup_printf("Call from %s to %s",
1183 pi->calling_number, pi->called_number);
1185 } else if (callsinfo->npackets == 2){ /* in the second packet we show the SPs */
1187 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
1189 mtp3_ni, mtp3_dpc, pinfo->circuit_id);
1191 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
1193 mtp3_ni, mtp3_opc, pinfo->circuit_id);
1198 switch(pi->message_type){
1200 callsinfo->call_state=VOIP_CALL_SETUP;
1202 case 7: /* CONNECT */
1203 case 9: /* ANSWER */
1204 callsinfo->call_state=VOIP_IN_CALL;
1206 case 12: /* RELEASE */
1207 if (callsinfo->call_state==VOIP_CALL_SETUP){
1209 callsinfo->call_state=VOIP_CANCELLED;
1212 callsinfo->call_state=VOIP_REJECTED;
1213 tapinfo->rejected_calls++;
1216 else if (callsinfo->call_state == VOIP_IN_CALL){
1217 callsinfo->call_state = VOIP_COMPLETED;
1218 tapinfo->completed_calls++;
1220 for (i=0;(q931_cause_code_vals[i].strptr!=NULL)&& (q931_cause_code_vals[i].value!=pi->cause_value);i++);
1221 if (q931_cause_code_vals[i].value==pi->cause_value){
1222 comment = g_strdup_printf("Cause %i - %s",pi->cause_value, q931_cause_code_vals[i].strptr);
1225 comment = g_strdup_printf("Cause %i",pi->cause_value);
1230 /* increment the packets counter of all calls */
1231 ++(tapinfo->npackets);
1233 /* add to the graph */
1234 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1236 g_free(frame_label);
1239 tapinfo->redraw = TRUE;
1241 return 1; /* refresh output */
1244 /****************************************************************************/
1246 static gboolean have_isup_tap_listener=FALSE;
1249 isup_calls_init_tap(void)
1251 GString *error_string;
1254 if(have_isup_tap_listener==FALSE)
1256 error_string = register_tap_listener("isup", &(the_tapinfo_struct.isup_dummy),
1258 voip_calls_dlg_reset,
1263 if (error_string != NULL) {
1264 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1265 "%s", error_string->str);
1266 g_string_free(error_string, TRUE);
1269 have_isup_tap_listener=TRUE;
1273 /****************************************************************************/
1276 remove_tap_listener_isup_calls(void)
1278 protect_thread_critical_region();
1279 remove_tap_listener(&(the_tapinfo_struct.isup_dummy));
1280 unprotect_thread_critical_region();
1282 have_isup_tap_listener=FALSE;
1286 /****************************************************************************/
1287 /* ***************************TAP for MTP3 **********************************/
1288 /****************************************************************************/
1291 /****************************************************************************/
1292 /* whenever a mtp3_ packet is seen by the tap listener */
1294 mtp3_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *mtp3_info _U_)
1296 const mtp3_tap_rec_t *pi = mtp3_info;
1298 /* keep the data in memory to use when the ISUP information arrives */
1300 mtp3_opc = pi->addr_opc.pc;
1301 mtp3_dpc = pi->addr_dpc.pc;
1302 mtp3_ni = pi->addr_opc.ni;
1303 mtp3_frame_num = pinfo->fd->num;
1308 /****************************************************************************/
1310 static gboolean have_mtp3_tap_listener=FALSE;
1311 static gboolean have_m3ua_tap_listener=FALSE;
1314 mtp3_calls_init_tap(void)
1316 GString *error_string;
1319 if(have_mtp3_tap_listener==FALSE)
1321 error_string = register_tap_listener("mtp3", &(the_tapinfo_struct.mtp3_dummy),
1323 voip_calls_dlg_reset,
1328 if (error_string != NULL) {
1329 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1330 "%s", error_string->str);
1331 g_string_free(error_string, TRUE);
1334 have_mtp3_tap_listener=TRUE;
1337 if(have_m3ua_tap_listener==FALSE)
1339 error_string = register_tap_listener("m3ua", &(the_tapinfo_struct.mtp3_dummy),
1341 voip_calls_dlg_reset,
1346 if (error_string != NULL) {
1347 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1348 "%s", error_string->str);
1349 g_string_free(error_string, TRUE);
1352 have_m3ua_tap_listener=TRUE;
1357 /****************************************************************************/
1360 remove_tap_listener_mtp3_calls(void)
1362 protect_thread_critical_region();
1363 remove_tap_listener(&(the_tapinfo_struct.mtp3_dummy));
1364 remove_tap_listener(&(the_tapinfo_struct.m3ua_dummy));
1365 unprotect_thread_critical_region();
1367 have_mtp3_tap_listener=FALSE;
1368 have_m3ua_tap_listener=FALSE;
1371 /****************************************************************************/
1372 /* ***************************TAP for Q931 **********************************/
1373 /****************************************************************************/
1374 void h245_add_to_graph(guint32 new_frame_num);
1375 static const e_guid_t guid_allzero = {0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };
1376 /* defines specific H323 data */
1378 static gchar *q931_calling_number;
1379 static gchar *q931_called_number;
1380 static guint8 q931_cause_value;
1381 static gint32 q931_crv;
1382 static guint32 q931_frame_num;
1384 static guint32 h225_frame_num = 0;
1385 static guint16 h225_call_num = 0;
1386 static h225_cs_type h225_cstype = H225_OTHER;
1387 static gboolean h225_is_faststart;
1389 static guint32 actrace_frame_num = 0;
1390 static gint32 actrace_trunk = 0;
1391 static gint32 actrace_direction = 0;
1394 /****************************************************************************/
1395 /* whenever a q931_ packet is seen by the tap listener */
1397 q931_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *q931_info _U_)
1400 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1401 h323_calls_info_t *tmp_h323info,*tmp2_h323info;
1402 actrace_isdn_calls_info_t *tmp_actrace_isdn_info;
1403 voip_calls_info_t *tmp_listinfo;
1404 voip_calls_info_t *callsinfo = NULL;
1405 h245_address_t *h245_add = NULL;
1408 const q931_packet_info *pi = q931_info;
1410 /* free previously allocated q931_calling/ed_number */
1411 g_free(q931_calling_number);
1412 g_free(q931_called_number);
1414 if (pi->calling_number!=NULL)
1415 q931_calling_number = g_strdup(pi->calling_number);
1417 q931_calling_number = g_strdup("");
1419 if (pi->called_number!=NULL)
1420 q931_called_number = g_strdup(pi->called_number);
1422 q931_called_number = g_strdup("");
1423 q931_cause_value = pi->cause_value;
1424 q931_frame_num = pinfo->fd->num;
1428 /* add staff to H323 calls */
1429 if (h225_frame_num == q931_frame_num) {
1430 tmp_h323info = NULL;
1431 list = g_list_first(tapinfo->callsinfo_list);
1434 tmp_listinfo=list->data;
1435 if ( (tmp_listinfo->protocol == VOIP_H323) && (tmp_listinfo->call_num == h225_call_num) ){
1436 tmp_h323info = tmp_listinfo->prot_info;
1437 callsinfo = (voip_calls_info_t*)(list->data);
1439 /* Add the CRV to the h323 call */
1440 if (tmp_h323info->q931_crv == -1) {
1441 tmp_h323info->q931_crv = q931_crv;
1442 } else if (tmp_h323info->q931_crv != q931_crv) {
1443 tmp_h323info->q931_crv2 = q931_crv;
1447 list = g_list_next (list);
1450 if (callsinfo != NULL) {
1452 if (h225_cstype == H225_SETUP) {
1453 /* set te calling and called number from the Q931 packet */
1454 if (q931_calling_number != NULL){
1455 g_free(callsinfo->from_identity);
1456 callsinfo->from_identity=g_strdup(q931_calling_number);
1458 if (q931_called_number != NULL){
1459 g_free(callsinfo->to_identity);
1460 callsinfo->to_identity=g_strdup(q931_called_number);
1463 /* check if there is an LRQ/LCF that match this Setup */
1464 /* TODO: we are just checking the DialedNumer in LRQ/LCF agains the Setup
1465 we should also check if the h225 signaling IP and port match the destination
1466 Setup ip and port */
1467 list = g_list_first(tapinfo->callsinfo_list);
1470 tmp_listinfo=list->data;
1471 if (tmp_listinfo->protocol == VOIP_H323){
1472 tmp2_h323info = tmp_listinfo->prot_info;
1474 /* check if the called number match a LRQ/LCF */
1475 if ( (strcmp(callsinfo->to_identity, tmp_listinfo->to_identity)==0)
1476 && (memcmp(&tmp2_h323info->guid, &guid_allzero, GUID_LEN) == 0) ){
1477 /* change the call graph to the LRQ/LCF to belong to this call */
1478 callsinfo->npackets += change_call_num_graph(tapinfo, tmp_listinfo->call_num, callsinfo->call_num);
1480 /* remove this LRQ/LCF call entry because we have found the Setup that match them */
1481 g_free(tmp_listinfo->from_identity);
1482 g_free(tmp_listinfo->to_identity);
1483 g_free(tmp2_h323info->guid);
1485 list2 = g_list_first(tmp2_h323info->h245_list);
1488 h245_add=list2->data;
1489 g_free((void *)h245_add->h245_address.data);
1490 g_free(list2->data);
1491 list2 = g_list_next(list2);
1493 g_list_free(tmp_h323info->h245_list);
1494 tmp_h323info->h245_list = NULL;
1495 g_free(tmp_listinfo->prot_info);
1496 tapinfo->callsinfo_list = g_list_remove(tapinfo->callsinfo_list, tmp_listinfo);
1500 list = g_list_next (list);
1503 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"),
1504 (h225_is_faststart==TRUE?"on":"off"));
1505 } else if (h225_cstype == H225_RELEASE_COMPLET) {
1506 /* get the Q931 Release cause code */
1507 if (q931_cause_value != 0xFF){
1508 comment = g_strdup_printf("H225 Q931 Rel Cause (%i):%s", q931_cause_value, val_to_str(q931_cause_value, q931_cause_code_vals, "<unknown>"));
1509 } else { /* Cause not set */
1510 comment = g_strdup("H225 No Q931 Rel Cause");
1513 /* change the graph comment for this new one */
1514 if (comment != NULL) {
1515 change_frame_graph(tapinfo, h225_frame_num, NULL, comment);
1519 /* we reset the h225_frame_num to 0 because there could be empty h225 in the same frame
1520 as non empty h225 (e.g connect), so we don't have to be here twice */
1523 /* add staff to H245 */
1524 } else if (h245_labels.frame_num == q931_frame_num) {
1525 /* there are empty H225 frames that don't have guid (guaid=0) but they have h245 info,
1526 so the only way to match those frames is with the Q931 CRV number */
1527 list = g_list_first(tapinfo->callsinfo_list);
1530 tmp_listinfo=list->data;
1531 if (tmp_listinfo->protocol == VOIP_H323){
1532 tmp_h323info = tmp_listinfo->prot_info;
1533 if ( ((tmp_h323info->q931_crv == q931_crv) || (tmp_h323info->q931_crv2 == q931_crv)) && (q931_crv!=-1)){
1534 /* if the frame number exists in graph, append to it*/
1535 if (!append_to_frame_graph(tapinfo, q931_frame_num, NULL, NULL)) {
1536 /* if not exist, add to the graph */
1537 add_to_graph(tapinfo, pinfo, NULL, NULL, tmp_listinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1538 ++(tmp_listinfo->npackets);
1539 /* increment the packets counter of all calls */
1540 ++(tapinfo->npackets);
1543 /* Add the H245 info if exists to the Graph */
1544 h245_add_to_graph(pinfo->fd->num);
1548 list = g_list_next (list);
1551 /* add staff to ACTRACE */
1552 } else if (actrace_frame_num == q931_frame_num) {
1557 list = g_list_first(tapinfo->callsinfo_list);
1560 tmp_listinfo=list->data;
1561 if ( tmp_listinfo->protocol == VOIP_AC_ISDN ){
1562 tmp_actrace_isdn_info = tmp_listinfo->prot_info;
1563 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
1564 if ( (tmp_actrace_isdn_info->crv == q931_crv) && (tmp_actrace_isdn_info->trunk == actrace_trunk) ) {
1565 callsinfo = (voip_calls_info_t*)(list->data);
1569 list = g_list_next (list);
1572 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, g_strdup("PSTN"));
1574 /* if it is a new call, add it to the list */
1576 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
1577 callsinfo->call_active_state = VOIP_ACTIVE;
1578 callsinfo->call_state = VOIP_CALL_SETUP;
1579 callsinfo->from_identity=g_strdup(q931_calling_number);
1580 callsinfo->to_identity=g_strdup(q931_called_number);
1581 COPY_ADDRESS(&(callsinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
1582 callsinfo->first_frame_num=pinfo->fd->num;
1583 callsinfo->selected=FALSE;
1584 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
1585 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1586 callsinfo->protocol=VOIP_AC_ISDN;
1587 callsinfo->prot_info=g_malloc(sizeof(actrace_isdn_calls_info_t));
1588 callsinfo->free_prot_info = g_free;
1589 tmp_actrace_isdn_info=callsinfo->prot_info;
1590 tmp_actrace_isdn_info->crv=q931_crv;
1591 tmp_actrace_isdn_info->trunk=actrace_trunk;
1592 callsinfo->npackets = 0;
1593 callsinfo->call_num = tapinfo->ncalls++;
1594 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
1597 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
1598 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1599 callsinfo->last_frame_num=pinfo->fd->num;
1600 ++(callsinfo->npackets);
1601 /* increment the packets counter of all calls */
1602 ++(tapinfo->npackets);
1604 switch(pi->message_type){
1606 comment = g_strdup_printf("AC_ISDN trunk:%u Calling: %s Called:%s", actrace_trunk, q931_calling_number, q931_called_number);
1607 callsinfo->call_state=VOIP_CALL_SETUP;
1610 callsinfo->call_state=VOIP_IN_CALL;
1612 case Q931_RELEASE_COMPLETE:
1614 case Q931_DISCONNECT:
1615 if (callsinfo->call_state==VOIP_CALL_SETUP){
1616 if (ADDRESSES_EQUAL(&(callsinfo->initial_speaker), actrace_direction?&pstn_add:&(pinfo->src) )){ /* forward direction */
1617 callsinfo->call_state=VOIP_CANCELLED;
1620 callsinfo->call_state=VOIP_REJECTED;
1621 tapinfo->rejected_calls++;
1623 } else if ( (callsinfo->call_state!=VOIP_CANCELLED) && (callsinfo->call_state!=VOIP_REJECTED) ){
1624 callsinfo->call_state=VOIP_COMPLETED;
1625 tapinfo->completed_calls++;
1627 if (q931_cause_value != 0xFF){
1628 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>"));
1629 } else { /* Cause not set */
1630 comment = g_strdup("AC_ISDN No Q931 Rel Cause");
1636 comment = g_strdup_printf("AC_ISDN trunk:%u", actrace_trunk );
1638 add_to_graph(tapinfo, pinfo, val_to_str(pi->message_type, q931_message_type_vals, "<unknown>") , comment, callsinfo->call_num,
1639 actrace_direction?&pstn_add:&(pinfo->src),
1640 actrace_direction?&(pinfo->src):&pstn_add,
1644 g_free((char *)pstn_add.data);
1647 tapinfo->redraw = TRUE;
1649 return 1; /* refresh output */
1652 /****************************************************************************/
1653 static gboolean have_q931_tap_listener=FALSE;
1656 q931_calls_init_tap(void)
1658 GString *error_string;
1661 if(have_q931_tap_listener==FALSE)
1663 error_string = register_tap_listener("q931", &(the_tapinfo_struct.q931_dummy),
1665 voip_calls_dlg_reset,
1670 if (error_string != NULL) {
1671 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1672 "%s", error_string->str);
1673 g_string_free(error_string, TRUE);
1676 have_q931_tap_listener=TRUE;
1680 /****************************************************************************/
1683 remove_tap_listener_q931_calls(void)
1685 protect_thread_critical_region();
1686 remove_tap_listener(&(the_tapinfo_struct.q931_dummy));
1687 unprotect_thread_critical_region();
1689 have_q931_tap_listener=FALSE;
1692 /****************************************************************************/
1693 /****************************TAP for H323 ***********************************/
1694 /****************************************************************************/
1696 static void add_h245_Address(h323_calls_info_t *h323info, h245_address_t *h245_address)
1698 h323info->h245_list = g_list_append(h323info->h245_list, h245_address);
1702 static void free_h225_info(gpointer p) {
1703 h323_calls_info_t *tmp_h323info = p;
1705 g_free(tmp_h323info->guid);
1707 if (tmp_h323info->h245_list) {
1708 GList *list2 = g_list_first(tmp_h323info->h245_list);
1711 h245_address_t *h245_add=list2->data;
1712 g_free((void *)h245_add->h245_address.data);
1713 g_free(list2->data);
1714 list2 = g_list_next(list2);
1717 g_list_free(tmp_h323info->h245_list);
1723 /****************************************************************************/
1724 /* whenever a H225 packet is seen by the tap listener */
1726 H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H225info)
1728 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1729 voip_calls_info_t *tmp_listinfo;
1730 voip_calls_info_t *callsinfo = NULL;
1731 h323_calls_info_t *tmp_h323info = NULL;
1735 h245_address_t *h245_add = NULL;
1737 const h225_packet_info *pi = H225info;
1739 /* if not guid and RAS and not LRQ, LCF or LRJ return because did not belong to a call */
1740 /* OR, if not guid and is H225 return because doesn't belong to a call */
1741 if ((memcmp(&pi->guid, &guid_allzero, GUID_LEN) == 0))
1742 if ( ((pi->msg_type == H225_RAS) && ((pi->msg_tag < 18) || (pi->msg_tag > 20))) || (pi->msg_type != H225_RAS) )
1745 /* if it is RAS LCF or LRJ*/
1746 if ( (pi->msg_type == H225_RAS) && ((pi->msg_tag == 19) || (pi->msg_tag == 20))) {
1747 /* if the LCF/LRJ doesn't match to a LRQ, just return */
1748 if (!pi->request_available) return 0;
1750 /* check whether we already have a call with this request SeqNum */
1751 list = g_list_first(tapinfo->callsinfo_list);
1754 tmp_listinfo=list->data;
1755 g_assert(tmp_listinfo != NULL);
1756 if (tmp_listinfo->protocol == VOIP_H323){
1757 tmp_h323info = tmp_listinfo->prot_info;
1758 if (tmp_h323info->requestSeqNum == pi->requestSeqNum) {
1759 callsinfo = (voip_calls_info_t*)(list->data);
1763 list = g_list_next (list);
1766 /* check whether we already have a call with this guid in the list */
1767 list = g_list_first(tapinfo->callsinfo_list);
1770 tmp_listinfo=list->data;
1771 if (tmp_listinfo->protocol == VOIP_H323){
1772 tmp_h323info = tmp_listinfo->prot_info;
1773 g_assert(tmp_h323info != NULL);
1774 if ( (memcmp(tmp_h323info->guid, &guid_allzero, GUID_LEN) != 0) && (memcmp(tmp_h323info->guid, &pi->guid,GUID_LEN)==0) ){
1775 callsinfo = (voip_calls_info_t*)(list->data);
1779 list = g_list_next (list);
1783 h225_cstype = pi->cs_type;
1784 h225_is_faststart = pi->is_faststart;
1786 /* not in the list? then create a new entry */
1787 if ((callsinfo==NULL)){
1788 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
1789 callsinfo->call_active_state = VOIP_ACTIVE;
1790 callsinfo->call_state = VOIP_UNKNOWN;
1791 callsinfo->from_identity=g_strdup("");
1792 callsinfo->to_identity=g_strdup("");
1793 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
1794 callsinfo->selected=FALSE;
1795 callsinfo->first_frame_num=pinfo->fd->num;
1796 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
1797 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
1798 callsinfo->protocol=VOIP_H323;
1799 callsinfo->prot_info=g_malloc(sizeof(h323_calls_info_t));
1800 callsinfo->free_prot_info = free_h225_info;
1802 tmp_h323info = callsinfo->prot_info;
1803 g_assert(tmp_h323info != NULL);
1804 tmp_h323info->guid = g_memdup(&pi->guid, sizeof pi->guid);
1805 tmp_h323info->h225SetupAddr.type = AT_NONE;
1806 tmp_h323info->h225SetupAddr.len = 0;
1807 tmp_h323info->h245_list = NULL;
1808 tmp_h323info->is_faststart_Setup = FALSE;
1809 tmp_h323info->is_faststart_Proc = FALSE;
1810 tmp_h323info->is_h245Tunneling = FALSE;
1811 tmp_h323info->is_h245 = FALSE;
1812 tmp_h323info->q931_crv = -1;
1813 tmp_h323info->q931_crv2 = -1;
1814 tmp_h323info->requestSeqNum = 0;
1815 callsinfo->call_num = tapinfo->ncalls++;
1816 callsinfo->npackets = 0;
1818 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
1821 if (callsinfo!=NULL){
1823 h225_frame_num = pinfo->fd->num;
1824 h225_call_num = callsinfo->call_num;
1826 /* let's analyze the call state */
1828 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
1829 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
1830 callsinfo->last_frame_num=pinfo->fd->num;
1831 ++(callsinfo->npackets);
1832 /* increment the packets counter of all calls */
1833 ++(tapinfo->npackets);
1836 /* XXX: it is supposed to be initialized isn't it? */
1837 g_assert(tmp_h323info != NULL);
1839 /* change the status */
1840 if (pi->msg_type == H225_CS){
1842 /* this is still IPv4 only, because the dissector is */
1843 if (pi->is_h245 == TRUE){
1844 h245_add = g_malloc(sizeof (h245_address_t));
1845 h245_add->h245_address.type=AT_IPv4;
1846 h245_add->h245_address.len=4;
1847 h245_add->h245_address.data = g_malloc(sizeof(pi->h245_address));
1848 memcpy((void *)(h245_add->h245_address.data), &(pi->h245_address), 4);
1849 h245_add->h245_port = pi->h245_port;
1850 add_h245_Address(tmp_h323info, h245_add);
1853 if (pi->cs_type != H225_RELEASE_COMPLET) tmp_h323info->is_h245Tunneling = pi->is_h245Tunneling;
1855 frame_label = g_strdup(pi->frame_label);
1857 switch(pi->cs_type){
1859 tmp_h323info->is_faststart_Setup = pi->is_faststart;
1861 /* Set the Setup address if it was not set */
1862 if (tmp_h323info->h225SetupAddr.type == AT_NONE)
1863 COPY_ADDRESS(&(tmp_h323info->h225SetupAddr), &(pinfo->src));
1864 callsinfo->call_state=VOIP_CALL_SETUP;
1865 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1866 (pi->is_faststart==TRUE?"on":"off"));
1869 callsinfo->call_state=VOIP_IN_CALL;
1870 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1871 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1872 (pi->is_faststart==TRUE?"on":"off"));
1874 case H225_RELEASE_COMPLET:
1875 if (callsinfo->call_state==VOIP_CALL_SETUP){
1876 if (ADDRESSES_EQUAL(&(tmp_h323info->h225SetupAddr),&(pinfo->src))){ /* forward direction */
1877 callsinfo->call_state=VOIP_CANCELLED;
1880 callsinfo->call_state=VOIP_REJECTED;
1881 tapinfo->rejected_calls++;
1884 callsinfo->call_state=VOIP_COMPLETED;
1885 tapinfo->completed_calls++;
1887 comment = g_strdup("H225 No Q931 Rel Cause");
1891 case H225_CALL_PROCEDING:
1892 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1893 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1894 (pi->is_faststart==TRUE?"on":"off"));
1897 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1898 (pi->is_faststart==TRUE?"on":"off"));
1902 else if (pi->msg_type == H225_RAS){
1903 switch(pi->msg_tag){
1905 if (!pi->is_duplicate){
1906 g_free(callsinfo->to_identity);
1907 callsinfo->to_identity=g_strdup(pi->dialedDigits);
1908 tmp_h323info->requestSeqNum = pi->requestSeqNum;
1911 if (strlen(pi->dialedDigits))
1912 comment = g_strdup_printf("H225 RAS dialedDigits: %s", pi->dialedDigits);
1914 comment = g_strdup("H225 RAS");
1917 comment = g_strdup("H225 RAS");
1919 frame_label = g_strdup(val_to_str(pi->msg_tag, h225_RasMessage_vals, "<unknown>"));
1921 frame_label = g_strdup("H225: Unknown");
1925 /* add to graph analysis */
1927 /* if the frame number exists in graph, append to it*/
1928 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, comment)) {
1929 /* if not exist, add to the graph */
1930 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1933 /* Add the H245 info if exists to the Graph */
1934 h245_add_to_graph(pinfo->fd->num);
1936 g_free(frame_label);
1940 tapinfo->redraw = TRUE;
1942 return 1; /* refresh output */
1946 /****************************************************************************/
1948 /****************************************************************************/
1949 static gboolean have_H225_tap_listener=FALSE;
1950 /****************************************************************************/
1952 h225_calls_init_tap(void)
1954 GString *error_string;
1956 if(have_H225_tap_listener==FALSE)
1958 /* don't register tap listener, if we have it already */
1959 error_string = register_tap_listener("h225", &(the_tapinfo_struct.h225_dummy), NULL,
1960 voip_calls_dlg_reset,
1965 if (error_string != NULL) {
1966 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1967 "%s", error_string->str);
1968 g_string_free(error_string, TRUE);
1971 have_H225_tap_listener=TRUE;
1975 /****************************************************************************/
1977 remove_tap_listener_h225_calls(void)
1979 protect_thread_critical_region();
1980 remove_tap_listener(&(the_tapinfo_struct.h225_dummy));
1981 unprotect_thread_critical_region();
1983 have_H225_tap_listener=FALSE;
1986 /* Add the h245 label info to the graph */
1987 void h245_add_to_graph(guint32 new_frame_num)
1991 if (new_frame_num != h245_labels.frame_num) return;
1993 for (n=0; n<h245_labels.labels_count; n++) {
1994 append_to_frame_graph(&the_tapinfo_struct, new_frame_num, h245_labels.labels[n].frame_label, h245_labels.labels[n].comment);
1995 g_free(h245_labels.labels[n].frame_label);
1996 h245_labels.labels[n].frame_label = NULL;
1997 g_free(h245_labels.labels[n].comment);
1998 h245_labels.labels[n].comment = NULL;
2000 h245_labels.frame_num = 0;
2001 h245_labels.labels_count = 0;
2004 /* free the h245_labels if the frame number is different */
2005 static void h245_free_labels(guint32 new_frame_num)
2009 if (new_frame_num == h245_labels.frame_num) return;
2011 for (n=0; n<h245_labels.labels_count; n++) {
2012 g_free(h245_labels.labels[n].frame_label);
2013 h245_labels.labels[n].frame_label = NULL;
2014 g_free(h245_labels.labels[n].comment);
2015 h245_labels.labels[n].comment = NULL;
2017 h245_labels.frame_num = 0;
2018 h245_labels.labels_count = 0;
2021 /* add the frame_label and comment to h245_labels and free the actual one if it is different frame num */
2022 static void h245_add_label(guint32 new_frame_num, const gchar *frame_label, const gchar *comment)
2024 h245_free_labels(new_frame_num);
2026 h245_labels.frame_num = new_frame_num;
2027 h245_labels.labels[h245_labels.labels_count].frame_label = g_strdup(frame_label);
2028 h245_labels.labels[h245_labels.labels_count].comment = g_strdup(comment);
2030 if (h245_labels.labels_count < (H245_MAX-1))
2031 h245_labels.labels_count++;
2035 /****************************************************************************/
2036 /* whenever a H245dg packet is seen by the tap listener (when H245 tunneling is ON) */
2038 H245dgcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H245info)
2040 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2041 voip_calls_info_t *tmp_listinfo;
2042 voip_calls_info_t *callsinfo = NULL;
2043 h323_calls_info_t *tmp_h323info;
2046 h245_address_t *h245_add = NULL;
2048 const h245_packet_info *pi = H245info;
2050 /* check if Tunneling is OFF and we have a call with this H245 add */
2051 list = g_list_first(tapinfo->callsinfo_list);
2054 tmp_listinfo=list->data;
2055 if (tmp_listinfo->protocol == VOIP_H323){
2056 tmp_h323info = tmp_listinfo->prot_info;
2058 list2 = g_list_first(tmp_h323info->h245_list);
2061 h245_add=list2->data;
2062 if ( (ADDRESSES_EQUAL(&(h245_add->h245_address),&(pinfo->src)) && (h245_add->h245_port == pinfo->srcport))
2063 || (ADDRESSES_EQUAL(&(h245_add->h245_address),&(pinfo->dst)) && (h245_add->h245_port == pinfo->destport)) ){
2064 callsinfo = (voip_calls_info_t*)(list->data);
2066 ++(callsinfo->npackets);
2067 /* increment the packets counter of all calls */
2068 ++(tapinfo->npackets);
2072 list2 = g_list_next(list2);
2074 if (callsinfo!=NULL) break;
2076 list = g_list_next(list);
2079 /* Tunnel is OFF, and we matched the h245 add so we add it to graph */
2080 if (callsinfo!=NULL){
2081 ++(callsinfo->npackets);
2082 /* increment the packets counter of all calls */
2083 ++(tapinfo->npackets);
2084 /* if the frame number exists in graph, append to it*/
2085 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, pi->comment)) {
2086 /* if not exist, add to the graph */
2087 add_to_graph(tapinfo, pinfo, pi->frame_label, pi->comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2090 /* Tunnel is ON, so we save the label info to use it into h225 or q931 tap. OR may be
2091 tunnel OFF but we did not matched the h245 add, in this case nobady will set this label
2092 since the frame_num will not match */
2094 h245_add_label(pinfo->fd->num, (gchar *) pi->frame_label, (gchar *) pi->comment);
2097 tapinfo->redraw = TRUE;
2099 return 1; /* refresh output */
2103 /****************************************************************************/
2105 /****************************************************************************/
2106 static gboolean have_H245dg_tap_listener=FALSE;
2107 /****************************************************************************/
2109 h245dg_calls_init_tap(void)
2111 GString *error_string;
2113 if(have_H245dg_tap_listener==FALSE)
2115 /* don't register tap listener, if we have it already */
2116 error_string = register_tap_listener("h245dg", &(the_tapinfo_struct.h245dg_dummy), NULL,
2117 voip_calls_dlg_reset,
2122 if (error_string != NULL) {
2123 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2124 "%s", error_string->str);
2125 g_string_free(error_string, TRUE);
2128 have_H245dg_tap_listener=TRUE;
2132 /****************************************************************************/
2134 remove_tap_listener_h245dg_calls(void)
2136 protect_thread_critical_region();
2137 remove_tap_listener(&(the_tapinfo_struct.h245dg_dummy));
2138 unprotect_thread_critical_region();
2140 have_H245dg_tap_listener=FALSE;
2143 /****************************************************************************/
2144 /****************************TAP for SDP PROTOCOL ***************************/
2145 /****************************************************************************/
2146 /* whenever a SDP packet is seen by the tap listener */
2148 SDPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SDPinfo)
2150 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2151 const sdp_packet_info *pi = SDPinfo;
2153 /* There are protocols like MGCP/SIP where the SDP is called before the tap for the
2154 MGCP/SIP packet, in those cases we assign the SPD summary to global lastSDPsummary
2157 g_free(sdp_summary);
2158 sdp_frame_num = pinfo->fd->num;
2159 /* Append to graph the SDP summary if the packet exists */
2160 sdp_summary = g_strdup_printf("SDP (%s)", pi->summary_str);
2161 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2163 tapinfo->redraw = TRUE;
2165 return 1; /* refresh output */
2169 /****************************************************************************/
2171 /****************************************************************************/
2172 static gboolean have_sdp_tap_listener=FALSE;
2173 /****************************************************************************/
2175 sdp_calls_init_tap(void)
2177 GString *error_string;
2179 if(have_sdp_tap_listener==FALSE)
2181 /* don't register tap listener, if we have it already */
2182 error_string = register_tap_listener("sdp", &(the_tapinfo_struct.sdp_dummy), NULL,
2183 voip_calls_dlg_reset,
2188 if (error_string != NULL) {
2189 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2190 "%s", error_string->str);
2191 g_string_free(error_string, TRUE);
2194 have_sdp_tap_listener=TRUE;
2198 /****************************************************************************/
2200 remove_tap_listener_sdp_calls(void)
2202 protect_thread_critical_region();
2203 remove_tap_listener(&(the_tapinfo_struct.sdp_dummy));
2204 unprotect_thread_critical_region();
2206 have_sdp_tap_listener=FALSE;
2211 /****************************************************************************/
2212 /* ***************************TAP for MGCP **********************************/
2213 /****************************************************************************/
2216 This function will look for a signal/event in the SignalReq/ObsEvent string
2217 and return true if it is found
2219 static gboolean isSignal(const gchar *signal, const gchar *signalStr)
2222 gchar **resultArray;
2224 /* if there is no signalStr, just return false */
2225 if (signalStr == NULL) return FALSE;
2227 /* if are both "blank" return true */
2228 if ( (*signal == '\0') && (*signalStr == '\0') ) return TRUE;
2230 /* look for signal in signalSre */
2231 resultArray = g_strsplit(signalStr, ",", 10);
2233 for (i = 0; resultArray[i]; i++) {
2234 g_strstrip(resultArray[i]);
2235 if (strcmp(resultArray[i], signal) == 0) return TRUE;
2238 g_strfreev(resultArray);
2244 This function will get the Caller ID info and replace the current string
2245 This is how it looks the caller Id: rg, ci(02/16/08/29, "3035550002","Ale Sipura 2")
2247 static void mgcpCallerID(gchar *signalStr, gchar **callerId)
2251 /* if there is no signalStr, just return false */
2252 if (signalStr == NULL) return;
2254 arrayStr = g_strsplit(signalStr, "\"", 10);
2256 if (arrayStr[0] == NULL) return;
2258 /* look for the ci signal */
2259 if (strstr(arrayStr[0], "ci(") && (arrayStr[1] != NULL) ) {
2260 /* free the previous "From" field of the call, and assign the new */
2262 *callerId = g_strdup(arrayStr[1]);
2264 g_strfreev(arrayStr);
2271 This function will get the Dialed Digits and replace the current string
2272 This is how it looks the dialed digits 5,5,5,0,0,0,2,#,*
2274 static void mgcpDialedDigits(gchar *signalStr, gchar **dialedDigits)
2277 gchar resultStr[50];
2280 /* if there is no signalStr, just return false */
2281 if (signalStr == NULL) return;
2283 tmpStr = g_strdup(signalStr);
2285 for ( i = 0 ; tmpStr[i] ; i++) {
2286 switch (tmpStr[i]) {
2287 case '0' : case '1' : case '2' : case '3' : case '4' :
2288 case '5' : case '6' : case '7' : case '8' : case '9' :
2289 case '#' : case '*' :
2297 for (i = 0, j = 0; tmpStr[i] && i<50; i++) {
2298 if (tmpStr[i] != '?')
2299 resultStr[j++] = tmpStr[i];
2301 resultStr[j] = '\0';
2303 if (*resultStr == '\0') return;
2305 g_free(*dialedDigits);
2306 *dialedDigits = g_strdup(resultStr);
2314 /****************************************************************************/
2315 /* whenever a MGCP packet is seen by the tap listener */
2317 MGCPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *MGCPinfo)
2319 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2321 voip_calls_info_t *tmp_listinfo;
2322 voip_calls_info_t *callsinfo = NULL;
2323 mgcp_calls_info_t *tmp_mgcpinfo = NULL;
2326 gchar *frame_label = NULL;
2327 gchar *comment = NULL;
2328 graph_analysis_item_t *gai;
2329 gboolean new = FALSE;
2330 gboolean fromEndpoint = FALSE; /* true for calls originated in Endpoints, false for calls from MGC */
2333 const mgcp_info_t *pi = MGCPinfo;
2336 if ((pi->mgcp_type == MGCP_REQUEST) && !pi->is_duplicate ){
2337 /* check whether we already have a call with this Endpoint and it is active*/
2338 list = g_list_first(tapinfo->callsinfo_list);
2341 tmp_listinfo=list->data;
2342 if ((tmp_listinfo->protocol == VOIP_MGCP) && (tmp_listinfo->call_active_state == VOIP_ACTIVE)){
2343 tmp_mgcpinfo = tmp_listinfo->prot_info;
2344 if (pi->endpointId != NULL){
2345 if (g_ascii_strcasecmp(tmp_mgcpinfo->endpointId,pi->endpointId) == 0){
2347 check first if it is an ended call. We can still match packets to this Endpoint 2 seconds
2348 after the call has been released
2350 diff_time = nstime_to_sec(&pinfo->fd->rel_ts) - tmp_listinfo->stop_sec - (double)tmp_listinfo->stop_usec/1000000;
2351 if ( ((tmp_listinfo->call_state == VOIP_CANCELLED) ||
2352 (tmp_listinfo->call_state == VOIP_COMPLETED) ||
2353 (tmp_listinfo->call_state == VOIP_REJECTED)) &&
2356 tmp_listinfo->call_active_state = VOIP_INACTIVE;
2358 callsinfo = (voip_calls_info_t*)(list->data);
2364 list = g_list_next (list);
2367 /* there is no call with this Endpoint, lets see if this a new call or not */
2368 if (callsinfo == NULL){
2369 if ( (strcmp(pi->code, "NTFY") == 0) && isSignal("hd", pi->observedEvents) ){ /* off hook transition */
2370 /* this is a new call from the Endpoint */
2371 fromEndpoint = TRUE;
2373 } else if (strcmp(pi->code, "CRCX") == 0){
2374 /* this is a new call from the MGC */
2375 fromEndpoint = FALSE;
2380 } else if ( ((pi->mgcp_type == MGCP_RESPONSE) && pi->request_available) ||
2381 ((pi->mgcp_type == MGCP_REQUEST) && pi->is_duplicate) ) {
2382 /* if it is a response OR if it is a duplicated Request, lets look in the Graph to see
2383 if there is a request that matches */
2384 listGraph = g_list_first(tapinfo->graph_analysis->list);
2387 gai = listGraph->data;
2388 if (gai->frame_num == pi->req_num){
2389 /* there is a request that match, so look the associated call with this call_num */
2390 list = g_list_first(tapinfo->callsinfo_list);
2393 tmp_listinfo=list->data;
2394 if (tmp_listinfo->protocol == VOIP_MGCP){
2395 if (tmp_listinfo->call_num == gai->conv_num){
2396 tmp_mgcpinfo = tmp_listinfo->prot_info;
2397 callsinfo = (voip_calls_info_t*)(list->data);
2401 list = g_list_next (list);
2403 if (callsinfo != NULL) break;
2405 listGraph = g_list_next(listGraph);
2407 /* if there is not a matching request, just return */
2408 if (callsinfo == NULL) return 0;
2411 /* not in the list? then create a new entry */
2412 if (callsinfo==NULL){
2413 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2414 callsinfo->call_active_state = VOIP_ACTIVE;
2415 callsinfo->call_state = VOIP_CALL_SETUP;
2417 callsinfo->from_identity=g_strdup(pi->endpointId);
2418 callsinfo->to_identity=g_strdup("");
2420 callsinfo->from_identity=g_strdup("");
2421 callsinfo->to_identity=g_strdup(pi->endpointId);
2423 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
2424 callsinfo->first_frame_num=pinfo->fd->num;
2425 callsinfo->selected=FALSE;
2426 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
2427 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
2428 callsinfo->protocol=VOIP_MGCP;
2429 callsinfo->prot_info=g_malloc(sizeof(mgcp_calls_info_t));
2430 callsinfo->free_prot_info = g_free;
2431 tmp_mgcpinfo=callsinfo->prot_info;
2432 tmp_mgcpinfo->endpointId = g_strdup(pi->endpointId);
2433 tmp_mgcpinfo->fromEndpoint = fromEndpoint;
2434 callsinfo->npackets = 0;
2435 callsinfo->call_num = tapinfo->ncalls++;
2436 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2439 g_assert(tmp_mgcpinfo != NULL);
2441 /* change call state and add to graph */
2442 switch (pi->mgcp_type)
2445 if ( (strcmp(pi->code, "NTFY") == 0) && (pi->observedEvents != NULL) ){
2446 frame_label = g_strdup_printf("%s ObsEvt:%s",pi->code, pi->observedEvents);
2448 if (tmp_mgcpinfo->fromEndpoint){
2449 /* use the Dialed digits to fill the "To" for the call, but use the first NTFY */
2450 if (callsinfo->to_identity[0] == '\0') mgcpDialedDigits(pi->observedEvents, &(callsinfo->to_identity));
2452 /* from MGC and the user picked up, the call is connected */
2453 } else if (isSignal("hd", pi->observedEvents))
2454 callsinfo->call_state=VOIP_IN_CALL;
2456 /* hung up signal */
2457 if (isSignal("hu", pi->observedEvents)) {
2458 if ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state == VOIP_RINGING)){
2459 callsinfo->call_state = VOIP_CANCELLED;
2461 callsinfo->call_state = VOIP_COMPLETED;
2465 } else if (strcmp(pi->code, "RQNT") == 0) {
2466 /* for calls from Endpoint: if there is a "no signal" RQNT and the call was RINGING, we assume this is the CONNECT */
2467 if ( tmp_mgcpinfo->fromEndpoint && isSignal("", pi->signalReq) && (callsinfo->call_state == VOIP_RINGING) ) {
2468 callsinfo->call_state = VOIP_IN_CALL;
2471 /* if there is ringback or ring tone, change state to ringing */
2472 if ( isSignal("rg", pi->signalReq) || isSignal("rt", pi->signalReq) ) {
2473 callsinfo->call_state = VOIP_RINGING;
2476 /* if there is a Busy or ReorderTone, and the call was Ringing or Setup the call is Rejected */
2477 if ( (isSignal("ro", pi->signalReq) || isSignal("bz", pi->signalReq)) && ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state = VOIP_RINGING)) ) {
2478 callsinfo->call_state = VOIP_REJECTED;
2481 if (pi->signalReq != NULL)
2482 frame_label = g_strdup_printf("%s%sSigReq:%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"", pi->signalReq);
2484 frame_label = g_strdup_printf("%s%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"");
2486 /* use the CallerID info to fill the "From" for the call */
2487 if (!tmp_mgcpinfo->fromEndpoint) mgcpCallerID(pi->signalReq, &(callsinfo->from_identity));
2489 } else if (strcmp(pi->code, "DLCX") == 0) {
2491 if there is a DLCX in a call To an Endpoint and the call was not connected, we use
2492 the DLCX as the end of the call
2494 if (!tmp_mgcpinfo->fromEndpoint){
2495 if ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state == VOIP_RINGING)){
2496 callsinfo->call_state = VOIP_CANCELLED;
2501 if (frame_label == NULL) frame_label = g_strdup(pi->code);
2504 frame_label = g_strdup_printf("%u (%s)",pi->rspcode, pi->code);
2507 /* XXX what to do? */
2512 comment = g_strdup_printf("MGCP %s %s%s", tmp_mgcpinfo->endpointId, (pi->mgcp_type == MGCP_REQUEST)?"Request":"Response", pi->is_duplicate?" Duplicate":"");
2514 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
2515 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
2516 callsinfo->last_frame_num=pinfo->fd->num;
2517 ++(callsinfo->npackets);
2518 /* increment the packets counter of all calls */
2519 ++(tapinfo->npackets);
2521 /* add to the graph */
2522 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2524 g_free(frame_label);
2526 /* add SDP info if apply */
2527 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
2528 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2529 g_free(sdp_summary);
2533 tapinfo->redraw = TRUE;
2535 return 1; /* refresh output */
2539 /****************************************************************************/
2541 /****************************************************************************/
2542 static gboolean have_MGCP_tap_listener=FALSE;
2543 /****************************************************************************/
2545 mgcp_calls_init_tap(void)
2547 GString *error_string;
2549 if(have_MGCP_tap_listener==FALSE)
2551 /* don't register tap listener, if we have it already */
2552 /* we send an empty filter, to force a non null "tree" in the mgcp dissector */
2553 error_string = register_tap_listener("mgcp", &(the_tapinfo_struct.mgcp_dummy), g_strdup(""),
2554 voip_calls_dlg_reset,
2558 if (error_string != NULL) {
2559 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2560 "%s", error_string->str);
2561 g_string_free(error_string, TRUE);
2564 have_MGCP_tap_listener=TRUE;
2568 /****************************************************************************/
2570 remove_tap_listener_mgcp_calls(void)
2572 protect_thread_critical_region();
2573 remove_tap_listener(&(the_tapinfo_struct.mgcp_dummy));
2574 unprotect_thread_critical_region();
2576 have_MGCP_tap_listener=FALSE;
2580 /****************************************************************************/
2581 /****************************TAP for ACTRACE (AudioCodes trace)**************/
2582 /****************************************************************************/
2584 /* whenever a ACTRACE packet is seen by the tap listener */
2586 ACTRACEcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *ACTRACEinfo)
2588 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2589 const actrace_info_t *pi = ACTRACEinfo;
2591 actrace_cas_calls_info_t *tmp_actrace_cas_info;
2592 voip_calls_info_t *tmp_listinfo;
2593 voip_calls_info_t *callsinfo = NULL;
2596 actrace_frame_num = pinfo->fd->num;
2597 actrace_trunk = pi->trunk;
2598 actrace_direction = pi->direction;
2600 if (pi->type == 1){ /* is CAS protocol */
2602 gchar *comment = NULL;
2605 list = g_list_first(tapinfo->callsinfo_list);
2608 tmp_listinfo=list->data;
2609 if ( tmp_listinfo->protocol == VOIP_AC_CAS ){
2610 tmp_actrace_cas_info = tmp_listinfo->prot_info;
2611 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
2612 if ( (tmp_actrace_cas_info->bchannel == pi->cas_bchannel) && (tmp_actrace_cas_info->trunk == actrace_trunk) ) {
2613 callsinfo = (voip_calls_info_t*)(list->data);
2617 list = g_list_next (list);
2620 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, "PSTN");
2622 /* if it is a new call, add it to the list */
2624 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2625 callsinfo->call_active_state = VOIP_ACTIVE;
2626 callsinfo->call_state = VOIP_CALL_SETUP;
2627 callsinfo->from_identity=g_strdup("N/A");
2628 callsinfo->to_identity=g_strdup("N/A");
2629 COPY_ADDRESS(&(callsinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
2630 callsinfo->first_frame_num=pinfo->fd->num;
2631 callsinfo->selected=FALSE;
2632 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
2633 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
2634 callsinfo->protocol=VOIP_AC_CAS;
2635 callsinfo->prot_info=g_malloc(sizeof(actrace_cas_calls_info_t));
2636 callsinfo->free_prot_info = g_free;
2638 tmp_actrace_cas_info=callsinfo->prot_info;
2639 tmp_actrace_cas_info->bchannel=pi->cas_bchannel;
2640 tmp_actrace_cas_info->trunk=actrace_trunk;
2641 callsinfo->npackets = 0;
2642 callsinfo->call_num = tapinfo->ncalls++;
2643 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2646 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
2647 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
2648 callsinfo->last_frame_num=pinfo->fd->num;
2649 ++(callsinfo->npackets);
2650 /* increment the packets counter of all calls */
2651 ++(tapinfo->npackets);
2653 comment = g_strdup_printf("AC_CAS trunk:%u", actrace_trunk);
2655 add_to_graph(tapinfo, pinfo, pi->cas_frame_label, comment, callsinfo->call_num,
2656 actrace_direction?&pstn_add:&(pinfo->src),
2657 actrace_direction?&(pinfo->src):&pstn_add,
2663 tapinfo->redraw = TRUE;
2665 return 1; /* refresh output */
2669 /****************************************************************************/
2671 /****************************************************************************/
2672 static gboolean have_actrace_tap_listener=FALSE;
2673 /****************************************************************************/
2675 actrace_calls_init_tap(void)
2677 GString *error_string;
2679 if(have_actrace_tap_listener==FALSE)
2681 /* don't register tap listener, if we have it already */
2682 error_string = register_tap_listener("actrace", &(the_tapinfo_struct.actrace_dummy), NULL,
2683 voip_calls_dlg_reset,
2684 ACTRACEcalls_packet,
2688 if (error_string != NULL) {
2689 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2690 "%s", error_string->str);
2691 g_string_free(error_string, TRUE);
2694 have_actrace_tap_listener=TRUE;
2698 /****************************************************************************/
2700 remove_tap_listener_actrace_calls(void)
2702 protect_thread_critical_region();
2703 remove_tap_listener(&(the_tapinfo_struct.actrace_dummy));
2704 unprotect_thread_critical_region();
2706 have_actrace_tap_listener=FALSE;
2710 /****************************************************************************/
2711 /**************************** TAP for H248/MEGACO **********************************/
2712 /****************************************************************************/
2713 static gboolean have_h248_tap_listener = FALSE;
2714 static gboolean have_megaco_tap_listener = FALSE;
2716 #define gcp_is_req(type) ( type == GCP_CMD_ADD_REQ || type == GCP_CMD_MOVE_REQ || type == GCP_CMD_MOD_REQ || \
2717 type == GCP_CMD_SUB_REQ || type == GCP_CMD_AUDITCAP_REQ || type == GCP_CMD_AUDITVAL_REQ || \
2718 type == GCP_CMD_NOTIFY_REQ || type == GCP_CMD_SVCCHG_REQ || type == GCP_CMD_TOPOLOGY_REQ || \
2719 type == GCP_CMD_CTX_ATTR_AUDIT_REQ )
2721 static int h248_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
2722 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2723 const gcp_cmd_t *cmd = prot_info;
2725 voip_calls_info_t *callsinfo = NULL;
2728 gchar mgw_addr[128];
2730 if (cmd->ctx->id == NULL_CONTEXT || cmd->ctx->id == ALL_CONTEXTS ) {
2734 if ( gcp_is_req(cmd->type) ) {
2735 mgw = &(pinfo->dst);
2736 mgc = &(pinfo->src);
2738 mgc = &(pinfo->dst);
2739 mgw = &(pinfo->src);
2742 address_to_str_buf(mgw, mgw_addr, 128);
2744 /* check whether we already have this context in the list */
2745 list = g_list_first(tapinfo->callsinfo_list);
2748 voip_calls_info_t* tmp_listinfo = list->data;
2750 if (tmp_listinfo->protocol == TEL_H248){
2751 if (tmp_listinfo->prot_info == cmd->ctx){
2752 callsinfo = (voip_calls_info_t*)(list->data);
2756 list = g_list_next (list);
2759 if (callsinfo==NULL){
2761 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2762 callsinfo->call_state = VOIP_NO_STATE;
2763 callsinfo->call_active_state = VOIP_ACTIVE;
2764 callsinfo->from_identity = g_strdup_printf("%s : %.8x", mgw_addr, cmd->ctx->id);
2765 callsinfo->to_identity = g_strdup("");
2766 callsinfo->prot_info = cmd->ctx;
2767 callsinfo->free_prot_info = NULL;
2769 callsinfo->npackets = 1;
2770 callsinfo->first_frame_num=pinfo->fd->num;
2771 callsinfo->last_frame_num=pinfo->fd->num;
2773 COPY_ADDRESS(&(callsinfo->initial_speaker), mgc);
2775 callsinfo->protocol = TEL_H248;
2776 callsinfo->call_num = tapinfo->ncalls++;
2777 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
2778 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs;
2779 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
2780 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
2782 callsinfo->selected = FALSE;
2784 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2787 GString *s = g_string_new("");
2788 gcp_terms_t *ctx_term;
2790 g_free(callsinfo->from_identity);
2791 callsinfo->from_identity = g_strdup_printf("%s : %.8x", mgw_addr, ((gcp_ctx_t*)callsinfo->prot_info)->id);
2793 g_free(callsinfo->to_identity);
2795 for (ctx_term = ((gcp_ctx_t*)callsinfo->prot_info)->terms.next;
2797 ctx_term = ctx_term->next ) {
2798 if ( ctx_term->term && ctx_term->term->str) {
2799 g_string_append_printf(s," %s",ctx_term->term->str);
2803 callsinfo->to_identity = s->str;
2804 g_string_free(s,FALSE);
2806 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
2807 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
2808 callsinfo->last_frame_num=pinfo->fd->num;
2809 ++(callsinfo->npackets);
2812 add_to_graph(tapinfo, pinfo, cmd->str ? cmd->str : "unknown Msg",
2813 ep_strdup_printf("TrxId = %u, CtxId = %.8x",cmd->trx->id,cmd->ctx->id),
2814 callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2816 ++(tapinfo->npackets);
2818 tapinfo->redraw = TRUE;
2823 void h248_calls_init_tap(void)
2825 GString *error_string;
2828 if(have_megaco_tap_listener==FALSE)
2830 error_string = register_tap_listener("megaco", &(the_tapinfo_struct.megaco_dummy),
2832 voip_calls_dlg_reset,
2834 voip_calls_dlg_draw);
2836 if (error_string != NULL) {
2837 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2838 "%s", error_string->str);
2839 g_string_free(error_string, TRUE);
2843 have_megaco_tap_listener=TRUE;
2846 if(have_h248_tap_listener==FALSE)
2848 error_string = register_tap_listener("h248", &(the_tapinfo_struct.h248_dummy),
2850 voip_calls_dlg_reset,
2852 voip_calls_dlg_draw);
2854 if (error_string != NULL) {
2855 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2856 "%s", error_string->str);
2857 g_string_free(error_string, TRUE);
2861 have_h248_tap_listener=TRUE;
2866 remove_tap_listener_h248_calls(void)
2868 protect_thread_critical_region();
2869 remove_tap_listener(&(the_tapinfo_struct.h248_dummy));
2870 remove_tap_listener(&(the_tapinfo_struct.megaco_dummy));
2871 unprotect_thread_critical_region();
2873 have_megaco_tap_listener=FALSE;
2874 have_h248_tap_listener=FALSE;
2877 /****************************************************************************/
2878 /**************************** TAP for SCCP and SUA **********************************/
2879 /**************************** ( RANAP and BSSAP ) **********************************/
2880 /****************************************************************************/
2882 static gboolean have_sccp_tap_listener = FALSE;
2883 static gboolean have_sua_tap_listener = FALSE;
2885 static const voip_protocol sccp_proto_map[] = {
2890 #define SP2VP(ap) ((ap) < SCCP_PLOAD_NUM_PLOADS ? sccp_proto_map[(ap)] : TEL_SCCP)
2891 const value_string* sccp_payload_values;
2893 static int sccp_calls(packet_info *pinfo, const void *prot_info) {
2894 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2895 const sccp_msg_info_t* msg = prot_info;
2896 sccp_assoc_info_t* assoc = msg->data.co.assoc;
2898 voip_calls_info_t *callsinfo = NULL;
2899 const gchar *label = NULL;
2900 const gchar *comment = NULL;
2901 /* check whether we already have this assoc in the list */
2903 for(list = g_list_first(tapinfo->callsinfo_list) ; list ; list = g_list_next (list) ) {
2904 if ( ((voip_calls_info_t*)(list->data))->prot_info == assoc ){
2905 callsinfo = (voip_calls_info_t*)(list->data);
2910 if (callsinfo==NULL){
2911 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
2912 callsinfo->call_state = VOIP_CALL_SETUP;
2913 callsinfo->call_active_state = VOIP_ACTIVE;
2914 if ( assoc->calling_party ) {
2915 callsinfo->from_identity = g_strdup(assoc->calling_party);
2917 callsinfo->from_identity = g_strdup("Unknown");
2920 if ( assoc->called_party ) {
2921 callsinfo->to_identity = g_strdup(assoc->called_party);
2923 callsinfo->to_identity = g_strdup("Unknown");
2926 callsinfo->prot_info = (void*)assoc;
2927 callsinfo->free_prot_info = NULL;
2929 callsinfo->npackets = 1;
2930 callsinfo->first_frame_num=pinfo->fd->num;
2931 callsinfo->last_frame_num=pinfo->fd->num;
2933 COPY_ADDRESS(&(callsinfo->initial_speaker), &(pinfo->src));
2935 callsinfo->protocol = SP2VP(assoc->payload);
2936 callsinfo->start_sec=(gint32) pinfo->fd->rel_ts.secs;
2937 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs;
2938 callsinfo->stop_sec=(gint32) pinfo->fd->rel_ts.secs;
2939 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
2941 callsinfo->selected = FALSE;
2942 callsinfo->call_num = tapinfo->ncalls++;
2944 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
2947 if ( assoc->calling_party ) {
2948 g_free(callsinfo->from_identity);
2949 callsinfo->from_identity = g_strdup(assoc->calling_party);
2952 if ( assoc->called_party ) {
2953 g_free(callsinfo->to_identity);
2954 callsinfo->to_identity = g_strdup(assoc->called_party);
2957 callsinfo->protocol = SP2VP(assoc->payload);
2958 callsinfo->stop_sec=(gint32) pinfo->fd->rel_ts.secs;
2959 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
2960 callsinfo->last_frame_num=pinfo->fd->num;
2961 ++(callsinfo->npackets);
2963 switch (msg->type) {
2964 case SCCP_MSG_TYPE_CC:
2965 callsinfo->call_state = VOIP_IN_CALL;
2967 case SCCP_MSG_TYPE_RLC:
2968 callsinfo->call_state = VOIP_COMPLETED;
2969 callsinfo->call_active_state = VOIP_INACTIVE;
2976 if (msg->data.co.label) {
2977 label = msg->data.co.label;
2979 label = val_to_str(msg->type, sccp_payload_values, "Unknown(%d)");
2982 if (msg->data.co.comment) {
2983 comment = msg->data.co.comment;
2988 add_to_graph(tapinfo, pinfo, label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2990 ++(tapinfo->npackets);
2992 tapinfo->redraw = TRUE;
2997 static int sccp_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
2998 sccp_payload_values = sccp_message_type_acro_values;
2999 return sccp_calls(pinfo, prot_info);
3003 static int sua_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
3004 sccp_payload_values = sua_co_class_type_acro_values;
3005 return sccp_calls(pinfo, prot_info);
3009 void sccp_calls_init_tap(void)
3011 GString *error_string;
3013 if(have_sccp_tap_listener==FALSE)
3015 error_string = register_tap_listener("sccp", &(the_tapinfo_struct.sccp_dummy),
3017 voip_calls_dlg_reset,
3019 voip_calls_dlg_draw);
3021 if (error_string != NULL) {
3022 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3023 "%s", error_string->str);
3024 g_string_free(error_string, TRUE);
3028 have_sccp_tap_listener=TRUE;
3031 if(have_sua_tap_listener==FALSE)
3033 error_string = register_tap_listener("sua", &(the_tapinfo_struct.sua_dummy),
3035 voip_calls_dlg_reset,
3037 voip_calls_dlg_draw);
3039 if (error_string != NULL) {
3040 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3041 "%s", error_string->str);
3042 g_string_free(error_string, TRUE);
3046 have_sua_tap_listener=TRUE;
3052 remove_tap_listener_sccp_calls(void)
3054 protect_thread_critical_region();
3055 remove_tap_listener(&(the_tapinfo_struct.sccp_dummy));
3056 unprotect_thread_critical_region();
3058 have_sccp_tap_listener=FALSE;
3059 have_sua_tap_listener=FALSE;
3063 /****************************************************************************/
3064 /****************************TAP for UNISTIM ********************************/
3065 /****************************************************************************/
3068 unistim_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *unistim_info)
3070 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3071 voip_calls_info_t *tmp_listinfo;
3072 voip_calls_info_t *callsinfo = NULL;
3073 unistim_info_t *tmp_unistim_info = NULL;
3075 GString *g_tmp = NULL;
3076 gchar *frame_label = NULL;
3077 gchar *comment = NULL;
3079 /* Fetch specific packet infos */
3080 const unistim_info_t *pi = unistim_info;
3083 g_tmp = g_string_new(NULL);
3085 /* Check to see if this is a dup */
3086 list = g_list_first(tapinfo->callsinfo_list);
3090 tmp_listinfo = list->data;
3092 if(tmp_listinfo->protocol == VOIP_UNISTIM){
3094 tmp_unistim_info = tmp_listinfo->prot_info;
3096 /* Search by termid if possible, otherwise use ni/it ip + port.. */
3097 if(pi->termid != 0){
3098 if(tmp_unistim_info->termid == pi->termid){
3099 /* If the call has ended, then we can reuse it.. */
3100 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
3103 callsinfo = (voip_calls_info_t*)(list->data);
3108 /* If no term id use ips / port to find entry */
3109 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)){
3110 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
3111 /* Do nothing previous call */
3113 callsinfo = (voip_calls_info_t*)(list->data);
3117 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)) {
3118 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
3119 /* Do nothing, it ain't our call.. */
3121 callsinfo = (voip_calls_info_t*)(list->data);
3128 /* Otherwise, go to the next one.. */
3129 list = g_list_next(list);
3132 if(pi->payload_type == 2 || pi->payload_type == 1){
3134 if(pi->key_state == 1 || pi->hook_state == 1){
3136 /* If the user hits a button,
3137 Session will be SETUP */
3139 /* If new add to list */
3140 if (callsinfo==NULL){
3142 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3143 callsinfo->call_active_state = VOIP_ACTIVE;
3144 callsinfo->call_state = VOIP_CALL_SETUP;
3145 callsinfo->from_identity=g_strdup_printf("%x",pi->termid);
3146 callsinfo->to_identity=g_strdup("UNKNOWN");
3147 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
3148 callsinfo->first_frame_num=pinfo->fd->num;
3149 callsinfo->selected=FALSE;
3151 /* Set this on init of struct so in case the call doesn't complete, we'll have a ref. */
3152 /* Otherwise if the call is completed we'll have the open/close streams to ref actual call duration */
3153 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3154 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3156 callsinfo->protocol=VOIP_UNISTIM;
3157 callsinfo->prot_info=g_malloc(sizeof(unistim_info_t));
3159 tmp_unistim_info = callsinfo->prot_info;
3161 /* Clear tap struct */
3162 tmp_unistim_info->rudp_type = 0;
3163 tmp_unistim_info->payload_type = 0;
3164 tmp_unistim_info->sequence = pi->sequence;
3165 tmp_unistim_info->termid = pi->termid;
3166 tmp_unistim_info->key_val = -1;
3167 tmp_unistim_info->key_state = -1;
3168 tmp_unistim_info->hook_state = -1;
3169 tmp_unistim_info->stream_connect = -1;
3170 tmp_unistim_info->trans_connect = -1;
3171 tmp_unistim_info->set_termid = -1;
3172 tmp_unistim_info->string_data = NULL;
3173 tmp_unistim_info->key_buffer = NULL;
3175 COPY_ADDRESS(&(tmp_unistim_info->it_ip),&(pi->it_ip));
3176 COPY_ADDRESS(&(tmp_unistim_info->ni_ip),&(pi->ni_ip));
3177 tmp_unistim_info->it_port = pi->it_port;
3179 callsinfo->free_prot_info = g_free;
3180 callsinfo->npackets = 0;
3181 callsinfo->call_num = tapinfo->ncalls++;
3182 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3186 /* Set up call wide info struct */
3187 tmp_unistim_info = callsinfo->prot_info;
3188 tmp_unistim_info->sequence = pi->sequence;
3191 /* Each packet COULD BE OUR LAST!!!! */
3192 callsinfo->stop_sec=(gint32)(pinfo->fd->rel_ts.secs);
3193 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
3194 callsinfo->last_frame_num=pinfo->fd->num;
3196 /* This is a valid packet so increment counter */
3197 ++(callsinfo->npackets);
3199 /* increment the packets counter of all calls */
3200 ++(tapinfo->npackets);
3202 /* Key was depressed.. update key buffer.. */
3203 if(pi->key_val >= 0 && pi->key_val <= 11){
3205 if(tmp_unistim_info->key_buffer != NULL){
3207 /* assign to temp variable */
3208 g_string_assign(g_tmp,tmp_unistim_info->key_buffer);
3210 /* Manipulate the data */
3211 if(pi->key_val == 10) {
3212 tmp_unistim_info->key_buffer = g_strdup_printf("%s*",g_tmp->str);
3213 } else if(pi->key_val == 11) {
3214 tmp_unistim_info->key_buffer = g_strdup_printf("%s#",g_tmp->str);
3216 tmp_unistim_info->key_buffer = g_strdup_printf("%s%d",g_tmp->str,pi->key_val);
3221 /* Create new string */
3222 if(pi->key_val == 10) {
3223 tmp_unistim_info->key_buffer = g_strdup("*");
3224 } else if(pi->key_val == 11) {
3225 tmp_unistim_info->key_buffer = g_strdup("#");
3227 tmp_unistim_info->key_buffer = g_strdup_printf("%d",pi->key_val);
3232 /* Select for non-digit characters */
3233 if(pi->key_val == 10) {
3234 comment = g_strdup_printf("Key Input Sent: * (%d)", pi->sequence);
3235 } else if(pi->key_val == 11) {
3236 comment = g_strdup_printf("Key Input Sent: # (%d)", pi->sequence);
3238 comment = g_strdup_printf("Key Input Sent: %d (%d)",pi->key_val, pi->sequence);
3240 } else if(pi->key_val == 12) {
3241 /* Set label and comment for graph */
3242 comment = g_strdup_printf("Key Input Sent: UP (%d)", pi->sequence);
3243 } else if(pi->key_val == 13) {
3244 /* Set label and comment for graph */
3245 comment = g_strdup_printf("Key Input Sent: DOWN (%d)", pi->sequence);
3246 } else if(pi->key_val == 14) {
3247 /* Set label and comment for graph */
3248 comment = g_strdup_printf("Key Input Sent: RIGHT (%d)", pi->sequence);
3249 } else if(pi->key_val == 15) {
3250 if(pi->key_buffer != NULL){
3252 g_string_assign(g_tmp,pi->key_buffer);
3254 /* Manipulate the data */
3255 g_string_truncate(g_tmp,g_tmp->len-1);
3257 /* Insert new data */
3258 tmp_unistim_info->key_buffer = g_strdup(g_tmp->str);
3261 /* Set label and comment for graph */
3262 comment = g_strdup_printf("Key Input Sent: LEFT (%d)", pi->sequence);
3263 } else if(pi->key_val == 20) {
3264 /* User pressed the soft key 0 probably dial */
3265 comment = g_strdup_printf("Key Input Sent: S0 (%d)", pi->sequence);
3266 } else if(pi->key_val == 21) {
3267 /* User pressed the soft key 1 */
3268 comment = g_strdup_printf("Key Input Sent: S1 (%d)", pi->sequence);
3269 } else if(pi->key_val == 22) {
3270 /* User pressed the soft key 2 */
3271 /* On cs2k phones, soft key 2 is backspace. */
3272 if(pi->key_buffer != NULL) {
3275 g_string_assign(g_tmp,pi->key_buffer);
3277 /* Manipulate the data */
3278 g_string_truncate(g_tmp,g_tmp->len-1);
3280 /* Insert new data */
3281 tmp_unistim_info->key_buffer = g_strdup(g_tmp->str);
3284 /* add label and comment */
3285 comment = g_strdup_printf("Key Input Sent: S2 (%d)", pi->sequence);
3286 } else if(pi->key_val == 28) {
3287 /* User pressed something */
3288 comment = g_strdup_printf("Key Input Sent: Release (%d)", pi->sequence);
3289 } else if(pi->key_val == 23) {
3290 /* User pressed the soft key 3 */
3291 /* Cancel on cs2k so clear buffer */
3292 /* On mcs its config which will clear the buffer too */
3293 tmp_unistim_info->key_buffer = g_strdup("\n");
3295 /* User pressed something, set labels*/
3296 comment = g_strdup_printf("Key Input Sent: S3 (%d)", pi->sequence);
3297 } else if(pi->key_val == 27) {
3298 /* User pressed something */
3299 comment = g_strdup_printf("Key Input Sent: Hold (%d)", pi->sequence);
3300 } else if(pi->key_val == 29) {
3301 /* User pressed something */
3302 comment = g_strdup_printf("Key Input Sent: Mute (%d)", pi->sequence);
3303 } else if(pi->key_val == 30) {
3304 /* User pressed something */
3305 comment = g_strdup_printf("Key Input Sent: Headset (%d)", pi->sequence);
3306 } else if(pi->key_val == 31) {
3307 /* Handsfree button */
3308 comment = g_strdup_printf("Key Input Sent: Handsfree (%d)", pi->sequence);
3309 } else if(pi->key_val >= 32 && pi->key_val <= 56) {
3311 comment = g_strdup_printf("Key Input Sent: Prog%d (%d)", (pi->key_val & 31), pi->sequence);
3314 if(pi->key_val != -1) {
3316 frame_label = "KEY INPUT";
3318 if (comment == NULL)
3319 /* Ouch! What do you do!? */
3320 /* User pressed something */
3321 comment = g_strdup_printf("Key Input Sent: UNKNOWN - %d (%d)", pi->key_val, pi->sequence);
3323 /* add to the graph */
3324 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3329 if(pi->hook_state == 1) {
3331 /* Phone is off hook */
3332 frame_label = "OFF HOOK";
3333 comment = g_strdup_printf("Off Hook (%d)", pi->sequence);
3335 /* add to the graph */
3336 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3339 } else if(pi->hook_state == 0) {
3341 /* Phone is on hook */
3342 frame_label = "ON HOOK";
3343 comment = g_strdup_printf("On Hook (%d)", pi->sequence);
3345 /* add to the graph */
3346 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3352 /* Open stream was sent from server */
3353 if(pi->stream_connect == 1 && callsinfo != NULL) {
3356 /* Signifies the start of the call so set start_sec & start_usec */
3357 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3358 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3360 /* Local packets too */
3361 ++(callsinfo->npackets);
3363 /* increment the packets counter of all calls */
3364 ++(tapinfo->npackets);
3366 /* ?? means we're not quite sure if this is accurate. Since Unistim isn't a true
3367 Call control protocol, we can only guess at the destination by messing with
3369 if(tmp_unistim_info->key_buffer != NULL){
3370 callsinfo->to_identity = g_strdup_printf("?? %s",tmp_unistim_info->key_buffer);
3373 /* change sequence number for ACK detection */
3374 tmp_unistim_info->sequence = pi->sequence;
3376 /* State changes too */
3377 callsinfo->call_active_state = VOIP_ACTIVE;
3378 callsinfo->call_state = VOIP_IN_CALL;
3380 /* Add graph data */
3381 frame_label = "STREAM OPENED";
3382 comment = g_strdup_printf("Stream Opened (%d)",pi->sequence);
3384 /* add to the graph */
3385 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3387 } else if(pi->stream_connect == 1 && callsinfo == NULL) {
3389 /* Research indicates some nortel products initiate stream first
3390 * without keypresses. therefore creating this solely on a keypress is
3392 * Sometimes calls start immediately with open stream.
3394 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3395 callsinfo->call_active_state = VOIP_ACTIVE;
3396 callsinfo->call_state = VOIP_CALL_SETUP;
3397 callsinfo->from_identity=g_strdup("UNKNOWN");
3398 callsinfo->to_identity=g_strdup("UNKNOWN");
3399 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
3400 callsinfo->first_frame_num=pinfo->fd->num;
3401 callsinfo->selected=FALSE;
3403 /* Set this on init of struct so in case the call doesn't complete, we'll have a ref. */
3404 /* Otherwise if the call is completed we'll have the open/close streams to ref actual call duration */
3405 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3406 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3408 callsinfo->protocol=VOIP_UNISTIM;
3409 callsinfo->prot_info=g_malloc(sizeof(unistim_info_t));
3411 tmp_unistim_info = callsinfo->prot_info;
3413 /* Clear tap struct */
3414 tmp_unistim_info->rudp_type = 0;
3415 tmp_unistim_info->payload_type = 0;
3416 tmp_unistim_info->sequence = pi->sequence;
3417 tmp_unistim_info->termid = 0;
3418 tmp_unistim_info->key_val = -1;
3419 tmp_unistim_info->key_state = -1;
3420 tmp_unistim_info->hook_state = -1;
3421 tmp_unistim_info->stream_connect = -1;
3422 tmp_unistim_info->trans_connect = -1;
3423 tmp_unistim_info->set_termid = -1;
3424 tmp_unistim_info->string_data = NULL;
3425 tmp_unistim_info->key_buffer = NULL;
3427 COPY_ADDRESS(&(tmp_unistim_info->it_ip),&(pi->it_ip));
3428 COPY_ADDRESS(&(tmp_unistim_info->ni_ip),&(pi->ni_ip));
3429 tmp_unistim_info->it_port = pi->it_port;
3431 callsinfo->free_prot_info = g_free;
3432 callsinfo->npackets = 0;
3433 callsinfo->call_num = tapinfo->ncalls++;
3434 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3437 /* Signifies the start of the call so set start_sec & start_usec */
3438 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3439 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3441 /* Local packets too */
3442 ++(callsinfo->npackets);
3444 /* increment the packets counter of all calls */
3445 ++(tapinfo->npackets);
3447 /* ?? means we're not quite sure if this is accurate. Since Unistim isn't a true
3448 Call control protocol, we can only guess at the destination by messing with
3450 if(tmp_unistim_info->key_buffer != NULL){
3451 callsinfo->to_identity = g_strdup_printf("?? %s",tmp_unistim_info->key_buffer);
3454 /* change sequence number for ACK detection */
3455 tmp_unistim_info->sequence = pi->sequence;
3457 /* State changes too */
3458 callsinfo->call_active_state = VOIP_ACTIVE;
3459 callsinfo->call_state = VOIP_IN_CALL;
3461 /* Add graph data */
3462 frame_label = "STREAM OPENED";
3463 comment = g_strdup_printf("Stream Opened (%d)",pi->sequence);
3465 /* add to the graph */
3466 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3468 } else if(pi->stream_connect == 0 && callsinfo != NULL) {
3471 /* Set stop seconds + usec */
3472 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
3473 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
3474 callsinfo->last_frame_num=pinfo->fd->num;
3476 tmp_unistim_info->sequence = pi->sequence;
3478 if(callsinfo->call_state == VOIP_IN_CALL){
3479 callsinfo->call_active_state = VOIP_INACTIVE;
3480 callsinfo->call_state = VOIP_COMPLETED;
3482 callsinfo->call_state = VOIP_UNKNOWN;
3483 callsinfo->call_active_state = VOIP_INACTIVE;
3486 frame_label = "STREAM CLOSED";
3487 comment = g_strdup_printf("Stream Closed (%d)",pi->sequence);
3489 /* add to the graph */
3490 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3495 } else if(pi->rudp_type == 1 && callsinfo != NULL) {
3497 /* Only show acks for processed seq #s */
3498 if(tmp_unistim_info->sequence == pi->sequence) {
3500 frame_label = "ACK";
3501 comment = g_strdup_printf("ACK for sequence %d",pi->sequence);
3503 /* add to the graph */
3504 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3508 } else if(pi->rudp_type == 0 && callsinfo != NULL) {
3511 frame_label = "NAK";
3512 comment = g_strdup_printf("NAK for sequence %d",pi->sequence);
3514 /* add to the graph */
3515 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3522 tapinfo->redraw = TRUE;
3527 /****************************************************************************/
3529 /****************************************************************************/
3530 static gboolean have_unistim_tap_listener=FALSE;
3531 /****************************************************************************/
3533 unistim_calls_init_tap(void){
3535 GString *error_string;
3537 if(have_unistim_tap_listener==FALSE) {
3539 error_string = register_tap_listener("unistim", &(the_tapinfo_struct.unistim_dummy),
3541 voip_calls_dlg_reset,
3542 unistim_calls_packet,
3546 if (error_string != NULL) {
3547 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3548 "%s", error_string->str);
3549 g_string_free(error_string, TRUE);
3553 have_unistim_tap_listener=TRUE;
3557 /****************************************************************************/
3559 remove_tap_listener_unistim_calls(void)
3561 protect_thread_critical_region();
3562 remove_tap_listener(&(the_tapinfo_struct.unistim_dummy));
3563 unprotect_thread_critical_region();
3565 have_unistim_tap_listener=FALSE;
3568 /****************************************************************************/
3569 /* ***************************TAP for SKINNY **********************************/
3570 /****************************************************************************/
3572 /* Telecaster to tap-voip call state mapping */
3573 static const voip_call_state skinny_tap_voip_state[] = {
3592 skinny_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *skinny_info)
3594 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3596 voip_calls_info_t *callsinfo = NULL;
3598 const skinny_info_t *si = skinny_info;
3599 skinny_calls_info_t *tmp_skinnyinfo;
3602 if (si == NULL || (si->callId == 0 && si->passThruId == 0))
3604 /* check whether we already have this context in the list */
3605 list = g_list_first(tapinfo->callsinfo_list);
3608 voip_calls_info_t* tmp_listinfo = list->data;
3609 if (tmp_listinfo->protocol == VOIP_SKINNY){
3610 tmp_skinnyinfo = tmp_listinfo->prot_info;
3611 if (tmp_skinnyinfo->callId == si->callId ||
3612 tmp_skinnyinfo->callId == si->passThruId){
3613 callsinfo = (voip_calls_info_t*)(list->data);
3617 list = g_list_next (list);
3620 if (si->messId >= 256)
3621 phone = &(pinfo->dst);
3623 phone = &(pinfo->src);
3625 if (callsinfo==NULL){
3626 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3627 callsinfo->call_state = VOIP_NO_STATE;
3628 callsinfo->call_active_state = VOIP_ACTIVE;
3629 /* callsinfo->from_identity = g_strdup_printf("%s : %.8x", "Skinny", 1); */
3630 callsinfo->from_identity = g_strdup("");
3631 callsinfo->to_identity = g_strdup("");
3632 callsinfo->prot_info = g_malloc(sizeof(skinny_calls_info_t));
3633 callsinfo->free_prot_info = g_free;
3634 tmp_skinnyinfo = callsinfo->prot_info;
3635 tmp_skinnyinfo->callId = si->callId ? si->callId : si->passThruId;
3636 callsinfo->npackets = 1;
3637 callsinfo->first_frame_num=pinfo->fd->num;
3638 callsinfo->last_frame_num=pinfo->fd->num;
3640 COPY_ADDRESS(&(callsinfo->initial_speaker), phone);
3642 callsinfo->protocol = VOIP_SKINNY;
3643 callsinfo->call_num = tapinfo->ncalls++;
3644 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3645 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs;
3646 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
3647 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
3649 callsinfo->selected = FALSE;
3650 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3652 if (si->callingParty) {
3653 g_free(callsinfo->from_identity);
3654 callsinfo->from_identity = g_strdup(si->callingParty);
3656 if (si->calledParty) {
3657 g_free(callsinfo->to_identity);
3658 callsinfo->to_identity = g_strdup(si->calledParty);
3660 if ((si->callState > 0) && (si->callState < (sizeof(skinny_tap_voip_state)/sizeof(skinny_tap_voip_state[0]))))
3661 callsinfo->call_state = skinny_tap_voip_state[si->callState];
3663 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
3664 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
3665 callsinfo->last_frame_num=pinfo->fd->num;
3666 ++(callsinfo->npackets);
3671 comment = g_strdup_printf("CallId = %u, PTId = %u", si->callId, si->passThruId);
3673 comment = g_strdup_printf("CallId = %u, LineId = %u", si->callId, si->lineId);
3676 comment = g_strdup_printf("PTId = %u", si->passThruId);
3681 add_to_graph(tapinfo, pinfo, si->messageName, comment,
3682 callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3689 /****************************************************************************/
3691 /****************************************************************************/
3692 static gboolean have_skinny_tap_listener=FALSE;
3693 /****************************************************************************/
3695 skinny_calls_init_tap(void)
3697 GString *error_string;
3699 if(have_skinny_tap_listener==FALSE)
3701 /* don't register tap listener, if we have it already */
3702 /* we send an empty filter, to force a non null "tree" in the SKINNY dissector */
3703 error_string = register_tap_listener("skinny", &(the_tapinfo_struct.skinny_dummy), g_strdup(""),
3704 voip_calls_dlg_reset,
3705 skinny_calls_packet,
3708 if (error_string != NULL) {
3709 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3710 "%s", error_string->str);
3711 g_string_free(error_string, TRUE);
3714 have_skinny_tap_listener=TRUE;
3718 /****************************************************************************/
3720 remove_tap_listener_skinny_calls(void)
3722 protect_thread_critical_region();
3723 remove_tap_listener(&(the_tapinfo_struct.skinny_dummy));
3724 unprotect_thread_critical_region();
3726 have_skinny_tap_listener=FALSE;
3729 /****************************************************************************/
3730 /* ***************************TAP for IAX2 **********************************/
3731 /****************************************************************************/
3733 /* IAX2 to tap-voip call state mapping */
3734 static const voip_call_state tap_iax_voip_state[] = {
3736 VOIP_CALL_SETUP, /*NEW*/
3739 VOIP_COMPLETED, /*HANGUP*/
3740 VOIP_REJECTED, /*REJECT*/
3741 VOIP_RINGING, /*ACCEPT*/
3756 VOIP_CALL_SETUP, /*DIAL*/
3775 static void free_iax2_info(gpointer p) {
3776 iax2_info_t *ii = p;
3782 /****************************************************************************/
3783 /* whenever a IAX2 packet is seen by the tap listener */
3785 iax2_calls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *iax2_info)
3787 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3789 voip_calls_info_t *callsinfo = NULL;
3791 const iax2_info_t *ii = iax2_info;
3792 iax2_info_t *tmp_iax2info;
3795 if (ii == NULL || ii->ptype != IAX2_FULL_PACKET || (ii->scallno == 0 && ii->dcallno == 0))
3797 /* check whether we already have this context in the list */
3798 list = g_list_first(tapinfo->callsinfo_list);
3801 voip_calls_info_t* tmp_listinfo = list->data;
3802 if (tmp_listinfo->protocol == VOIP_IAX2){
3803 tmp_iax2info = tmp_listinfo->prot_info;
3804 if (tmp_iax2info->scallno == ii->scallno ||
3805 tmp_iax2info->scallno == ii->dcallno){
3806 callsinfo = (voip_calls_info_t*)(list->data);
3810 list = g_list_next (list);
3812 phone = &(pinfo->src);
3815 if (callsinfo==NULL){
3816 /* We only care about real calls, i.e., no registration stuff */
3817 if (ii->ftype != AST_FRAME_IAX || ii->csub != IAX_COMMAND_NEW)
3819 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3820 callsinfo->call_state = VOIP_NO_STATE;
3821 callsinfo->call_active_state = VOIP_ACTIVE;
3822 callsinfo->prot_info=g_malloc(sizeof(iax2_info_t));
3823 callsinfo->free_prot_info = free_iax2_info;
3824 tmp_iax2info = callsinfo->prot_info;
3826 tmp_iax2info->scallno = ii->scallno;
3827 if (tmp_iax2info->scallno == 0) tmp_iax2info->scallno = ii->dcallno;
3828 tmp_iax2info->callState = tap_iax_voip_state[ii->callState];
3830 callsinfo->npackets = 1;
3831 callsinfo->first_frame_num=pinfo->fd->num;
3832 callsinfo->last_frame_num=pinfo->fd->num;
3834 COPY_ADDRESS(&(callsinfo->initial_speaker), phone);
3835 callsinfo->from_identity = g_strdup(ii->callingParty);
3836 callsinfo->to_identity = g_strdup(ii->calledParty);
3838 callsinfo->protocol = VOIP_IAX2;
3839 callsinfo->call_num = tapinfo->ncalls++;
3840 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3841 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs;
3842 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
3843 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
3845 callsinfo->selected = FALSE;
3846 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3849 if ((ii->callState > 0) && (ii->callState < (sizeof(tap_iax_voip_state)/sizeof(tap_iax_voip_state[0]))))
3850 callsinfo->call_state = tap_iax_voip_state[ii->callState];
3852 callsinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
3853 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs;
3854 callsinfo->last_frame_num=pinfo->fd->num;
3855 ++(callsinfo->npackets);
3860 add_to_graph(tapinfo, pinfo, ii->messageName, comment,
3861 callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3868 /****************************************************************************/
3870 /****************************************************************************/
3871 static gboolean have_iax2_tap_listener=FALSE;
3872 /****************************************************************************/
3874 iax2_calls_init_tap(void)
3876 GString *error_string;
3878 if(have_iax2_tap_listener==FALSE)
3880 /* don't register tap listener, if we have it already */
3881 /* we send an empty filter, to force a non null "tree" in the IAX2 dissector */
3882 error_string = register_tap_listener("IAX2", &(the_tapinfo_struct.iax2_dummy), g_strdup(""),
3883 voip_calls_dlg_reset,
3887 if (error_string != NULL) {
3888 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s",
3890 g_string_free(error_string, TRUE);
3893 have_iax2_tap_listener=TRUE;
3897 /****************************************************************************/
3899 remove_tap_listener_iax2_calls(void)
3901 protect_thread_critical_region();
3902 remove_tap_listener(&(the_tapinfo_struct.iax2_dummy));
3903 unprotect_thread_critical_region();
3905 have_iax2_tap_listener=FALSE;
3908 /****************************************************************************/
3909 /* ***************************TAP for OTHER PROTOCOL **********************************/
3910 /****************************************************************************/
3913 VoIPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *VoIPinfo)
3915 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3916 voip_calls_info_t *callsinfo = NULL;
3917 voip_calls_info_t *tmp_listinfo;
3919 const voip_packet_info_t *pi = VoIPinfo;
3922 list = g_list_first(tapinfo->callsinfo_list);
3924 tmp_listinfo = list->data;
3925 if ( tmp_listinfo->protocol == VOIP_COMMON ) {
3926 if (!strcmp(pi->call_id, tmp_listinfo->call_id)) {
3927 callsinfo = (voip_calls_info_t*)(list->data);
3931 list = g_list_next(list);
3934 if (callsinfo == NULL) {
3935 callsinfo = g_malloc0(sizeof(voip_calls_info_t));
3936 callsinfo->call_active_state = pi->call_active_state;
3937 callsinfo->call_state = pi->call_state;
3938 callsinfo->call_id=g_strdup((pi->call_id)?pi->call_id:"");
3939 callsinfo->from_identity = g_strdup((pi->from_identity)?pi->from_identity:"");
3940 callsinfo->to_identity = g_strdup((pi->to_identity)?pi->to_identity:"");
3941 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
3942 callsinfo->selected=FALSE;
3943 callsinfo->first_frame_num=pinfo->fd->num;
3944 callsinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
3945 callsinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
3946 callsinfo->protocol=VOIP_COMMON;
3947 callsinfo->protocol_name=g_strdup((pi->protocol_name)?pi->protocol_name:"");
3948 callsinfo->call_comment=g_strdup((pi->call_comment)?pi->call_comment:"");
3949 callsinfo->prot_info=NULL;
3950 callsinfo->free_prot_info = NULL;
3952 callsinfo->call_num = tapinfo->ncalls++;
3953 callsinfo->npackets = 0;
3955 tapinfo->callsinfo_list = g_list_append(tapinfo->callsinfo_list, callsinfo);
3958 if (callsinfo != NULL) {
3959 callsinfo->call_active_state = pi->call_active_state;
3960 if ((callsinfo->call_state != VOIP_COMPLETED) && (pi->call_state == VOIP_COMPLETED))
3961 tapinfo->completed_calls++;
3962 if (pi->call_state != VOIP_NO_STATE)
3963 callsinfo->call_state = pi->call_state;
3964 if (pi->call_comment) {
3965 g_free(callsinfo->call_comment);
3966 callsinfo->call_comment=g_strdup(pi->call_comment);
3968 callsinfo->stop_sec=(gint32)(pinfo->fd->rel_ts.secs);
3969 callsinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
3970 callsinfo->last_frame_num=pinfo->fd->num;
3971 ++(callsinfo->npackets);
3972 ++(tapinfo->npackets);
3975 /* add to the graph */
3976 add_to_graph(tapinfo, pinfo, (pi->frame_label)?pi->frame_label:"VoIP msg", pi->frame_comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3978 tapinfo->redraw = TRUE;
3982 /****************************************************************************/
3983 static gboolean have_voip_tap_listener=FALSE;
3986 VoIPcalls_init_tap(void)
3988 GString *error_string;
3990 if(have_voip_tap_listener==FALSE)
3992 error_string = register_tap_listener("voip", &(the_tapinfo_struct.voip_dummy),
3994 voip_calls_dlg_reset,
3999 if (error_string != NULL) {
4000 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4001 "%s", error_string->str);
4002 g_string_free(error_string, TRUE);
4005 have_voip_tap_listener=TRUE;
4008 /****************************************************************************/
4010 remove_tap_listener_voip_calls(void)
4012 protect_thread_critical_region();
4013 remove_tap_listener(&(the_tapinfo_struct.voip_dummy));
4014 unprotect_thread_critical_region();
4016 have_voip_tap_listener=FALSE;
4020 /****************************************************************************/
4021 /* ***************************TAP for OTHER PROTOCOL **********************************/
4022 /****************************************************************************/
4024 /****************************************************************************/
4025 /* whenever a prot_ packet is seen by the tap listener */
4028 prot_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info _U_)
4030 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
4031 if (callsinfo!=NULL){
4032 callsinfo->stop_sec=pinfo->fd->rel_secs;
4033 callsinfo->stop_usec=pinfo->fd->rel_usecs;
4034 callsinfo->last_frame_num=pinfo->fd->num;
4035 ++(callsinfo->npackets);
4036 ++(tapinfo->npackets);
4039 tapinfo->redraw = TRUE;
4044 /****************************************************************************/
4046 static gboolean have_prot__tap_listener=FALSE;
4049 prot_calls_init_tap(void)
4051 GString *error_string;
4053 if(have_prot__tap_listener==FALSE)
4055 error_string = register_tap_listener("prot_", &(the_tapinfo_struct.prot__dummy),
4057 voip_calls_dlg_reset,
4062 if (error_string != NULL) {
4063 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4064 "%s", error_string->str);
4065 g_string_free(error_string, TRUE);
4068 have_prot__tap_listener=TRUE;
4072 /****************************************************************************/
4075 remove_tap_listener_prot__calls(void)
4077 protect_thread_critical_region();
4078 remove_tap_listener(&(the_tapinfo_struct.prot__dummy));
4079 unprotect_thread_critical_region();
4081 have_prot__tap_listener=FALSE;