add parameter dcerpc_info to PIDL_dissect_ipv?address()
[wireshark-wip.git] / ui / gtk / voip_calls.c
blob14356083cc37ecfc4dee4632137f183e2b41200c
1 /* voip_calls.c
2 * VoIP calls summary addition for Wireshark
4 * $Id$
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
36 #include "config.h"
37 #include <string.h>
39 #include <epan/epan.h>
40 #include <epan/packet.h>
41 #include <epan/tap.h>
42 #include <epan/tap-voip.h>
43 #include <epan/dissectors/packet-sip.h>
44 #include <epan/dissectors/packet-mtp3.h>
45 #include <epan/dissectors/packet-isup.h>
46 #include <epan/dissectors/packet-h225.h>
47 #include <epan/dissectors/packet-h245.h>
48 #include <epan/dissectors/packet-q931.h>
49 #include <epan/dissectors/packet-sdp.h>
50 #include <epan/dissectors/packet-mgcp.h>
51 #include <epan/dissectors/packet-actrace.h>
52 #include <epan/dissectors/packet-rtp.h>
53 #include <epan/dissectors/packet-rtp-events.h>
54 #include <epan/dissectors/packet-t38.h>
55 #include <epan/dissectors/packet-t30.h>
56 #include <epan/dissectors/packet-h248.h>
57 #include <epan/dissectors/packet-sccp.h>
58 #include <plugins/unistim/packet-unistim.h>
59 #include <epan/dissectors/packet-skinny.h>
60 #include <epan/dissectors/packet-iax2.h>
61 #include <epan/rtp_pt.h>
63 #include "ui/alert_box.h"
64 #include "ui/simple_dialog.h"
65 #include "ui/ui_util.h"
67 #include "ui/gtk/graph_analysis.h"
68 #include "ui/gtk/voip_calls.h"
69 #include "ui/gtk/voip_calls_dlg.h"
70 #include "ui/gtk/main.h"
72 #ifdef HAVE_LIBPORTAUDIO
73 #include "ui/gtk/rtp_player.h"
74 #endif /* HAVE_LIBPORTAUDIO */
77 #define DUMP_PTR1(p) printf("#=> %p\n",(void *)p)
78 #define DUMP_PTR2(p) printf("==> %p\n",(void *)p)
80 const char *voip_call_state_name[8]={
81 "",
82 "CALL SETUP",
83 "RINGING",
84 "IN CALL",
85 "CANCELLED",
86 "COMPLETED",
87 "REJECTED",
88 "UNKNOWN"
91 /* defines whether we can consider the call active */
92 const char *voip_protocol_name[]={
93 "SIP",
94 "ISUP",
95 "H.323",
96 "MGCP",
97 "AC_ISDN",
98 "AC_CAS",
99 "T.38",
100 "H.248",
101 "SCCP",
102 "BSSMAP",
103 "RANAP",
104 "UNISTIM",
105 "SKINNY",
106 "IAX2",
107 "VoIP"
110 typedef struct {
111 gchar *frame_label;
112 gchar *comment;
113 } graph_str;
115 #define H245_MAX 6
117 typedef struct {
118 guint32 frame_num;
119 gint8 labels_count;
120 graph_str labels[H245_MAX];
121 } h245_labels_t;
123 static h245_labels_t h245_labels;
125 /* defines a RTP stream */
126 typedef struct _voip_rtp_stream_info {
127 address src_addr;
128 guint16 src_port;
129 address dest_addr;
130 guint16 dest_port;
131 guint32 ssrc;
132 guint32 pt;
133 gchar *pt_str;
134 gboolean is_srtp;
135 guint32 npackets;
136 gboolean end_stream;
138 guint32 setup_frame_number; /* frame number of setup message */
139 /* The frame_data struct holds the frame number and timing information needed. */
140 frame_data *start_fd;
141 nstime_t start_rel_ts;
142 frame_data *stop_fd;
143 nstime_t stop_rel_ts;
144 gint32 rtp_event;
145 } voip_rtp_stream_info_t;
147 /****************************************************************************/
148 /* the one and only global voip_calls_tapinfo_t structure */
149 static voip_calls_tapinfo_t the_tapinfo_struct =
150 {0, NULL, {0}, 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, 0};
152 /* the one and only global voip_rtp_tapinfo_t structure */
153 static voip_rtp_tapinfo_t the_tapinfo_rtp_struct =
154 {0, NULL, 0, 0};
156 /****************************************************************************/
157 /* when there is a [re]reading of packet's */
158 void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
160 voip_calls_info_t *callsinfo;
161 voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
162 voip_rtp_stream_info_t *strinfo;
163 seq_analysis_item_t *graph_item;
164 GList *list;
166 #ifdef HAVE_LIBPORTAUDIO
167 /* reset the RTP player */
168 reset_rtp_player();
169 #endif
171 /* free the data items first */
172 list = g_list_first(tapinfo->callsinfo_list);
173 while (list)
175 callsinfo = (voip_calls_info_t *)list->data;
176 g_free(callsinfo->call_id);
177 g_free(callsinfo->from_identity);
178 g_free(callsinfo->to_identity);
179 g_free((void *)(callsinfo->initial_speaker.data));
180 g_free(callsinfo->protocol_name);
181 g_free(callsinfo->call_comment);
183 if (callsinfo->free_prot_info && callsinfo->prot_info)
184 callsinfo->free_prot_info(callsinfo->prot_info);
186 g_free(list->data);
187 list = g_list_next(list);
189 g_list_free(tapinfo->callsinfo_list);
190 /* free the SIP_HASH */
191 if(NULL!=tapinfo->callsinfo_hashtable[SIP_HASH])
192 g_hash_table_remove_all (tapinfo->callsinfo_hashtable[SIP_HASH]);
193 tapinfo->callsinfo_list = NULL;
194 tapinfo->ncalls = 0;
195 tapinfo->npackets = 0;
196 tapinfo->start_packets = 0;
197 tapinfo->completed_calls = 0;
198 tapinfo->rejected_calls = 0;
199 tapinfo->reversed= 0;
201 /* free the graph data items first */
202 if(NULL!=tapinfo->graph_analysis->ht)
203 g_hash_table_remove_all(tapinfo->graph_analysis->ht);
204 list = g_list_first(tapinfo->graph_analysis->list);
205 while (list)
207 graph_item = (seq_analysis_item_t *)list->data;
208 g_free(graph_item->frame_label);
209 g_free(graph_item->comment);
210 g_free((void *)graph_item->src_addr.data);
211 g_free((void *)graph_item->dst_addr.data);
212 g_free(graph_item->time_str);
213 g_free(list->data);
214 list = g_list_next(list);
216 g_list_free(tapinfo->graph_analysis->list);
217 tapinfo->graph_analysis->nconv = 0;
218 tapinfo->graph_analysis->list = NULL;
220 ++(tapinfo->launch_count);
222 /* free the strinfo data items first */
223 list = g_list_first(rtp_tapinfo->list);
224 while(list)
226 strinfo = (voip_rtp_stream_info_t *)list->data;
227 g_free(strinfo->pt_str);
228 list = g_list_next(list);
230 g_list_free(rtp_tapinfo->list);
231 rtp_tapinfo->list = NULL;
233 return;
236 /****************************************************************************/
237 void graph_analysis_data_init(void) {
238 the_tapinfo_struct.graph_analysis = (seq_analysis_info_t *)g_malloc(sizeof(seq_analysis_info_t));
239 the_tapinfo_struct.graph_analysis->nconv = 0;
240 the_tapinfo_struct.graph_analysis->list = NULL;
241 the_tapinfo_struct.graph_analysis->ht= g_hash_table_new(g_int_hash, g_int_equal);
244 /****************************************************************************/
245 /* Add a new item into the graph */
246 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)
248 seq_analysis_item_t *gai;
249 gchar time_str[COL_MAX_LEN];
251 gai = (seq_analysis_item_t *)g_malloc(sizeof(seq_analysis_item_t));
252 gai->fd = pinfo->fd;
253 COPY_ADDRESS(&(gai->src_addr),src_addr);
254 COPY_ADDRESS(&(gai->dst_addr),dst_addr);
256 gai->port_src=pinfo->srcport;
257 gai->port_dst=pinfo->destport;
258 if (frame_label != NULL)
259 gai->frame_label = g_strdup(frame_label);
260 else
261 gai->frame_label = g_strdup("");
263 if (comment != NULL)
264 gai->comment = g_strdup(comment);
265 else
266 gai->comment = g_strdup("");
267 gai->conv_num=call_num;
268 gai->line_style=line_style;
269 set_fd_time(cfile.epan, gai->fd, time_str);
270 gai->time_str = g_strdup(time_str);
271 gai->display=FALSE;
273 tapinfo->graph_analysis->list = g_list_prepend(tapinfo->graph_analysis->list, gai);
274 g_hash_table_insert(tapinfo->graph_analysis->ht, &gai->fd->num, gai);
278 /****************************************************************************/
279 /* Append str to frame_label and comment in a graph item */
280 /* return 0 if the frame_num is not in the graph list */
281 static int append_to_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
283 seq_analysis_item_t *gai=NULL;
284 gchar *frame_label = NULL;
285 gchar *comment = NULL;
287 if(NULL!=tapinfo->graph_analysis->ht)
288 gai=(seq_analysis_item_t *)g_hash_table_lookup(tapinfo->graph_analysis->ht, &frame_num);
289 if(gai) {
290 frame_label = gai->frame_label;
291 comment = gai->comment;
293 if (new_frame_label != NULL) {
294 gai->frame_label = g_strdup_printf("%s %s", frame_label, new_frame_label);
295 g_free(frame_label);
298 if (new_comment != NULL) {
299 gai->comment = g_strdup_printf("%s %s", comment, new_comment);
300 g_free(comment);
304 return gai? 1 : 0;
307 /****************************************************************************/
308 /* Change the frame_label and comment in a graph item if not NULL*/
309 /* return 0 if the frame_num is not in the graph list */
310 static int change_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
312 seq_analysis_item_t *gai=NULL;
313 gchar *frame_label = NULL;
314 gchar *comment = NULL;
316 if(NULL!=tapinfo->graph_analysis->ht)
317 gai=(seq_analysis_item_t *)g_hash_table_lookup(tapinfo->graph_analysis->ht, &frame_num);
318 if(gai) {
319 frame_label = gai->frame_label;
320 comment = gai->comment;
322 if (new_frame_label != NULL) {
323 gai->frame_label = g_strdup(new_frame_label);
324 g_free(frame_label);
327 if (new_comment != NULL) {
328 gai->comment = g_strdup(new_comment);
329 g_free(comment);
333 return gai? 1 : 0;
336 /****************************************************************************/
337 /* Change all the graph items with call_num to new_call_num */
338 static guint change_call_num_graph(voip_calls_tapinfo_t *tapinfo _U_, guint16 call_num, guint16 new_call_num)
340 seq_analysis_item_t *gai;
341 GList *list;
342 guint items_changed;
344 items_changed = 0;
345 list = g_list_first(tapinfo->graph_analysis->list);
346 while (list)
348 gai = (seq_analysis_item_t *)list->data;
349 if (gai->conv_num == call_num) {
350 gai->conv_num = new_call_num;
351 items_changed++;
353 list = g_list_next(list);
355 return items_changed;
358 /****************************************************************************/
359 /* Insert the item in the graph list */
360 static void insert_to_graph_t38(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, const gchar *frame_label, const gchar *comment, guint16 call_num, address *src_addr, address *dst_addr, guint16 line_style, guint32 frame_num)
362 seq_analysis_item_t *gai, *new_gai;
363 GList *list;
364 guint item_num;
365 gboolean inserted;
366 gchar time_str[COL_MAX_LEN];
368 new_gai = (seq_analysis_item_t *)g_malloc(sizeof(seq_analysis_item_t));
369 new_gai->fd = packet_list_get_row_data(frame_num);
370 COPY_ADDRESS(&(new_gai->src_addr),src_addr);
371 COPY_ADDRESS(&(new_gai->dst_addr),dst_addr);
373 new_gai->port_src=pinfo->srcport;
374 new_gai->port_dst=pinfo->destport;
375 if (frame_label != NULL)
376 new_gai->frame_label = g_strdup(frame_label);
377 else
378 new_gai->frame_label = g_strdup("");
380 if (comment != NULL)
381 new_gai->comment = g_strdup(comment);
382 else
383 new_gai->comment = g_strdup("");
384 new_gai->conv_num=call_num;
385 new_gai->line_style=line_style;
386 set_fd_time(cfile.epan, new_gai->fd, time_str);
387 new_gai->time_str = g_strdup(time_str);
388 new_gai->display=FALSE;
390 item_num = 0;
391 inserted = FALSE;
392 list = g_list_first(tapinfo->graph_analysis->list);
393 while (list)
395 gai = (seq_analysis_item_t *)list->data;
396 if (gai->fd->num > frame_num) {
397 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item_num);
398 g_hash_table_insert(tapinfo->graph_analysis->ht, &new_gai->fd->num, new_gai);
399 inserted = TRUE;
400 break;
402 list = g_list_next(list);
403 item_num++;
406 if (!inserted) {
407 tapinfo->graph_analysis->list = g_list_prepend(tapinfo->graph_analysis->list, new_gai);
408 g_hash_table_insert(tapinfo->graph_analysis->ht, &new_gai->fd->num, new_gai);
412 /****************************************************************************/
413 /* ***************************TAP for RTP Events*****************************/
414 /****************************************************************************/
416 static guint32 rtp_evt_frame_num = 0;
417 static guint8 rtp_evt = 0;
418 static gboolean rtp_evt_end = FALSE;
419 /*static guint32 rtp_evt_setup_frame_num = 0;*/
421 /****************************************************************************/
422 /* whenever a rtp event packet is seen by the tap listener */
423 static int
424 rtp_event_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *rtp_event_info)
426 const struct _rtp_event_info *pi = (const struct _rtp_event_info *)rtp_event_info;
428 /* do not consider RTP events packets without a setup frame */
429 if (pi->info_setup_frame_num == 0) {
430 return 0;
433 rtp_evt_frame_num = pinfo->fd->num;
434 rtp_evt = pi->info_rtp_evt;
435 rtp_evt_end = pi->info_end;
437 return 0;
440 /****************************************************************************/
441 static gboolean have_rtp_event_tap_listener=FALSE;
443 void
444 rtp_event_init_tap(void)
446 GString *error_string;
449 if(have_rtp_event_tap_listener==FALSE)
451 error_string = register_tap_listener("rtpevent", &(the_tapinfo_rtp_struct.rtp_event_dummy),
452 NULL,
454 NULL,
455 rtp_event_packet,
456 NULL
459 if (error_string != NULL) {
460 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
461 "%s", error_string->str);
462 g_string_free(error_string, TRUE);
463 exit(1);
465 have_rtp_event_tap_listener=TRUE;
469 /****************************************************************************/
471 void
472 remove_tap_listener_rtp_event(void)
474 remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_event_dummy));
476 have_rtp_event_tap_listener=FALSE;
479 /****************************************************************************/
480 /* ***************************TAP for RTP **********************************/
481 /****************************************************************************/
483 /****************************************************************************/
484 /* when there is a [re]reading of RTP packet's */
485 static void voip_rtp_reset(void *ptr _U_)
487 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
488 GList *list;
489 /* free the data items first */
490 list = g_list_first(tapinfo->list);
491 while (list)
493 g_free(list->data);
494 list = g_list_next(list);
496 g_list_free(tapinfo->list);
497 tapinfo->list = NULL;
498 tapinfo->nstreams = 0;
499 return;
502 /****************************************************************************/
503 /* whenever a RTP packet is seen by the tap listener */
504 static int
505 RTP_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void const *RTPinfo)
507 voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
508 voip_rtp_stream_info_t *tmp_listinfo;
509 voip_rtp_stream_info_t *strinfo = NULL;
510 GList *list;
511 struct _rtp_conversation_info *p_conv_data = NULL;
513 const struct _rtp_info *pi = (const struct _rtp_info *)RTPinfo;
515 /* do not consider RTP packets without a setup frame */
516 if (pi->info_setup_frame_num == 0) {
517 return 0;
520 /* add this RTP for future listening using the RTP Player*/
521 #ifdef HAVE_LIBPORTAUDIO
522 add_rtp_packet(pi, pinfo);
523 #endif
525 /* check whether we already have a RTP stream with this setup frame and ssrc in the list */
526 list = g_list_first(tapinfo->list);
527 while (list)
529 tmp_listinfo=(voip_rtp_stream_info_t *)list->data;
530 if ( (tmp_listinfo->setup_frame_number == pi->info_setup_frame_num)
531 && (tmp_listinfo->ssrc == pi->info_sync_src) && (tmp_listinfo->end_stream == FALSE)) {
532 /* if the payload type has changed, we mark the stream as finished to create a new one
533 this is to show multiple payload changes in the Graph for example for DTMF RFC2833 */
534 if ( tmp_listinfo->pt != pi->info_payload_type ) {
535 tmp_listinfo->end_stream = TRUE;
536 } else {
537 strinfo = (voip_rtp_stream_info_t*)(list->data);
538 break;
541 list = g_list_next(list);
544 /* if this is a duplicated RTP Event End, just return */
545 if ((rtp_evt_frame_num == pinfo->fd->num) && !strinfo && (rtp_evt_end == TRUE)) {
546 return 0;
549 /* not in the list? then create a new entry */
550 if (strinfo==NULL) {
551 strinfo = (voip_rtp_stream_info_t *)g_malloc(sizeof(voip_rtp_stream_info_t));
552 COPY_ADDRESS(&(strinfo->src_addr), &(pinfo->src));
553 strinfo->src_port = pinfo->srcport;
554 COPY_ADDRESS(&(strinfo->dest_addr), &(pinfo->dst));
555 strinfo->dest_port = pinfo->destport;
556 strinfo->ssrc = pi->info_sync_src;
557 strinfo->end_stream = FALSE;
558 strinfo->pt = pi->info_payload_type;
559 strinfo->pt_str = NULL;
560 strinfo->is_srtp = pi->info_is_srtp;
561 /* if it is dynamic payload, let use the conv data to see if it is defined */
562 if ( (strinfo->pt >= PT_UNDF_96) && (strinfo->pt <= PT_UNDF_127) ) {
563 /* Use existing packet info if available */
564 p_conv_data = (struct _rtp_conversation_info *)p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name("rtp"), 0);
565 if (p_conv_data && p_conv_data->rtp_dyn_payload) {
566 encoding_name_and_rate_t *encoding_name_and_rate_pt = NULL;
567 encoding_name_and_rate_pt = (encoding_name_and_rate_t *)g_hash_table_lookup(p_conv_data->rtp_dyn_payload, &strinfo->pt);
568 if (encoding_name_and_rate_pt) {
569 strinfo->pt_str = g_strdup(encoding_name_and_rate_pt->encoding_name);
573 if (!strinfo->pt_str) strinfo->pt_str = g_strdup(val_to_str_ext(strinfo->pt, &rtp_payload_type_short_vals_ext, "%u"));
574 strinfo->npackets = 0;
575 strinfo->start_fd = pinfo->fd;
576 strinfo->start_rel_ts = pinfo->rel_ts;
577 strinfo->setup_frame_number = pi->info_setup_frame_num;
578 strinfo->rtp_event = -1;
579 tapinfo->list = g_list_prepend(tapinfo->list, strinfo);
582 /* Add the info to the existing RTP stream */
583 strinfo->npackets++;
584 strinfo->stop_fd = pinfo->fd;
585 strinfo->stop_rel_ts = pinfo->rel_ts;
587 /* process RTP Event */
588 if (rtp_evt_frame_num == pinfo->fd->num) {
589 strinfo->rtp_event = rtp_evt;
590 if (rtp_evt_end == TRUE) {
591 strinfo->end_stream = TRUE;
595 the_tapinfo_struct.redraw = TRUE;
597 return 1;
600 /****************************************************************************/
601 /* whenever a redraw in the RTP tap listener */
602 static void RTP_packet_draw(void *prs _U_)
604 voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
605 GList *rtp_streams_list;
606 voip_rtp_stream_info_t *rtp_listinfo;
607 /* GList *voip_calls_graph_list; */
608 seq_analysis_item_t *gai;
609 seq_analysis_item_t *new_gai;
610 guint16 conv_num;
611 guint32 duration;
612 gchar time_str[COL_MAX_LEN];
614 /* add each rtp stream to the graph */
615 rtp_streams_list = g_list_first(rtp_tapinfo->list);
616 while (rtp_streams_list)
618 rtp_listinfo = (voip_rtp_stream_info_t *)rtp_streams_list->data;
620 /* using the setup frame number of the RTP stream, we get the call number that it belongs to*/
621 /* voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list); */
623 gai = (seq_analysis_item_t *)g_hash_table_lookup(the_tapinfo_struct.graph_analysis->ht, &rtp_listinfo->setup_frame_number);
624 if(gai != NULL) {
625 /* Found the setup frame*/
626 conv_num = gai->conv_num;
627 /* if RTP was already in the Graph, just update the comment information */
628 gai = (seq_analysis_item_t *)g_hash_table_lookup(the_tapinfo_struct.graph_analysis->ht, &rtp_listinfo->start_fd->num);
629 if(gai != NULL) {
630 duration = (guint32)(nstime_to_msec(&rtp_listinfo->stop_rel_ts) - nstime_to_msec(&rtp_listinfo->start_rel_ts));
631 g_free(gai->comment);
632 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/1000,(duration%1000), rtp_listinfo->ssrc);
635 }else {
636 new_gai = (seq_analysis_item_t *)g_malloc(sizeof(seq_analysis_item_t));
637 new_gai->fd = rtp_listinfo->start_fd;
638 COPY_ADDRESS(&(new_gai->src_addr),&(rtp_listinfo->src_addr));
639 COPY_ADDRESS(&(new_gai->dst_addr),&(rtp_listinfo->dest_addr));
640 new_gai->port_src = rtp_listinfo->src_port;
641 new_gai->port_dst = rtp_listinfo->dest_port;
642 duration = (guint32)(nstime_to_msec(&rtp_listinfo->stop_rel_ts) - nstime_to_msec(&rtp_listinfo->start_rel_ts));
643 new_gai->frame_label = g_strdup_printf("%s (%s) %s",
644 (rtp_listinfo->is_srtp)?"SRTP":"RTP",
645 rtp_listinfo->pt_str,
646 (rtp_listinfo->rtp_event == -1)?
647 "":val_to_str_const(rtp_listinfo->rtp_event, rtp_event_type_values, "Unknown RTP Event"));
648 new_gai->comment = g_strdup_printf("%s Num packets:%u Duration:%u.%03us SSRC:0x%X",
649 (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->npackets,
650 duration/1000,(duration%1000), rtp_listinfo->ssrc);
651 new_gai->conv_num = conv_num;
652 set_fd_time(cfile.epan, new_gai->fd, time_str);
653 new_gai->time_str = g_strdup(time_str);
654 new_gai->display=FALSE;
655 new_gai->line_style = 2; /* the arrow line will be 2 pixels width */
656 the_tapinfo_struct.graph_analysis->list = g_list_prepend(the_tapinfo_struct.graph_analysis->list, new_gai);
657 g_hash_table_insert(the_tapinfo_struct.graph_analysis->ht, &rtp_listinfo->start_fd, new_gai);
660 rtp_streams_list = g_list_next(rtp_streams_list);
661 }/* while (rtp_streams_list) */
663 #if 0
664 static void RTP_packet_draw(void *prs _U_)
666 voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
667 GList *rtp_streams_list;
668 voip_rtp_stream_info_t *rtp_listinfo;
669 GList *voip_calls_graph_list;
670 guint item;
671 seq_analysis_item_t *gai;
672 seq_analysis_item_t *new_gai;
673 guint16 conv_num;
674 guint32 duration;
675 gchar time_str[COL_MAX_LEN];
677 /* add each rtp stream to the graph */
678 rtp_streams_list = g_list_first(rtp_tapinfo->list);
679 while (rtp_streams_list)
681 rtp_listinfo = rtp_streams_list->data;
683 /* using the setup frame number of the RTP stream, we get the call number that it belongs to*/
684 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
685 while (voip_calls_graph_list)
687 gai = voip_calls_graph_list->data;
688 conv_num = gai->conv_num;
689 /* if we get the setup frame number, then get the time position to graph the RTP arrow */
690 if (rtp_listinfo->setup_frame_number == gai->fd->num) {
691 /* look again from the beginning because there are cases where the Setup frame is after the RTP */
692 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
693 item = 0;
694 while(voip_calls_graph_list) {
695 gai = voip_calls_graph_list->data;
696 /* if RTP was already in the Graph, just update the comment information */
697 if (rtp_listinfo->start_fd->num == gai->fd->num) {
698 duration = (guint32)(nstime_to_msec(&rtp_listinfo->stop_fd->rel_ts) - nstime_to_msec(&rtp_listinfo->start_fd->rel_ts));
699 g_free(gai->comment);
700 gai->comment = g_strdup_printf("%s Num packets:%u Duration:%u.%03us SSRC:0x%X",
701 (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->npackets,
702 duration/1000,(duration%1000), rtp_listinfo->ssrc);
703 break;
706 /* 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 */
707 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
708 if (!voip_calls_graph_list) item++;
710 /* add the RTP item to the graph if was not there*/
711 if (rtp_listinfo->start_fd->num<gai->fd->num || !voip_calls_graph_list) {
712 new_gai = g_malloc(sizeof(seq_analysis_item_t));
713 new_gai->fd = rtp_listinfo->start_fd;
714 COPY_ADDRESS(&(new_gai->src_addr),&(rtp_listinfo->src_addr));
715 COPY_ADDRESS(&(new_gai->dst_addr),&(rtp_listinfo->dest_addr));
716 new_gai->port_src = rtp_listinfo->src_port;
717 new_gai->port_dst = rtp_listinfo->dest_port;
718 duration = (guint32)(nstime_to_msec(&rtp_listinfo->stop_fd->rel_ts) - nstime_to_msec(&rtp_listinfo->start_fd->rel_ts));
719 new_gai->frame_label = g_strdup_printf("%s (%s) %s",
720 (rtp_listinfo->is_srtp)?"SRTP":"RTP",
721 rtp_listinfo->pt_str,
722 (rtp_listinfo->rtp_event == -1)?
723 "":val_to_str_const(rtp_listinfo->rtp_event, rtp_event_type_values, "Unknown RTP Event"));
724 new_gai->comment = g_strdup_printf("%s Num packets:%u Duration:%u.%03us SSRC:0x%X",
725 (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->npackets,
726 duration/1000,(duration%1000), rtp_listinfo->ssrc);
727 new_gai->conv_num = conv_num;
728 set_fd_time(cfile.epan, new_gai->fd, time_str);
729 new_gai->time_str = g_strdup(time_str);
730 new_gai->display=FALSE;
731 new_gai->line_style = 2; /* the arrow line will be 2 pixels width */
732 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item);
733 break;
735 if (voip_calls_graph_list) item++;
737 break;
739 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
741 rtp_streams_list = g_list_next(rtp_streams_list);
744 #endif
745 static gboolean have_RTP_tap_listener=FALSE;
746 /****************************************************************************/
747 void
748 rtp_init_tap(void)
750 GString *error_string;
752 if(have_RTP_tap_listener==FALSE)
754 /* don't register tap listener, if we have it already */
755 error_string = register_tap_listener("rtp", &(the_tapinfo_rtp_struct.rtp_dummy), NULL,
757 voip_rtp_reset,
758 RTP_packet,
759 RTP_packet_draw
761 if (error_string != NULL) {
762 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
763 "%s", error_string->str);
764 g_string_free(error_string, TRUE);
765 exit(1);
767 have_RTP_tap_listener=TRUE;
771 /****************************************************************************/
772 void
773 remove_tap_listener_rtp(void)
775 remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_dummy));
777 have_RTP_tap_listener=FALSE;
780 /****************************************************************************/
781 /******************************TAP for T38 **********************************/
782 /****************************************************************************/
784 /****************************************************************************/
785 /* whenever a T38 packet is seen by the tap listener */
786 static int
787 T38_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *T38info)
789 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
791 voip_calls_info_t *callsinfo = NULL;
792 voip_calls_info_t *tmp_listinfo;
793 GList *voip_calls_graph_list;
794 GList *list;
795 gchar *frame_label = NULL;
796 gchar *comment = NULL;
797 seq_analysis_item_t *tmp_gai, *gai = NULL;
798 guint16 line_style = 2;
799 double duration;
800 int conv_num = -1;
802 const t38_packet_info *pi = (const t38_packet_info *)T38info;
804 if (pi->setup_frame_number != 0) {
805 /* using the setup frame number of the T38 packet, we get the call number that it belongs */
806 voip_calls_graph_list = g_list_first(tapinfo->graph_analysis->list);
807 while (voip_calls_graph_list)
809 tmp_gai = (seq_analysis_item_t *)voip_calls_graph_list->data;
810 if (pi->setup_frame_number == tmp_gai->fd->num) {
811 gai = tmp_gai;
812 break;
814 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
816 if (gai) conv_num = (int) gai->conv_num;
819 /* 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
820 * have the associated Voip calls. It probably means the the packet was decoded using the default t38 port, or using "Decode as.."
821 * in this case we create a "voip" call that only have t38 media (no signaling)
822 * OR if we have not found the Setup message in the graph.
824 if ( (pi->setup_frame_number == 0) || (gai == NULL) ) {
825 /* check whether we already have a call with these parameters in the list */
826 list = g_list_first(tapinfo->callsinfo_list);
827 while (list)
829 tmp_listinfo=(voip_calls_info_t *)list->data;
830 if (tmp_listinfo->protocol == MEDIA_T38) {
831 callsinfo = (voip_calls_info_t*)(list->data);
832 break;
834 list = g_list_next (list);
837 /* not in the list? then create a new entry */
838 if (callsinfo==NULL) {
839 callsinfo = (voip_calls_info_t *)g_malloc0(sizeof(voip_calls_info_t));
840 callsinfo->call_active_state = VOIP_ACTIVE;
841 callsinfo->call_state = VOIP_UNKNOWN;
842 callsinfo->from_identity=g_strdup("T38 Media only");
843 callsinfo->to_identity=g_strdup("T38 Media only");
844 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
845 callsinfo->selected=FALSE;
846 callsinfo->start_fd = pinfo->fd;
847 callsinfo->start_rel_ts = pinfo->rel_ts;
848 callsinfo->protocol=MEDIA_T38;
849 callsinfo->prot_info=NULL;
850 callsinfo->free_prot_info = NULL;
851 callsinfo->npackets = 0;
852 callsinfo->call_num = tapinfo->ncalls++;
853 tapinfo->callsinfo_list = g_list_prepend(tapinfo->callsinfo_list, callsinfo);
855 callsinfo->stop_fd = pinfo->fd;
856 callsinfo->stop_rel_ts = pinfo->rel_ts;
857 ++(callsinfo->npackets);
858 /* increment the packets counter of all calls */
859 ++(tapinfo->npackets);
861 conv_num = (int) callsinfo->call_num;
864 /* at this point we should have found the call num for this t38 packets belong */
865 if (conv_num == -1) {
866 return 0;
869 /* add the item to the graph list */
870 if (pi->type_msg == 0) { /* 0=t30-indicator */
871 frame_label = g_strdup(val_to_str(pi->t30ind_value, t38_T30_indicator_vals, "Ukn (0x%02X)") );
872 comment = g_strdup_printf("t38:t30 Ind:%s",val_to_str(pi->t30ind_value, t38_T30_indicator_vals, "Ukn (0x%02X)") );
873 line_style = 1;
874 } else if (pi->type_msg == 1) { /* 1=data */
875 switch(pi->Data_Field_field_type_value) {
876 case 0: /* hdlc-data */
877 break;
878 case 2: /* hdlc-fcs-OK */
879 case 4: /* hdlc-fcs-OK-sig-end */
880 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);
881 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)"));
882 break;
883 case 3: /* hdlc-fcs-BAD */
884 case 5: /* hdlc-fcs-BAD-sig-end */
885 frame_label = g_strdup(pi->Data_Field_field_type_value == 3 ? "fcs-BAD" : "fcs-BAD-sig-end");
886 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");
887 break;
888 case 7: /* t4-non-ecm-sig-end */
889 duration = nstime_to_sec(&pinfo->rel_ts) - pi->time_first_t4_data;
890 frame_label = g_strdup_printf("t4-non-ecm-data:%s",val_to_str(pi->data_value, t38_T30_data_vals, "Ukn (0x%02X)") );
891 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 );
892 insert_to_graph_t38(tapinfo, pinfo, frame_label, comment, (guint16)conv_num, &(pinfo->src), &(pinfo->dst), line_style, pi->frame_num_first_t4_data);
893 break;
897 if (frame_label && !(pi->Data_Field_field_type_value == 7 && pi->type_msg == 1)) {
898 add_to_graph(tapinfo, pinfo, frame_label, comment, (guint16)conv_num, &(pinfo->src), &(pinfo->dst), line_style);
901 g_free(comment);
902 g_free(frame_label);
904 tapinfo->redraw = TRUE;
906 return 1; /* refresh output */
909 static gboolean have_T38_tap_listener=FALSE;
910 /****************************************************************************/
911 void
912 t38_init_tap(void)
914 GString *error_string;
916 if(have_T38_tap_listener==FALSE)
918 /* don't register tap listener, if we have it already */
919 error_string = register_tap_listener("t38", &(the_tapinfo_struct.t38_dummy), NULL,
921 voip_calls_dlg_reset,
922 T38_packet,
923 voip_calls_dlg_draw
925 if (error_string != NULL) {
926 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
927 "%s", error_string->str);
928 g_string_free(error_string, TRUE);
929 exit(1);
931 have_T38_tap_listener=TRUE;
935 /****************************************************************************/
936 void
937 remove_tap_listener_t38(void)
939 remove_tap_listener(&(the_tapinfo_struct.t38_dummy));
941 have_T38_tap_listener=FALSE;
945 /****************************************************************************/
946 static gchar *sdp_summary = NULL;
947 static guint32 sdp_frame_num = 0;
949 /****************************************************************************/
950 /* ***************************TAP for SIP **********************************/
951 /****************************************************************************/
954 static void free_sip_info(gpointer p) {
955 sip_calls_info_t *si = (sip_calls_info_t *)p;
957 g_free(si->call_identifier);
958 g_free(si);
961 /****************************************************************************/
962 /* whenever a SIP packet is seen by the tap listener */
963 static int
964 SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SIPinfo)
966 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
967 /* we just take note of the ISUP data here; when we receive the MTP3 part everything will
968 be compared with existing calls */
970 voip_calls_info_t *callsinfo = NULL;
971 sip_calls_info_t *tmp_sipinfo = NULL;
972 address tmp_src, tmp_dst;
973 gchar *frame_label = NULL;
974 gchar *comment = NULL;
975 gchar *key=NULL;
977 const sip_info_value_t *pi = (const sip_info_value_t *)SIPinfo;
979 /* do not consider packets without call_id */
980 if (pi->tap_call_id ==NULL) {
981 return 0;
983 key=pi->tap_call_id;
984 /* init the hash table */
985 if(NULL==tapinfo->callsinfo_hashtable[SIP_HASH]) {
986 /* TODO: check how efficient g_str_hash is for sip call ids */
987 tapinfo->callsinfo_hashtable[SIP_HASH]=g_hash_table_new_full(g_str_hash,
988 g_str_equal,
989 NULL, /* key_destroy_func */
990 NULL);/* value_destroy_func */
992 /* search the call information in the SIP_HASH */
993 callsinfo = (voip_calls_info_t *)g_hash_table_lookup(tapinfo->callsinfo_hashtable[SIP_HASH], key);
995 /* not in the hash? then create a new entry if the message is INVITE -i.e. if this session is a call*/
996 if ((callsinfo==NULL) &&(pi->request_method!=NULL)) {
997 if (strcmp(pi->request_method,"INVITE")==0) {
998 callsinfo = (voip_calls_info_t *)g_malloc0(sizeof(voip_calls_info_t));
999 callsinfo->call_active_state = VOIP_ACTIVE;
1000 callsinfo->call_state = VOIP_CALL_SETUP;
1001 callsinfo->from_identity=g_strdup(pi->tap_from_addr);
1002 callsinfo->to_identity=g_strdup(pi->tap_to_addr);
1003 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
1004 callsinfo->selected=FALSE;
1005 callsinfo->start_fd=pinfo->fd;
1006 callsinfo->start_rel_ts=pinfo->rel_ts;
1007 callsinfo->protocol=VOIP_SIP;
1008 callsinfo->prot_info=g_malloc(sizeof(sip_calls_info_t));
1009 callsinfo->free_prot_info = free_sip_info;
1010 tmp_sipinfo = (sip_calls_info_t *)callsinfo->prot_info;
1011 tmp_sipinfo->call_identifier = g_strdup(pi->tap_call_id);
1012 tmp_sipinfo->sip_state = SIP_INVITE_SENT;
1013 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
1014 callsinfo->npackets = 0;
1015 callsinfo->call_num = tapinfo->ncalls++;
1016 tapinfo->callsinfo_list = g_list_prepend(tapinfo->callsinfo_list, callsinfo);
1017 /* insert the call information in the SIP_HASH */
1018 g_hash_table_insert(tapinfo->callsinfo_hashtable[SIP_HASH],
1019 tmp_sipinfo->call_identifier, callsinfo);
1023 if (callsinfo!=NULL) {
1024 tmp_sipinfo = (sip_calls_info_t *)callsinfo->prot_info;
1026 /* let's analyze the call state */
1028 COPY_ADDRESS(&(tmp_src), &(pinfo->src));
1029 COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
1031 if (pi->request_method == NULL) {
1032 frame_label = g_strdup_printf("%u %s", pi->response_code, pi->reason_phrase );
1033 comment = g_strdup("SIP Status");
1035 if ((tmp_sipinfo && pi->tap_cseq_number == tmp_sipinfo->invite_cseq)&&(ADDRESSES_EQUAL(&tmp_dst,&(callsinfo->initial_speaker)))) {
1036 if ((pi->response_code > 199) && (pi->response_code<300) && (tmp_sipinfo->sip_state == SIP_INVITE_SENT)) {
1037 tmp_sipinfo->sip_state = SIP_200_REC;
1039 else if ((pi->response_code>299)&&(tmp_sipinfo->sip_state == SIP_INVITE_SENT)) {
1040 callsinfo->call_state = VOIP_REJECTED;
1041 tapinfo->rejected_calls++;
1046 else {
1047 frame_label = g_strdup(pi->request_method);
1049 if ((strcmp(pi->request_method,"INVITE")==0)&&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))) {
1050 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
1051 callsinfo->call_state = VOIP_CALL_SETUP;
1052 comment = g_strdup_printf("SIP From: %s To:%s", callsinfo->from_identity, callsinfo->to_identity);
1054 else if ((strcmp(pi->request_method,"ACK")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
1055 &&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))&&(tmp_sipinfo->sip_state==SIP_200_REC)
1056 &&(callsinfo->call_state == VOIP_CALL_SETUP)) {
1057 callsinfo->call_state = VOIP_IN_CALL;
1058 comment = g_strdup("SIP Request");
1060 else if (strcmp(pi->request_method,"BYE")==0) {
1061 callsinfo->call_state = VOIP_COMPLETED;
1062 tapinfo->completed_calls++;
1063 comment = g_strdup("SIP Request");
1065 else if ((strcmp(pi->request_method,"CANCEL")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
1066 &&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))&&(callsinfo->call_state==VOIP_CALL_SETUP)) {
1067 callsinfo->call_state = VOIP_CANCELLED;
1068 tmp_sipinfo->sip_state = SIP_CANCEL_SENT;
1069 comment = g_strdup("SIP Request");
1070 } else {
1071 comment = g_strdup("SIP Request");
1075 callsinfo->stop_fd = pinfo->fd;
1076 callsinfo->stop_rel_ts = pinfo->rel_ts;
1077 ++(callsinfo->npackets);
1078 /* increment the packets counter of all calls */
1079 ++(tapinfo->npackets);
1081 /* add to the graph */
1082 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1083 g_free(comment);
1084 g_free(frame_label);
1085 g_free((void *)tmp_src.data);
1086 g_free((void *)tmp_dst.data);
1088 /* add SDP info if apply */
1089 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ) {
1090 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
1091 g_free(sdp_summary);
1092 sdp_summary = NULL;
1096 tapinfo->redraw = TRUE;
1098 return 1; /* refresh output */
1102 /****************************************************************************/
1103 voip_calls_tapinfo_t* voip_calls_get_info(void)
1105 return &the_tapinfo_struct;
1108 /****************************************************************************/
1109 /* TAP INTERFACE */
1110 /****************************************************************************/
1111 static gboolean have_SIP_tap_listener=FALSE;
1112 /****************************************************************************/
1113 void
1114 sip_calls_init_tap(void)
1116 GString *error_string;
1118 if(have_SIP_tap_listener==FALSE)
1120 /* don't register tap listener, if we have it already */
1121 error_string = register_tap_listener("sip", &(the_tapinfo_struct.sip_dummy), NULL,
1123 voip_calls_dlg_reset,
1124 SIPcalls_packet,
1125 voip_calls_dlg_draw
1127 if (error_string != NULL) {
1128 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1129 "%s", error_string->str);
1130 g_string_free(error_string, TRUE);
1131 exit(1);
1133 have_SIP_tap_listener=TRUE;
1137 /****************************************************************************/
1138 void
1139 remove_tap_listener_sip_calls(void)
1141 remove_tap_listener(&(the_tapinfo_struct.sip_dummy));
1143 have_SIP_tap_listener=FALSE;
1146 /****************************************************************************/
1147 /* ***************************TAP for ISUP **********************************/
1148 /****************************************************************************/
1150 static guint32 mtp3_opc, mtp3_dpc;
1151 static guint8 mtp3_ni;
1152 static guint32 mtp3_frame_num;
1155 /****************************************************************************/
1156 /* whenever a isup_ packet is seen by the tap listener */
1157 static int
1158 isup_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *isup_info _U_)
1160 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1161 voip_calls_info_t *tmp_listinfo;
1162 voip_calls_info_t *callsinfo = NULL;
1163 isup_calls_info_t *tmp_isupinfo;
1164 gboolean found = FALSE;
1165 gboolean forward = FALSE;
1166 gboolean right_pair;
1167 GList *list;
1168 gchar *frame_label = NULL;
1169 gchar *comment = NULL;
1171 /*voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct; unused */
1172 const isup_tap_rec_t *pi = (const isup_tap_rec_t *)isup_info;
1174 /* check if the lower layer is MTP matching the frame number */
1175 if (mtp3_frame_num != pinfo->fd->num) return 0;
1177 /* check whether we already have a call with these parameters in the list */
1178 list = g_list_first(tapinfo->callsinfo_list);
1179 while (list)
1181 right_pair = TRUE;
1182 tmp_listinfo=(voip_calls_info_t *)list->data;
1183 if ((tmp_listinfo->protocol == VOIP_ISUP)&&(tmp_listinfo->call_active_state==VOIP_ACTIVE)) {
1184 tmp_isupinfo = (isup_calls_info_t *)tmp_listinfo->prot_info;
1185 if ((tmp_isupinfo->cic == pinfo->circuit_id)&&(tmp_isupinfo->ni == mtp3_ni)) {
1186 if ((tmp_isupinfo->opc == mtp3_opc)&&(tmp_isupinfo->dpc == mtp3_dpc)) {
1187 forward = TRUE;
1188 } else if ((tmp_isupinfo->dpc == mtp3_opc)&&(tmp_isupinfo->opc == mtp3_dpc)) {
1189 forward = FALSE;
1190 } else {
1191 right_pair = FALSE;
1194 if (right_pair) {
1195 /* if there is an IAM for a call that is not in setup state, that means the previous call in the same
1196 cic is no longer active */
1197 if (tmp_listinfo->call_state == VOIP_CALL_SETUP) {
1198 found = TRUE;
1199 } else if (pi->message_type != 1) {
1200 found = TRUE;
1201 } else {
1202 tmp_listinfo->call_active_state=VOIP_INACTIVE;
1206 if (found) {
1207 callsinfo = (voip_calls_info_t*)(list->data);
1208 break;
1212 list = g_list_next (list);
1215 /* not in the list? then create a new entry if the message is IAM
1216 -i.e. if this session is a call*/
1219 if ((callsinfo==NULL) &&(pi->message_type==1)) {
1220 callsinfo = (voip_calls_info_t *)g_malloc0(sizeof(voip_calls_info_t));
1221 callsinfo->call_active_state = VOIP_ACTIVE;
1222 callsinfo->call_state = VOIP_UNKNOWN;
1223 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
1224 callsinfo->selected=FALSE;
1225 callsinfo->start_fd=pinfo->fd;
1226 callsinfo->start_rel_ts=pinfo->rel_ts;
1227 callsinfo->protocol=VOIP_ISUP;
1228 if (pi->calling_number!=NULL) {
1229 callsinfo->from_identity=g_strdup(pi->calling_number);
1231 if (pi->called_number!=NULL) {
1232 callsinfo->to_identity=g_strdup(pi->called_number);
1234 callsinfo->prot_info=g_malloc(sizeof(isup_calls_info_t));
1235 callsinfo->free_prot_info = g_free;
1236 tmp_isupinfo=(isup_calls_info_t *)callsinfo->prot_info;
1237 tmp_isupinfo->opc = mtp3_opc;
1238 tmp_isupinfo->dpc = mtp3_dpc;
1239 tmp_isupinfo->ni = mtp3_ni;
1240 tmp_isupinfo->cic = pinfo->circuit_id;
1241 callsinfo->npackets = 0;
1242 callsinfo->call_num = tapinfo->ncalls++;
1243 tapinfo->callsinfo_list = g_list_prepend(tapinfo->callsinfo_list, callsinfo);
1247 if (callsinfo!=NULL) {
1248 callsinfo->stop_fd = pinfo->fd;
1249 callsinfo->stop_rel_ts = pinfo->rel_ts;
1250 ++(callsinfo->npackets);
1252 /* Let's analyze the call state */
1254 frame_label = g_strdup(val_to_str_ext_const(pi->message_type, &isup_message_type_value_acro_ext, "Unknown"));
1256 if (callsinfo->npackets == 1) { /* this is the first packet, that must be an IAM */
1258 if ((pi->calling_number!=NULL)&&(pi->called_number !=NULL)) {
1259 comment = g_strdup_printf("Call from %s to %s",
1260 pi->calling_number, pi->called_number);
1262 } else if (callsinfo->npackets == 2) { /* in the second packet we show the SPs */
1263 if (forward) {
1264 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
1265 mtp3_ni, mtp3_opc,
1266 mtp3_ni, mtp3_dpc, pinfo->circuit_id);
1267 } else {
1268 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
1269 mtp3_ni, mtp3_dpc,
1270 mtp3_ni, mtp3_opc, pinfo->circuit_id);
1275 switch(pi->message_type) {
1276 case 1: /* IAM */
1277 callsinfo->call_state=VOIP_CALL_SETUP;
1278 break;
1279 case 7: /* CONNECT */
1280 case 9: /* ANSWER */
1281 callsinfo->call_state=VOIP_IN_CALL;
1282 break;
1283 case 12: /* RELEASE */
1284 if (callsinfo->call_state==VOIP_CALL_SETUP) {
1285 if (forward) {
1286 callsinfo->call_state=VOIP_CANCELLED;
1288 else {
1289 callsinfo->call_state=VOIP_REJECTED;
1290 tapinfo->rejected_calls++;
1293 else if (callsinfo->call_state == VOIP_IN_CALL) {
1294 callsinfo->call_state = VOIP_COMPLETED;
1295 tapinfo->completed_calls++;
1297 comment = g_strdup_printf("Cause %i - %s",
1298 pi->cause_value,
1299 val_to_str_ext_const(pi->cause_value, &q931_cause_code_vals_ext, "(Unknown)"));
1300 break;
1303 /* increment the packets counter of all calls */
1304 ++(tapinfo->npackets);
1306 /* add to the graph */
1307 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1308 g_free(comment);
1309 g_free(frame_label);
1312 tapinfo->redraw = TRUE;
1314 return 1; /* refresh output */
1317 /****************************************************************************/
1319 static gboolean have_isup_tap_listener=FALSE;
1321 void
1322 isup_calls_init_tap(void)
1324 GString *error_string;
1327 if(have_isup_tap_listener==FALSE)
1329 error_string = register_tap_listener("isup", &(the_tapinfo_struct.isup_dummy),
1330 NULL,
1332 voip_calls_dlg_reset,
1333 isup_calls_packet,
1334 voip_calls_dlg_draw
1337 if (error_string != NULL) {
1338 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1339 "%s", error_string->str);
1340 g_string_free(error_string, TRUE);
1341 exit(1);
1343 have_isup_tap_listener=TRUE;
1347 /****************************************************************************/
1349 void
1350 remove_tap_listener_isup_calls(void)
1352 remove_tap_listener(&(the_tapinfo_struct.isup_dummy));
1354 have_isup_tap_listener=FALSE;
1358 /****************************************************************************/
1359 /* ***************************TAP for MTP3 **********************************/
1360 /****************************************************************************/
1363 /****************************************************************************/
1364 /* whenever a mtp3_ packet is seen by the tap listener */
1365 static int
1366 mtp3_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *mtp3_info _U_)
1368 const mtp3_tap_rec_t *pi = (mtp3_tap_rec_t *)mtp3_info;
1370 /* keep the data in memory to use when the ISUP information arrives */
1372 mtp3_opc = pi->addr_opc.pc;
1373 mtp3_dpc = pi->addr_dpc.pc;
1374 mtp3_ni = pi->addr_opc.ni;
1375 mtp3_frame_num = pinfo->fd->num;
1377 return 0;
1380 /****************************************************************************/
1382 static gboolean have_mtp3_tap_listener=FALSE;
1383 static gboolean have_m3ua_tap_listener=FALSE;
1385 void
1386 mtp3_calls_init_tap(void)
1388 GString *error_string;
1391 if(have_mtp3_tap_listener==FALSE)
1393 error_string = register_tap_listener("mtp3", &(the_tapinfo_struct.mtp3_dummy),
1394 NULL,
1396 voip_calls_dlg_reset,
1397 mtp3_calls_packet,
1398 voip_calls_dlg_draw
1401 if (error_string != NULL) {
1402 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1403 "%s", error_string->str);
1404 g_string_free(error_string, TRUE);
1405 exit(1);
1407 have_mtp3_tap_listener=TRUE;
1410 if(have_m3ua_tap_listener==FALSE)
1412 error_string = register_tap_listener("m3ua", &(the_tapinfo_struct.mtp3_dummy),
1413 NULL,
1415 voip_calls_dlg_reset,
1416 mtp3_calls_packet,
1417 voip_calls_dlg_draw
1420 if (error_string != NULL) {
1421 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1422 "%s", error_string->str);
1423 g_string_free(error_string, TRUE);
1424 exit(1);
1426 have_m3ua_tap_listener=TRUE;
1431 /****************************************************************************/
1433 void
1434 remove_tap_listener_mtp3_calls(void)
1436 remove_tap_listener(&(the_tapinfo_struct.mtp3_dummy));
1437 remove_tap_listener(&(the_tapinfo_struct.m3ua_dummy));
1439 have_mtp3_tap_listener=FALSE;
1440 have_m3ua_tap_listener=FALSE;
1443 /****************************************************************************/
1444 /* ***************************TAP for Q931 **********************************/
1445 /****************************************************************************/
1446 void h245_add_to_graph(guint32 new_frame_num);
1447 static const e_guid_t guid_allzero = {0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };
1448 /* defines specific H323 data */
1450 static gchar *q931_calling_number;
1451 static gchar *q931_called_number;
1452 static guint8 q931_cause_value;
1453 static gint32 q931_crv;
1454 static guint32 q931_frame_num;
1456 static guint32 h225_frame_num = 0;
1457 static guint16 h225_call_num = 0;
1458 static h225_cs_type h225_cstype = H225_OTHER;
1459 static gboolean h225_is_faststart;
1461 static guint32 actrace_frame_num = 0;
1462 static gint32 actrace_trunk = 0;
1463 static gint32 actrace_direction = 0;
1466 /****************************************************************************/
1467 /* whenever a q931_ packet is seen by the tap listener */
1468 static int
1469 q931_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *q931_info)
1471 GList *list,*list2;
1472 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1473 h323_calls_info_t *tmp_h323info,*tmp2_h323info;
1474 actrace_isdn_calls_info_t *tmp_actrace_isdn_info;
1475 voip_calls_info_t *tmp_listinfo;
1476 voip_calls_info_t *callsinfo = NULL;
1477 h245_address_t *h245_add = NULL;
1478 gchar *comment;
1480 const q931_packet_info *pi = (const q931_packet_info *)q931_info;
1482 /* free previously allocated q931_calling/ed_number */
1483 g_free(q931_calling_number);
1484 g_free(q931_called_number);
1486 if (pi->calling_number!=NULL)
1487 q931_calling_number = g_strdup(pi->calling_number);
1488 else
1489 q931_calling_number = g_strdup("");
1491 if (pi->called_number!=NULL)
1492 q931_called_number = g_strdup(pi->called_number);
1493 else
1494 q931_called_number = g_strdup("");
1495 q931_cause_value = pi->cause_value;
1496 q931_frame_num = pinfo->fd->num;
1497 q931_crv = pi->crv;
1500 /* add staff to H323 calls */
1501 if (h225_frame_num == q931_frame_num) {
1502 tmp_h323info = NULL;
1503 list = g_list_first(tapinfo->callsinfo_list);
1504 while (list)
1506 tmp_listinfo=(voip_calls_info_t *)list->data;
1507 if ( (tmp_listinfo->protocol == VOIP_H323) && (tmp_listinfo->call_num == h225_call_num) ) {
1508 tmp_h323info = (h323_calls_info_t *)tmp_listinfo->prot_info;
1509 callsinfo = (voip_calls_info_t*)(list->data);
1511 /* Add the CRV to the h323 call */
1512 if (tmp_h323info->q931_crv == -1) {
1513 tmp_h323info->q931_crv = q931_crv;
1514 } else if (tmp_h323info->q931_crv != q931_crv) {
1515 tmp_h323info->q931_crv2 = q931_crv;
1517 break;
1519 list = g_list_next (list);
1522 if (callsinfo != NULL) {
1523 comment = NULL;
1524 if (h225_cstype == H225_SETUP) {
1525 /* set te calling and called number from the Q931 packet */
1526 if (q931_calling_number != NULL) {
1527 g_free(callsinfo->from_identity);
1528 callsinfo->from_identity=g_strdup(q931_calling_number);
1530 if (q931_called_number != NULL) {
1531 g_free(callsinfo->to_identity);
1532 callsinfo->to_identity=g_strdup(q931_called_number);
1535 /* check if there is an LRQ/LCF that match this Setup */
1536 /* TODO: we are just checking the DialedNumer in LRQ/LCF agains the Setup
1537 we should also check if the h225 signaling IP and port match the destination
1538 Setup ip and port */
1539 list = g_list_first(tapinfo->callsinfo_list);
1540 while (list)
1542 tmp_listinfo=(voip_calls_info_t *)list->data;
1543 if (tmp_listinfo->protocol == VOIP_H323) {
1544 tmp2_h323info = (h323_calls_info_t *)tmp_listinfo->prot_info;
1546 /* check if the called number match a LRQ/LCF */
1547 if ( (strcmp(callsinfo->to_identity, tmp_listinfo->to_identity)==0)
1548 && (memcmp(&tmp2_h323info->guid, &guid_allzero, GUID_LEN) == 0) ) {
1549 /* change the call graph to the LRQ/LCF to belong to this call */
1550 callsinfo->npackets += change_call_num_graph(tapinfo, tmp_listinfo->call_num, callsinfo->call_num);
1552 /* remove this LRQ/LCF call entry because we have found the Setup that match them */
1553 g_free(tmp_listinfo->from_identity);
1554 g_free(tmp_listinfo->to_identity);
1555 DUMP_PTR2(tmp2_h323info->guid);
1556 g_free(tmp2_h323info->guid);
1558 list2 = g_list_first(tmp2_h323info->h245_list);
1559 while (list2)
1561 h245_add=(h245_address_t *)list2->data;
1562 g_free((void *)h245_add->h245_address.data);
1563 g_free(list2->data);
1564 list2 = g_list_next(list2);
1566 g_list_free(tmp_h323info->h245_list);
1567 tmp_h323info->h245_list = NULL;
1568 g_free(tmp_listinfo->prot_info);
1569 tapinfo->callsinfo_list = g_list_remove(tapinfo->callsinfo_list, tmp_listinfo);
1570 break;
1573 list = g_list_next (list);
1576 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"),
1577 (h225_is_faststart==TRUE?"on":"off"));
1578 } else if (h225_cstype == H225_RELEASE_COMPLET) {
1579 /* get the Q931 Release cause code */
1580 if (q931_cause_value != 0xFF) {
1581 comment = g_strdup_printf("H225 Q931 Rel Cause (%i):%s", q931_cause_value,
1582 val_to_str_ext_const(q931_cause_value, &q931_cause_code_vals_ext, "<unknown>"));
1583 } else { /* Cause not set */
1584 comment = g_strdup("H225 No Q931 Rel Cause");
1587 /* change the graph comment for this new one */
1588 if (comment != NULL) {
1589 change_frame_graph(tapinfo, h225_frame_num, NULL, comment);
1590 g_free(comment);
1593 /* we reset the h225_frame_num to 0 because there could be empty h225 in the same frame
1594 as non empty h225 (e.g connect), so we don't have to be here twice */
1595 h225_frame_num = 0;
1597 /* add staff to H245 */
1598 } else if (h245_labels.frame_num == q931_frame_num) {
1599 /* there are empty H225 frames that don't have guid (guaid=0) but they have h245 info,
1600 so the only way to match those frames is with the Q931 CRV number */
1601 list = g_list_first(tapinfo->callsinfo_list);
1602 while (list)
1604 tmp_listinfo=(voip_calls_info_t *)list->data;
1605 if (tmp_listinfo->protocol == VOIP_H323) {
1606 tmp_h323info = (h323_calls_info_t *)tmp_listinfo->prot_info;
1607 if ( ((tmp_h323info->q931_crv == q931_crv) || (tmp_h323info->q931_crv2 == q931_crv)) && (q931_crv!=-1)) {
1608 /* if the frame number exists in graph, append to it*/
1609 if (!append_to_frame_graph(tapinfo, q931_frame_num, NULL, NULL)) {
1610 /* if not exist, add to the graph */
1611 add_to_graph(tapinfo, pinfo, NULL, NULL, tmp_listinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1612 ++(tmp_listinfo->npackets);
1613 /* increment the packets counter of all calls */
1614 ++(tapinfo->npackets);
1617 /* Add the H245 info if exists to the Graph */
1618 h245_add_to_graph(pinfo->fd->num);
1619 break;
1622 list = g_list_next (list);
1625 /* add stuff to ACTRACE */
1626 } else {
1627 address pstn_add;
1629 comment = NULL;
1630 callsinfo = NULL;
1631 list = g_list_first(tapinfo->callsinfo_list);
1632 while (list)
1634 tmp_listinfo=(voip_calls_info_t *)list->data;
1635 if ( tmp_listinfo->protocol == VOIP_AC_ISDN ) {
1636 tmp_actrace_isdn_info = (actrace_isdn_calls_info_t *)tmp_listinfo->prot_info;
1637 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
1638 if ( (tmp_actrace_isdn_info->crv == q931_crv) && (tmp_actrace_isdn_info->trunk == actrace_trunk) ) {
1639 callsinfo = (voip_calls_info_t*)(list->data);
1640 break;
1643 list = g_list_next (list);
1646 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, g_strdup("PSTN"));
1648 /* if it is a new call, add it to the list */
1649 if (!callsinfo) {
1650 callsinfo = (voip_calls_info_t *)g_malloc0(sizeof(voip_calls_info_t));
1651 callsinfo->call_active_state = VOIP_ACTIVE;
1652 callsinfo->call_state = VOIP_CALL_SETUP;
1653 callsinfo->from_identity=g_strdup(q931_calling_number);
1654 callsinfo->to_identity=g_strdup(q931_called_number);
1655 COPY_ADDRESS(&(callsinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
1656 callsinfo->selected=FALSE;
1657 callsinfo->start_fd=pinfo->fd;
1658 callsinfo->start_rel_ts=pinfo->rel_ts;
1659 callsinfo->protocol=VOIP_AC_ISDN;
1660 callsinfo->prot_info=g_malloc(sizeof(actrace_isdn_calls_info_t));
1661 callsinfo->free_prot_info = g_free;
1662 tmp_actrace_isdn_info=(actrace_isdn_calls_info_t *)callsinfo->prot_info;
1663 tmp_actrace_isdn_info->crv=q931_crv;
1664 tmp_actrace_isdn_info->trunk=actrace_trunk;
1665 callsinfo->npackets = 0;
1666 callsinfo->call_num = tapinfo->ncalls++;
1667 tapinfo->callsinfo_list = g_list_prepend(tapinfo->callsinfo_list, callsinfo);
1670 callsinfo->stop_fd = pinfo->fd;
1671 callsinfo->stop_rel_ts = pinfo->rel_ts;
1672 ++(callsinfo->npackets);
1673 /* increment the packets counter of all calls */
1674 ++(tapinfo->npackets);
1676 switch(pi->message_type) {
1677 case Q931_SETUP:
1678 comment = g_strdup_printf("AC_ISDN trunk:%u Calling: %s Called:%s", actrace_trunk, q931_calling_number, q931_called_number);
1679 callsinfo->call_state=VOIP_CALL_SETUP;
1680 break;
1681 case Q931_CONNECT:
1682 callsinfo->call_state=VOIP_IN_CALL;
1683 break;
1684 case Q931_RELEASE_COMPLETE:
1685 case Q931_RELEASE:
1686 case Q931_DISCONNECT:
1687 if (callsinfo->call_state==VOIP_CALL_SETUP) {
1688 if (ADDRESSES_EQUAL(&(callsinfo->initial_speaker), actrace_direction?&pstn_add:&(pinfo->src) )) { /* forward direction */
1689 callsinfo->call_state=VOIP_CANCELLED;
1691 else { /* reverse */
1692 callsinfo->call_state=VOIP_REJECTED;
1693 tapinfo->rejected_calls++;
1695 } else if ( (callsinfo->call_state!=VOIP_CANCELLED) && (callsinfo->call_state!=VOIP_REJECTED) ) {
1696 callsinfo->call_state=VOIP_COMPLETED;
1697 tapinfo->completed_calls++;
1699 if (q931_cause_value != 0xFF) {
1700 comment = g_strdup_printf("AC_ISDN trunk:%u Q931 Rel Cause (%i):%s", actrace_trunk, q931_cause_value,
1701 val_to_str_ext_const(q931_cause_value, &q931_cause_code_vals_ext, "<unknown>"));
1702 } else { /* Cause not set */
1703 comment = g_strdup("AC_ISDN No Q931 Rel Cause");
1705 break;
1708 if (!comment)
1709 comment = g_strdup_printf("AC_ISDN trunk:%u", actrace_trunk );
1711 add_to_graph(tapinfo, pinfo, val_to_str(pi->message_type, q931_message_type_vals, "<unknown>") , comment, callsinfo->call_num,
1712 actrace_direction?&pstn_add:&(pinfo->src),
1713 actrace_direction?&(pinfo->src):&pstn_add,
1714 1 );
1716 g_free(comment);
1717 g_free((char *)pstn_add.data);
1720 tapinfo->redraw = TRUE;
1722 return 1; /* refresh output */
1725 /****************************************************************************/
1726 static gboolean have_q931_tap_listener=FALSE;
1728 void
1729 q931_calls_init_tap(void)
1731 GString *error_string;
1734 if(have_q931_tap_listener==FALSE)
1736 error_string = register_tap_listener("q931", &(the_tapinfo_struct.q931_dummy),
1737 NULL,
1739 voip_calls_dlg_reset,
1740 q931_calls_packet,
1741 voip_calls_dlg_draw
1744 if (error_string != NULL) {
1745 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1746 "%s", error_string->str);
1747 g_string_free(error_string, TRUE);
1748 exit(1);
1750 have_q931_tap_listener=TRUE;
1754 /****************************************************************************/
1756 void
1757 remove_tap_listener_q931_calls(void)
1759 remove_tap_listener(&(the_tapinfo_struct.q931_dummy));
1761 have_q931_tap_listener=FALSE;
1764 /****************************************************************************/
1765 /****************************TAP for H323 ***********************************/
1766 /****************************************************************************/
1768 static void add_h245_Address(h323_calls_info_t *h323info, h245_address_t *h245_address)
1770 h323info->h245_list = g_list_prepend(h323info->h245_list, h245_address);
1774 static void free_h225_info(gpointer p) {
1775 h323_calls_info_t *tmp_h323info = (h323_calls_info_t *)p;
1777 DUMP_PTR2(tmp_h323info->guid);
1778 g_free(tmp_h323info->guid);
1780 if (tmp_h323info->h245_list) {
1781 GList *list2 = g_list_first(tmp_h323info->h245_list);
1782 while (list2)
1784 h245_address_t *h245_add=(h245_address_t *)list2->data;
1785 g_free((void *)h245_add->h245_address.data);
1786 g_free(list2->data);
1787 list2 = g_list_next(list2);
1790 g_list_free(tmp_h323info->h245_list);
1794 g_free(p);
1796 /****************************************************************************/
1797 /* whenever a H225 packet is seen by the tap listener */
1798 static int
1799 H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H225info)
1801 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1802 voip_calls_info_t *tmp_listinfo;
1803 voip_calls_info_t *callsinfo = NULL;
1804 h323_calls_info_t *tmp_h323info = NULL;
1805 gchar *frame_label;
1806 gchar *comment;
1807 GList *list;
1808 h245_address_t *h245_add = NULL;
1810 const h225_packet_info *pi = (const h225_packet_info *)H225info;
1812 /* if not guid and RAS and not LRQ, LCF or LRJ return because did not belong to a call */
1813 /* OR, if not guid and is H225 return because doesn't belong to a call */
1814 if ((memcmp(&pi->guid, &guid_allzero, GUID_LEN) == 0))
1815 if ( ((pi->msg_type == H225_RAS) && ((pi->msg_tag < 18) || (pi->msg_tag > 20))) || (pi->msg_type != H225_RAS) )
1816 return 0;
1818 /* if it is RAS LCF or LRJ*/
1819 if ( (pi->msg_type == H225_RAS) && ((pi->msg_tag == 19) || (pi->msg_tag == 20))) {
1820 /* if the LCF/LRJ doesn't match to a LRQ, just return */
1821 if (!pi->request_available) return 0;
1823 /* check whether we already have a call with this request SeqNum */
1824 list = g_list_first(tapinfo->callsinfo_list);
1825 while (list)
1827 tmp_listinfo=(voip_calls_info_t *)list->data;
1828 g_assert(tmp_listinfo != NULL);
1829 if (tmp_listinfo->protocol == VOIP_H323) {
1830 tmp_h323info = (h323_calls_info_t *)tmp_listinfo->prot_info;
1831 if (tmp_h323info->requestSeqNum == pi->requestSeqNum) {
1832 callsinfo = (voip_calls_info_t*)(list->data);
1833 break;
1836 list = g_list_next (list);
1838 } else {
1839 /* check whether we already have a call with this guid in the list */
1840 list = g_list_first(tapinfo->callsinfo_list);
1841 while (list)
1843 tmp_listinfo=(voip_calls_info_t *)list->data;
1844 if (tmp_listinfo->protocol == VOIP_H323) {
1845 tmp_h323info = (h323_calls_info_t *)tmp_listinfo->prot_info;
1846 g_assert(tmp_h323info != NULL);
1847 if ( (memcmp(tmp_h323info->guid, &guid_allzero, GUID_LEN) != 0) && (memcmp(tmp_h323info->guid, &pi->guid,GUID_LEN)==0) ) {
1848 callsinfo = (voip_calls_info_t*)(list->data);
1849 break;
1852 list = g_list_next (list);
1856 h225_cstype = pi->cs_type;
1857 h225_is_faststart = pi->is_faststart;
1859 /* not in the list? then create a new entry */
1860 if (callsinfo==NULL) {
1861 callsinfo = (voip_calls_info_t *)g_malloc0(sizeof(voip_calls_info_t));
1862 callsinfo->call_active_state = VOIP_ACTIVE;
1863 callsinfo->call_state = VOIP_UNKNOWN;
1864 callsinfo->from_identity=g_strdup("");
1865 callsinfo->to_identity=g_strdup("");
1866 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
1867 callsinfo->selected=FALSE;
1868 callsinfo->start_fd=pinfo->fd;
1869 callsinfo->start_rel_ts=pinfo->rel_ts;
1870 callsinfo->protocol=VOIP_H323;
1871 callsinfo->prot_info=g_malloc(sizeof(h323_calls_info_t));
1872 callsinfo->free_prot_info = free_h225_info;
1874 tmp_h323info = (h323_calls_info_t *)callsinfo->prot_info;
1875 g_assert(tmp_h323info != NULL);
1876 tmp_h323info->guid = (e_guid_t *)g_memdup(&pi->guid, sizeof pi->guid);
1877 DUMP_PTR1(tmp_h323info->guid);
1879 tmp_h323info->h225SetupAddr.type = AT_NONE;
1880 tmp_h323info->h225SetupAddr.len = 0;
1881 tmp_h323info->h245_list = NULL;
1882 tmp_h323info->is_faststart_Setup = FALSE;
1883 tmp_h323info->is_faststart_Proc = FALSE;
1884 tmp_h323info->is_h245Tunneling = FALSE;
1885 tmp_h323info->is_h245 = FALSE;
1886 tmp_h323info->q931_crv = -1;
1887 tmp_h323info->q931_crv2 = -1;
1888 tmp_h323info->requestSeqNum = 0;
1889 callsinfo->call_num = tapinfo->ncalls++;
1890 callsinfo->npackets = 0;
1892 tapinfo->callsinfo_list = g_list_prepend(tapinfo->callsinfo_list, callsinfo);
1895 h225_frame_num = pinfo->fd->num;
1896 h225_call_num = callsinfo->call_num;
1898 /* let's analyze the call state */
1900 callsinfo->stop_fd = pinfo->fd;
1901 callsinfo->stop_rel_ts = pinfo->rel_ts;
1902 ++(callsinfo->npackets);
1903 /* increment the packets counter of all calls */
1904 ++(tapinfo->npackets);
1907 /* XXX: it is supposed to be initialized isn't it? */
1908 g_assert(tmp_h323info != NULL);
1910 /* change the status */
1911 if (pi->msg_type == H225_CS) {
1913 /* this is still IPv4 only, because the dissector is */
1914 if (pi->is_h245 == TRUE) {
1915 h245_add = (h245_address_t *)g_malloc(sizeof (h245_address_t));
1916 h245_add->h245_address.type=AT_IPv4;
1917 h245_add->h245_address.len=4;
1918 h245_add->h245_address.data = g_malloc(sizeof(pi->h245_address));
1919 memcpy((void *)(h245_add->h245_address.data), &(pi->h245_address), 4);
1920 h245_add->h245_port = pi->h245_port;
1921 add_h245_Address(tmp_h323info, h245_add);
1924 if (pi->cs_type != H225_RELEASE_COMPLET) tmp_h323info->is_h245Tunneling = pi->is_h245Tunneling;
1926 frame_label = g_strdup(pi->frame_label);
1928 switch(pi->cs_type) {
1929 case H225_SETUP:
1930 tmp_h323info->is_faststart_Setup = pi->is_faststart;
1932 /* Set the Setup address if it was not set */
1933 if (tmp_h323info->h225SetupAddr.type == AT_NONE)
1934 COPY_ADDRESS(&(tmp_h323info->h225SetupAddr), &(pinfo->src));
1935 callsinfo->call_state=VOIP_CALL_SETUP;
1936 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1937 (pi->is_faststart==TRUE?"on":"off"));
1938 break;
1939 case H225_CONNECT:
1940 callsinfo->call_state=VOIP_IN_CALL;
1941 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1942 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1943 (pi->is_faststart==TRUE?"on":"off"));
1944 break;
1945 case H225_RELEASE_COMPLET:
1946 if (callsinfo->call_state==VOIP_CALL_SETUP) {
1947 if (ADDRESSES_EQUAL(&(tmp_h323info->h225SetupAddr),&(pinfo->src))) { /* forward direction */
1948 callsinfo->call_state=VOIP_CANCELLED;
1950 else { /* reverse */
1951 callsinfo->call_state=VOIP_REJECTED;
1952 tapinfo->rejected_calls++;
1954 } else {
1955 callsinfo->call_state=VOIP_COMPLETED;
1956 tapinfo->completed_calls++;
1958 comment = g_strdup("H225 No Q931 Rel Cause");
1959 break;
1960 case H225_PROGRESS:
1961 case H225_ALERTING:
1962 case H225_CALL_PROCEDING:
1963 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1964 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1965 (pi->is_faststart==TRUE?"on":"off"));
1966 break;
1967 default:
1968 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"),
1969 (pi->is_faststart==TRUE?"on":"off"));
1973 else if (pi->msg_type == H225_RAS) {
1974 switch(pi->msg_tag) {
1975 case 18: /* LRQ */
1976 if (!pi->is_duplicate) {
1977 g_free(callsinfo->to_identity);
1978 callsinfo->to_identity=g_strdup(pi->dialedDigits);
1979 tmp_h323info->requestSeqNum = pi->requestSeqNum;
1981 case 19: /* LCF */
1982 if (strlen(pi->dialedDigits))
1983 comment = g_strdup_printf("H225 RAS dialedDigits: %s", pi->dialedDigits);
1984 else
1985 comment = g_strdup("H225 RAS");
1986 break;
1987 default:
1988 comment = g_strdup("H225 RAS");
1990 frame_label = g_strdup(val_to_str_const(pi->msg_tag, h225_RasMessage_vals, "<unknown>"));
1991 } else {
1992 frame_label = g_strdup("H225: Unknown");
1993 comment = NULL;
1996 /* add to graph analysis */
1998 /* if the frame number exists in graph, append to it*/
1999 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, comment)) {
2000 /* if not exist, add to the graph */
2001 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2004 /* Add the H245 info if exists to the Graph */
2005 h245_add_to_graph(pinfo->fd->num);
2007 g_free(frame_label);
2008 g_free(comment);
2010 tapinfo->redraw = TRUE;
2012 return 1; /* refresh output */
2016 /****************************************************************************/
2017 /* TAP INTERFACE */
2018 /****************************************************************************/
2019 static gboolean have_H225_tap_listener=FALSE;
2020 /****************************************************************************/
2021 void
2022 h225_calls_init_tap(void)
2024 GString *error_string;
2026 if(have_H225_tap_listener==FALSE)
2028 /* don't register tap listener, if we have it already */
2029 error_string = register_tap_listener("h225", &(the_tapinfo_struct.h225_dummy), NULL,
2031 voip_calls_dlg_reset,
2032 H225calls_packet,
2033 voip_calls_dlg_draw
2036 if (error_string != NULL) {
2037 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2038 "%s", error_string->str);
2039 g_string_free(error_string, TRUE);
2040 exit(1);
2042 have_H225_tap_listener=TRUE;
2046 /****************************************************************************/
2047 void
2048 remove_tap_listener_h225_calls(void)
2050 remove_tap_listener(&(the_tapinfo_struct.h225_dummy));
2052 have_H225_tap_listener=FALSE;
2055 /* Add the h245 label info to the graph */
2056 void h245_add_to_graph(guint32 new_frame_num)
2058 gint8 n;
2060 if (new_frame_num != h245_labels.frame_num) return;
2062 for (n=0; n<h245_labels.labels_count; n++) {
2063 append_to_frame_graph(&the_tapinfo_struct, new_frame_num, h245_labels.labels[n].frame_label, h245_labels.labels[n].comment);
2064 g_free(h245_labels.labels[n].frame_label);
2065 h245_labels.labels[n].frame_label = NULL;
2066 g_free(h245_labels.labels[n].comment);
2067 h245_labels.labels[n].comment = NULL;
2069 h245_labels.frame_num = 0;
2070 h245_labels.labels_count = 0;
2073 /* free the h245_labels if the frame number is different */
2074 static void h245_free_labels(guint32 new_frame_num)
2076 gint8 n;
2078 if (new_frame_num == h245_labels.frame_num) return;
2080 for (n=0; n<h245_labels.labels_count; n++) {
2081 g_free(h245_labels.labels[n].frame_label);
2082 h245_labels.labels[n].frame_label = NULL;
2083 g_free(h245_labels.labels[n].comment);
2084 h245_labels.labels[n].comment = NULL;
2086 h245_labels.frame_num = 0;
2087 h245_labels.labels_count = 0;
2090 /* add the frame_label and comment to h245_labels and free the actual one if it is different frame num */
2091 static void h245_add_label(guint32 new_frame_num, const gchar *frame_label, const gchar *comment)
2093 h245_free_labels(new_frame_num);
2095 h245_labels.frame_num = new_frame_num;
2096 h245_labels.labels[h245_labels.labels_count].frame_label = g_strdup(frame_label);
2097 h245_labels.labels[h245_labels.labels_count].comment = g_strdup(comment);
2099 if (h245_labels.labels_count < (H245_MAX-1))
2100 h245_labels.labels_count++;
2104 /****************************************************************************/
2105 /* whenever a H245dg packet is seen by the tap listener (when H245 tunneling is ON) */
2106 static int
2107 H245dgcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H245info)
2109 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2110 voip_calls_info_t *tmp_listinfo;
2111 voip_calls_info_t *callsinfo = NULL;
2112 h323_calls_info_t *tmp_h323info;
2113 GList *list;
2114 GList *list2;
2115 h245_address_t *h245_add = NULL;
2117 const h245_packet_info *pi = (h245_packet_info *)H245info;
2119 /* check if Tunneling is OFF and we have a call with this H245 add */
2120 list = g_list_first(tapinfo->callsinfo_list);
2121 while (list)
2123 tmp_listinfo=(voip_calls_info_t *)list->data;
2124 if (tmp_listinfo->protocol == VOIP_H323) {
2125 tmp_h323info = (h323_calls_info_t *)tmp_listinfo->prot_info;
2127 list2 = g_list_first(tmp_h323info->h245_list);
2128 while (list2)
2130 h245_add=(h245_address_t *)list2->data;
2131 if ( (ADDRESSES_EQUAL(&(h245_add->h245_address),&(pinfo->src)) && (h245_add->h245_port == pinfo->srcport))
2132 || (ADDRESSES_EQUAL(&(h245_add->h245_address),&(pinfo->dst)) && (h245_add->h245_port == pinfo->destport)) ) {
2133 callsinfo = (voip_calls_info_t*)(list->data);
2135 ++(callsinfo->npackets);
2136 /* increment the packets counter of all calls */
2137 ++(tapinfo->npackets);
2139 break;
2141 list2 = g_list_next(list2);
2143 if (callsinfo!=NULL) break;
2145 list = g_list_next(list);
2148 /* Tunnel is OFF, and we matched the h245 add so we add it to graph */
2149 if (callsinfo!=NULL) {
2150 ++(callsinfo->npackets);
2151 /* increment the packets counter of all calls */
2152 ++(tapinfo->npackets);
2153 /* if the frame number exists in graph, append to it*/
2154 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, pi->comment)) {
2155 /* if not exist, add to the graph */
2156 add_to_graph(tapinfo, pinfo, pi->frame_label, pi->comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2158 } else {
2159 /* Tunnel is ON, so we save the label info to use it into h225 or q931 tap. OR may be
2160 tunnel OFF but we did not matched the h245 add, in this case nobady will set this label
2161 since the frame_num will not match */
2163 h245_add_label(pinfo->fd->num, (gchar *) pi->frame_label, (gchar *) pi->comment);
2166 tapinfo->redraw = TRUE;
2168 return 1; /* refresh output */
2172 /****************************************************************************/
2173 /* TAP INTERFACE */
2174 /****************************************************************************/
2175 static gboolean have_H245dg_tap_listener=FALSE;
2176 /****************************************************************************/
2177 void
2178 h245dg_calls_init_tap(void)
2180 GString *error_string;
2182 if(have_H245dg_tap_listener==FALSE)
2184 /* don't register tap listener, if we have it already */
2185 error_string = register_tap_listener("h245dg", &(the_tapinfo_struct.h245dg_dummy), NULL,
2187 voip_calls_dlg_reset,
2188 H245dgcalls_packet,
2189 voip_calls_dlg_draw
2192 if (error_string != NULL) {
2193 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2194 "%s", error_string->str);
2195 g_string_free(error_string, TRUE);
2196 exit(1);
2198 have_H245dg_tap_listener=TRUE;
2202 /****************************************************************************/
2203 void
2204 remove_tap_listener_h245dg_calls(void)
2206 remove_tap_listener(&(the_tapinfo_struct.h245dg_dummy));
2208 have_H245dg_tap_listener=FALSE;
2211 /****************************************************************************/
2212 /****************************TAP for SDP PROTOCOL ***************************/
2213 /****************************************************************************/
2214 /* whenever a SDP packet is seen by the tap listener */
2215 static int
2216 SDPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SDPinfo)
2218 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2219 const sdp_packet_info *pi = (sdp_packet_info *)SDPinfo;
2221 /* There are protocols like MGCP/SIP where the SDP is called before the tap for the
2222 MGCP/SIP packet, in those cases we assign the SPD summary to global lastSDPsummary
2223 to use it later
2225 g_free(sdp_summary);
2226 sdp_frame_num = pinfo->fd->num;
2227 /* Append to graph the SDP summary if the packet exists */
2228 sdp_summary = g_strdup_printf("SDP (%s)", pi->summary_str);
2229 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2231 tapinfo->redraw = TRUE;
2233 return 1; /* refresh output */
2237 /****************************************************************************/
2238 /* TAP INTERFACE */
2239 /****************************************************************************/
2240 static gboolean have_sdp_tap_listener=FALSE;
2241 /****************************************************************************/
2242 void
2243 sdp_calls_init_tap(void)
2245 GString *error_string;
2247 if(have_sdp_tap_listener==FALSE)
2249 /* don't register tap listener, if we have it already */
2250 error_string = register_tap_listener("sdp", &(the_tapinfo_struct.sdp_dummy), NULL,
2252 voip_calls_dlg_reset,
2253 SDPcalls_packet,
2254 voip_calls_dlg_draw
2257 if (error_string != NULL) {
2258 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2259 "%s", error_string->str);
2260 g_string_free(error_string, TRUE);
2261 exit(1);
2263 have_sdp_tap_listener=TRUE;
2267 /****************************************************************************/
2268 void
2269 remove_tap_listener_sdp_calls(void)
2271 remove_tap_listener(&(the_tapinfo_struct.sdp_dummy));
2273 have_sdp_tap_listener=FALSE;
2278 /****************************************************************************/
2279 /* ***************************TAP for MGCP **********************************/
2280 /****************************************************************************/
2283 This function will look for a signal/event in the SignalReq/ObsEvent string
2284 and return true if it is found
2286 static gboolean isSignal(const gchar *signal_str_p, const gchar *signalStr)
2288 gint i;
2289 gchar **resultArray;
2291 /* if there is no signalStr, just return false */
2292 if (signalStr == NULL) return FALSE;
2294 /* if are both "blank" return true */
2295 if ( (*signal_str_p == '\0') && (*signalStr == '\0') ) return TRUE;
2297 /* look for signal in signalStr */
2298 resultArray = g_strsplit(signalStr, ",", 10);
2300 for (i = 0; resultArray[i]; i++) {
2301 g_strstrip(resultArray[i]);
2302 if (strcmp(resultArray[i], signal_str_p) == 0) return TRUE;
2305 g_strfreev(resultArray);
2307 return FALSE;
2311 This function will get the Caller ID info and replace the current string
2312 This is how it looks the caller Id: rg, ci(02/16/08/29, "3035550002","Ale Sipura 2")
2314 static void mgcpCallerID(gchar *signalStr, gchar **callerId)
2316 gchar **arrayStr;
2318 /* if there is no signalStr, just return false */
2319 if (signalStr == NULL) return;
2321 arrayStr = g_strsplit(signalStr, "\"", 10);
2323 if (arrayStr[0] == NULL) return;
2325 /* look for the ci signal */
2326 if (strstr(arrayStr[0], "ci(") && (arrayStr[1] != NULL) ) {
2327 /* free the previous "From" field of the call, and assign the new */
2328 g_free(*callerId);
2329 *callerId = g_strdup(arrayStr[1]);
2331 g_strfreev(arrayStr);
2333 return;
2338 This function will get the Dialed Digits and replace the current string
2339 This is how it looks the dialed digits 5,5,5,0,0,0,2,#,*
2341 static void mgcpDialedDigits(gchar *signalStr, gchar **dialedDigits)
2343 gchar *tmpStr;
2344 gchar *resultStr;
2345 gint i,j;
2347 /* start with 1 for the null-terminator */
2348 guint resultStrLen = 1;
2350 /* if there is no signalStr, just return false */
2351 if (signalStr == NULL) return;
2353 tmpStr = g_strdup(signalStr);
2355 for ( i = 0 ; tmpStr[i] ; i++) {
2356 switch (tmpStr[i]) {
2357 case '0' : case '1' : case '2' : case '3' : case '4' :
2358 case '5' : case '6' : case '7' : case '8' : case '9' :
2359 case '#' : case '*' :
2360 resultStrLen++;
2361 break;
2362 default:
2363 tmpStr[i] = '?';
2364 break;
2368 if (resultStrLen == 1) {
2369 g_free(tmpStr);
2370 return;
2373 resultStr = (gchar *)g_malloc(resultStrLen);
2375 for (i = 0, j = 0; tmpStr[i]; i++) {
2376 if (tmpStr[i] != '?')
2377 resultStr[j++] = tmpStr[i];
2379 resultStr[j] = '\0';
2381 g_free(*dialedDigits);
2382 g_free(tmpStr);
2384 *dialedDigits = resultStr;
2386 return;
2391 /****************************************************************************/
2392 /* whenever a MGCP packet is seen by the tap listener */
2393 static int
2394 MGCPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *MGCPinfo)
2396 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2398 voip_calls_info_t *tmp_listinfo;
2399 voip_calls_info_t *callsinfo = NULL;
2400 mgcp_calls_info_t *tmp_mgcpinfo = NULL;
2401 GList *list;
2402 GList *listGraph;
2403 gchar *frame_label = NULL;
2404 gchar *comment = NULL;
2405 seq_analysis_item_t *gai;
2406 gboolean newcall = FALSE;
2407 gboolean fromEndpoint = FALSE; /* true for calls originated in Endpoints, false for calls from MGC */
2408 gdouble diff_time;
2410 const mgcp_info_t *pi = (mgcp_info_t *)MGCPinfo;
2413 if ((pi->mgcp_type == MGCP_REQUEST) && !pi->is_duplicate ) {
2414 /* check whether we already have a call with this Endpoint and it is active*/
2415 list = g_list_first(tapinfo->callsinfo_list);
2416 while (list)
2418 tmp_listinfo=(voip_calls_info_t *)list->data;
2419 if ((tmp_listinfo->protocol == VOIP_MGCP) && (tmp_listinfo->call_active_state == VOIP_ACTIVE)) {
2420 tmp_mgcpinfo = (mgcp_calls_info_t *)tmp_listinfo->prot_info;
2421 if (pi->endpointId != NULL) {
2422 if (g_ascii_strcasecmp(tmp_mgcpinfo->endpointId,pi->endpointId) == 0) {
2424 check first if it is an ended call. We can still match packets to this Endpoint 2 seconds
2425 after the call has been released
2427 diff_time = nstime_to_sec(&pinfo->rel_ts) - nstime_to_sec(&tmp_listinfo->stop_rel_ts);
2428 if ( ((tmp_listinfo->call_state == VOIP_CANCELLED) ||
2429 (tmp_listinfo->call_state == VOIP_COMPLETED) ||
2430 (tmp_listinfo->call_state == VOIP_REJECTED)) &&
2431 (diff_time > 2) )
2433 tmp_listinfo->call_active_state = VOIP_INACTIVE;
2434 } else {
2435 callsinfo = (voip_calls_info_t*)(list->data);
2436 break;
2441 list = g_list_next (list);
2444 /* there is no call with this Endpoint, lets see if this a new call or not */
2445 if (callsinfo == NULL) {
2446 if ( (strcmp(pi->code, "NTFY") == 0) && isSignal("hd", pi->observedEvents) ) { /* off hook transition */
2447 /* this is a new call from the Endpoint */
2448 fromEndpoint = TRUE;
2449 newcall = TRUE;
2450 } else if (strcmp(pi->code, "CRCX") == 0) {
2451 /* this is a new call from the MGC */
2452 fromEndpoint = FALSE;
2453 newcall = TRUE;
2455 if (!newcall) return 0;
2457 } else if ( ((pi->mgcp_type == MGCP_RESPONSE) && pi->request_available) ||
2458 ((pi->mgcp_type == MGCP_REQUEST) && pi->is_duplicate) ) {
2459 /* if it is a response OR if it is a duplicated Request, lets look in the Graph to see
2460 if there is a request that matches */
2461 listGraph = g_list_first(tapinfo->graph_analysis->list);
2462 while (listGraph)
2464 gai = (seq_analysis_item_t *)listGraph->data;
2465 if (gai->fd->num == pi->req_num) {
2466 /* there is a request that match, so look the associated call with this call_num */
2467 list = g_list_first(tapinfo->callsinfo_list);
2468 while (list)
2470 tmp_listinfo=(voip_calls_info_t *)list->data;
2471 if (tmp_listinfo->protocol == VOIP_MGCP) {
2472 if (tmp_listinfo->call_num == gai->conv_num) {
2473 tmp_mgcpinfo = (mgcp_calls_info_t *)tmp_listinfo->prot_info;
2474 callsinfo = (voip_calls_info_t*)(list->data);
2475 break;
2478 list = g_list_next (list);
2480 if (callsinfo != NULL) break;
2482 listGraph = g_list_next(listGraph);
2484 /* if there is not a matching request, just return */
2485 if (callsinfo == NULL) return 0;
2486 } else return 0;
2488 /* not in the list? then create a new entry */
2489 if (callsinfo==NULL) {
2490 callsinfo = (voip_calls_info_t *)g_malloc0(sizeof(voip_calls_info_t));
2491 callsinfo->call_active_state = VOIP_ACTIVE;
2492 callsinfo->call_state = VOIP_CALL_SETUP;
2493 if (fromEndpoint) {
2494 callsinfo->from_identity=g_strdup(pi->endpointId);
2495 callsinfo->to_identity=g_strdup("");
2496 } else {
2497 callsinfo->from_identity=g_strdup("");
2498 callsinfo->to_identity=g_strdup(pi->endpointId);
2500 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
2501 callsinfo->selected=FALSE;
2502 callsinfo->start_fd=pinfo->fd;
2503 callsinfo->start_rel_ts=pinfo->rel_ts;
2504 callsinfo->protocol=VOIP_MGCP;
2505 callsinfo->prot_info=g_malloc(sizeof(mgcp_calls_info_t));
2506 callsinfo->free_prot_info = g_free;
2507 tmp_mgcpinfo=(mgcp_calls_info_t *)callsinfo->prot_info;
2508 tmp_mgcpinfo->endpointId = g_strdup(pi->endpointId);
2509 tmp_mgcpinfo->fromEndpoint = fromEndpoint;
2510 callsinfo->npackets = 0;
2511 callsinfo->call_num = tapinfo->ncalls++;
2512 tapinfo->callsinfo_list = g_list_prepend(tapinfo->callsinfo_list, callsinfo);
2515 g_assert(tmp_mgcpinfo != NULL);
2517 /* change call state and add to graph */
2518 switch (pi->mgcp_type)
2520 case MGCP_REQUEST:
2521 if ( (strcmp(pi->code, "NTFY") == 0) && (pi->observedEvents != NULL) ) {
2522 frame_label = g_strdup_printf("%s ObsEvt:%s",pi->code, pi->observedEvents);
2524 if (tmp_mgcpinfo->fromEndpoint) {
2525 /* use the Dialed digits to fill the "To" for the call, but use the first NTFY */
2526 if (callsinfo->to_identity[0] == '\0') mgcpDialedDigits(pi->observedEvents, &(callsinfo->to_identity));
2528 /* from MGC and the user picked up, the call is connected */
2529 } else if (isSignal("hd", pi->observedEvents))
2530 callsinfo->call_state=VOIP_IN_CALL;
2532 /* hung up signal */
2533 if (isSignal("hu", pi->observedEvents)) {
2534 if ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state == VOIP_RINGING)) {
2535 callsinfo->call_state = VOIP_CANCELLED;
2536 } else {
2537 callsinfo->call_state = VOIP_COMPLETED;
2541 } else if (strcmp(pi->code, "RQNT") == 0) {
2542 /* for calls from Endpoint: if there is a "no signal" RQNT and the call was RINGING, we assume this is the CONNECT */
2543 if ( tmp_mgcpinfo->fromEndpoint && isSignal("", pi->signalReq) && (callsinfo->call_state == VOIP_RINGING) ) {
2544 callsinfo->call_state = VOIP_IN_CALL;
2547 /* if there is ringback or ring tone, change state to ringing */
2548 if ( isSignal("rg", pi->signalReq) || isSignal("rt", pi->signalReq) ) {
2549 callsinfo->call_state = VOIP_RINGING;
2552 /* if there is a Busy or ReorderTone, and the call was Ringing or Setup the call is Rejected */
2553 if ( (isSignal("ro", pi->signalReq) || isSignal("bz", pi->signalReq)) && ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state == VOIP_RINGING)) ) {
2554 callsinfo->call_state = VOIP_REJECTED;
2557 if (pi->signalReq != NULL)
2558 frame_label = g_strdup_printf("%s%sSigReq:%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"", pi->signalReq);
2559 else
2560 frame_label = g_strdup_printf("%s%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"");
2562 /* use the CallerID info to fill the "From" for the call */
2563 if (!tmp_mgcpinfo->fromEndpoint) mgcpCallerID(pi->signalReq, &(callsinfo->from_identity));
2565 } else if (strcmp(pi->code, "DLCX") == 0) {
2567 if there is a DLCX in a call To an Endpoint and the call was not connected, we use
2568 the DLCX as the end of the call
2570 if (!tmp_mgcpinfo->fromEndpoint) {
2571 if ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state == VOIP_RINGING)) {
2572 callsinfo->call_state = VOIP_CANCELLED;
2577 if (frame_label == NULL) frame_label = g_strdup(pi->code);
2578 break;
2579 case MGCP_RESPONSE:
2580 frame_label = g_strdup_printf("%u (%s)",pi->rspcode, pi->code);
2581 break;
2582 case MGCP_OTHERS:
2583 /* XXX what to do? */
2584 break;
2588 comment = g_strdup_printf("MGCP %s %s%s", tmp_mgcpinfo->endpointId, (pi->mgcp_type == MGCP_REQUEST)?"Request":"Response", pi->is_duplicate?" Duplicate":"");
2590 callsinfo->stop_fd = pinfo->fd;
2591 callsinfo->stop_rel_ts = pinfo->rel_ts;
2592 ++(callsinfo->npackets);
2593 /* increment the packets counter of all calls */
2594 ++(tapinfo->npackets);
2596 /* add to the graph */
2597 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2598 g_free(comment);
2599 g_free(frame_label);
2601 /* add SDP info if apply */
2602 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ) {
2603 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2604 g_free(sdp_summary);
2605 sdp_summary = NULL;
2608 tapinfo->redraw = TRUE;
2610 return 1; /* refresh output */
2614 /****************************************************************************/
2615 /* TAP INTERFACE */
2616 /****************************************************************************/
2617 static gboolean have_MGCP_tap_listener=FALSE;
2618 /****************************************************************************/
2619 void
2620 mgcp_calls_init_tap(void)
2622 GString *error_string;
2624 if(have_MGCP_tap_listener==FALSE)
2627 * Don't register the tap listener if we have it already.
2628 * We set TL_REQUIRES_PROTO_TREE to force a non-null "tree"
2629 * in the MGCP dissector; otherwise, the dissector
2630 * doesn't fill in the info passed to the tap's packet
2631 * routine.
2633 error_string = register_tap_listener("mgcp",
2634 &(the_tapinfo_struct.mgcp_dummy),
2635 NULL,
2636 TL_REQUIRES_PROTO_TREE,
2637 voip_calls_dlg_reset,
2638 MGCPcalls_packet,
2639 voip_calls_dlg_draw
2641 if (error_string != NULL) {
2642 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2643 "%s", error_string->str);
2644 g_string_free(error_string, TRUE);
2645 exit(1);
2647 have_MGCP_tap_listener=TRUE;
2651 /****************************************************************************/
2652 void
2653 remove_tap_listener_mgcp_calls(void)
2655 remove_tap_listener(&(the_tapinfo_struct.mgcp_dummy));
2657 have_MGCP_tap_listener=FALSE;
2661 /****************************************************************************/
2662 /****************************TAP for ACTRACE (AudioCodes trace)**************/
2663 /****************************************************************************/
2665 /* whenever a ACTRACE packet is seen by the tap listener */
2666 static int
2667 ACTRACEcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *ACTRACEinfo)
2669 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2670 const actrace_info_t *pi = (const actrace_info_t *)ACTRACEinfo;
2671 GList *list;
2672 actrace_cas_calls_info_t *tmp_actrace_cas_info;
2673 voip_calls_info_t *tmp_listinfo;
2674 voip_calls_info_t *callsinfo = NULL;
2677 actrace_frame_num = pinfo->fd->num;
2678 actrace_trunk = pi->trunk;
2679 actrace_direction = pi->direction;
2681 if (pi->type == 1) { /* is CAS protocol */
2682 address pstn_add;
2683 gchar *comment = NULL;
2685 callsinfo = NULL;
2686 list = g_list_first(tapinfo->callsinfo_list);
2687 while (list)
2689 tmp_listinfo=(voip_calls_info_t *)list->data;
2690 if ( tmp_listinfo->protocol == VOIP_AC_CAS ) {
2691 tmp_actrace_cas_info = (actrace_cas_calls_info_t *)tmp_listinfo->prot_info;
2692 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
2693 if ( (tmp_actrace_cas_info->bchannel == pi->cas_bchannel) && (tmp_actrace_cas_info->trunk == actrace_trunk) ) {
2694 callsinfo = (voip_calls_info_t*)(list->data);
2695 break;
2698 list = g_list_next (list);
2701 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, "PSTN");
2703 /* if it is a new call, add it to the list */
2704 if (!callsinfo) {
2705 callsinfo = (voip_calls_info_t *)g_malloc0(sizeof(voip_calls_info_t));
2706 callsinfo->call_active_state = VOIP_ACTIVE;
2707 callsinfo->call_state = VOIP_CALL_SETUP;
2708 callsinfo->from_identity=g_strdup("N/A");
2709 callsinfo->to_identity=g_strdup("N/A");
2710 COPY_ADDRESS(&(callsinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
2711 callsinfo->selected=FALSE;
2712 callsinfo->start_fd=pinfo->fd;
2713 callsinfo->start_rel_ts=pinfo->rel_ts;
2714 callsinfo->protocol=VOIP_AC_CAS;
2715 callsinfo->prot_info=g_malloc(sizeof(actrace_cas_calls_info_t));
2716 callsinfo->free_prot_info = g_free;
2718 tmp_actrace_cas_info=(actrace_cas_calls_info_t *)callsinfo->prot_info;
2719 tmp_actrace_cas_info->bchannel=pi->cas_bchannel;
2720 tmp_actrace_cas_info->trunk=actrace_trunk;
2721 callsinfo->npackets = 0;
2722 callsinfo->call_num = tapinfo->ncalls++;
2723 tapinfo->callsinfo_list = g_list_prepend(tapinfo->callsinfo_list, callsinfo);
2726 callsinfo->stop_fd = pinfo->fd;
2727 callsinfo->stop_rel_ts = pinfo->rel_ts;
2728 ++(callsinfo->npackets);
2729 /* increment the packets counter of all calls */
2730 ++(tapinfo->npackets);
2732 comment = g_strdup_printf("AC_CAS trunk:%u", actrace_trunk);
2734 add_to_graph(tapinfo, pinfo, pi->cas_frame_label, comment, callsinfo->call_num,
2735 actrace_direction?&pstn_add:&(pinfo->src),
2736 actrace_direction?&(pinfo->src):&pstn_add,
2737 1 );
2739 g_free(comment);
2742 tapinfo->redraw = TRUE;
2744 return 1; /* refresh output */
2748 /****************************************************************************/
2749 /* TAP INTERFACE */
2750 /****************************************************************************/
2751 static gboolean have_actrace_tap_listener=FALSE;
2752 /****************************************************************************/
2753 void
2754 actrace_calls_init_tap(void)
2756 GString *error_string;
2758 if(have_actrace_tap_listener==FALSE)
2760 /* don't register tap listener, if we have it already */
2761 error_string = register_tap_listener("actrace", &(the_tapinfo_struct.actrace_dummy), NULL,
2763 voip_calls_dlg_reset,
2764 ACTRACEcalls_packet,
2765 voip_calls_dlg_draw
2768 if (error_string != NULL) {
2769 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2770 "%s", error_string->str);
2771 g_string_free(error_string, TRUE);
2772 exit(1);
2774 have_actrace_tap_listener=TRUE;
2778 /****************************************************************************/
2779 void
2780 remove_tap_listener_actrace_calls(void)
2782 remove_tap_listener(&(the_tapinfo_struct.actrace_dummy));
2784 have_actrace_tap_listener=FALSE;
2788 /****************************************************************************/
2789 /**************************** TAP for H248/MEGACO **********************************/
2790 /****************************************************************************/
2791 static gboolean have_h248_tap_listener = FALSE;
2792 static gboolean have_megaco_tap_listener = FALSE;
2794 #define gcp_is_req(type) ( type == GCP_CMD_ADD_REQ || type == GCP_CMD_MOVE_REQ || type == GCP_CMD_MOD_REQ || \
2795 type == GCP_CMD_SUB_REQ || type == GCP_CMD_AUDITCAP_REQ || type == GCP_CMD_AUDITVAL_REQ || \
2796 type == GCP_CMD_NOTIFY_REQ || type == GCP_CMD_SVCCHG_REQ || type == GCP_CMD_TOPOLOGY_REQ || \
2797 type == GCP_CMD_CTX_ATTR_AUDIT_REQ )
2799 static int h248_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
2800 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2801 const gcp_cmd_t *cmd = (gcp_cmd_t *)prot_info;
2802 GList *list;
2803 voip_calls_info_t *callsinfo = NULL;
2804 address *mgw;
2805 address *mgc;
2806 gchar mgw_addr[128];
2808 if (cmd->ctx->id == NULL_CONTEXT || cmd->ctx->id == ALL_CONTEXTS ) {
2809 return 0;
2812 if ( gcp_is_req(cmd->type) ) {
2813 mgw = &(pinfo->dst);
2814 mgc = &(pinfo->src);
2815 } else {
2816 mgc = &(pinfo->dst);
2817 mgw = &(pinfo->src);
2820 address_to_str_buf(mgw, mgw_addr, 128);
2822 /* check whether we already have this context in the list */
2823 list = g_list_first(tapinfo->callsinfo_list);
2824 while (list)
2826 voip_calls_info_t* tmp_listinfo = (voip_calls_info_t *)list->data;
2828 if (tmp_listinfo->protocol == TEL_H248) {
2829 if (tmp_listinfo->prot_info == cmd->ctx) {
2830 callsinfo = (voip_calls_info_t*)(list->data);
2831 break;
2834 list = g_list_next (list);
2837 if (callsinfo==NULL) {
2839 callsinfo = (voip_calls_info_t *)g_malloc0(sizeof(voip_calls_info_t));
2840 callsinfo->call_state = VOIP_NO_STATE;
2841 callsinfo->call_active_state = VOIP_ACTIVE;
2842 callsinfo->from_identity = g_strdup_printf("%s : %.8x", mgw_addr, cmd->ctx->id);
2843 callsinfo->to_identity = g_strdup("");
2844 callsinfo->prot_info = cmd->ctx;
2845 callsinfo->free_prot_info = NULL;
2847 callsinfo->npackets = 1;
2849 COPY_ADDRESS(&(callsinfo->initial_speaker), mgc);
2851 callsinfo->protocol = TEL_H248;
2852 callsinfo->call_num = tapinfo->ncalls++;
2853 callsinfo->start_fd = pinfo->fd;
2854 callsinfo->start_rel_ts = pinfo->rel_ts;
2855 callsinfo->stop_fd = pinfo->fd;
2856 callsinfo->stop_rel_ts = pinfo->rel_ts;
2858 callsinfo->selected = FALSE;
2860 tapinfo->callsinfo_list = g_list_prepend(tapinfo->callsinfo_list, callsinfo);
2862 } else {
2863 GString *s = g_string_new("");
2864 gcp_terms_t *ctx_term;
2866 g_free(callsinfo->from_identity);
2867 callsinfo->from_identity = g_strdup_printf("%s : %.8x", mgw_addr, ((gcp_ctx_t*)callsinfo->prot_info)->id);
2869 g_free(callsinfo->to_identity);
2871 for (ctx_term = ((gcp_ctx_t*)callsinfo->prot_info)->terms.next;
2872 ctx_term;
2873 ctx_term = ctx_term->next ) {
2874 if ( ctx_term->term && ctx_term->term->str) {
2875 g_string_append_printf(s," %s",ctx_term->term->str);
2879 callsinfo->to_identity = s->str;
2880 g_string_free(s,FALSE);
2882 callsinfo->stop_fd = pinfo->fd;
2883 callsinfo->stop_rel_ts = pinfo->rel_ts;
2884 ++(callsinfo->npackets);
2887 add_to_graph(tapinfo, pinfo, cmd->str ? cmd->str : "unknown Msg",
2888 ep_strdup_printf("TrxId = %u, CtxId = %.8x",cmd->trx->id,cmd->ctx->id),
2889 callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2891 ++(tapinfo->npackets);
2893 tapinfo->redraw = TRUE;
2895 return 1;
2898 void h248_calls_init_tap(void)
2900 GString *error_string;
2903 if(have_megaco_tap_listener==FALSE)
2905 error_string = register_tap_listener("megaco", &(the_tapinfo_struct.megaco_dummy),
2906 NULL,
2908 voip_calls_dlg_reset,
2909 h248_calls_packet,
2910 voip_calls_dlg_draw);
2912 if (error_string != NULL) {
2913 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2914 "%s", error_string->str);
2915 g_string_free(error_string, TRUE);
2916 exit(1);
2919 have_megaco_tap_listener=TRUE;
2922 if(have_h248_tap_listener==FALSE)
2924 error_string = register_tap_listener("h248", &(the_tapinfo_struct.h248_dummy),
2925 NULL,
2927 voip_calls_dlg_reset,
2928 h248_calls_packet,
2929 voip_calls_dlg_draw);
2931 if (error_string != NULL) {
2932 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2933 "%s", error_string->str);
2934 g_string_free(error_string, TRUE);
2935 exit(1);
2938 have_h248_tap_listener=TRUE;
2942 void
2943 remove_tap_listener_h248_calls(void)
2945 remove_tap_listener(&(the_tapinfo_struct.h248_dummy));
2946 remove_tap_listener(&(the_tapinfo_struct.megaco_dummy));
2948 have_megaco_tap_listener=FALSE;
2949 have_h248_tap_listener=FALSE;
2952 /****************************************************************************/
2953 /**************************** TAP for SCCP and SUA **********************************/
2954 /**************************** ( RANAP and BSSAP ) **********************************/
2955 /****************************************************************************/
2957 static gboolean have_sccp_tap_listener = FALSE;
2958 static gboolean have_sua_tap_listener = FALSE;
2960 static const voip_protocol sccp_proto_map[] = {
2961 TEL_SCCP,
2962 TEL_BSSMAP,
2963 TEL_RANAP
2965 #define SP2VP(ap) ((ap) < SCCP_PLOAD_NUM_PLOADS ? sccp_proto_map[(ap)] : TEL_SCCP)
2966 const value_string* sccp_payload_values;
2968 static int sccp_calls(packet_info *pinfo, const void *prot_info) {
2969 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2970 const sccp_msg_info_t* msg = (const sccp_msg_info_t *)prot_info;
2971 sccp_assoc_info_t* assoc = msg->data.co.assoc;
2972 GList *list;
2973 voip_calls_info_t *callsinfo = NULL;
2974 const gchar *label = NULL;
2975 const gchar *comment = NULL;
2976 /* check whether we already have this assoc in the list */
2978 for(list = g_list_first(tapinfo->callsinfo_list) ; list ; list = g_list_next (list) ) {
2979 if ( ((voip_calls_info_t*)(list->data))->prot_info == assoc ) {
2980 callsinfo = (voip_calls_info_t*)(list->data);
2981 break;
2985 if (callsinfo==NULL) {
2986 callsinfo = (voip_calls_info_t *)g_malloc0(sizeof(voip_calls_info_t));
2987 callsinfo->call_state = VOIP_CALL_SETUP;
2988 callsinfo->call_active_state = VOIP_ACTIVE;
2989 if ( assoc->calling_party ) {
2990 callsinfo->from_identity = g_strdup(assoc->calling_party);
2991 } else {
2992 callsinfo->from_identity = g_strdup("Unknown");
2995 if ( assoc->called_party ) {
2996 callsinfo->to_identity = g_strdup(assoc->called_party);
2997 } else {
2998 callsinfo->to_identity = g_strdup("Unknown");
3001 callsinfo->prot_info = (void*)assoc;
3002 callsinfo->free_prot_info = NULL;
3004 callsinfo->npackets = 1;
3006 COPY_ADDRESS(&(callsinfo->initial_speaker), &(pinfo->src));
3008 callsinfo->protocol = SP2VP(assoc->payload);
3009 /* Store frame data which holds time and frame number */
3010 callsinfo->start_fd = pinfo->fd;
3011 callsinfo->start_rel_ts = pinfo->rel_ts;
3012 callsinfo->stop_fd = pinfo->fd;
3013 callsinfo->stop_rel_ts = pinfo->rel_ts;
3015 callsinfo->selected = FALSE;
3016 callsinfo->call_num = tapinfo->ncalls++;
3018 tapinfo->callsinfo_list = g_list_prepend(tapinfo->callsinfo_list, callsinfo);
3019 } else {
3021 if ( assoc->calling_party ) {
3022 g_free(callsinfo->from_identity);
3023 callsinfo->from_identity = g_strdup(assoc->calling_party);
3026 if ( assoc->called_party ) {
3027 g_free(callsinfo->to_identity);
3028 callsinfo->to_identity = g_strdup(assoc->called_party);
3031 callsinfo->protocol = SP2VP(assoc->payload);
3032 /* Store frame data which holds stop time and frame number */
3033 callsinfo->stop_fd = pinfo->fd;
3034 callsinfo->stop_rel_ts = pinfo->rel_ts;
3035 ++(callsinfo->npackets);
3037 switch (msg->type) {
3038 case SCCP_MSG_TYPE_CC:
3039 callsinfo->call_state = VOIP_IN_CALL;
3040 break;
3041 case SCCP_MSG_TYPE_RLC:
3042 callsinfo->call_state = VOIP_COMPLETED;
3043 callsinfo->call_active_state = VOIP_INACTIVE;
3044 break;
3045 default:
3046 break;
3050 if (msg->data.co.label) {
3051 label = msg->data.co.label;
3052 } else {
3053 label = val_to_str(msg->type, sccp_payload_values, "Unknown(%d)");
3056 if (msg->data.co.comment) {
3057 comment = msg->data.co.comment;
3058 } else {
3059 comment = NULL;
3062 add_to_graph(tapinfo, pinfo, label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3064 ++(tapinfo->npackets);
3066 tapinfo->redraw = TRUE;
3068 return 1;
3071 static int sccp_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
3072 sccp_payload_values = sccp_message_type_acro_values;
3073 return sccp_calls(pinfo, prot_info);
3077 static int sua_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info) {
3078 sccp_payload_values = sua_co_class_type_acro_values;
3079 return sccp_calls(pinfo, prot_info);
3083 void sccp_calls_init_tap(void)
3085 GString *error_string;
3087 if(have_sccp_tap_listener==FALSE)
3089 error_string = register_tap_listener("sccp", &(the_tapinfo_struct.sccp_dummy),
3090 NULL,
3092 voip_calls_dlg_reset,
3093 sccp_calls_packet,
3094 voip_calls_dlg_draw);
3096 if (error_string != NULL) {
3097 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3098 "%s", error_string->str);
3099 g_string_free(error_string, TRUE);
3100 exit(1);
3103 have_sccp_tap_listener=TRUE;
3106 if(have_sua_tap_listener==FALSE)
3108 error_string = register_tap_listener("sua", &(the_tapinfo_struct.sua_dummy),
3109 NULL,
3111 voip_calls_dlg_reset,
3112 sua_calls_packet,
3113 voip_calls_dlg_draw);
3115 if (error_string != NULL) {
3116 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3117 "%s", error_string->str);
3118 g_string_free(error_string, TRUE);
3119 exit(1);
3122 have_sua_tap_listener=TRUE;
3127 void
3128 remove_tap_listener_sccp_calls(void)
3130 remove_tap_listener(&(the_tapinfo_struct.sccp_dummy));
3132 have_sccp_tap_listener=FALSE;
3133 have_sua_tap_listener=FALSE;
3137 /****************************************************************************/
3138 /****************************TAP for UNISTIM ********************************/
3139 /****************************************************************************/
3141 static int
3142 unistim_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *unistim_info)
3144 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3145 voip_calls_info_t *tmp_listinfo;
3146 voip_calls_info_t *callsinfo = NULL;
3147 unistim_info_t *tmp_unistim_info = NULL;
3148 GList *list = NULL;
3149 GString *g_tmp = NULL;
3150 const gchar *frame_label = NULL;
3151 gchar *comment = NULL;
3153 /* Fetch specific packet infos */
3154 const unistim_info_t *pi = (const unistim_info_t *)unistim_info;
3156 /* Init gstring */
3157 g_tmp = g_string_new(NULL);
3159 /* Check to see if this is a dup */
3160 list = g_list_first(tapinfo->callsinfo_list);
3162 while(list)
3164 tmp_listinfo = (voip_calls_info_t *)list->data;
3166 if(tmp_listinfo->protocol == VOIP_UNISTIM) {
3168 tmp_unistim_info = (unistim_info_t *)tmp_listinfo->prot_info;
3170 /* Search by termid if possible, otherwise use ni/it ip + port.. */
3171 if(pi->termid != 0) {
3172 if(tmp_unistim_info->termid == pi->termid) {
3173 /* If the call has ended, then we can reuse it.. */
3174 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN) {
3175 /* Do nothing */
3176 } else {
3177 callsinfo = (voip_calls_info_t*)(list->data);
3178 break;
3181 } else {
3182 /* If no term id use ips / port to find entry */
3183 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)) {
3184 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN) {
3185 /* Do nothing previous call */
3186 } else {
3187 callsinfo = (voip_calls_info_t*)(list->data);
3188 break;
3191 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)) {
3192 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN) {
3193 /* Do nothing, it ain't our call.. */
3194 } else {
3195 callsinfo = (voip_calls_info_t*)(list->data);
3196 break;
3202 /* Otherwise, go to the next one.. */
3203 list = g_list_next(list);
3206 if(pi->payload_type == 2 || pi->payload_type == 1) {
3208 if(pi->key_state == 1 || pi->hook_state == 1) {
3210 /* If the user hits a button,
3211 Session will be SETUP */
3213 /* If new add to list */
3214 if (callsinfo==NULL) {
3216 callsinfo = (voip_calls_info_t *)g_malloc0(sizeof(voip_calls_info_t));
3217 callsinfo->call_active_state = VOIP_ACTIVE;
3218 callsinfo->call_state = VOIP_CALL_SETUP;
3219 callsinfo->from_identity=g_strdup_printf("%x",pi->termid);
3220 callsinfo->to_identity=g_strdup("UNKNOWN");
3221 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
3222 callsinfo->selected=FALSE;
3224 /* Set this on init of struct so in case the call doesn't complete, we'll have a ref. */
3225 /* Otherwise if the call is completed we'll have the open/close streams to ref actual call duration */
3226 /* Store frame data which holds time and frame number */
3227 callsinfo->start_fd=pinfo->fd;
3228 callsinfo->start_rel_ts=pinfo->rel_ts;
3230 callsinfo->protocol=VOIP_UNISTIM;
3231 callsinfo->prot_info=g_malloc(sizeof(unistim_info_t));
3233 tmp_unistim_info = (unistim_info_t *)callsinfo->prot_info;
3235 /* Clear tap struct */
3236 tmp_unistim_info->rudp_type = 0;
3237 tmp_unistim_info->payload_type = 0;
3238 tmp_unistim_info->sequence = pi->sequence;
3239 tmp_unistim_info->termid = pi->termid;
3240 tmp_unistim_info->key_val = -1;
3241 tmp_unistim_info->key_state = -1;
3242 tmp_unistim_info->hook_state = -1;
3243 tmp_unistim_info->stream_connect = -1;
3244 tmp_unistim_info->trans_connect = -1;
3245 tmp_unistim_info->set_termid = -1;
3246 tmp_unistim_info->string_data = NULL;
3247 tmp_unistim_info->key_buffer = NULL;
3249 COPY_ADDRESS(&(tmp_unistim_info->it_ip),&(pi->it_ip));
3250 COPY_ADDRESS(&(tmp_unistim_info->ni_ip),&(pi->ni_ip));
3251 tmp_unistim_info->it_port = pi->it_port;
3253 callsinfo->free_prot_info = g_free;
3254 callsinfo->npackets = 0;
3255 callsinfo->call_num = tapinfo->ncalls++;
3256 tapinfo->callsinfo_list = g_list_prepend(tapinfo->callsinfo_list, callsinfo);
3258 } else {
3260 /* Set up call wide info struct */
3261 tmp_unistim_info = (unistim_info_t *)callsinfo->prot_info;
3262 tmp_unistim_info->sequence = pi->sequence;
3265 /* Each packet COULD BE OUR LAST!!!! */
3266 /* Store frame data which holds time and frame number */
3267 callsinfo->stop_fd = pinfo->fd;
3268 callsinfo->stop_rel_ts = pinfo->rel_ts;
3270 /* This is a valid packet so increment counter */
3271 ++(callsinfo->npackets);
3273 /* increment the packets counter of all calls */
3274 ++(tapinfo->npackets);
3276 /* Key was depressed.. update key buffer.. */
3277 if(pi->key_val >= 0 && pi->key_val <= 11) {
3279 if(tmp_unistim_info->key_buffer != NULL) {
3281 /* assign to temp variable */
3282 g_string_assign(g_tmp,tmp_unistim_info->key_buffer);
3284 /* Manipulate the data */
3285 if(pi->key_val == 10) {
3286 tmp_unistim_info->key_buffer = g_strdup_printf("%s*",g_tmp->str);
3287 } else if(pi->key_val == 11) {
3288 tmp_unistim_info->key_buffer = g_strdup_printf("%s#",g_tmp->str);
3289 } else {
3290 tmp_unistim_info->key_buffer = g_strdup_printf("%s%d",g_tmp->str,pi->key_val);
3293 } else {
3295 /* Create new string */
3296 if(pi->key_val == 10) {
3297 tmp_unistim_info->key_buffer = g_strdup("*");
3298 } else if(pi->key_val == 11) {
3299 tmp_unistim_info->key_buffer = g_strdup("#");
3300 } else {
3301 tmp_unistim_info->key_buffer = g_strdup_printf("%d",pi->key_val);
3306 /* Select for non-digit characters */
3307 if(pi->key_val == 10) {
3308 comment = g_strdup_printf("Key Input Sent: * (%d)", pi->sequence);
3309 } else if(pi->key_val == 11) {
3310 comment = g_strdup_printf("Key Input Sent: # (%d)", pi->sequence);
3311 } else {
3312 comment = g_strdup_printf("Key Input Sent: %d (%d)",pi->key_val, pi->sequence);
3314 } else if(pi->key_val == 12) {
3315 /* Set label and comment for graph */
3316 comment = g_strdup_printf("Key Input Sent: UP (%d)", pi->sequence);
3317 } else if(pi->key_val == 13) {
3318 /* Set label and comment for graph */
3319 comment = g_strdup_printf("Key Input Sent: DOWN (%d)", pi->sequence);
3320 } else if(pi->key_val == 14) {
3321 /* Set label and comment for graph */
3322 comment = g_strdup_printf("Key Input Sent: RIGHT (%d)", pi->sequence);
3323 } else if(pi->key_val == 15) {
3324 if(pi->key_buffer != NULL) {
3325 /* Get data */
3326 g_string_assign(g_tmp,pi->key_buffer);
3328 /* Manipulate the data */
3329 g_string_truncate(g_tmp,g_tmp->len-1);
3331 /* Insert new data */
3332 tmp_unistim_info->key_buffer = g_strdup(g_tmp->str);
3335 /* Set label and comment for graph */
3336 comment = g_strdup_printf("Key Input Sent: LEFT (%d)", pi->sequence);
3337 } else if(pi->key_val == 20) {
3338 /* User pressed the soft key 0 probably dial */
3339 comment = g_strdup_printf("Key Input Sent: S0 (%d)", pi->sequence);
3340 } else if(pi->key_val == 21) {
3341 /* User pressed the soft key 1 */
3342 comment = g_strdup_printf("Key Input Sent: S1 (%d)", pi->sequence);
3343 } else if(pi->key_val == 22) {
3344 /* User pressed the soft key 2 */
3345 /* On cs2k phones, soft key 2 is backspace. */
3346 if(pi->key_buffer != NULL) {
3348 /* Get data */
3349 g_string_assign(g_tmp,pi->key_buffer);
3351 /* Manipulate the data */
3352 g_string_truncate(g_tmp,g_tmp->len-1);
3354 /* Insert new data */
3355 tmp_unistim_info->key_buffer = g_strdup(g_tmp->str);
3358 /* add label and comment */
3359 comment = g_strdup_printf("Key Input Sent: S2 (%d)", pi->sequence);
3360 } else if(pi->key_val == 28) {
3361 /* User pressed something */
3362 comment = g_strdup_printf("Key Input Sent: Release (%d)", pi->sequence);
3363 } else if(pi->key_val == 23) {
3364 /* User pressed the soft key 3 */
3365 /* Cancel on cs2k so clear buffer */
3366 /* On mcs it's config which will clear the buffer too */
3367 tmp_unistim_info->key_buffer = g_strdup("\n");
3369 /* User pressed something, set labels*/
3370 comment = g_strdup_printf("Key Input Sent: S3 (%d)", pi->sequence);
3371 } else if(pi->key_val == 27) {
3372 /* User pressed something */
3373 comment = g_strdup_printf("Key Input Sent: Hold (%d)", pi->sequence);
3374 } else if(pi->key_val == 29) {
3375 /* User pressed something */
3376 comment = g_strdup_printf("Key Input Sent: Mute (%d)", pi->sequence);
3377 } else if(pi->key_val == 30) {
3378 /* User pressed something */
3379 comment = g_strdup_printf("Key Input Sent: Headset (%d)", pi->sequence);
3380 } else if(pi->key_val == 31) {
3381 /* Handsfree button */
3382 comment = g_strdup_printf("Key Input Sent: Handsfree (%d)", pi->sequence);
3383 } else if(pi->key_val >= 32 && pi->key_val <= 56) {
3384 /* Prog. Key X */
3385 comment = g_strdup_printf("Key Input Sent: Prog%d (%d)", (pi->key_val & 31), pi->sequence);
3388 if(pi->key_val != -1) {
3390 frame_label = "KEY INPUT";
3392 if (comment == NULL)
3393 /* Ouch! What do you do!? */
3394 /* User pressed something */
3395 comment = g_strdup_printf("Key Input Sent: UNKNOWN - %d (%d)", pi->key_val, pi->sequence);
3397 /* add to the graph */
3398 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3400 g_free(comment);
3403 if(pi->hook_state == 1) {
3405 /* Phone is off hook */
3406 frame_label = "OFF HOOK";
3407 comment = g_strdup_printf("Off Hook (%d)", pi->sequence);
3409 /* add to the graph */
3410 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3412 g_free(comment);
3413 } else if(pi->hook_state == 0) {
3415 /* Phone is on hook */
3416 frame_label = "ON HOOK";
3417 comment = g_strdup_printf("On Hook (%d)", pi->sequence);
3419 /* add to the graph */
3420 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3422 g_free(comment);
3426 /* Open stream was sent from server */
3427 if(pi->stream_connect == 1 && callsinfo != NULL) {
3429 /* Open stream */
3430 /* Signifies the start of the call so set start_sec & start_usec */
3431 /* Frame data holds the time info */
3432 callsinfo->start_fd=pinfo->fd;
3433 callsinfo->start_rel_ts=pinfo->rel_ts;
3434 /* Each packet COULD BE OUR LAST!!!! */
3435 /* Store frame data which holds time and frame number */
3436 callsinfo->stop_fd = pinfo->fd;
3437 callsinfo->stop_rel_ts = pinfo->rel_ts;
3439 /* Local packets too */
3440 ++(callsinfo->npackets);
3442 /* increment the packets counter of all calls */
3443 ++(tapinfo->npackets);
3445 /* ?? means we're not quite sure if this is accurate. Since Unistim isn't a true
3446 Call control protocol, we can only guess at the destination by messing with
3447 key buffers. */
3448 if(tmp_unistim_info->key_buffer != NULL) {
3449 callsinfo->to_identity = g_strdup_printf("?? %s",tmp_unistim_info->key_buffer);
3452 /* change sequence number for ACK detection */
3453 tmp_unistim_info->sequence = pi->sequence;
3455 /* State changes too */
3456 callsinfo->call_active_state = VOIP_ACTIVE;
3457 callsinfo->call_state = VOIP_IN_CALL;
3459 /* Add graph data */
3460 frame_label = "STREAM OPENED";
3461 comment = g_strdup_printf("Stream Opened (%d)",pi->sequence);
3463 /* add to the graph */
3464 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3466 } else if(pi->stream_connect == 1 && callsinfo == NULL) {
3468 /* Research indicates some nortel products initiate stream first
3469 * without keypresses. therefore creating this solely on a keypress is
3470 * ineffective.
3471 * Sometimes calls start immediately with open stream.
3473 callsinfo = (voip_calls_info_t *)g_malloc0(sizeof(voip_calls_info_t));
3474 callsinfo->call_active_state = VOIP_ACTIVE;
3475 callsinfo->call_state = VOIP_CALL_SETUP;
3476 callsinfo->from_identity=g_strdup("UNKNOWN");
3477 callsinfo->to_identity=g_strdup("UNKNOWN");
3478 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
3479 callsinfo->selected=FALSE;
3481 /* Set this on init of struct so in case the call doesn't complete, we'll have a ref. */
3482 /* Otherwise if the call is completed we'll have the open/close streams to ref actual call duration */
3483 callsinfo->start_fd=pinfo->fd;
3484 callsinfo->start_rel_ts=pinfo->rel_ts;
3486 callsinfo->protocol=VOIP_UNISTIM;
3487 callsinfo->prot_info=g_malloc(sizeof(unistim_info_t));
3489 tmp_unistim_info = (unistim_info_t *)callsinfo->prot_info;
3491 /* Clear tap struct */
3492 tmp_unistim_info->rudp_type = 0;
3493 tmp_unistim_info->payload_type = 0;
3494 tmp_unistim_info->sequence = pi->sequence;
3495 tmp_unistim_info->termid = 0;
3496 tmp_unistim_info->key_val = -1;
3497 tmp_unistim_info->key_state = -1;
3498 tmp_unistim_info->hook_state = -1;
3499 tmp_unistim_info->stream_connect = -1;
3500 tmp_unistim_info->trans_connect = -1;
3501 tmp_unistim_info->set_termid = -1;
3502 tmp_unistim_info->string_data = NULL;
3503 tmp_unistim_info->key_buffer = NULL;
3505 COPY_ADDRESS(&(tmp_unistim_info->it_ip),&(pi->it_ip));
3506 COPY_ADDRESS(&(tmp_unistim_info->ni_ip),&(pi->ni_ip));
3507 tmp_unistim_info->it_port = pi->it_port;
3509 callsinfo->free_prot_info = g_free;
3510 callsinfo->npackets = 0;
3511 callsinfo->call_num = tapinfo->ncalls++;
3512 tapinfo->callsinfo_list = g_list_prepend(tapinfo->callsinfo_list, callsinfo);
3514 /* Open stream */
3515 /* Each packet COULD BE OUR LAST!!!! */
3516 /* Store frame data which holds time and frame number */
3517 callsinfo->stop_fd = pinfo->fd;
3518 callsinfo->stop_rel_ts = pinfo->rel_ts;
3519 /* Local packets too */
3520 ++(callsinfo->npackets);
3522 /* increment the packets counter of all calls */
3523 ++(tapinfo->npackets);
3525 /* ?? means we're not quite sure if this is accurate. Since Unistim isn't a true
3526 Call control protocol, we can only guess at the destination by messing with
3527 key buffers. */
3528 if(tmp_unistim_info->key_buffer != NULL) {
3529 callsinfo->to_identity = g_strdup_printf("?? %s",tmp_unistim_info->key_buffer);
3532 /* change sequence number for ACK detection */
3533 tmp_unistim_info->sequence = pi->sequence;
3535 /* State changes too */
3536 callsinfo->call_active_state = VOIP_ACTIVE;
3537 callsinfo->call_state = VOIP_IN_CALL;
3539 /* Add graph data */
3540 frame_label = "STREAM OPENED";
3541 comment = g_strdup_printf("Stream Opened (%d)",pi->sequence);
3543 /* add to the graph */
3544 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3546 } else if(pi->stream_connect == 0 && callsinfo != NULL) {
3547 /* Close Stream */
3549 /* Set stop seconds + usec */
3550 /* frame_data holds the time info */
3551 callsinfo->stop_fd = pinfo->fd;
3552 callsinfo->stop_rel_ts = pinfo->rel_ts;
3554 tmp_unistim_info->sequence = pi->sequence;
3556 if(callsinfo->call_state == VOIP_IN_CALL) {
3557 callsinfo->call_active_state = VOIP_INACTIVE;
3558 callsinfo->call_state = VOIP_COMPLETED;
3559 } else {
3560 callsinfo->call_state = VOIP_UNKNOWN;
3561 callsinfo->call_active_state = VOIP_INACTIVE;
3564 frame_label = "STREAM CLOSED";
3565 comment = g_strdup_printf("Stream Closed (%d)",pi->sequence);
3567 /* add to the graph */
3568 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3570 } else
3571 comment = NULL;
3573 } else if(pi->rudp_type == 1 && callsinfo != NULL) {
3574 /* ACK */
3575 /* Only show acks for processed seq #s */
3576 if(tmp_unistim_info->sequence == pi->sequence) {
3578 frame_label = "ACK";
3579 comment = g_strdup_printf("ACK for sequence %d",pi->sequence);
3581 /* add to the graph */
3582 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3586 } else if(pi->rudp_type == 0 && callsinfo != NULL) {
3588 /* NAK */
3589 frame_label = "NAK";
3590 comment = g_strdup_printf("NAK for sequence %d",pi->sequence);
3592 /* add to the graph */
3593 add_to_graph(tapinfo, pinfo, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3597 /* free data */
3598 g_free(comment);
3600 tapinfo->redraw = TRUE;
3602 return 1;
3605 /****************************************************************************/
3606 /* TAP INTERFACE */
3607 /****************************************************************************/
3608 static gboolean have_unistim_tap_listener=FALSE;
3609 /****************************************************************************/
3610 void
3611 unistim_calls_init_tap(void) {
3613 GString *error_string;
3615 if(have_unistim_tap_listener==FALSE) {
3617 error_string = register_tap_listener("unistim", &(the_tapinfo_struct.unistim_dummy),
3618 NULL,
3620 voip_calls_dlg_reset,
3621 unistim_calls_packet,
3622 voip_calls_dlg_draw
3625 if (error_string != NULL) {
3626 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3627 "%s", error_string->str);
3628 g_string_free(error_string, TRUE);
3629 exit(1);
3632 have_unistim_tap_listener=TRUE;
3636 /****************************************************************************/
3637 void
3638 remove_tap_listener_unistim_calls(void)
3640 remove_tap_listener(&(the_tapinfo_struct.unistim_dummy));
3642 have_unistim_tap_listener=FALSE;
3645 /****************************************************************************/
3646 /* ***************************TAP for SKINNY **********************************/
3647 /****************************************************************************/
3649 /* Telecaster to tap-voip call state mapping */
3650 static const voip_call_state skinny_tap_voip_state[] = {
3651 VOIP_NO_STATE,
3652 VOIP_CALL_SETUP,
3653 VOIP_COMPLETED,
3654 VOIP_RINGING,
3655 VOIP_RINGING,
3656 VOIP_IN_CALL,
3657 VOIP_REJECTED,
3658 VOIP_REJECTED,
3659 VOIP_IN_CALL,
3660 VOIP_IN_CALL,
3661 VOIP_COMPLETED,
3662 VOIP_COMPLETED,
3663 VOIP_CALL_SETUP,
3664 VOIP_UNKNOWN,
3665 VOIP_REJECTED
3668 static int
3669 skinny_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *skinny_info)
3671 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3672 GList* list;
3673 voip_calls_info_t *callsinfo = NULL;
3674 address* phone;
3675 const skinny_info_t *si = (skinny_info_t *)skinny_info;
3676 skinny_calls_info_t *tmp_skinnyinfo;
3677 gchar *comment;
3679 if (si == NULL || (si->callId == 0 && si->passThruId == 0))
3680 return 0;
3681 /* check whether we already have this context in the list */
3682 list = g_list_first(tapinfo->callsinfo_list);
3683 while (list)
3685 voip_calls_info_t* tmp_listinfo = (voip_calls_info_t *)list->data;
3686 if (tmp_listinfo->protocol == VOIP_SKINNY) {
3687 tmp_skinnyinfo = (skinny_calls_info_t *)tmp_listinfo->prot_info;
3688 if (tmp_skinnyinfo->callId == si->callId ||
3689 tmp_skinnyinfo->callId == si->passThruId) {
3690 callsinfo = (voip_calls_info_t*)(list->data);
3691 break;
3694 list = g_list_next (list);
3697 if (si->messId >= 256)
3698 phone = &(pinfo->dst);
3699 else
3700 phone = &(pinfo->src);
3702 if (callsinfo==NULL) {
3703 callsinfo = (voip_calls_info_t *)g_malloc0(sizeof(voip_calls_info_t));
3704 callsinfo->call_state = VOIP_NO_STATE;
3705 callsinfo->call_active_state = VOIP_ACTIVE;
3706 /* callsinfo->from_identity = g_strdup_printf("%s : %.8x", "Skinny", 1); */
3707 callsinfo->from_identity = g_strdup("");
3708 callsinfo->to_identity = g_strdup("");
3709 callsinfo->prot_info = g_malloc(sizeof(skinny_calls_info_t));
3710 callsinfo->free_prot_info = g_free;
3711 tmp_skinnyinfo = (skinny_calls_info_t *)callsinfo->prot_info;
3712 tmp_skinnyinfo->callId = si->callId ? si->callId : si->passThruId;
3713 callsinfo->npackets = 1;
3715 COPY_ADDRESS(&(callsinfo->initial_speaker), phone);
3717 callsinfo->protocol = VOIP_SKINNY;
3718 callsinfo->call_num = tapinfo->ncalls++;
3719 callsinfo->start_fd = pinfo->fd;
3720 callsinfo->start_rel_ts = pinfo->rel_ts;
3721 callsinfo->stop_fd = pinfo->fd;
3722 callsinfo->stop_rel_ts = pinfo->rel_ts;
3724 callsinfo->selected = FALSE;
3725 tapinfo->callsinfo_list = g_list_prepend(tapinfo->callsinfo_list, callsinfo);
3726 } else {
3727 if (si->callingParty) {
3728 g_free(callsinfo->from_identity);
3729 callsinfo->from_identity = g_strdup(si->callingParty);
3731 if (si->calledParty) {
3732 g_free(callsinfo->to_identity);
3733 callsinfo->to_identity = g_strdup(si->calledParty);
3735 if ((si->callState > 0) && (si->callState < (sizeof(skinny_tap_voip_state)/sizeof(skinny_tap_voip_state[0]))))
3736 callsinfo->call_state = skinny_tap_voip_state[si->callState];
3738 callsinfo->stop_fd = pinfo->fd;
3739 callsinfo->stop_rel_ts = pinfo->rel_ts;
3740 ++(callsinfo->npackets);
3743 if (si->callId) {
3744 if (si->passThruId)
3745 comment = g_strdup_printf("CallId = %u, PTId = %u", si->callId, si->passThruId);
3746 else
3747 comment = g_strdup_printf("CallId = %u, LineId = %u", si->callId, si->lineId);
3748 } else {
3749 if (si->passThruId)
3750 comment = g_strdup_printf("PTId = %u", si->passThruId);
3751 else
3752 comment = NULL;
3755 add_to_graph(tapinfo, pinfo, si->messageName, comment,
3756 callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3757 g_free(comment);
3759 return 1;
3763 /****************************************************************************/
3764 /* TAP INTERFACE */
3765 /****************************************************************************/
3766 static gboolean have_skinny_tap_listener=FALSE;
3767 /****************************************************************************/
3768 void
3769 skinny_calls_init_tap(void)
3771 GString *error_string;
3773 if(have_skinny_tap_listener==FALSE)
3776 * Don't register the tap listener if we have it already.
3777 * We set TL_REQUIRES_PROTO_TREE to force a non-null "tree"
3778 * in the SKINNY dissector; otherwise, the dissector
3779 * doesn't fill in the info passed to the tap's packet
3780 * routine.
3782 error_string = register_tap_listener("skinny",
3783 &(the_tapinfo_struct.skinny_dummy),
3784 NULL,
3785 TL_REQUIRES_PROTO_TREE,
3786 voip_calls_dlg_reset,
3787 skinny_calls_packet,
3788 voip_calls_dlg_draw
3790 if (error_string != NULL) {
3791 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3792 "%s", error_string->str);
3793 g_string_free(error_string, TRUE);
3794 exit(1);
3796 have_skinny_tap_listener=TRUE;
3800 /****************************************************************************/
3801 void
3802 remove_tap_listener_skinny_calls(void)
3804 remove_tap_listener(&(the_tapinfo_struct.skinny_dummy));
3806 have_skinny_tap_listener=FALSE;
3809 /****************************************************************************/
3810 /* ***************************TAP for IAX2 **********************************/
3811 /****************************************************************************/
3813 static void free_iax2_info(gpointer p) {
3814 iax2_info_t *ii = (iax2_info_t *)p;
3816 g_free(ii);
3820 /****************************************************************************/
3821 /* whenever a IAX2 packet is seen by the tap listener */
3822 static int
3823 iax2_calls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *iax2_info)
3825 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3826 GList* list;
3827 voip_calls_info_t *callsinfo = NULL;
3828 address* phone;
3829 const iax2_info_t *ii = (iax2_info_t *)iax2_info;
3830 iax2_info_t *tmp_iax2info;
3832 if (ii == NULL || ii->ptype != IAX2_FULL_PACKET || (ii->scallno == 0 && ii->dcallno == 0))
3833 return 0;
3834 /* check whether we already have this context in the list */
3835 list = g_list_first(tapinfo->callsinfo_list);
3836 while (list)
3838 voip_calls_info_t* tmp_listinfo = (voip_calls_info_t *)list->data;
3839 if (tmp_listinfo->protocol == VOIP_IAX2) {
3840 tmp_iax2info = (iax2_info_t *)tmp_listinfo->prot_info;
3841 if (tmp_iax2info->scallno == ii->scallno ||
3842 tmp_iax2info->scallno == ii->dcallno) {
3843 callsinfo = (voip_calls_info_t*)(list->data);
3844 break;
3847 list = g_list_next (list);
3849 phone = &(pinfo->src);
3852 if (callsinfo==NULL) {
3853 /* We only care about real calls, i.e., no registration stuff */
3854 if (ii->ftype != AST_FRAME_IAX || ii->csub != IAX_COMMAND_NEW)
3855 return 0;
3856 callsinfo = (voip_calls_info_t *)g_malloc0(sizeof(voip_calls_info_t));
3857 callsinfo->call_state = VOIP_NO_STATE;
3858 callsinfo->call_active_state = VOIP_ACTIVE;
3859 callsinfo->prot_info=g_malloc(sizeof(iax2_info_t));
3860 callsinfo->free_prot_info = free_iax2_info;
3861 tmp_iax2info = (iax2_info_t *)callsinfo->prot_info;
3863 tmp_iax2info->scallno = ii->scallno;
3864 if (tmp_iax2info->scallno == 0) tmp_iax2info->scallno = ii->dcallno;
3865 tmp_iax2info->callState = ii->callState;
3867 callsinfo->npackets = 1;
3869 COPY_ADDRESS(&(callsinfo->initial_speaker), phone);
3870 callsinfo->from_identity = g_strdup(ii->callingParty);
3871 callsinfo->to_identity = g_strdup(ii->calledParty);
3873 callsinfo->protocol = VOIP_IAX2;
3874 callsinfo->call_num = tapinfo->ncalls++;
3875 callsinfo->start_fd=pinfo->fd;
3876 callsinfo->start_rel_ts=pinfo->rel_ts;
3877 callsinfo->stop_fd = pinfo->fd;
3878 callsinfo->stop_rel_ts = pinfo->rel_ts;
3880 callsinfo->selected = FALSE;
3881 tapinfo->callsinfo_list = g_list_prepend(tapinfo->callsinfo_list, callsinfo);
3883 } else {
3884 callsinfo->call_state = ii->callState;
3886 callsinfo->stop_fd = pinfo->fd;
3887 callsinfo->stop_rel_ts = pinfo->rel_ts;
3888 ++(callsinfo->npackets);
3891 add_to_graph(tapinfo, pinfo, ii->messageName, "",
3892 callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3894 return 1;
3899 /****************************************************************************/
3900 /* TAP INTERFACE */
3901 /****************************************************************************/
3902 static gboolean have_iax2_tap_listener=FALSE;
3903 /****************************************************************************/
3904 void
3905 iax2_calls_init_tap(void)
3907 GString *error_string;
3909 if(have_iax2_tap_listener==FALSE)
3912 * Don't register the tap listener if we have it already.
3913 * We set TL_REQUIRES_PROTO_TREE to force a non-null "tree"
3914 * in the IAX2 dissector; otherwise, the dissector
3915 * doesn't fill in the info passed to the tap's packet
3916 * routine.
3917 * XXX - that appears to be true of the MGCP and SKINNY
3918 * dissectors, but, unless I've missed something, it doesn't
3919 * appear to be true of the IAX2 dissector.
3921 error_string = register_tap_listener("IAX2",
3922 &(the_tapinfo_struct.iax2_dummy),
3923 NULL,
3924 TL_REQUIRES_PROTO_TREE,
3925 voip_calls_dlg_reset,
3926 iax2_calls_packet,
3927 voip_calls_dlg_draw
3929 if (error_string != NULL) {
3930 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s",
3931 error_string->str);
3932 g_string_free(error_string, TRUE);
3933 exit(1);
3935 have_iax2_tap_listener=TRUE;
3939 /****************************************************************************/
3940 void
3941 remove_tap_listener_iax2_calls(void)
3943 remove_tap_listener(&(the_tapinfo_struct.iax2_dummy));
3945 have_iax2_tap_listener=FALSE;
3948 /****************************************************************************/
3949 /* ***************************TAP for OTHER PROTOCOL **********************************/
3950 /****************************************************************************/
3952 static int
3953 VoIPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *VoIPinfo)
3955 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
3956 voip_calls_info_t *callsinfo = NULL;
3957 voip_calls_info_t *tmp_listinfo;
3958 GList *list = NULL;
3959 const voip_packet_info_t *pi = (voip_packet_info_t *)VoIPinfo;
3961 if (pi->call_id)
3962 list = g_list_first(tapinfo->callsinfo_list);
3963 while (list) {
3964 tmp_listinfo = (voip_calls_info_t *)list->data;
3965 if ( tmp_listinfo->protocol == VOIP_COMMON ) {
3966 if (!strcmp(pi->call_id, tmp_listinfo->call_id)) {
3967 callsinfo = (voip_calls_info_t*)(list->data);
3968 break;
3971 list = g_list_next(list);
3974 if (callsinfo == NULL) {
3975 callsinfo = (voip_calls_info_t *)g_malloc0(sizeof(voip_calls_info_t));
3976 callsinfo->call_active_state = pi->call_active_state;
3977 callsinfo->call_state = pi->call_state;
3978 callsinfo->call_id=g_strdup((pi->call_id)?pi->call_id:"");
3979 callsinfo->from_identity = g_strdup((pi->from_identity)?pi->from_identity:"");
3980 callsinfo->to_identity = g_strdup((pi->to_identity)?pi->to_identity:"");
3981 COPY_ADDRESS(&(callsinfo->initial_speaker),&(pinfo->src));
3982 callsinfo->selected=FALSE;
3983 callsinfo->start_fd=pinfo->fd;
3984 callsinfo->start_rel_ts=pinfo->rel_ts;
3985 callsinfo->protocol=VOIP_COMMON;
3986 callsinfo->protocol_name=g_strdup((pi->protocol_name)?pi->protocol_name:"");
3987 callsinfo->call_comment=g_strdup((pi->call_comment)?pi->call_comment:"");
3988 callsinfo->prot_info=NULL;
3989 callsinfo->free_prot_info = NULL;
3991 callsinfo->call_num = tapinfo->ncalls++;
3992 callsinfo->npackets = 0;
3994 tapinfo->callsinfo_list = g_list_prepend(tapinfo->callsinfo_list, callsinfo);
3997 callsinfo->call_active_state = pi->call_active_state;
3998 if ((callsinfo->call_state != VOIP_COMPLETED) && (pi->call_state == VOIP_COMPLETED))
3999 tapinfo->completed_calls++;
4000 if (pi->call_state != VOIP_NO_STATE)
4001 callsinfo->call_state = pi->call_state;
4002 if (pi->call_comment) {
4003 g_free(callsinfo->call_comment);
4004 callsinfo->call_comment=g_strdup(pi->call_comment);
4006 callsinfo->stop_fd = pinfo->fd;
4007 callsinfo->stop_rel_ts = pinfo->rel_ts;
4008 ++(callsinfo->npackets);
4009 ++(tapinfo->npackets);
4011 /* add to the graph */
4012 add_to_graph(tapinfo, pinfo, (pi->frame_label)?pi->frame_label:"VoIP msg", pi->frame_comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
4014 tapinfo->redraw = TRUE;
4016 return 1;
4018 /****************************************************************************/
4019 static gboolean have_voip_tap_listener=FALSE;
4021 void
4022 VoIPcalls_init_tap(void)
4024 GString *error_string;
4026 if(have_voip_tap_listener==FALSE)
4028 error_string = register_tap_listener("voip", &(the_tapinfo_struct.voip_dummy),
4029 NULL,
4031 voip_calls_dlg_reset,
4032 VoIPcalls_packet,
4033 voip_calls_dlg_draw
4036 if (error_string != NULL) {
4037 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4038 "%s", error_string->str);
4039 g_string_free(error_string, TRUE);
4040 exit(1);
4042 have_voip_tap_listener=TRUE;
4045 /****************************************************************************/
4046 void
4047 remove_tap_listener_voip_calls(void)
4049 remove_tap_listener(&(the_tapinfo_struct.voip_dummy));
4051 have_voip_tap_listener=FALSE;
4055 /****************************************************************************/
4056 /* ***************************TAP for OTHER PROTOCOL **********************************/
4057 /****************************************************************************/
4059 /****************************************************************************/
4060 /* whenever a prot_ packet is seen by the tap listener */
4062 static int
4063 prot_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info _U_)
4065 voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
4066 if (callsinfo!=NULL) {
4067 callsinfo->stop_abs = pinfo->fd->abs_ts;
4068 callsinfo->stop_rel = pinfo->rel_ts;
4069 callsinfo->last_frame_num=pinfo->fd->num;
4070 ++(callsinfo->npackets);
4071 ++(tapinfo->npackets);
4074 tapinfo->redraw = TRUE;
4076 return 1;
4079 /****************************************************************************/
4081 static gboolean have_prot__tap_listener=FALSE;
4083 void
4084 prot_calls_init_tap(void)
4086 GString *error_string;
4088 if(have_prot__tap_listener==FALSE)
4090 error_string = register_tap_listener("prot_", &(the_tapinfo_struct.prot__dummy),
4091 NULL,
4093 voip_calls_dlg_reset,
4094 prot__calls_packet,
4095 voip_calls_dlg_draw
4098 if (error_string != NULL) {
4099 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4100 "%s", error_string->str);
4101 g_string_free(error_string, TRUE);
4102 exit(1);
4104 have_prot__tap_listener=TRUE;
4108 /****************************************************************************/
4110 void
4111 remove_tap_listener_prot__calls(void)
4113 remove_tap_listener(&(the_tapinfo_struct.prot__dummy));
4115 have_prot__tap_listener=FALSE;
4121 * Editor modelines - http://www.wireshark.org/tools/modelines.html
4123 * Local variables:
4124 * c-basic-offset: 8
4125 * tab-width: 8
4126 * indent-tabs-mode: t
4127 * End:
4129 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
4130 * :indentSize=8:tabSize=8:noTabs=false: