dcerpc SPLIT auth_session_key
[wireshark-sm.git] / ui / voip_calls.c
blob2e6b5604980a6a353749a49af2a287830d0d1154
1 /* voip_calls.c
2 * VoIP calls summary addition for Wireshark
4 * Copyright 2004, Ericsson, Spain
5 * By Francisco Alcoba <francisco.alcoba@ericsson.com>
7 * based on h323_calls.c
8 * Copyright 2004, Iskratel, Ltd, Kranj
9 * By Miha Jemec <m.jemec@iskratel.si>
11 * H323, RTP, RTP Event, MGCP, AudioCodes (ISDN PRI and CAS), T38 and Graph Support
12 * By Alejandro Vaquero, alejandro.vaquero@verso.com
13 * Copyright 2005, Verso Technologies Inc.
15 * Wireshark - Network traffic analyzer
16 * By Gerald Combs <gerald@wireshark.org>
17 * Copyright 1998 Gerald Combs
19 * SPDX-License-Identifier: GPL-2.0-or-later
22 #include "config.h"
24 #include <stdlib.h>
25 #include <string.h>
27 #include "epan/epan_dissect.h"
28 #include "epan/packet.h"
29 #include "epan/proto_data.h"
30 #include "epan/to_str.h"
31 #include "epan/dissectors/packet-sip.h"
32 #include "epan/dissectors/packet-h225.h"
33 #include "epan/dissectors/packet-h245.h"
34 #include "epan/dissectors/packet-isup.h"
35 #include "epan/dissectors/packet-sdp.h"
36 #include "epan/dissectors/packet-mgcp.h"
37 #include "epan/dissectors/packet-mtp3.h"
38 #include "epan/dissectors/packet-actrace.h"
39 #include "epan/dissectors/packet-q931.h"
40 #include "epan/dissectors/packet-rtp.h"
41 #include "epan/dissectors/packet-rtp-events.h"
42 #include "epan/dissectors/packet-t38.h"
43 #include "epan/dissectors/packet-t30.h"
44 #include "epan/dissectors/packet-h248.h"
45 #include "epan/dissectors/packet-sccp.h"
46 #include "plugins/epan/unistim/packet-unistim.h"
47 #include "epan/dissectors/packet-skinny.h"
48 #include "epan/dissectors/packet-iax2.h"
49 #include "epan/rtp_pt.h"
51 #include "ui/rtp_stream.h"
52 #include "ui/simple_dialog.h"
53 #include "ui/tap-rtp-common.h"
54 #include "ui/ws_ui_util.h"
55 #include "ui/voip_calls.h"
57 #include "wsutil/glib-compat.h"
58 #include <wsutil/ws_assert.h>
60 #define DUMP_PTR1(p) printf("#=> %p\n",(void *)p)
61 #define DUMP_PTR2(p) printf("==> %p\n",(void *)p)
63 const char *voip_call_state_name[8]={
64 "",
65 "CALL SETUP",
66 "RINGING",
67 "IN CALL",
68 "CANCELLED",
69 "COMPLETED",
70 "REJECTED",
71 "UNKNOWN"
74 /* defines whether we can consider the call active */
75 const char *voip_protocol_name[]={
76 "SIP",
77 "ISUP",
78 "H.323",
79 "MGCP",
80 "AC_ISDN",
81 "AC_CAS",
82 "T.38",
83 "H.248",
84 "SCCP",
85 "BSSMAP",
86 "RANAP",
87 "UNISTIM",
88 "SKINNY",
89 "IAX2",
90 "VoIP"
94 * Tap IDs must be unique. Since different taps need to share the
95 * same voip_calls_tapinfo_t *, make it unique by offsetting its
96 * value.
98 enum {
99 tap_id_offset_actrace_,
100 tap_id_offset_h225_,
101 tap_id_offset_h245dg_,
102 tap_id_offset_h248_,
103 tap_id_offset_iax2_,
104 tap_id_offset_isup_,
105 tap_id_offset_m3ua_,
106 tap_id_offset_megaco_,
107 tap_id_offset_mgcp_,
108 tap_id_offset_mtp3_,
109 tap_id_offset_q931_,
110 tap_id_offset_rtp_,
111 tap_id_offset_rtp_event_,
112 tap_id_offset_sccp_,
113 tap_id_offset_sdp_,
114 tap_id_offset_sip_,
115 tap_id_offset_skinny_,
116 tap_id_offset_sua_,
117 tap_id_offset_t38_,
118 tap_id_offset_unistim_,
119 tap_id_offset_voip_
122 #define REDRAW_ACTRACE (1 << tap_id_offset_actrace_)
123 #define REDRAW_H225 (1 << tap_id_offset_h225_)
124 #define REDRAW_H245DG (1 << tap_id_offset_h245dg_)
125 #define REDRAW_H248 (1 << tap_id_offset_h248_)
126 #define REDRAW_IAX2 (1 << tap_id_offset_iax2_)
127 #define REDRAW_ISUP (1 << tap_id_offset_isup_)
128 #define REDRAW_M3UA (1 << tap_id_offset_m3ua_)
129 #define REDRAW_MEGACO (1 << tap_id_offset_megaco_)
130 #define REDRAW_MGCP (1 << tap_id_offset_mgcp_)
131 #define REDRAW_MTP3 (1 << tap_id_offset_mtp3_)
132 #define REDRAW_Q931 (1 << tap_id_offset_q931_)
133 #define REDRAW_RTP (1 << tap_id_offset_rtp_)
134 #define REDRAW_RTP_EVENT (1 << tap_id_offset_rtp_event_)
135 #define REDRAW_SCCP (1 << tap_id_offset_sccp_)
136 #define REDRAW_SDP (1 << tap_id_offset_sdp_)
137 #define REDRAW_SIP (1 << tap_id_offset_sip_)
138 #define REDRAW_SKINNY (1 << tap_id_offset_skinny_)
139 #define REDRAW_SUA (1 << tap_id_offset_sua_)
140 #define REDRAW_T38 (1 << tap_id_offset_t38_)
141 #define REDRAW_UNISTIM (1 << tap_id_offset_unistim_)
142 #define REDRAW_VOIP (1 << tap_id_offset_voip_)
144 static inline void *
145 tap_base_to_id(voip_calls_tapinfo_t* tap_base, int offset) {
146 return GSIZE_TO_POINTER(GPOINTER_TO_SIZE(tap_base) + offset);
149 static inline voip_calls_tapinfo_t *
150 tap_id_to_base(void* tap_id, int offset) {
151 return (voip_calls_tapinfo_t *) GSIZE_TO_POINTER(GPOINTER_TO_SIZE(tap_id) - offset);
154 typedef struct {
155 char *frame_label;
156 char *comment;
157 } graph_str;
159 #define H245_MAX 6
161 typedef struct _h245_labels {
162 uint32_t frame_num;
163 int8_t labels_count;
164 graph_str labels[H245_MAX];
165 } h245_labels_t;
167 static void actrace_calls_init_tap(voip_calls_tapinfo_t *tap_id_base);
168 static void h225_calls_init_tap(voip_calls_tapinfo_t *tap_id_base);
169 static void h245dg_calls_init_tap(voip_calls_tapinfo_t *tap_id_base);
170 static void h248_calls_init_tap(voip_calls_tapinfo_t *tap_id_base);
171 static void iax2_calls_init_tap(voip_calls_tapinfo_t *tap_id_base);
172 static void isup_calls_init_tap(voip_calls_tapinfo_t *tap_id_base);
173 static void mgcp_calls_init_tap(voip_calls_tapinfo_t *tap_id_base);
174 static void mtp3_calls_init_tap(voip_calls_tapinfo_t *tap_id_base);
175 static void q931_calls_init_tap(voip_calls_tapinfo_t *tap_id_base);
176 static void rtp_event_init_tap(voip_calls_tapinfo_t *tap_id_base);
177 static void rtp_init_tap(voip_calls_tapinfo_t *tap_id_base);
178 static void sccp_calls_init_tap(voip_calls_tapinfo_t *tap_id_base);
179 static void sdp_calls_init_tap(voip_calls_tapinfo_t *tap_id_base);
180 static void sip_calls_init_tap(voip_calls_tapinfo_t *tap_id_base);
181 static void skinny_calls_init_tap(voip_calls_tapinfo_t *tap_id_base);
182 static void t38_init_tap(voip_calls_tapinfo_t *tap_id_base);
183 static void unistim_calls_init_tap(voip_calls_tapinfo_t *tap_id_base);
184 static void voip_calls_init_tap(voip_calls_tapinfo_t *tap_id_base);
186 void
187 voip_calls_init_all_taps(voip_calls_tapinfo_t *tap_id_base)
189 actrace_calls_init_tap(tap_id_base);
190 h225_calls_init_tap(tap_id_base);
191 h245dg_calls_init_tap(tap_id_base);
192 h248_calls_init_tap(tap_id_base);
193 iax2_calls_init_tap(tap_id_base);
194 isup_calls_init_tap(tap_id_base);
195 mgcp_calls_init_tap(tap_id_base);
196 mtp3_calls_init_tap(tap_id_base);
197 q931_calls_init_tap(tap_id_base);
198 rtp_event_init_tap(tap_id_base);
199 rtp_init_tap(tap_id_base); /* This calls tap_reset_cb, tap_packet_cb, and tap_draw_cb */
200 sccp_calls_init_tap(tap_id_base);
201 sdp_calls_init_tap(tap_id_base);
202 sip_calls_init_tap(tap_id_base);
203 skinny_calls_init_tap(tap_id_base);
204 t38_init_tap(tap_id_base);
205 /* We don't register this tap if we don't have the unistim plugin loaded.*/
206 if (find_tap_id("unistim")) {
207 unistim_calls_init_tap(tap_id_base);
209 if (find_tap_id("voip")) {
210 voip_calls_init_tap(tap_id_base);
214 static void remove_tap_listener_actrace_calls(voip_calls_tapinfo_t *tap_id_base);
215 static void remove_tap_listener_h225_calls(voip_calls_tapinfo_t *tap_id_base);
216 static void remove_tap_listener_h245dg_calls(voip_calls_tapinfo_t *tap_id_base);
217 static void remove_tap_listener_h248_calls(voip_calls_tapinfo_t *tap_id_base);
218 static void remove_tap_listener_iax2_calls(voip_calls_tapinfo_t *tap_id_base);
219 static void remove_tap_listener_isup_calls(voip_calls_tapinfo_t *tap_id_base);
220 static void remove_tap_listener_mgcp_calls(voip_calls_tapinfo_t *tap_id_base);
221 static void remove_tap_listener_mtp3_calls(voip_calls_tapinfo_t *tap_id_base);
222 static void remove_tap_listener_q931_calls(voip_calls_tapinfo_t *tap_id_base);
223 static void remove_tap_listener_rtp(voip_calls_tapinfo_t *tap_id_base);
224 static void remove_tap_listener_rtp_event(voip_calls_tapinfo_t *tap_id_base);
225 static void remove_tap_listener_sccp_calls(voip_calls_tapinfo_t *tap_id_base);
226 static void remove_tap_listener_sdp_calls(voip_calls_tapinfo_t *tap_id_base);
227 static void remove_tap_listener_sip_calls(voip_calls_tapinfo_t *tap_id_base);
228 static void remove_tap_listener_skinny_calls(voip_calls_tapinfo_t *tap_id_base);
229 static void remove_tap_listener_t38(voip_calls_tapinfo_t *tap_id_base);
230 static void remove_tap_listener_unistim_calls(voip_calls_tapinfo_t *tap_id_base);
231 static void remove_tap_listener_voip_calls(voip_calls_tapinfo_t *tap_id_base);
233 void voip_calls_remove_all_tap_listeners(voip_calls_tapinfo_t *tap_id_base)
235 /* Remove the calls tap listener */
236 remove_tap_listener_actrace_calls(tap_id_base);
237 remove_tap_listener_h225_calls(tap_id_base);
238 remove_tap_listener_h245dg_calls(tap_id_base);
239 remove_tap_listener_h248_calls(tap_id_base);
240 remove_tap_listener_iax2_calls(tap_id_base);
241 remove_tap_listener_isup_calls(tap_id_base);
242 remove_tap_listener_mgcp_calls(tap_id_base);
243 remove_tap_listener_mtp3_calls(tap_id_base);
244 remove_tap_listener_q931_calls(tap_id_base);
245 remove_tap_listener_rtp(tap_id_base);
246 remove_tap_listener_rtp_event(tap_id_base);
247 remove_tap_listener_sccp_calls(tap_id_base);
248 remove_tap_listener_sdp_calls(tap_id_base);
249 remove_tap_listener_sip_calls(tap_id_base);
250 remove_tap_listener_skinny_calls(tap_id_base);
251 remove_tap_listener_t38(tap_id_base);
252 if (find_tap_id("unistim")) { /* The plugin may be missing */
253 remove_tap_listener_unistim_calls(tap_id_base);
255 if (find_tap_id("voip")) {
256 remove_tap_listener_voip_calls(tap_id_base);
260 /****************************************************************************/
261 /* when there is a [re]reading of packet's */
262 void
263 voip_calls_reset_all_taps(voip_calls_tapinfo_t *tapinfo)
265 voip_calls_info_t *callsinfo;
266 rtpstream_info_t *strinfo;
267 GList *list = NULL;
269 /* VOIP_CALLS_DEBUG("reset packets: %d streams: %d", tapinfo->npackets, tapinfo->nrtpstreams); */
271 /* free the data items first */
272 list = g_queue_peek_nth_link(tapinfo->callsinfos, 0);
273 while (list)
275 callsinfo = (voip_calls_info_t *)list->data;
276 voip_calls_free_callsinfo(callsinfo);
277 list = g_list_next(list);
279 g_queue_clear(tapinfo->callsinfos);
280 /* free the SIP_HASH */
281 if(NULL!=tapinfo->callsinfo_hashtable[SIP_HASH])
283 g_hash_table_destroy(tapinfo->callsinfo_hashtable[SIP_HASH]);
284 tapinfo->callsinfo_hashtable[SIP_HASH] = NULL;
287 /* free the strinfo data items first */
288 list = g_list_first(tapinfo->rtpstream_list);
289 while(list)
291 strinfo = (rtpstream_info_t *)list->data;
292 rtpstream_info_free_all(strinfo);
293 list = g_list_next(list);
295 g_list_free(tapinfo->rtpstream_list);
296 tapinfo->rtpstream_list = NULL;
298 g_free(tapinfo->sdp_summary);
299 tapinfo->sdp_summary = NULL;
301 if (tapinfo->h245_labels) {
302 memset(tapinfo->h245_labels, 0, sizeof(h245_labels_t));
305 tapinfo->ncalls = 0;
306 tapinfo->start_packets = 0;
307 tapinfo->completed_calls = 0;
308 tapinfo->rejected_calls = 0;
310 return;
313 /****************************************************************************/
314 /* free one callsinfo */
315 void
316 voip_calls_free_callsinfo(voip_calls_info_t *callsinfo)
318 g_free(callsinfo->call_id);
319 g_free(callsinfo->from_identity);
320 g_free(callsinfo->to_identity);
321 free_address(&callsinfo->initial_speaker);
322 g_free(callsinfo->protocol_name);
323 g_free(callsinfo->call_comment);
325 if (callsinfo->free_prot_info && callsinfo->prot_info)
326 callsinfo->free_prot_info(callsinfo->prot_info);
328 g_free(callsinfo);
331 /****************************************************************************/
332 /* Add a new item into the graph */
333 static void
334 add_to_graph(voip_calls_tapinfo_t *tapinfo, packet_info *pinfo, epan_dissect_t *edt, const char *frame_label, const char *comment, uint16_t call_num, address *src_addr, address *dst_addr, uint16_t line_style)
336 seq_analysis_item_t *gai;
337 char time_str[COL_MAX_LEN];
339 if (!tapinfo->graph_analysis) {
340 return;
343 gai = g_new0(seq_analysis_item_t, 1);
344 gai->frame_number = pinfo->num;
345 copy_address(&(gai->src_addr),src_addr);
346 copy_address(&(gai->dst_addr),dst_addr);
348 gai->port_src=pinfo->srcport;
349 gai->port_dst=pinfo->destport;
351 if (frame_label != NULL)
352 gai->frame_label = g_strdup(frame_label);
353 else
354 gai->frame_label = g_strdup("");
356 if (comment != NULL)
357 gai->comment = g_strdup(comment);
358 else
359 gai->comment = g_strdup("");
361 gai->conv_num=call_num;
362 gai->line_style=line_style;
363 set_fd_time(edt->session, pinfo->fd, time_str);
364 gai->time_str = g_strdup(time_str);
365 gai->display=false;
367 g_queue_push_tail(tapinfo->graph_analysis->items, gai);
368 g_hash_table_insert(tapinfo->graph_analysis->ht, GUINT_TO_POINTER(gai->frame_number), gai);
371 /****************************************************************************/
372 /* Append str to frame_label and comment in a graph item */
373 /* return 0 if the frame_num is not in the graph list */
374 static int append_to_frame_graph(voip_calls_tapinfo_t *tapinfo, uint32_t frame_num, const char *new_frame_label, const char *new_comment)
376 seq_analysis_item_t *gai=NULL;
377 char *frame_label = NULL;
378 char *comment = NULL;
380 if(tapinfo->graph_analysis && NULL!=tapinfo->graph_analysis->ht)
381 gai=(seq_analysis_item_t *)g_hash_table_lookup(tapinfo->graph_analysis->ht, GUINT_TO_POINTER(frame_num));
382 if(gai) {
383 frame_label = gai->frame_label;
384 comment = gai->comment;
386 if (new_frame_label != NULL) {
387 gai->frame_label = ws_strdup_printf("%s %s", frame_label, new_frame_label);
388 g_free(frame_label);
391 if (new_comment != NULL) {
392 gai->comment = ws_strdup_printf("%s %s", comment, new_comment);
393 g_free(comment);
397 return gai? 1 : 0;
400 /****************************************************************************/
401 /* Change the frame_label and comment in a graph item if not NULL*/
402 /* return 0 if the frame_num is not in the graph list */
403 static int change_frame_graph(voip_calls_tapinfo_t *tapinfo, uint32_t frame_num, const char *new_frame_label, const char *new_comment)
405 seq_analysis_item_t *gai=NULL;
406 char *frame_label = NULL;
407 char *comment = NULL;
409 if(tapinfo->graph_analysis && NULL!=tapinfo->graph_analysis->ht)
410 gai=(seq_analysis_item_t *)g_hash_table_lookup(tapinfo->graph_analysis->ht, GUINT_TO_POINTER(frame_num));
411 if(gai) {
412 frame_label = gai->frame_label;
413 comment = gai->comment;
415 if (new_frame_label != NULL) {
416 gai->frame_label = g_strdup(new_frame_label);
417 g_free(frame_label);
420 if (new_comment != NULL) {
421 gai->comment = g_strdup(new_comment);
422 g_free(comment);
426 return gai? 1 : 0;
429 /****************************************************************************/
430 /* Change all the graph items with call_num to new_call_num */
431 static unsigned change_call_num_graph(voip_calls_tapinfo_t *tapinfo, uint16_t call_num, uint16_t new_call_num)
433 seq_analysis_item_t *gai;
434 GList *list;
435 unsigned items_changed;
437 items_changed = 0;
438 if(tapinfo->graph_analysis){
439 list = g_queue_peek_nth_link(tapinfo->graph_analysis->items, 0);
440 while (list)
442 gai = (seq_analysis_item_t *)list->data;
443 if (gai->conv_num == call_num) {
444 gai->conv_num = new_call_num;
445 items_changed++;
447 list = g_list_next(list);
450 return items_changed;
453 /****************************************************************************/
454 /* Insert the item in the graph list */
455 static void insert_to_graph_t38(voip_calls_tapinfo_t *tapinfo, packet_info *pinfo, epan_dissect_t *edt, const char *frame_label, const char *comment, uint16_t call_num, address *src_addr, address *dst_addr, uint16_t line_style, uint32_t frame_num)
457 seq_analysis_item_t *gai, *new_gai;
458 GList *list;
459 bool inserted;
460 char time_str[COL_MAX_LEN];
462 if (!tapinfo->graph_analysis){
463 /* Nothing to do */
464 return;
467 new_gai = g_new0(seq_analysis_item_t, 1);
468 new_gai->frame_number = frame_num;
469 copy_address(&(new_gai->src_addr),src_addr);
470 copy_address(&(new_gai->dst_addr),dst_addr);
472 new_gai->port_src=pinfo->srcport;
473 new_gai->port_dst=pinfo->destport;
474 if (frame_label != NULL)
475 new_gai->frame_label = g_strdup(frame_label);
476 else
477 new_gai->frame_label = g_strdup("");
479 if (comment != NULL)
480 new_gai->comment = g_strdup(comment);
481 else
482 new_gai->comment = g_strdup("");
483 new_gai->conv_num=call_num;
484 new_gai->line_style=line_style;
485 set_fd_time(edt->session, pinfo->fd, time_str);
486 new_gai->time_str = g_strdup(time_str);
487 new_gai->display=false;
489 inserted = false;
491 list = g_queue_peek_nth_link(tapinfo->graph_analysis->items, 0);
492 while (list)
494 gai = (seq_analysis_item_t *)list->data;
495 if (gai->frame_number > frame_num) {
496 g_queue_insert_before(tapinfo->graph_analysis->items, list, new_gai);
497 g_hash_table_insert(tapinfo->graph_analysis->ht, GUINT_TO_POINTER(new_gai->frame_number), new_gai);
498 inserted = true;
499 break;
501 list = g_list_next(list);
504 if (!inserted) {
505 /* Just add to the end */
506 g_queue_push_tail(tapinfo->graph_analysis->items, new_gai);
507 g_hash_table_insert(tapinfo->graph_analysis->ht, GUINT_TO_POINTER(new_gai->frame_number), new_gai);
511 /****************************************************************************/
512 /* ***************************TAP for RTP Events*****************************/
513 /****************************************************************************/
515 /*static uint32_t rtp_evt_setup_frame_num = 0;*/
517 /****************************************************************************/
518 /* whenever a rtp event packet is seen by the tap listener */
519 static tap_packet_status
520 rtp_event_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt _U_, const void *rtp_event_info, tap_flags_t flags _U_)
522 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_rtp_event_);
523 const struct _rtp_event_info *pi = (const struct _rtp_event_info *)rtp_event_info;
525 /* if display filtering activated and packet do not match, ignore it */
526 if (tapinfo->apply_display_filter && (pinfo->fd->passed_dfilter == 0)) {
527 return TAP_PACKET_DONT_REDRAW;
529 /* do not consider RTP events packets without a setup frame */
530 if (pi->info_setup_frame_num == 0) {
531 return TAP_PACKET_DONT_REDRAW;
534 tapinfo->rtp_evt_frame_num = pinfo->num;
535 tapinfo->rtp_evt = pi->info_rtp_evt;
536 tapinfo->rtp_evt_end = pi->info_end;
538 return TAP_PACKET_DONT_REDRAW;
541 /****************************************************************************/
542 void
543 rtp_event_init_tap(voip_calls_tapinfo_t *tap_id_base)
545 GString *error_string;
547 error_string = register_tap_listener("rtpevent", tap_base_to_id(tap_id_base, tap_id_offset_rtp_event_),
548 NULL,
550 NULL,
551 rtp_event_packet,
552 NULL,
553 NULL
556 if (error_string != NULL) {
557 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
558 "%s", error_string->str);
559 g_string_free(error_string, TRUE);
563 /****************************************************************************/
565 void
566 remove_tap_listener_rtp_event(voip_calls_tapinfo_t *tap_id_base)
568 remove_tap_listener(tap_base_to_id(tap_id_base, tap_id_offset_rtp_event_));
571 /****************************************************************************/
572 /* ***************************TAP for RTP **********************************/
573 /****************************************************************************/
575 /****************************************************************************/
576 /* when there is a [re]reading of RTP packets */
577 static void
578 rtp_reset(void *tap_offset_ptr)
580 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_rtp_);
581 GList *list;
582 rtpstream_info_t *stream_info;
584 /* free the data items first */
585 list = g_list_first(tapinfo->rtpstream_list);
586 while (list)
588 stream_info = (rtpstream_info_t*)(list->data);
589 rtpstream_info_free_data(stream_info);
590 g_free(list->data);
591 list = g_list_next(list);
593 g_list_free(tapinfo->rtpstream_list);
594 tapinfo->rtpstream_list = NULL;
595 tapinfo->nrtpstreams = 0;
597 // Do not touch graph_analysis, it is handled by caller
599 if (tapinfo->tap_reset) {
600 tapinfo->tap_reset(tapinfo);
603 return;
606 /****************************************************************************/
607 /* whenever a RTP packet is seen by the tap listener */
608 static tap_packet_status
609 rtp_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt, void const *rtp_info_ptr, tap_flags_t flags)
611 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_rtp_);
612 rtpstream_info_t *tmp_listinfo;
613 rtpstream_info_t *strinfo = NULL;
614 GList *list;
615 struct _rtp_packet_info *p_packet_data = NULL;
617 const struct _rtp_info *rtp_info = (const struct _rtp_info *)rtp_info_ptr;
619 /* if display filtering activated and packet do not match, ignore it */
620 if (tapinfo->apply_display_filter && (pinfo->fd->passed_dfilter == 0)) {
621 return TAP_PACKET_DONT_REDRAW;
624 /* do not consider RTP packets without a setup frame */
625 if (rtp_info->info_setup_frame_num == 0) {
626 return TAP_PACKET_DONT_REDRAW;
629 if (tapinfo->tap_packet) {
630 tapinfo->tap_packet(tapinfo, pinfo, edt, rtp_info_ptr, flags);
633 /* check whether we already have a RTP stream with this setup frame and ssrc in the list */
634 list = g_list_first(tapinfo->rtpstream_list);
635 while (list)
637 tmp_listinfo=(rtpstream_info_t *)list->data;
638 if ( (tmp_listinfo->setup_frame_number == rtp_info->info_setup_frame_num)
639 && (tmp_listinfo->id.ssrc == rtp_info->info_sync_src) && (tmp_listinfo->end_stream == false)) {
640 /* if the payload type has changed, we mark the stream as finished to create a new one
641 this is to show multiple payload changes in the Graph for example for DTMF RFC2833 */
642 if ( tmp_listinfo->first_payload_type != rtp_info->info_payload_type ) {
643 tmp_listinfo->end_stream = true;
644 } else if ( ( ( tmp_listinfo->ed137_info == NULL ) && (rtp_info->info_ed137_info != NULL) ) ||
645 ( ( tmp_listinfo->ed137_info != NULL ) && (rtp_info->info_ed137_info == NULL) ) ||
646 ( ( tmp_listinfo->ed137_info != NULL ) && (rtp_info->info_ed137_info != NULL) &&
647 ( 0!=strcmp(tmp_listinfo->ed137_info, rtp_info->info_ed137_info) )
650 /* if ed137_info has changed, create new stream */
651 tmp_listinfo->end_stream = true;
652 } else {
653 strinfo = (rtpstream_info_t*)(list->data);
654 break;
657 list = g_list_next(list);
660 /* if this is a duplicated RTP Event End, just return */
661 if ((tapinfo->rtp_evt_frame_num == pinfo->num) && !strinfo && (tapinfo->rtp_evt_end == true)) {
662 return TAP_PACKET_DONT_REDRAW;
665 /* not in the list? then create a new entry */
666 if (strinfo==NULL) {
667 strinfo = rtpstream_info_malloc_and_init();
668 rtpstream_id_copy_pinfo(pinfo,&(strinfo->id),false);
669 strinfo->id.ssrc = rtp_info->info_sync_src;
670 strinfo->first_payload_type = rtp_info->info_payload_type;
671 strinfo->is_srtp = rtp_info->info_is_srtp;
672 /* if it is dynamic payload, let use the conv data to see if it is defined */
673 if ( (strinfo->first_payload_type >= PT_UNDF_96) && (strinfo->first_payload_type <= PT_UNDF_127) ) {
674 /* Use existing packet info if available */
675 p_packet_data = (struct _rtp_packet_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_get_id_by_filter_name("rtp"), RTP_CONVERSATION_PROTO_DATA);
676 if (p_packet_data && p_packet_data->rtp_dyn_payload) {
677 const char *encoding_name = rtp_dyn_payload_get_name(p_packet_data->rtp_dyn_payload, strinfo->first_payload_type);
678 if (encoding_name) {
679 strinfo->first_payload_type_name = encoding_name;
683 if (!strinfo->first_payload_type_name) {
684 strinfo->first_payload_type_name = val_to_str_ext(strinfo->first_payload_type, &rtp_payload_type_short_vals_ext, "%u");
686 strinfo->start_fd = pinfo->fd;
687 strinfo->start_rel_time = pinfo->rel_ts;
688 strinfo->start_abs_time = pinfo->abs_ts;
689 strinfo->setup_frame_number = rtp_info->info_setup_frame_num;
690 strinfo->call_num = -1;
691 strinfo->rtp_event = -1;
692 if (rtp_info->info_ed137_info != NULL) {
693 strinfo->ed137_info = rtp_info->info_ed137_info;
694 } else {
695 strinfo->ed137_info = NULL;
697 tapinfo->rtpstream_list = g_list_prepend(tapinfo->rtpstream_list, strinfo);
700 /* Add the info to the existing RTP stream */
701 strinfo->packet_count++;
702 strinfo->stop_fd = pinfo->fd;
703 strinfo->stop_rel_time = pinfo->rel_ts;
705 /* process RTP Event */
706 if (tapinfo->rtp_evt_frame_num == pinfo->num) {
707 strinfo->rtp_event = tapinfo->rtp_evt;
708 if (tapinfo->rtp_evt_end == true) {
709 strinfo->end_stream = true;
713 tapinfo->redraw |= REDRAW_RTP;
715 return TAP_PACKET_DONT_REDRAW;
718 /****************************************************************************/
719 /* whenever a redraw in the RTP tap listener */
720 static void
721 rtp_draw(void *tap_offset_ptr)
723 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_rtp_);
724 GList *rtpstreams_list;
725 rtpstream_info_t *rtp_listinfo;
726 /* GList *voip_calls_graph_list; */
727 seq_analysis_item_t *gai = NULL;
728 seq_analysis_item_t *new_gai;
729 uint16_t conv_num;
730 double duration;
731 char time_str[COL_MAX_LEN];
733 /* add each rtp stream to the graph */
734 rtpstreams_list = g_list_first(tapinfo->rtpstream_list);
735 while (rtpstreams_list)
737 rtp_listinfo = (rtpstream_info_t *)rtpstreams_list->data;
739 /* using the setup frame number of the RTP stream, we get the call number that it belongs to*/
740 /* voip_calls_graph_list = g_list_first(tapinfo->graph_analysis->list); */
741 if(tapinfo->graph_analysis){
742 gai = (seq_analysis_item_t *)g_hash_table_lookup(tapinfo->graph_analysis->ht, GUINT_TO_POINTER(rtp_listinfo->setup_frame_number));
744 if(gai != NULL) {
745 const char *comment_fmt_src = "%%s, %%u packets. Duration: %%.%dfs SSRC: 0x%%X";
746 char *comment_fmt = ws_strdup_printf(comment_fmt_src, prefs.gui_decimal_places1);
747 /* Found the setup frame*/
748 conv_num = gai->conv_num;
749 /* if RTP was already in the Graph, just update the comment information */
750 gai = (seq_analysis_item_t *)g_hash_table_lookup(tapinfo->graph_analysis->ht, GUINT_TO_POINTER(rtp_listinfo->start_fd->num));
751 if (gai != NULL) {
752 duration = (double)(nstime_to_msec(&rtp_listinfo->stop_rel_time) - nstime_to_msec(&rtp_listinfo->start_rel_time));
753 g_free(gai->comment);
754 gai->comment = ws_strdup_printf(comment_fmt,
755 (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->packet_count,
756 duration/1000, rtp_listinfo->id.ssrc);
757 } else {
758 new_gai = g_new0(seq_analysis_item_t, 1);
759 new_gai->frame_number = rtp_listinfo->start_fd->num;
760 copy_address(&(new_gai->src_addr),&(rtp_listinfo->id.src_addr));
761 copy_address(&(new_gai->dst_addr),&(rtp_listinfo->id.dst_addr));
762 new_gai->port_src = rtp_listinfo->id.src_port;
763 new_gai->port_dst = rtp_listinfo->id.dst_port;
764 duration = (double)(nstime_to_msec(&rtp_listinfo->stop_rel_time) - nstime_to_msec(&rtp_listinfo->start_rel_time));
765 new_gai->frame_label = ws_strdup_printf("%s (%s) %s%s%s",
766 (rtp_listinfo->is_srtp)?"SRTP":"RTP",
767 rtp_listinfo->first_payload_type_name,
768 (rtp_listinfo->rtp_event == -1)?
769 "":val_to_str_ext_const(rtp_listinfo->rtp_event, &rtp_event_type_values_ext, "Unknown RTP Event"),
770 (rtp_listinfo->ed137_info!=NULL?" ":""),
771 (rtp_listinfo->ed137_info!=NULL?rtp_listinfo->ed137_info:"")
773 new_gai->comment = ws_strdup_printf(comment_fmt,
774 (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->packet_count,
775 duration/1000, rtp_listinfo->id.ssrc);
776 new_gai->info_type=GA_INFO_TYPE_RTP;
777 rtpstream_info_t *new_info = g_new(rtpstream_info_t, 1);
778 new_gai->info_ptr = new_info;
779 rtpstream_info_init(new_info);
780 rtpstream_id_copy(&rtp_listinfo->id, &new_info->id);
781 new_info->packet_count = rtp_listinfo->packet_count;
782 new_info->setup_frame_number = rtp_listinfo->setup_frame_number;
783 new_info->rtp_stats = rtp_listinfo->rtp_stats;
784 nstime_copy(&new_info->start_rel_time, &rtp_listinfo->start_rel_time);
785 nstime_copy(&new_info->stop_rel_time, &rtp_listinfo->stop_rel_time);
786 nstime_copy(&new_info->start_abs_time, &rtp_listinfo->start_abs_time);
787 new_gai->conv_num = conv_num;
788 set_fd_time(tapinfo->session, rtp_listinfo->start_fd, time_str);
789 new_gai->time_str = g_strdup(time_str);
790 new_gai->display=false;
791 new_gai->line_style = 2; /* the arrow line will be 2 pixels width */
792 g_queue_push_tail(tapinfo->graph_analysis->items, new_gai);
793 g_hash_table_insert(tapinfo->graph_analysis->ht, GUINT_TO_POINTER(rtp_listinfo->start_fd->num), new_gai);
795 g_free(comment_fmt);
797 rtpstreams_list = g_list_next(rtpstreams_list);
798 } /* while (rtpstreams_list) */
800 if (tapinfo->tap_draw && (tapinfo->redraw & REDRAW_RTP)) {
801 tapinfo->tap_draw(tapinfo);
802 tapinfo->redraw &= ~REDRAW_RTP;
805 #if 0
806 static void
807 rtp_packet_draw(void *tap_offset_ptr)
809 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_rtp_);
810 GList *rtpstreams_list;
811 rtpstream_info_t *rtp_listinfo;
812 GList *voip_calls_graph_list;
813 unsigned item;
814 seq_analysis_item_t *gai;
815 seq_analysis_item_t *new_gai;
816 uint16_t conv_num;
817 uint32_t duration;
818 char time_str[COL_MAX_LEN];
820 /* add each rtp stream to the graph */
821 rtpstreams_list = g_list_first(tapinfo->stream_list);
822 while (rtpstreams_list)
824 rtp_listinfo = rtpstreams_list->data;
826 /* using the setup frame number of the RTP stream, we get the call number that it belongs to*/
827 voip_calls_graph_list = g_list_first(tapinfo->graph_analysis->list);
828 while (voip_calls_graph_list)
830 gai = voip_calls_graph_list->data;
831 conv_num = gai->conv_num;
832 /* if we get the setup frame number, then get the time position to graph the RTP arrow */
833 if (rtp_listinfo->setup_frame_number == gai->frame_number) {
834 /* look again from the beginning because there are cases where the Setup frame is after the RTP */
835 voip_calls_graph_list = g_list_first(tapinfo->graph_analysis->list);
836 item = 0;
837 while(voip_calls_graph_list) {
838 gai = voip_calls_graph_list->data;
839 /* if RTP was already in the Graph, just update the comment information */
840 if (rtp_listinfo->start_fd->num == gai->frame_number) {
841 duration = (uint32_t)(nstime_to_msec(&rtp_listinfo->stop_fd->rel_ts) - nstime_to_msec(&rtp_listinfo->start_fd->rel_ts));
842 g_free(gai->comment);
843 gai->comment = ws_strdup_printf("%s Num packets:%u Duration:%u.%03us SSRC:0x%X",
844 (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->npackets,
845 duration/1000,(duration%1000), rtp_listinfo->id.ssrc);
846 break;
849 /* 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 */
850 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
851 if (!voip_calls_graph_list) item++;
853 /* add the RTP item to the graph if was not there*/
854 if (rtp_listinfo->start_fd->num<gai->frame_number || !voip_calls_graph_list) {
855 new_gai = g_new0(seq_analysis_item_t, 1);
856 new_gai->frame_number = rtp_listinfo->start_fd->num;
857 copy_address(&(new_gai->src_addr),&(rtp_listinfo->src_addr));
858 copy_address(&(new_gai->dst_addr),&(rtp_listinfo->dst_addr));
859 new_gai->port_src = rtp_listinfo->id.src_port;
860 new_gai->port_dst = rtp_listinfo->id.dst_port;
861 new_gai->protocol = g_strdup(port_type_to_str(pinfo->ptype));
862 duration = (uint32_t)(nstime_to_msec(&rtp_listinfo->stop_fd->rel_ts) - nstime_to_msec(&rtp_listinfo->start_fd->rel_ts));
863 new_gai->frame_label = ws_strdup_printf("%s (%s) %s",
864 (rtp_listinfo->is_srtp)?"SRTP":"RTP",
865 rtp_listinfo->first_payload_type_str,
866 (rtp_listinfo->rtp_event == -1)?
867 "":val_to_str_ext_const(rtp_listinfo->rtp_event, &rtp_event_type_values_ext, "Unknown RTP Event"));
868 new_gai->comment = ws_strdup_printf("%s Num packets:%u Duration:%u.%03us SSRC:0x%X",
869 (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->npackets,
870 duration/1000,(duration%1000), rtp_listinfo->id.ssrc);
871 new_gai->conv_num = conv_num;
872 set_fd_time(cfile.epan, rtp_listinfo->start_fd, time_str);
873 new_gai->time_str = g_strdup(time_str);
874 new_gai->display=false;
875 new_gai->line_style = 2; /* the arrow line will be 2 pixels width */
876 tapinfo->graph_analysis->list = g_list_insert(tapinfo->graph_analysis->list, new_gai, item);
877 break;
879 if (voip_calls_graph_list) item++;
881 break;
883 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
885 rtpstreams_list = g_list_next(rtpstreams_list);
888 #endif
890 /****************************************************************************/
891 void
892 rtp_init_tap(voip_calls_tapinfo_t *tap_id_base)
894 GString *error_string;
896 error_string = register_tap_listener("rtp", tap_base_to_id(tap_id_base, tap_id_offset_rtp_), NULL,
898 rtp_reset,
899 rtp_packet,
900 rtp_draw,
901 NULL
903 if (error_string != NULL) {
904 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
905 "%s", error_string->str);
906 g_string_free(error_string, TRUE);
910 /****************************************************************************/
911 void
912 remove_tap_listener_rtp(voip_calls_tapinfo_t *tap_id_base)
914 remove_tap_listener(tap_base_to_id(tap_id_base, tap_id_offset_rtp_));
917 /****************************************************************************/
918 /******************************TAP for T38 **********************************/
919 /****************************************************************************/
921 /****************************************************************************/
922 /* whenever a T38 packet is seen by the tap listener */
923 static tap_packet_status
924 t38_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt, const void *t38_info_ptr, tap_flags_t flags _U_)
926 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_t38_);
928 voip_calls_info_t *callsinfo = NULL;
929 voip_calls_info_t *tmp_listinfo;
930 GList *voip_calls_graph_list = NULL;
931 GList *list;
932 char *frame_label = NULL;
933 char *comment = NULL;
934 seq_analysis_item_t *tmp_gai, *gai = NULL;
935 char *tmp_str1, *tmp_str2;
936 uint16_t line_style = 2;
937 double duration;
938 int conv_num = -1;
940 const t38_packet_info *t38_info = (const t38_packet_info *)t38_info_ptr;
942 /* if display filtering activated and packet do not match, ignore it */
943 if (tapinfo->apply_display_filter && (pinfo->fd->passed_dfilter == 0)) {
944 return TAP_PACKET_DONT_REDRAW;
947 if (t38_info->setup_frame_number != 0) {
948 /* using the setup frame number of the T38 packet, we get the call number that it belongs */
949 if(tapinfo->graph_analysis){
950 voip_calls_graph_list = g_queue_peek_nth_link(tapinfo->graph_analysis->items, 0);
952 while (voip_calls_graph_list)
954 tmp_gai = (seq_analysis_item_t *)voip_calls_graph_list->data;
955 if (t38_info->setup_frame_number == tmp_gai->frame_number) {
956 gai = tmp_gai;
957 break;
959 voip_calls_graph_list = g_list_next(voip_calls_graph_list);
961 if (gai) conv_num = (int) gai->conv_num;
964 /* if setup_frame_number in the t38 packet is 0, it means it was not set using an SDP or H245 session, which means we don't
965 * have the associated Voip calls. It probably means that the packet was decoded using the default t38 port, or using "Decode as.."
966 * in this case we create a "voip" call that only have t38 media (no signaling)
967 * OR if we have not found the Setup message in the graph.
969 if ( (t38_info->setup_frame_number == 0) || (gai == NULL) ) {
970 /* check whether we already have a call with these parameters in the list */
971 list = g_queue_peek_nth_link(tapinfo->callsinfos, 0);
972 while (list)
974 tmp_listinfo=(voip_calls_info_t *)list->data;
975 if (tmp_listinfo->protocol == MEDIA_T38) {
976 callsinfo = (voip_calls_info_t*)(list->data);
977 break;
979 list = g_list_next (list);
982 /* not in the list? then create a new entry */
983 if (callsinfo==NULL) {
984 callsinfo = g_new0(voip_calls_info_t, 1);
985 callsinfo->call_active_state = VOIP_ACTIVE;
986 callsinfo->call_state = VOIP_UNKNOWN;
987 callsinfo->from_identity=g_strdup("T38 Media only");
988 callsinfo->to_identity=g_strdup("T38 Media only");
989 copy_address(&(callsinfo->initial_speaker),&(pinfo->src));
990 callsinfo->start_fd = pinfo->fd;
991 callsinfo->start_rel_ts = pinfo->rel_ts;
992 callsinfo->protocol=MEDIA_T38;
993 callsinfo->prot_info=NULL;
994 callsinfo->free_prot_info = NULL;
995 callsinfo->npackets = 0;
996 callsinfo->call_num = tapinfo->ncalls++;
997 g_queue_push_tail(tapinfo->callsinfos, callsinfo);
999 callsinfo->stop_fd = pinfo->fd;
1000 callsinfo->stop_rel_ts = pinfo->rel_ts;
1001 ++(callsinfo->npackets);
1002 /* increment the packets counter of all calls */
1003 ++(tapinfo->npackets);
1005 conv_num = (int) callsinfo->call_num;
1008 /* at this point we should have found the call num for this t38 packets belong */
1009 if (conv_num == -1) {
1010 return TAP_PACKET_DONT_REDRAW;
1013 /* add the item to the graph list */
1014 if (t38_info->type_msg == 0) { /* 0=t30-indicator */
1015 tmp_str1 = val_to_str_wmem(NULL, t38_info->t30ind_value, t38_T30_indicator_vals, "Ukn (0x%02X)");
1016 frame_label = g_strdup(tmp_str1);
1017 comment = ws_strdup_printf("t38:t30 Ind:%s", tmp_str1);
1018 wmem_free(NULL, tmp_str1);
1019 line_style = 1;
1020 } else if (t38_info->type_msg == 1) { /* 1=data */
1021 switch(t38_info->Data_Field_field_type_value) {
1022 case 0: /* hdlc-data */
1023 break;
1024 case 2: /* hdlc-fcs-OK */
1025 case 4: /* hdlc-fcs-OK-sig-end */
1026 tmp_str1 = val_to_str_ext_wmem(NULL, t38_info->t30_Facsimile_Control & 0x7F,
1027 &t30_facsimile_control_field_vals_short_ext,
1028 "Ukn (0x%02X)");
1029 frame_label = ws_strdup_printf("%s %s",
1030 tmp_str1,
1031 t38_info->desc);
1032 wmem_free(NULL, tmp_str1);
1034 tmp_str1 = val_to_str_ext_wmem(NULL, t38_info->t30_Facsimile_Control & 0x7F,
1035 &t30_facsimile_control_field_vals_ext,
1036 "Ukn (0x%02X)");
1037 tmp_str2 = val_to_str_wmem(NULL, t38_info->data_value,
1038 t38_T30_data_vals,
1039 "Ukn (0x%02X)");
1040 comment = ws_strdup_printf("t38:%s:HDLC:%s", tmp_str2, tmp_str1);
1041 wmem_free(NULL, tmp_str1);
1042 wmem_free(NULL, tmp_str2);
1043 break;
1044 case 3: /* hdlc-fcs-BAD */
1045 case 5: /* hdlc-fcs-BAD-sig-end */
1046 frame_label = g_strdup(t38_info->Data_Field_field_type_value == 3 ? "fcs-BAD" : "fcs-BAD-sig-end");
1047 tmp_str1 = val_to_str_wmem(NULL, t38_info->data_value, t38_T30_data_vals, "Ukn (0x%02X)");
1048 comment = ws_strdup_printf("WARNING: received t38:%s:HDLC:%s",
1049 tmp_str1,
1050 t38_info->Data_Field_field_type_value == 3 ? "fcs-BAD" : "fcs-BAD-sig-end");
1051 wmem_free(NULL, tmp_str1);
1052 break;
1053 case 7: /* t4-non-ecm-sig-end */
1054 duration = nstime_to_sec(&pinfo->rel_ts) - t38_info->time_first_t4_data;
1055 tmp_str1 = val_to_str_wmem(NULL, t38_info->data_value, t38_T30_data_vals, "Ukn (0x%02X)");
1056 frame_label = ws_strdup_printf("t4-non-ecm-data:%s", tmp_str1);
1057 const char *comment_fmt_src = "t38:t4-non-ecm-data:%%s Duration: %%.%dfs %%s";
1058 char *comment_fmt = ws_strdup_printf(comment_fmt_src, prefs.gui_decimal_places1);
1059 comment = ws_strdup_printf(comment_fmt,
1060 tmp_str1, duration, t38_info->desc_comment );
1061 insert_to_graph_t38(tapinfo, pinfo, edt, frame_label, comment,
1062 (uint16_t)conv_num, &(pinfo->src), &(pinfo->dst),
1063 line_style, t38_info->frame_num_first_t4_data);
1064 g_free(comment_fmt);
1065 wmem_free(NULL, tmp_str1);
1066 break;
1070 if (frame_label && !(t38_info->Data_Field_field_type_value == 7 && t38_info->type_msg == 1)) {
1071 add_to_graph(tapinfo, pinfo, edt, frame_label, comment, (uint16_t)conv_num, &(pinfo->src), &(pinfo->dst), line_style);
1074 g_free(comment);
1075 g_free(frame_label);
1077 tapinfo->redraw |= REDRAW_T38;
1079 return TAP_PACKET_REDRAW; /* refresh output */
1082 /****************************************************************************/
1083 static void
1084 t38_draw(void *tap_offset_ptr)
1086 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_t38_);
1088 if (tapinfo->tap_draw && (tapinfo->redraw & REDRAW_T38)) {
1089 tapinfo->tap_draw(tapinfo);
1090 tapinfo->redraw &= ~REDRAW_T38;
1094 /****************************************************************************/
1095 void
1096 t38_init_tap(voip_calls_tapinfo_t *tap_id_base)
1098 GString *error_string;
1100 error_string = register_tap_listener("t38", tap_base_to_id(tap_id_base, tap_id_offset_t38_), NULL,
1102 NULL,
1103 t38_packet,
1104 t38_draw,
1105 NULL
1107 if (error_string != NULL) {
1108 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1109 "%s", error_string->str);
1110 g_string_free(error_string, TRUE);
1114 /****************************************************************************/
1115 void
1116 remove_tap_listener_t38(voip_calls_tapinfo_t *tap_id_base)
1118 remove_tap_listener(tap_base_to_id(tap_id_base, tap_id_offset_t38_));
1122 /****************************************************************************/
1123 /* ***************************TAP for SIP **********************************/
1124 /****************************************************************************/
1126 static void
1127 free_sip_info(void *p) {
1128 sip_calls_info_t *si = (sip_calls_info_t *)p;
1130 g_free(si->call_identifier);
1131 g_free(si);
1134 /****************************************************************************/
1135 /* whenever a SIP packet is seen by the tap listener */
1136 static tap_packet_status
1137 sip_calls_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt , const void *SIPinfo, tap_flags_t flags _U_)
1139 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_sip_);
1140 /* we just take note of the ISUP data here; when we receive the MTP3 part everything will
1141 be compared with existing calls */
1143 voip_calls_info_t *callsinfo = NULL;
1144 sip_calls_info_t *tmp_sipinfo = NULL;
1145 address tmp_src, tmp_dst;
1146 char *frame_label = NULL;
1147 char *comment = NULL;
1148 char *old_comment = NULL;
1149 char *key = NULL;
1151 const sip_info_value_t *pi = (const sip_info_value_t *)SIPinfo;
1153 /* if display filtering activated and packet do not match, ignore it */
1154 if (tapinfo->apply_display_filter && (pinfo->fd->passed_dfilter == 0)) {
1155 return TAP_PACKET_DONT_REDRAW;
1158 tapinfo->sip_frame_num = pinfo->num;
1160 /* do not consider packets without call_id */
1161 if (pi->tap_call_id ==NULL) {
1162 return TAP_PACKET_DONT_REDRAW;
1164 key=pi->tap_call_id;
1165 /* init the hash table */
1166 if(NULL==tapinfo->callsinfo_hashtable[SIP_HASH]) {
1167 /* TODO: check how efficient g_str_hash is for sip call ids */
1168 tapinfo->callsinfo_hashtable[SIP_HASH]=g_hash_table_new_full(g_str_hash,
1169 g_str_equal,
1170 NULL, /* key_destroy_func */
1171 NULL);/* value_destroy_func */
1173 /* search the call information in the SIP_HASH */
1174 callsinfo = (voip_calls_info_t *)g_hash_table_lookup(tapinfo->callsinfo_hashtable[SIP_HASH], key);
1176 /* Create a new flow entry if the message is INVITE in case of FLOW_ONLY_INVITES,
1177 Create a new flow entry for all messages which have a method in case of FLOW_ALL.
1178 Flows for REGISTER, OPTIONS, MESSAGE and other SIP methods can be seen. */
1180 if ((callsinfo==NULL) && (pi->request_method!=NULL)) {
1182 /* check VoIPcalls_get_flow_show_option() == FLOW_ALL or FLOW_ONLY_INVITES */
1184 if (tapinfo->fs_option == FLOW_ALL ||
1185 (tapinfo->fs_option == FLOW_ONLY_INVITES &&
1186 strcmp(pi->request_method,"INVITE")==0)) {
1187 callsinfo = g_new0(voip_calls_info_t, 1);
1188 callsinfo->call_active_state = VOIP_ACTIVE;
1189 callsinfo->call_state = VOIP_CALL_SETUP;
1190 callsinfo->from_identity=g_strdup(pi->tap_from_addr);
1191 callsinfo->to_identity=g_strdup(pi->tap_to_addr);
1192 copy_address(&(callsinfo->initial_speaker),&(pinfo->src));
1193 callsinfo->start_fd=pinfo->fd;
1194 callsinfo->start_rel_ts=pinfo->rel_ts;
1195 callsinfo->protocol=VOIP_SIP;
1196 callsinfo->prot_info=g_new(sip_calls_info_t, 1);
1197 callsinfo->free_prot_info = free_sip_info;
1198 callsinfo->call_id = g_strdup(pi->tap_call_id);
1199 tmp_sipinfo = (sip_calls_info_t *)callsinfo->prot_info;
1200 tmp_sipinfo->call_identifier = g_strdup(pi->tap_call_id);
1201 tmp_sipinfo->sip_state = SIP_INVITE_SENT;
1202 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
1203 callsinfo->npackets = 0;
1204 callsinfo->call_num = tapinfo->ncalls++;
1206 /* show method in comment in conversation list dialog, user can discern different conversation types */
1207 callsinfo->call_comment=g_strdup(pi->request_method);
1209 g_queue_push_tail(tapinfo->callsinfos, callsinfo);
1210 /* insert the call information in the SIP_HASH */
1211 g_hash_table_insert(tapinfo->callsinfo_hashtable[SIP_HASH],
1212 tmp_sipinfo->call_identifier, callsinfo);
1216 if (callsinfo != NULL) {
1217 tmp_sipinfo = (sip_calls_info_t *)callsinfo->prot_info;
1219 /* let's analyze the call state */
1221 copy_address(&(tmp_src), &(pinfo->src));
1222 copy_address(&(tmp_dst), &(pinfo->dst));
1224 if (pi->request_method == NULL) {
1225 frame_label = ws_strdup_printf("%u %s", pi->response_code, pi->reason_phrase );
1226 comment = ws_strdup_printf("SIP Status %u %s", pi->response_code, pi->reason_phrase );
1228 if ((tmp_sipinfo && pi->tap_cseq_number == tmp_sipinfo->invite_cseq)&&(addresses_equal(&tmp_dst,&(callsinfo->initial_speaker)))) {
1229 if ((pi->response_code > 199) && (pi->response_code<300) && (tmp_sipinfo->sip_state == SIP_INVITE_SENT)) {
1230 tmp_sipinfo->sip_state = SIP_200_REC;
1232 else if ((pi->response_code>299)&&(tmp_sipinfo->sip_state == SIP_INVITE_SENT)) {
1233 callsinfo->call_state = VOIP_REJECTED;
1234 tapinfo->rejected_calls++;
1237 /* UPDATE comment in conversation list dialog with response code and reason.
1238 Multiple code(+reason) may be appended, so skip over intermediate codes (100 trying, 183 ringing, e.t.c.)
1239 TODO: is useful but not perfect, what is appended is truncated when displayed in dialog window */
1240 if (pi->response_code >= 200) {
1241 old_comment = callsinfo->call_comment;
1242 callsinfo->call_comment=ws_strdup_printf("%s %u",
1243 callsinfo->call_comment,
1244 pi->response_code/*, pi->reason_phrase*/);
1246 g_free(old_comment);
1252 else {
1253 frame_label = g_strdup(pi->request_method);
1255 if ((strcmp(pi->request_method,"INVITE")==0)&&(addresses_equal(&tmp_src,&(callsinfo->initial_speaker)))) {
1256 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
1257 callsinfo->call_state = VOIP_CALL_SETUP;
1258 /* TODO: sometimes truncated when displayed in dialog window */
1259 comment = ws_strdup_printf("SIP INVITE From: %s To:%s Call-ID:%s CSeq:%d",
1260 callsinfo->from_identity, callsinfo->to_identity,
1261 callsinfo->call_id, pi->tap_cseq_number);
1263 else if ((strcmp(pi->request_method,"ACK")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
1264 &&(addresses_equal(&tmp_src,&(callsinfo->initial_speaker)))&&(tmp_sipinfo->sip_state==SIP_200_REC)
1265 &&(callsinfo->call_state == VOIP_CALL_SETUP)) {
1266 callsinfo->call_state = VOIP_IN_CALL;
1267 comment = ws_strdup_printf("SIP Request INVITE ACK 200 CSeq:%d", pi->tap_cseq_number);
1269 else if (strcmp(pi->request_method,"BYE")==0) {
1270 callsinfo->call_state = VOIP_COMPLETED;
1271 tapinfo->completed_calls++;
1272 comment = ws_strdup_printf("SIP Request BYE CSeq:%d", pi->tap_cseq_number);
1274 else if ((strcmp(pi->request_method,"CANCEL")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
1275 &&(addresses_equal(&tmp_src,&(callsinfo->initial_speaker)))&&(callsinfo->call_state==VOIP_CALL_SETUP)) {
1276 callsinfo->call_state = VOIP_CANCELLED;
1277 tmp_sipinfo->sip_state = SIP_CANCEL_SENT;
1278 comment = ws_strdup_printf("SIP Request CANCEL CSeq:%d", pi->tap_cseq_number);
1279 } else {
1280 /* comment = ws_strdup_printf("SIP %s", pi->request_method); */
1281 comment = ws_strdup_printf("SIP %s From: %s To:%s CSeq:%d",
1282 pi->request_method,
1283 callsinfo->from_identity,
1284 callsinfo->to_identity, pi->tap_cseq_number);
1288 callsinfo->stop_fd = pinfo->fd;
1289 callsinfo->stop_rel_ts = pinfo->rel_ts;
1290 ++(callsinfo->npackets);
1291 /* increment the packets counter of all calls */
1292 ++(tapinfo->npackets);
1294 /* add to the graph */
1295 add_to_graph(tapinfo, pinfo, edt, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1296 g_free(comment);
1297 g_free(frame_label);
1298 free_address(&tmp_src);
1299 free_address(&tmp_dst);
1301 /* add SDP info if apply */
1302 if ( (tapinfo->sdp_summary != NULL) && (tapinfo->sdp_frame_num == pinfo->num) ) {
1303 append_to_frame_graph(tapinfo, pinfo->num, tapinfo->sdp_summary, NULL);
1304 g_free(tapinfo->sdp_summary);
1305 tapinfo->sdp_summary = NULL;
1310 tapinfo->redraw |= REDRAW_SIP;
1312 return TAP_PACKET_REDRAW; /* refresh output */
1315 /****************************************************************************/
1316 static void
1317 sip_calls_draw(void *tap_offset_ptr)
1319 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_sip_);
1321 if (tapinfo->tap_draw && (tapinfo->redraw & REDRAW_SIP)) {
1322 tapinfo->tap_draw(tapinfo);
1323 tapinfo->redraw &= ~REDRAW_SIP;
1327 /****************************************************************************/
1328 /* TAP INTERFACE */
1329 /****************************************************************************/
1331 void
1332 sip_calls_init_tap(voip_calls_tapinfo_t *tap_id_base)
1334 GString *error_string;
1336 error_string = register_tap_listener("sip", tap_base_to_id(tap_id_base, tap_id_offset_sip_), NULL,
1338 NULL,
1339 sip_calls_packet,
1340 sip_calls_draw,
1341 NULL
1343 if (error_string != NULL) {
1344 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1345 "%s", error_string->str);
1346 g_string_free(error_string, TRUE);
1350 /****************************************************************************/
1351 void
1352 remove_tap_listener_sip_calls(voip_calls_tapinfo_t *tap_id_base)
1354 remove_tap_listener(tap_base_to_id(tap_id_base, tap_id_offset_sip_));
1357 /****************************************************************************/
1358 /* ***************************TAP for ISUP **********************************/
1359 /****************************************************************************/
1361 /****************************************************************************/
1362 /* whenever a isup_ packet is seen by the tap listener */
1363 static tap_packet_status
1364 isup_calls_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt, const void *isup_info, tap_flags_t flags _U_)
1366 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_isup_);
1367 voip_calls_info_t *tmp_listinfo;
1368 voip_calls_info_t *callsinfo = NULL;
1369 isup_calls_info_t *tmp_isupinfo;
1370 bool found = false;
1371 bool forward = false;
1372 bool right_pair;
1373 GList *list;
1374 char *frame_label = NULL;
1375 char *comment = NULL;
1377 const isup_tap_rec_t *pi = (const isup_tap_rec_t *)isup_info;
1379 /* if display filtering activated and packet do not match, ignore it */
1380 if (tapinfo->apply_display_filter && (pinfo->fd->passed_dfilter == 0)) {
1381 return TAP_PACKET_DONT_REDRAW;
1384 /* check if the lower layer is MTP matching the frame number */
1385 if (tapinfo->mtp3_frame_num != pinfo->num)
1386 return TAP_PACKET_DONT_REDRAW;
1388 /* check whether we already have a call with these parameters in the list */
1389 list = g_queue_peek_nth_link(tapinfo->callsinfos, 0);
1390 while (list)
1392 right_pair = true;
1393 tmp_listinfo=(voip_calls_info_t *)list->data;
1394 if ((tmp_listinfo->protocol == VOIP_ISUP)&&(tmp_listinfo->call_active_state==VOIP_ACTIVE)) {
1395 tmp_isupinfo = (isup_calls_info_t *)tmp_listinfo->prot_info;
1396 if ((tmp_isupinfo->cic == pi->circuit_id)&&(tmp_isupinfo->ni == tapinfo->mtp3_ni)) {
1397 if ((tmp_isupinfo->opc == tapinfo->mtp3_opc)&&(tmp_isupinfo->dpc == tapinfo->mtp3_dpc)) {
1398 forward = true;
1399 } else if ((tmp_isupinfo->dpc == tapinfo->mtp3_opc)&&(tmp_isupinfo->opc == tapinfo->mtp3_dpc)) {
1400 forward = false;
1401 } else {
1402 right_pair = false;
1405 if (right_pair) {
1406 /* if there is an IAM for a call that is not in setup state, that means the previous call in the same
1407 cic is no longer active */
1408 if (tmp_listinfo->call_state == VOIP_CALL_SETUP) {
1409 found = true;
1410 } else if (pi->message_type != 1) {
1411 found = true;
1412 } else {
1413 tmp_listinfo->call_active_state=VOIP_INACTIVE;
1417 if (found) {
1418 callsinfo = (voip_calls_info_t*)(list->data);
1419 break;
1423 list = g_list_next (list);
1426 /* not in the list? then create a new entry if the message is IAM
1427 -i.e. if this session is a call*/
1429 if ((callsinfo==NULL) &&(pi->message_type==1)) {
1430 callsinfo = g_new0(voip_calls_info_t, 1);
1431 callsinfo->call_active_state = VOIP_ACTIVE;
1432 callsinfo->call_state = VOIP_UNKNOWN;
1433 copy_address(&(callsinfo->initial_speaker),&(pinfo->src));
1434 callsinfo->start_fd = pinfo->fd;
1435 callsinfo->start_rel_ts = pinfo->rel_ts;
1436 callsinfo->protocol = VOIP_ISUP;
1437 callsinfo->from_identity = g_strdup(pi->calling_number);
1438 callsinfo->to_identity = g_strdup(pi->called_number);
1439 callsinfo->prot_info = g_new(isup_calls_info_t, 1);
1440 callsinfo->free_prot_info = g_free;
1441 tmp_isupinfo = (isup_calls_info_t *)callsinfo->prot_info;
1442 tmp_isupinfo->opc = tapinfo->mtp3_opc;
1443 tmp_isupinfo->dpc = tapinfo->mtp3_dpc;
1444 tmp_isupinfo->ni = tapinfo->mtp3_ni;
1445 tmp_isupinfo->cic = pi->circuit_id;
1446 callsinfo->npackets = 0;
1447 callsinfo->call_num = tapinfo->ncalls++;
1448 g_queue_push_tail(tapinfo->callsinfos, callsinfo);
1452 if (callsinfo!=NULL) {
1453 callsinfo->stop_fd = pinfo->fd;
1454 callsinfo->stop_rel_ts = pinfo->rel_ts;
1455 ++(callsinfo->npackets);
1457 /* Let's analyze the call state */
1459 frame_label = g_strdup(val_to_str_ext_const(pi->message_type, &isup_message_type_value_acro_ext, "Unknown"));
1461 if (callsinfo->npackets == 1) { /* this is the first packet, that must be an IAM */
1463 if ((pi->calling_number!=NULL)&&(pi->called_number !=NULL)) {
1464 comment = ws_strdup_printf("Call from %s to %s",
1465 pi->calling_number, pi->called_number);
1467 } else if (callsinfo->npackets == 2) { /* in the second packet we show the SPs */
1468 if (forward) {
1469 comment = ws_strdup_printf("%i-%i -> %i-%i. Cic:%i",
1470 tapinfo->mtp3_ni, tapinfo->mtp3_opc,
1471 tapinfo->mtp3_ni, tapinfo->mtp3_dpc, pi->circuit_id);
1472 } else {
1473 comment = ws_strdup_printf("%i-%i -> %i-%i. Cic:%i",
1474 tapinfo->mtp3_ni, tapinfo->mtp3_dpc,
1475 tapinfo->mtp3_ni, tapinfo->mtp3_opc, pi->circuit_id);
1479 switch(pi->message_type) {
1480 case 1: /* IAM */
1481 callsinfo->call_state=VOIP_CALL_SETUP;
1482 break;
1483 case 7: /* CONNECT */
1484 case 9: /* ANSWER */
1485 callsinfo->call_state=VOIP_IN_CALL;
1486 break;
1487 case 12: /* RELEASE */
1488 if (callsinfo->call_state==VOIP_CALL_SETUP) {
1489 if (forward) {
1490 callsinfo->call_state=VOIP_CANCELLED;
1492 else {
1493 callsinfo->call_state=VOIP_REJECTED;
1494 tapinfo->rejected_calls++;
1497 else if (callsinfo->call_state == VOIP_IN_CALL) {
1498 callsinfo->call_state = VOIP_COMPLETED;
1499 tapinfo->completed_calls++;
1501 /* Overwrite any comment set above */
1502 g_free(comment);
1503 comment = ws_strdup_printf("Cause %i - %s",
1504 pi->cause_value,
1505 val_to_str_ext_const(pi->cause_value, &q931_cause_code_vals_ext, "(Unknown)"));
1506 break;
1509 /* increment the packets counter of all calls */
1510 ++(tapinfo->npackets);
1512 /* add to the graph */
1513 add_to_graph(tapinfo, pinfo, edt, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1514 g_free(comment);
1515 g_free(frame_label);
1518 tapinfo->redraw |= REDRAW_ISUP;
1520 return TAP_PACKET_REDRAW; /* refresh output */
1523 /****************************************************************************/
1524 static void
1525 isup_calls_draw(void *tap_offset_ptr)
1527 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_isup_);
1529 if (tapinfo->tap_draw && (tapinfo->redraw & REDRAW_ISUP)) {
1530 tapinfo->tap_draw(tapinfo);
1531 tapinfo->redraw &= ~REDRAW_ISUP;
1535 /****************************************************************************/
1537 void
1538 isup_calls_init_tap(voip_calls_tapinfo_t *tap_id_base)
1540 GString *error_string;
1542 error_string = register_tap_listener("isup", tap_base_to_id(tap_id_base, tap_id_offset_isup_),
1543 NULL,
1545 NULL,
1546 isup_calls_packet,
1547 isup_calls_draw,
1548 NULL
1551 if (error_string != NULL) {
1552 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1553 "%s", error_string->str);
1554 g_string_free(error_string, TRUE);
1558 /****************************************************************************/
1560 void
1561 remove_tap_listener_isup_calls(voip_calls_tapinfo_t *tap_id_base)
1563 remove_tap_listener(tap_base_to_id(tap_id_base, tap_id_offset_isup_));
1566 /****************************************************************************/
1567 /* ***************************TAP for MTP3 **********************************/
1568 /****************************************************************************/
1571 /****************************************************************************/
1572 /* whenever a mtp3_ packet is seen by the tap listener */
1573 static tap_packet_status
1574 mtp3_calls_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt _U_, const void *mtp3_info, tap_flags_t flags _U_)
1576 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_mtp3_);
1577 const mtp3_tap_rec_t *pi = (const mtp3_tap_rec_t *)mtp3_info;
1579 /* if display filtering activated and packet do not match, ignore it */
1580 if (tapinfo->apply_display_filter && (pinfo->fd->passed_dfilter == 0)) {
1581 return TAP_PACKET_DONT_REDRAW;
1584 /* keep the data in memory to use when the ISUP information arrives */
1586 tapinfo->mtp3_opc = pi->addr_opc.pc;
1587 tapinfo->mtp3_dpc = pi->addr_dpc.pc;
1588 tapinfo->mtp3_ni = pi->addr_opc.ni;
1589 tapinfo->mtp3_frame_num = pinfo->num;
1591 return TAP_PACKET_DONT_REDRAW;
1594 static tap_packet_status
1595 m3ua_calls_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt _U_, const void *mtp3_info, tap_flags_t flags _U_)
1597 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_m3ua_);
1598 const mtp3_tap_rec_t *pi = (const mtp3_tap_rec_t *)mtp3_info;
1600 /* if display filtering activated and packet do not match, ignore it */
1601 if (tapinfo->apply_display_filter && (pinfo->fd->passed_dfilter == 0)) {
1602 return TAP_PACKET_DONT_REDRAW;
1605 /* keep the data in memory to use when the ISUP information arrives */
1607 tapinfo->mtp3_opc = pi->addr_opc.pc;
1608 tapinfo->mtp3_dpc = pi->addr_dpc.pc;
1609 tapinfo->mtp3_ni = pi->addr_opc.ni;
1610 tapinfo->mtp3_frame_num = pinfo->num;
1612 return TAP_PACKET_DONT_REDRAW;
1615 /****************************************************************************/
1617 void
1618 mtp3_calls_init_tap(voip_calls_tapinfo_t *tap_id_base)
1620 GString *error_string;
1622 error_string = register_tap_listener("mtp3", tap_base_to_id(tap_id_base, tap_id_offset_mtp3_),
1623 NULL,
1625 NULL,
1626 mtp3_calls_packet,
1627 NULL,
1628 NULL
1631 if (error_string != NULL) {
1632 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1633 "%s", error_string->str);
1634 g_string_free(error_string, TRUE);
1637 error_string = register_tap_listener("m3ua", tap_base_to_id(tap_id_base, tap_id_offset_m3ua_),
1638 NULL,
1640 NULL,
1641 m3ua_calls_packet,
1642 NULL,
1643 NULL
1646 if (error_string != NULL) {
1647 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1648 "%s", error_string->str);
1649 g_string_free(error_string, TRUE);
1654 /****************************************************************************/
1656 void
1657 remove_tap_listener_mtp3_calls(voip_calls_tapinfo_t *tap_id_base)
1659 remove_tap_listener(tap_base_to_id(tap_id_base, tap_id_offset_mtp3_));
1660 remove_tap_listener(tap_base_to_id(tap_id_base, tap_id_offset_m3ua_));
1663 /****************************************************************************/
1664 /* ***************************TAP for Q931 **********************************/
1665 /****************************************************************************/
1666 static void h245_add_to_graph(voip_calls_tapinfo_t *tapinfo, uint32_t new_frame_num);
1667 static const e_guid_t guid_allzero = {0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };
1668 /* defines specific H323 data */
1670 /****************************************************************************/
1671 /* whenever a q931_ packet is seen by the tap listener */
1672 static tap_packet_status
1673 q931_calls_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt, const void *q931_info, tap_flags_t flags _U_)
1675 GList *list,*list2;
1676 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_q931_);
1677 h323_calls_info_t *tmp_h323info,*tmp2_h323info;
1678 actrace_isdn_calls_info_t *tmp_actrace_isdn_info;
1679 voip_calls_info_t *tmp_listinfo;
1680 voip_calls_info_t *callsinfo = NULL;
1681 h245_address_t *h245_add = NULL;
1682 char *comment, *tmp_str;
1684 const q931_packet_info *pi = (const q931_packet_info *)q931_info;
1686 /* if display filtering activated and packet do not match, ignore it */
1687 if (tapinfo->apply_display_filter && (pinfo->fd->passed_dfilter == 0)) {
1688 return TAP_PACKET_DONT_REDRAW;
1691 /* free previously allocated q931_calling/ed_number */
1692 g_free(tapinfo->q931_calling_number);
1693 g_free(tapinfo->q931_called_number);
1695 if (pi->calling_number!=NULL)
1696 tapinfo->q931_calling_number = g_strdup(pi->calling_number);
1697 else
1698 tapinfo->q931_calling_number = g_strdup("");
1700 if (pi->called_number!=NULL)
1701 tapinfo->q931_called_number = g_strdup(pi->called_number);
1702 else
1703 tapinfo->q931_called_number = g_strdup("");
1704 tapinfo->q931_cause_value = pi->cause_value;
1705 tapinfo->q931_frame_num = pinfo->num;
1706 tapinfo->q931_crv = pi->crv;
1709 /* add staff to H323 calls */
1710 if (tapinfo->h225_frame_num == tapinfo->q931_frame_num) {
1711 tmp_h323info = NULL;
1712 list = g_queue_peek_nth_link(tapinfo->callsinfos, 0);
1713 while (list)
1715 tmp_listinfo=(voip_calls_info_t *)list->data;
1716 if ( (tmp_listinfo->protocol == VOIP_H323) && (tmp_listinfo->call_num == tapinfo->h225_call_num) ) {
1717 tmp_h323info = (h323_calls_info_t *)tmp_listinfo->prot_info;
1718 callsinfo = (voip_calls_info_t*)(list->data);
1720 /* Add the CRV to the h323 call */
1721 if (tmp_h323info->q931_crv == -1) {
1722 tmp_h323info->q931_crv = tapinfo->q931_crv;
1723 } else if (tmp_h323info->q931_crv != tapinfo->q931_crv) {
1724 tmp_h323info->q931_crv2 = tapinfo->q931_crv;
1726 break;
1728 list = g_list_next (list);
1731 if (callsinfo != NULL) {
1732 comment = NULL;
1733 if (tapinfo->h225_cstype == H225_SETUP) {
1734 /* set the calling and called number from the Q931 packet */
1735 if (tapinfo->q931_calling_number != NULL) {
1736 g_free(callsinfo->from_identity);
1737 callsinfo->from_identity=g_strdup(tapinfo->q931_calling_number);
1739 if (tapinfo->q931_called_number != NULL) {
1740 g_free(callsinfo->to_identity);
1741 callsinfo->to_identity=g_strdup(tapinfo->q931_called_number);
1744 /* check if there is an LRQ/LCF that match this Setup */
1745 /* TODO: we are just checking the DialedNumer in LRQ/LCF against the Setup
1746 we should also check if the h225 signaling IP and port match the destination
1747 Setup ip and port */
1748 list = g_queue_peek_nth_link(tapinfo->callsinfos, 0);
1749 while (list)
1751 tmp_listinfo=(voip_calls_info_t *)list->data;
1752 if (tmp_listinfo->protocol == VOIP_H323) {
1753 tmp2_h323info = (h323_calls_info_t *)tmp_listinfo->prot_info;
1755 /* check if the called number match a LRQ/LCF */
1756 if ( (strcmp(callsinfo->to_identity, tmp_listinfo->to_identity)==0)
1757 && (memcmp(tmp2_h323info->guid, &guid_allzero, GUID_LEN) == 0) ) {
1758 /* change the call graph to the LRQ/LCF to belong to this call */
1759 callsinfo->npackets += change_call_num_graph(tapinfo, tmp_listinfo->call_num, callsinfo->call_num);
1761 /* remove this LRQ/LCF call entry because we have found the Setup that match them */
1762 g_free(tmp_listinfo->from_identity);
1763 g_free(tmp_listinfo->to_identity);
1764 /* DUMP_PTR2(tmp2_h323info->guid); */
1765 g_free(tmp2_h323info->guid);
1767 list2 = g_list_first(tmp2_h323info->h245_list);
1768 while (list2)
1770 h245_add=(h245_address_t *)list2->data;
1771 free_address(&h245_add->h245_address);
1772 g_free(list2->data);
1773 list2 = g_list_next(list2);
1775 g_list_free(tmp_h323info->h245_list);
1776 tmp_h323info->h245_list = NULL;
1777 g_free(tmp_listinfo->prot_info);
1778 g_queue_unlink(tapinfo->callsinfos, list);
1779 break;
1782 list = g_list_next (list);
1785 comment = ws_strdup_printf("H225 From: %s To:%s TunnH245:%s FS:%s", callsinfo->from_identity, callsinfo->to_identity, (tmp_h323info->is_h245Tunneling==true?"on":"off"),
1786 (tapinfo->h225_is_faststart==true?"on":"off"));
1787 } else if (tapinfo->h225_cstype == H225_RELEASE_COMPLET) {
1788 /* get the Q931 Release cause code */
1789 if (tapinfo->q931_cause_value != 0xFF) {
1790 comment = ws_strdup_printf("H225 Q931 Rel Cause (%i):%s", tapinfo->q931_cause_value,
1791 val_to_str_ext_const(tapinfo->q931_cause_value, &q931_cause_code_vals_ext, "<unknown>"));
1792 } else { /* Cause not set */
1793 comment = g_strdup("H225 No Q931 Rel Cause");
1796 /* change the graph comment for this new one */
1797 if (comment != NULL) {
1798 change_frame_graph(tapinfo, tapinfo->h225_frame_num, NULL, comment);
1799 g_free(comment);
1802 /* we reset the h225_frame_num to 0 because there could be empty h225 in the same frame
1803 as non empty h225 (e.g connect), so we don't have to be here twice */
1804 tapinfo->h225_frame_num = 0;
1806 /* add staff to H245 */
1807 } else if (tapinfo->h245_labels->frame_num == tapinfo->q931_frame_num) {
1808 /* there are empty H225 frames that don't have guid (guaid=0) but they have h245 info,
1809 so the only way to match those frames is with the Q931 CRV number */
1810 list = g_queue_peek_nth_link(tapinfo->callsinfos, 0);
1811 while (list)
1813 tmp_listinfo=(voip_calls_info_t *)list->data;
1814 if (tmp_listinfo->protocol == VOIP_H323) {
1815 tmp_h323info = (h323_calls_info_t *)tmp_listinfo->prot_info;
1816 if ( ((tmp_h323info->q931_crv == tapinfo->q931_crv) || (tmp_h323info->q931_crv2 == tapinfo->q931_crv)) && (tapinfo->q931_crv!=-1)) {
1817 /* if the frame number exists in graph, append to it*/
1818 if (!append_to_frame_graph(tapinfo, tapinfo->q931_frame_num, NULL, NULL)) {
1819 /* if not exist, add to the graph */
1820 add_to_graph(tapinfo, pinfo, edt, NULL, NULL, tmp_listinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
1821 ++(tmp_listinfo->npackets);
1822 /* increment the packets counter of all calls */
1823 ++(tapinfo->npackets);
1826 /* Add the H245 info if exists to the Graph */
1827 h245_add_to_graph(tapinfo, pinfo->num);
1828 break;
1831 list = g_list_next (list);
1833 /* SIP-Q */
1834 } else if (tapinfo->sip_frame_num == tapinfo->q931_frame_num) {
1835 /* Do nothing for now */
1836 /* add stuff to ACTRACE */
1837 } else {
1838 address pstn_add;
1840 comment = NULL;
1841 callsinfo = NULL;
1842 list = g_queue_peek_nth_link(tapinfo->callsinfos, 0);
1843 while (list)
1845 tmp_listinfo=(voip_calls_info_t *)list->data;
1846 if ( tmp_listinfo->protocol == VOIP_AC_ISDN ) {
1847 tmp_actrace_isdn_info = (actrace_isdn_calls_info_t *)tmp_listinfo->prot_info;
1848 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
1849 if ( (tmp_actrace_isdn_info->crv == tapinfo->q931_crv) && (tmp_actrace_isdn_info->trunk == tapinfo->actrace_trunk) ) {
1850 callsinfo = (voip_calls_info_t*)(list->data);
1851 break;
1854 list = g_list_next (list);
1857 set_address(&pstn_add, AT_STRINGZ, 5, g_strdup("PSTN"));
1859 /* if it is a new call, add it to the list */
1860 if (!callsinfo) {
1861 callsinfo = g_new0(voip_calls_info_t, 1);
1862 callsinfo->call_active_state = VOIP_ACTIVE;
1863 callsinfo->call_state = VOIP_CALL_SETUP;
1864 callsinfo->from_identity=g_strdup(tapinfo->q931_calling_number);
1865 callsinfo->to_identity=g_strdup(tapinfo->q931_called_number);
1866 copy_address(&(callsinfo->initial_speaker),tapinfo->actrace_direction?&pstn_add:&(pinfo->src));
1867 callsinfo->start_fd=pinfo->fd;
1868 callsinfo->start_rel_ts=pinfo->rel_ts;
1869 callsinfo->protocol=VOIP_AC_ISDN;
1870 callsinfo->prot_info=g_new(actrace_isdn_calls_info_t, 1);
1871 callsinfo->free_prot_info = g_free;
1872 tmp_actrace_isdn_info=(actrace_isdn_calls_info_t *)callsinfo->prot_info;
1873 tmp_actrace_isdn_info->crv=tapinfo->q931_crv;
1874 tmp_actrace_isdn_info->trunk=tapinfo->actrace_trunk;
1875 callsinfo->npackets = 0;
1876 callsinfo->call_num = tapinfo->ncalls++;
1877 g_queue_push_tail(tapinfo->callsinfos, callsinfo);
1880 callsinfo->stop_fd = pinfo->fd;
1881 callsinfo->stop_rel_ts = pinfo->rel_ts;
1882 ++(callsinfo->npackets);
1883 /* increment the packets counter of all calls */
1884 ++(tapinfo->npackets);
1886 switch(pi->message_type) {
1887 case Q931_SETUP:
1888 comment = ws_strdup_printf("AC_ISDN trunk:%u Calling: %s Called:%s", tapinfo->actrace_trunk, tapinfo->q931_calling_number, tapinfo->q931_called_number);
1889 callsinfo->call_state=VOIP_CALL_SETUP;
1890 break;
1891 case Q931_CONNECT:
1892 callsinfo->call_state=VOIP_IN_CALL;
1893 break;
1894 case Q931_RELEASE_COMPLETE:
1895 case Q931_RELEASE:
1896 case Q931_DISCONNECT:
1897 if (callsinfo->call_state==VOIP_CALL_SETUP) {
1898 if (addresses_equal(&(callsinfo->initial_speaker), tapinfo->actrace_direction?&pstn_add:&(pinfo->src) )) { /* forward direction */
1899 callsinfo->call_state=VOIP_CANCELLED;
1901 else { /* reverse */
1902 callsinfo->call_state=VOIP_REJECTED;
1903 tapinfo->rejected_calls++;
1905 } else if ( (callsinfo->call_state!=VOIP_CANCELLED) && (callsinfo->call_state!=VOIP_REJECTED) ) {
1906 callsinfo->call_state=VOIP_COMPLETED;
1907 tapinfo->completed_calls++;
1909 if (tapinfo->q931_cause_value != 0xFF) {
1910 comment = ws_strdup_printf("AC_ISDN trunk:%u Q931 Rel Cause (%i):%s", tapinfo->actrace_trunk, tapinfo->q931_cause_value,
1911 val_to_str_ext_const(tapinfo->q931_cause_value, &q931_cause_code_vals_ext, "<unknown>"));
1912 } else { /* Cause not set */
1913 comment = g_strdup("AC_ISDN No Q931 Rel Cause");
1915 break;
1918 if (!comment)
1919 comment = ws_strdup_printf("AC_ISDN trunk:%u", tapinfo->actrace_trunk );
1921 tmp_str = val_to_str_wmem(NULL, pi->message_type, q931_message_type_vals, "<unknown (%d)>");
1922 add_to_graph(tapinfo, pinfo, edt, tmp_str, comment, callsinfo->call_num,
1923 tapinfo->actrace_direction?&pstn_add:&(pinfo->src),
1924 tapinfo->actrace_direction?&(pinfo->src):&pstn_add,
1925 1 );
1926 wmem_free(NULL, tmp_str);
1928 g_free(comment);
1929 free_address(&pstn_add);
1932 tapinfo->redraw |= REDRAW_Q931;
1934 return TAP_PACKET_REDRAW; /* refresh output */
1937 /****************************************************************************/
1938 static void
1939 q931_calls_draw(void *tap_offset_ptr)
1941 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_q931_);
1943 if (tapinfo->tap_draw && (tapinfo->redraw & REDRAW_Q931)) {
1944 tapinfo->tap_draw(tapinfo);
1945 tapinfo->redraw &= ~REDRAW_Q931;
1949 /****************************************************************************/
1951 void
1952 q931_calls_init_tap(voip_calls_tapinfo_t *tap_id_base)
1954 GString *error_string;
1956 error_string = register_tap_listener("q931", tap_base_to_id(tap_id_base, tap_id_offset_q931_),
1957 NULL,
1959 NULL,
1960 q931_calls_packet,
1961 q931_calls_draw,
1962 NULL
1965 if (error_string != NULL) {
1966 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1967 "%s", error_string->str);
1968 g_string_free(error_string, TRUE);
1972 /****************************************************************************/
1974 void
1975 remove_tap_listener_q931_calls(voip_calls_tapinfo_t *tap_id_base)
1977 remove_tap_listener(tap_base_to_id(tap_id_base, tap_id_offset_q931_));
1980 /****************************************************************************/
1981 /****************************TAP for H323 ***********************************/
1982 /****************************************************************************/
1984 static void
1985 add_h245_Address(h323_calls_info_t *h323info, h245_address_t *h245_address)
1987 h323info->h245_list = g_list_prepend(h323info->h245_list, h245_address);
1991 static void
1992 free_h225_info(void *p) {
1993 h323_calls_info_t *tmp_h323info = (h323_calls_info_t *)p;
1995 /* DUMP_PTR2(tmp_h323info->guid); */
1996 g_free(tmp_h323info->guid);
1998 if (tmp_h323info->h245_list) {
1999 GList *list2 = g_list_first(tmp_h323info->h245_list);
2000 while (list2)
2002 h245_address_t *h245_add=(h245_address_t *)list2->data;
2003 free_address(&h245_add->h245_address);
2004 g_free(list2->data);
2005 list2 = g_list_next(list2);
2008 g_list_free(tmp_h323info->h245_list);
2012 g_free(p);
2014 /****************************************************************************/
2015 /* whenever a H225 packet is seen by the tap listener */
2016 static tap_packet_status
2017 h225_calls_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt, const void *H225info, tap_flags_t flags _U_)
2019 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_h225_);
2020 voip_calls_info_t *tmp_listinfo;
2021 voip_calls_info_t *callsinfo = NULL;
2022 h323_calls_info_t *tmp_h323info = NULL;
2023 char *frame_label;
2024 char *comment;
2025 GList *list;
2026 h245_address_t *h245_add = NULL;
2028 const h225_packet_info *pi = (const h225_packet_info *)H225info;
2030 /* if display filtering activated and packet do not match, ignore it */
2031 if (tapinfo->apply_display_filter && (pinfo->fd->passed_dfilter == 0)) {
2032 return TAP_PACKET_DONT_REDRAW;
2035 /* if not guid and RAS and not LRQ, LCF or LRJ return because did not belong to a call */
2036 /* OR, if not guid and is H225 return because doesn't belong to a call */
2037 if ((memcmp(&pi->guid, &guid_allzero, GUID_LEN) == 0))
2038 if ( ((pi->msg_type == H225_RAS) && ((pi->msg_tag < 18) || (pi->msg_tag > 20))) || (pi->msg_type != H225_RAS) )
2039 return TAP_PACKET_DONT_REDRAW;
2041 /* if it is RAS LCF or LRJ*/
2042 if ( (pi->msg_type == H225_RAS) && ((pi->msg_tag == 19) || (pi->msg_tag == 20))) {
2043 /* if the LCF/LRJ doesn't match to a LRQ, just return */
2044 if (!pi->request_available) return TAP_PACKET_DONT_REDRAW;
2046 /* check whether we already have a call with this request SeqNum */
2047 list = g_queue_peek_nth_link(tapinfo->callsinfos, 0);
2048 while (list)
2050 tmp_listinfo=(voip_calls_info_t *)list->data;
2051 ws_assert(tmp_listinfo != NULL);
2052 if (tmp_listinfo->protocol == VOIP_H323) {
2053 tmp_h323info = (h323_calls_info_t *)tmp_listinfo->prot_info;
2054 if (tmp_h323info->requestSeqNum == pi->requestSeqNum) {
2055 callsinfo = (voip_calls_info_t*)(list->data);
2056 break;
2059 list = g_list_next (list);
2061 } else {
2062 /* check whether we already have a call with this guid in the list */
2063 list = g_queue_peek_nth_link(tapinfo->callsinfos, 0);
2064 while (list)
2066 tmp_listinfo=(voip_calls_info_t *)list->data;
2067 if (tmp_listinfo->protocol == VOIP_H323) {
2068 tmp_h323info = (h323_calls_info_t *)tmp_listinfo->prot_info;
2069 ws_assert(tmp_h323info != NULL);
2070 if ( (memcmp(tmp_h323info->guid, &guid_allzero, GUID_LEN) != 0) && (memcmp(tmp_h323info->guid, &pi->guid,GUID_LEN)==0) ) {
2071 callsinfo = (voip_calls_info_t*)(list->data);
2072 break;
2075 list = g_list_next (list);
2079 tapinfo->h225_cstype = pi->cs_type;
2080 tapinfo->h225_is_faststart = pi->is_faststart;
2082 /* not in the list? then create a new entry */
2083 if (callsinfo==NULL) {
2084 callsinfo = g_new0(voip_calls_info_t, 1);
2085 callsinfo->call_active_state = VOIP_ACTIVE;
2086 callsinfo->call_state = VOIP_UNKNOWN;
2087 callsinfo->from_identity=g_strdup("");
2088 callsinfo->to_identity=g_strdup("");
2089 copy_address(&(callsinfo->initial_speaker),&(pinfo->src));
2090 callsinfo->start_fd=pinfo->fd;
2091 callsinfo->start_rel_ts=pinfo->rel_ts;
2092 callsinfo->protocol=VOIP_H323;
2093 callsinfo->prot_info=g_new(h323_calls_info_t, 1);
2094 callsinfo->free_prot_info = free_h225_info;
2096 tmp_h323info = (h323_calls_info_t *)callsinfo->prot_info;
2097 ws_assert(tmp_h323info != NULL);
2098 tmp_h323info->guid = (e_guid_t *)g_memdup2(&pi->guid, sizeof pi->guid);
2099 /* DUMP_PTR1(tmp_h323info->guid); */
2101 clear_address(&tmp_h323info->h225SetupAddr);
2102 tmp_h323info->h245_list = NULL;
2103 tmp_h323info->is_faststart_Setup = false;
2104 tmp_h323info->is_faststart_Proc = false;
2105 tmp_h323info->is_h245Tunneling = false;
2106 tmp_h323info->is_h245 = false;
2107 tmp_h323info->q931_crv = -1;
2108 tmp_h323info->q931_crv2 = -1;
2109 tmp_h323info->requestSeqNum = 0;
2110 callsinfo->call_num = tapinfo->ncalls++;
2111 callsinfo->npackets = 0;
2113 g_queue_push_tail(tapinfo->callsinfos, callsinfo);
2116 tapinfo->h225_frame_num = pinfo->num;
2117 tapinfo->h225_call_num = callsinfo->call_num;
2119 /* let's analyze the call state */
2121 callsinfo->stop_fd = pinfo->fd;
2122 callsinfo->stop_rel_ts = pinfo->rel_ts;
2123 ++(callsinfo->npackets);
2124 /* increment the packets counter of all calls */
2125 ++(tapinfo->npackets);
2128 /* XXX: it is supposed to be initialized isn't it? */
2129 ws_assert(tmp_h323info != NULL);
2131 /* change the status */
2132 if (pi->msg_type == H225_CS) {
2134 /* this is still IPv4 only, because the dissector is */
2135 if (pi->is_h245 == true) {
2136 h245_add = g_new(h245_address_t, 1);
2137 alloc_address_wmem(NULL, &h245_add->h245_address, AT_IPv4, 4, &pi->h245_address);
2138 h245_add->h245_port = pi->h245_port;
2139 add_h245_Address(tmp_h323info, h245_add);
2142 if (pi->cs_type != H225_RELEASE_COMPLET) tmp_h323info->is_h245Tunneling = pi->is_h245Tunneling;
2144 frame_label = g_strdup(pi->frame_label);
2146 switch(pi->cs_type) {
2147 case H225_SETUP:
2148 tmp_h323info->is_faststart_Setup = pi->is_faststart;
2150 /* Set the Setup address if it was not set */
2151 if (tmp_h323info->h225SetupAddr.type == AT_NONE)
2152 copy_address(&(tmp_h323info->h225SetupAddr), &(pinfo->src));
2153 callsinfo->call_state=VOIP_CALL_SETUP;
2154 comment = ws_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==true?"on":"off"),
2155 (pi->is_faststart==true?"on":"off"));
2156 break;
2157 case H225_CONNECT:
2158 callsinfo->call_state=VOIP_IN_CALL;
2159 if (pi->is_faststart == true) tmp_h323info->is_faststart_Proc = true;
2160 comment = ws_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==true?"on":"off"),
2161 (pi->is_faststart==true?"on":"off"));
2162 break;
2163 case H225_RELEASE_COMPLET:
2164 if (callsinfo->call_state==VOIP_CALL_SETUP) {
2165 if (addresses_equal(&(tmp_h323info->h225SetupAddr),&(pinfo->src))) { /* forward direction */
2166 callsinfo->call_state=VOIP_CANCELLED;
2168 else { /* reverse */
2169 callsinfo->call_state=VOIP_REJECTED;
2170 tapinfo->rejected_calls++;
2172 } else {
2173 callsinfo->call_state=VOIP_COMPLETED;
2174 tapinfo->completed_calls++;
2176 comment = g_strdup("H225 No Q931 Rel Cause");
2177 break;
2178 case H225_PROGRESS:
2179 case H225_ALERTING:
2180 case H225_CALL_PROCEDING:
2181 if (pi->is_faststart == true) tmp_h323info->is_faststart_Proc = true;
2182 comment = ws_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==true?"on":"off"),
2183 (pi->is_faststart==true?"on":"off"));
2184 break;
2185 default:
2186 comment = ws_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==true?"on":"off"),
2187 (pi->is_faststart==true?"on":"off"));
2191 else if (pi->msg_type == H225_RAS) {
2192 switch(pi->msg_tag) {
2193 case 18: /* LRQ */
2194 if (!pi->is_duplicate) {
2195 g_free(callsinfo->to_identity);
2196 callsinfo->to_identity=g_strdup(pi->dialedDigits);
2197 tmp_h323info->requestSeqNum = pi->requestSeqNum;
2199 /* Fall Through */
2200 case 19: /* LCF */
2201 if (strlen(pi->dialedDigits))
2202 comment = ws_strdup_printf("H225 RAS dialedDigits: %s", pi->dialedDigits);
2203 else
2204 comment = g_strdup("H225 RAS");
2205 break;
2206 default:
2207 comment = g_strdup("H225 RAS");
2209 frame_label = g_strdup(val_to_str_const(pi->msg_tag, h225_RasMessage_vals, "<unknown>"));
2210 } else {
2211 frame_label = g_strdup("H225: Unknown");
2212 comment = NULL;
2215 /* add to graph analysis */
2217 /* if the frame number exists in graph, append to it*/
2218 if (!append_to_frame_graph(tapinfo, pinfo->num, pi->frame_label, comment)) {
2219 /* if not exist, add to the graph */
2220 add_to_graph(tapinfo, pinfo, edt, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2223 /* Add the H245 info if exists to the Graph */
2224 h245_add_to_graph(tapinfo, pinfo->num);
2226 g_free(frame_label);
2227 g_free(comment);
2229 tapinfo->redraw |= REDRAW_H225;
2231 return TAP_PACKET_REDRAW; /* refresh output */
2234 /****************************************************************************/
2235 static void
2236 h225_calls_draw(void *tap_offset_ptr)
2238 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_h225_);
2240 if (tapinfo->tap_draw && (tapinfo->redraw & REDRAW_H225)) {
2241 tapinfo->tap_draw(tapinfo);
2242 tapinfo->redraw &= ~REDRAW_H225;
2246 /****************************************************************************/
2247 /* TAP INTERFACE */
2248 /****************************************************************************/
2249 void
2250 h225_calls_init_tap(voip_calls_tapinfo_t *tap_id_base)
2252 GString *error_string;
2254 error_string = register_tap_listener("h225", tap_base_to_id(tap_id_base, tap_id_offset_h225_), NULL,
2256 NULL,
2257 h225_calls_packet,
2258 h225_calls_draw,
2259 NULL
2262 if (error_string != NULL) {
2263 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2264 "%s", error_string->str);
2265 g_string_free(error_string, TRUE);
2269 /****************************************************************************/
2270 void
2271 remove_tap_listener_h225_calls(voip_calls_tapinfo_t *tap_id_base)
2273 remove_tap_listener(tap_base_to_id(tap_id_base, tap_id_offset_h225_));
2276 /* Add the h245 label info to the graph */
2277 void
2278 h245_add_to_graph(voip_calls_tapinfo_t *tapinfo, uint32_t new_frame_num)
2280 int8_t n;
2282 if (new_frame_num != tapinfo->h245_labels->frame_num) return;
2284 for (n=0; n<tapinfo->h245_labels->labels_count; n++) {
2285 append_to_frame_graph(tapinfo, new_frame_num, tapinfo->h245_labels->labels[n].frame_label, tapinfo->h245_labels->labels[n].comment);
2286 g_free(tapinfo->h245_labels->labels[n].frame_label);
2287 tapinfo->h245_labels->labels[n].frame_label = NULL;
2288 g_free(tapinfo->h245_labels->labels[n].comment);
2289 tapinfo->h245_labels->labels[n].comment = NULL;
2291 tapinfo->h245_labels->frame_num = 0;
2292 tapinfo->h245_labels->labels_count = 0;
2295 /* free the h245_labels if the frame number is different */
2296 static void
2297 h245_free_labels(voip_calls_tapinfo_t *tapinfo, uint32_t new_frame_num)
2299 int8_t n;
2301 if (new_frame_num == tapinfo->h245_labels->frame_num) return;
2303 for (n=0; n<tapinfo->h245_labels->labels_count; n++) {
2304 g_free(tapinfo->h245_labels->labels[n].frame_label);
2305 tapinfo->h245_labels->labels[n].frame_label = NULL;
2306 g_free(tapinfo->h245_labels->labels[n].comment);
2307 tapinfo->h245_labels->labels[n].comment = NULL;
2309 tapinfo->h245_labels->frame_num = 0;
2310 tapinfo->h245_labels->labels_count = 0;
2313 /* add the frame_label and comment to h245_labels and free the actual one if it is different frame num */
2314 static void
2315 h245_add_label(voip_calls_tapinfo_t *tapinfo, uint32_t new_frame_num, const char *frame_label, const char *comment)
2317 h245_free_labels(tapinfo, new_frame_num);
2319 tapinfo->h245_labels->frame_num = new_frame_num;
2320 tapinfo->h245_labels->labels[tapinfo->h245_labels->labels_count].frame_label = g_strdup(frame_label);
2321 tapinfo->h245_labels->labels[tapinfo->h245_labels->labels_count].comment = g_strdup(comment);
2323 if (tapinfo->h245_labels->labels_count < (H245_MAX-1))
2324 tapinfo->h245_labels->labels_count++;
2328 /****************************************************************************/
2329 /* whenever a H245dg packet is seen by the tap listener (when H245 tunneling is ON) */
2330 static tap_packet_status
2331 h245dg_calls_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt, const void *H245info, tap_flags_t flags _U_)
2333 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_h245dg_);
2334 voip_calls_info_t *tmp_listinfo;
2335 voip_calls_info_t *callsinfo = NULL;
2336 h323_calls_info_t *tmp_h323info;
2337 GList *list;
2338 GList *list2;
2339 h245_address_t *h245_add = NULL;
2341 const h245_packet_info *pi = (const h245_packet_info *)H245info;
2343 /* if display filtering activated and packet do not match, ignore it */
2344 if (tapinfo->apply_display_filter && (pinfo->fd->passed_dfilter == 0)) {
2345 return TAP_PACKET_DONT_REDRAW;
2348 /* check if Tunneling is OFF and we have a call with this H245 add */
2349 list = g_queue_peek_nth_link(tapinfo->callsinfos, 0);
2350 while (list)
2352 tmp_listinfo=(voip_calls_info_t *)list->data;
2353 if (tmp_listinfo->protocol == VOIP_H323) {
2354 tmp_h323info = (h323_calls_info_t *)tmp_listinfo->prot_info;
2356 list2 = g_list_first(tmp_h323info->h245_list);
2357 while (list2)
2359 h245_add=(h245_address_t *)list2->data;
2360 if ( (addresses_equal(&(h245_add->h245_address),&(pinfo->src)) && (h245_add->h245_port == pinfo->srcport))
2361 || (addresses_equal(&(h245_add->h245_address),&(pinfo->dst)) && (h245_add->h245_port == pinfo->destport)) ) {
2362 callsinfo = (voip_calls_info_t*)(list->data);
2364 ++(callsinfo->npackets);
2365 /* increment the packets counter of all calls */
2366 ++(tapinfo->npackets);
2368 break;
2370 list2 = g_list_next(list2);
2372 if (callsinfo!=NULL) break;
2374 list = g_list_next(list);
2377 /* Tunnel is OFF, and we matched the h245 add so we add it to graph */
2378 if (callsinfo!=NULL) {
2379 ++(callsinfo->npackets);
2380 /* increment the packets counter of all calls */
2381 ++(tapinfo->npackets);
2382 /* if the frame number exists in graph, append to it*/
2383 if (!append_to_frame_graph(tapinfo, pinfo->num, pi->frame_label, pi->comment)) {
2384 /* if not exist, add to the graph */
2385 add_to_graph(tapinfo, pinfo, edt, pi->frame_label, pi->comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2387 } else {
2388 /* Tunnel is ON, so we save the label info to use it into h225 or q931 tap. OR may be
2389 tunnel OFF but we did not matched the h245 add, in this case nobady will set this label
2390 since the frame_num will not match */
2392 h245_add_label(tapinfo, pinfo->num, pi->frame_label, pi->comment);
2395 tapinfo->redraw |= REDRAW_H245DG;
2397 return TAP_PACKET_REDRAW; /* refresh output */
2400 /****************************************************************************/
2401 static void
2402 h245dg_calls_draw(void *tap_offset_ptr)
2404 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_h245dg_);
2406 if (tapinfo->tap_draw && (tapinfo->redraw & REDRAW_H245DG)) {
2407 tapinfo->tap_draw(tapinfo);
2408 tapinfo->redraw &= ~REDRAW_H245DG;
2412 /****************************************************************************/
2413 /* TAP INTERFACE */
2414 /****************************************************************************/
2415 void
2416 h245dg_calls_init_tap(voip_calls_tapinfo_t *tap_id_base)
2418 GString *error_string;
2420 if (!tap_id_base->h245_labels) {
2421 tap_id_base->h245_labels = g_new0(h245_labels_t, 1);
2424 error_string = register_tap_listener("h245dg", tap_base_to_id(tap_id_base, tap_id_offset_h245dg_), NULL,
2426 NULL,
2427 h245dg_calls_packet,
2428 h245dg_calls_draw,
2429 NULL
2432 if (error_string != NULL) {
2433 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2434 "%s", error_string->str);
2435 g_string_free(error_string, TRUE);
2439 /****************************************************************************/
2440 void
2441 remove_tap_listener_h245dg_calls(voip_calls_tapinfo_t *tap_id_base)
2443 if (tap_id_base->h245_labels) {
2444 g_free(tap_id_base->h245_labels);
2445 tap_id_base->h245_labels = NULL;
2447 remove_tap_listener(tap_base_to_id(tap_id_base, tap_id_offset_h245dg_));
2450 /****************************************************************************/
2451 /****************************TAP for SDP PROTOCOL ***************************/
2452 /****************************************************************************/
2453 /* whenever a SDP packet is seen by the tap listener */
2454 static tap_packet_status
2455 sdp_calls_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SDPinfo, tap_flags_t flags _U_)
2457 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_sdp_);
2458 const sdp_packet_info *pi = (const sdp_packet_info *)SDPinfo;
2460 /* if display filtering activated and packet do not match, ignore it */
2461 if (tapinfo->apply_display_filter && (pinfo->fd->passed_dfilter == 0)) {
2462 return TAP_PACKET_DONT_REDRAW;
2465 /* There are protocols like MGCP/SIP where the SDP is called before the tap for the
2466 MGCP/SIP packet, in those cases we assign the SPD summary to global lastSDPsummary
2467 to use it later
2469 g_free(tapinfo->sdp_summary);
2470 tapinfo->sdp_frame_num = pinfo->num;
2471 /* Append to graph the SDP summary if the packet exists */
2472 tapinfo->sdp_summary = ws_strdup_printf("SDP (%s)", pi->summary_str);
2473 append_to_frame_graph(tapinfo, pinfo->num, tapinfo->sdp_summary, NULL);
2475 tapinfo->redraw |= REDRAW_SDP;
2477 return TAP_PACKET_REDRAW; /* refresh output */
2480 /****************************************************************************/
2481 static void
2482 sdp_calls_draw(void *tap_offset_ptr)
2484 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_sdp_);
2486 if (tapinfo->tap_draw && (tapinfo->redraw & REDRAW_SDP)) {
2487 tapinfo->tap_draw(tapinfo);
2488 tapinfo->redraw &= ~REDRAW_SDP;
2492 /****************************************************************************/
2493 /* TAP INTERFACE */
2494 /****************************************************************************/
2495 void
2496 sdp_calls_init_tap(voip_calls_tapinfo_t *tap_id_base)
2498 GString *error_string;
2500 error_string = register_tap_listener("sdp", tap_base_to_id(tap_id_base, tap_id_offset_sdp_), NULL,
2502 NULL,
2503 sdp_calls_packet,
2504 sdp_calls_draw,
2505 NULL
2508 if (error_string != NULL) {
2509 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2510 "%s", error_string->str);
2511 g_string_free(error_string, TRUE);
2515 /****************************************************************************/
2516 void
2517 remove_tap_listener_sdp_calls(voip_calls_tapinfo_t *tap_id_base)
2519 remove_tap_listener(tap_base_to_id(tap_id_base, tap_id_offset_sdp_));
2522 /****************************************************************************/
2523 /* ***************************TAP for MGCP **********************************/
2524 /****************************************************************************/
2527 This function will look for a signal/event in the SignalReq/ObsEvent string
2528 and return true if it is found
2530 static bool
2531 is_mgcp_signal(const char *signal_str_p, const char *signalStr)
2533 int i;
2534 char **resultArray;
2535 bool found = false;
2537 /* if there is no signalStr, just return false */
2538 if (signalStr == NULL) return false;
2540 /* if are both "blank" return true */
2541 if ( (*signal_str_p == '\0') && (*signalStr == '\0') ) return true;
2543 /* look for signal in signalStr */
2544 resultArray = g_strsplit(signalStr, ",", 10);
2546 for (i = 0; resultArray[i]; i++) {
2547 g_strstrip(resultArray[i]);
2548 if (strcmp(resultArray[i], signal_str_p) == 0) {
2549 found = true;
2550 break;
2554 g_strfreev(resultArray);
2556 return found;
2560 This function will get the Caller ID info and replace the current string
2561 This is how it looks the caller Id: rg, ci(02/16/08/29, "3035550002","Ale Sipura 2")
2563 static void
2564 mgcp_caller_id(char *signalStr, char **callerId)
2566 char **arrayStr;
2568 /* if there is no signalStr, just return false */
2569 if (signalStr == NULL) return;
2571 arrayStr = g_strsplit(signalStr, "\"", 3);
2573 /* look for the ci signal */
2574 if (g_strv_length(arrayStr) == 3 && strstr(arrayStr[0], "ci(")) {
2575 /* free the previous "From" field of the call, and assign the new */
2576 g_free(*callerId);
2577 *callerId = g_strdup(arrayStr[1]);
2579 g_strfreev(arrayStr);
2583 This function will get the Dialed Digits and replace the current string
2584 This is how it looks the dialed digits 5,5,5,0,0,0,2,#,*
2586 static void
2587 mgcp_dialed_digits(char *signalStr, char **dialedDigits)
2589 char *tmpStr;
2590 char *resultStr;
2591 int i,j;
2593 /* start with 1 for the null-terminator */
2594 unsigned resultStrLen = 1;
2596 /* if there is no signalStr, just return false */
2597 if (signalStr == NULL) return;
2599 tmpStr = g_strdup(signalStr);
2601 for ( i = 0 ; tmpStr[i] ; i++) {
2602 switch (tmpStr[i]) {
2603 case '0' : case '1' : case '2' : case '3' : case '4' :
2604 case '5' : case '6' : case '7' : case '8' : case '9' :
2605 case '#' : case '*' :
2606 resultStrLen++;
2607 break;
2608 default:
2609 tmpStr[i] = '?';
2610 break;
2614 if (resultStrLen == 1) {
2615 g_free(tmpStr);
2616 return;
2619 resultStr = (char *)g_malloc(resultStrLen);
2621 for (i = 0, j = 0; tmpStr[i]; i++) {
2622 if (tmpStr[i] != '?')
2623 resultStr[j++] = tmpStr[i];
2625 resultStr[j] = '\0';
2627 g_free(*dialedDigits);
2628 g_free(tmpStr);
2630 *dialedDigits = resultStr;
2632 return;
2637 /****************************************************************************/
2638 /* whenever a MGCP packet is seen by the tap listener */
2639 static tap_packet_status
2640 mgcp_calls_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt, const void *MGCPinfo, tap_flags_t flags _U_)
2642 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_mgcp_);
2643 voip_calls_info_t *tmp_listinfo;
2644 voip_calls_info_t *callsinfo = NULL;
2645 mgcp_calls_info_t *tmp_mgcpinfo = NULL;
2646 GList *list;
2647 GList *listGraph = NULL;
2648 char *frame_label = NULL;
2649 char *comment = NULL;
2650 seq_analysis_item_t *gai = NULL;
2651 bool newcall = false;
2652 bool fromEndpoint = false; /* true for calls originated in Endpoints, false for calls from MGC */
2653 double diff_time;
2655 const mgcp_info_t *pi = (const mgcp_info_t *)MGCPinfo;
2657 /* if display filtering activated and packet do not match, ignore it */
2658 if (tapinfo->apply_display_filter && (pinfo->fd->passed_dfilter == 0)) {
2659 return TAP_PACKET_DONT_REDRAW;
2662 if ((pi->mgcp_type == MGCP_REQUEST) && !pi->is_duplicate ) {
2663 /* check whether we already have a call with this Endpoint and it is active*/
2664 list = g_queue_peek_nth_link(tapinfo->callsinfos, 0);
2665 while (list)
2667 tmp_listinfo=(voip_calls_info_t *)list->data;
2668 if ((tmp_listinfo->protocol == VOIP_MGCP) && (tmp_listinfo->call_active_state == VOIP_ACTIVE)) {
2669 tmp_mgcpinfo = (mgcp_calls_info_t *)tmp_listinfo->prot_info;
2670 if (pi->endpointId != NULL) {
2671 if (g_ascii_strcasecmp(tmp_mgcpinfo->endpointId,pi->endpointId) == 0) {
2673 check first if it is an ended call. We can still match packets to this Endpoint 2 seconds
2674 after the call has been released
2676 diff_time = nstime_to_sec(&pinfo->rel_ts) - nstime_to_sec(&tmp_listinfo->stop_rel_ts);
2677 if ( ((tmp_listinfo->call_state == VOIP_CANCELLED) ||
2678 (tmp_listinfo->call_state == VOIP_COMPLETED) ||
2679 (tmp_listinfo->call_state == VOIP_REJECTED)) &&
2680 (diff_time > 2) )
2682 tmp_listinfo->call_active_state = VOIP_INACTIVE;
2683 } else {
2684 callsinfo = (voip_calls_info_t*)(list->data);
2685 break;
2690 list = g_list_next (list);
2693 /* there is no call with this Endpoint, lets see if this a new call or not */
2694 if (callsinfo == NULL) {
2695 if ( (strcmp(pi->code, "NTFY") == 0) && is_mgcp_signal("hd", pi->observedEvents) ) { /* off hook transition */
2696 /* this is a new call from the Endpoint */
2697 fromEndpoint = true;
2698 newcall = true;
2699 } else if (strcmp(pi->code, "CRCX") == 0) {
2700 /* this is a new call from the MGC */
2701 fromEndpoint = false;
2702 newcall = true;
2704 if (!newcall) return TAP_PACKET_DONT_REDRAW;
2706 } else if ( ((pi->mgcp_type == MGCP_RESPONSE) && pi->request_available) ||
2707 ((pi->mgcp_type == MGCP_REQUEST) && pi->is_duplicate) ) {
2708 /* if it is a response OR if it is a duplicated Request, lets look in the Graph to see
2709 if there is a request that matches */
2710 if(tapinfo->graph_analysis){
2711 listGraph = g_queue_peek_nth_link(tapinfo->graph_analysis->items, 0);
2713 while (listGraph)
2715 gai = (seq_analysis_item_t *)listGraph->data;
2716 if (gai->frame_number == pi->req_num) {
2717 /* there is a request that match, so look the associated call with this call_num */
2718 list = g_queue_peek_nth_link(tapinfo->callsinfos, 0);
2719 while (list)
2721 tmp_listinfo=(voip_calls_info_t *)list->data;
2722 if (tmp_listinfo->protocol == VOIP_MGCP) {
2723 if (tmp_listinfo->call_num == gai->conv_num) {
2724 tmp_mgcpinfo = (mgcp_calls_info_t *)tmp_listinfo->prot_info;
2725 callsinfo = (voip_calls_info_t*)(list->data);
2726 break;
2729 list = g_list_next (list);
2731 if (callsinfo != NULL) break;
2733 listGraph = g_list_next(listGraph);
2735 /* if there is not a matching request, just return */
2736 if (callsinfo == NULL) return TAP_PACKET_DONT_REDRAW;
2737 } else return TAP_PACKET_DONT_REDRAW;
2739 /* not in the list? then create a new entry */
2740 if (callsinfo==NULL) {
2741 callsinfo = g_new0(voip_calls_info_t, 1);
2742 callsinfo->call_active_state = VOIP_ACTIVE;
2743 callsinfo->call_state = VOIP_CALL_SETUP;
2744 if (fromEndpoint) {
2745 callsinfo->from_identity=g_strdup(pi->endpointId);
2746 callsinfo->to_identity=g_strdup("");
2747 } else {
2748 callsinfo->from_identity=g_strdup("");
2749 callsinfo->to_identity=g_strdup(pi->endpointId);
2751 copy_address(&(callsinfo->initial_speaker),&(pinfo->src));
2752 callsinfo->start_fd=pinfo->fd;
2753 callsinfo->start_rel_ts=pinfo->rel_ts;
2754 callsinfo->protocol=VOIP_MGCP;
2755 callsinfo->prot_info=g_new(mgcp_calls_info_t, 1);
2756 callsinfo->free_prot_info = g_free;
2757 tmp_mgcpinfo=(mgcp_calls_info_t *)callsinfo->prot_info;
2758 tmp_mgcpinfo->endpointId = g_strdup(pi->endpointId);
2759 tmp_mgcpinfo->fromEndpoint = fromEndpoint;
2760 callsinfo->npackets = 0;
2761 callsinfo->call_num = tapinfo->ncalls++;
2762 g_queue_push_tail(tapinfo->callsinfos, callsinfo);
2765 ws_assert(tmp_mgcpinfo != NULL);
2767 /* change call state and add to graph */
2768 switch (pi->mgcp_type)
2770 case MGCP_REQUEST:
2771 if ( (strcmp(pi->code, "NTFY") == 0) && (pi->observedEvents != NULL) ) {
2772 frame_label = ws_strdup_printf("%s ObsEvt:%s",pi->code, pi->observedEvents);
2774 if (tmp_mgcpinfo->fromEndpoint) {
2775 /* use the Dialed digits to fill the "To" for the call, but use the first NTFY */
2776 if (callsinfo->to_identity[0] == '\0') mgcp_dialed_digits(pi->observedEvents, &(callsinfo->to_identity));
2778 /* from MGC and the user picked up, the call is connected */
2779 } else if (is_mgcp_signal("hd", pi->observedEvents))
2780 callsinfo->call_state=VOIP_IN_CALL;
2782 /* hung up signal */
2783 if (is_mgcp_signal("hu", pi->observedEvents)) {
2784 if ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state == VOIP_RINGING)) {
2785 callsinfo->call_state = VOIP_CANCELLED;
2786 } else {
2787 callsinfo->call_state = VOIP_COMPLETED;
2791 } else if (strcmp(pi->code, "RQNT") == 0) {
2792 /* for calls from Endpoint: if there is a "no signal" RQNT and the call was RINGING, we assume this is the CONNECT */
2793 if ( tmp_mgcpinfo->fromEndpoint && is_mgcp_signal("", pi->signalReq) && (callsinfo->call_state == VOIP_RINGING) ) {
2794 callsinfo->call_state = VOIP_IN_CALL;
2797 /* if there is ringback or ring tone, change state to ringing */
2798 if ( is_mgcp_signal("rg", pi->signalReq) || is_mgcp_signal("rt", pi->signalReq) ) {
2799 callsinfo->call_state = VOIP_RINGING;
2802 /* if there is a Busy or ReorderTone, and the call was Ringing or Setup the call is Rejected */
2803 if ( (is_mgcp_signal("ro", pi->signalReq) || is_mgcp_signal("bz", pi->signalReq)) && ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state == VOIP_RINGING)) ) {
2804 callsinfo->call_state = VOIP_REJECTED;
2807 if (pi->signalReq != NULL)
2808 frame_label = ws_strdup_printf("%s%sSigReq:%s",pi->code, (pi->hasDigitMap == true)?" DigitMap ":"", pi->signalReq);
2809 else
2810 frame_label = ws_strdup_printf("%s%s",pi->code, (pi->hasDigitMap == true)?" DigitMap ":"");
2812 /* use the CallerID info to fill the "From" for the call */
2813 if (!tmp_mgcpinfo->fromEndpoint) mgcp_caller_id(pi->signalReq, &(callsinfo->from_identity));
2815 } else if (strcmp(pi->code, "DLCX") == 0) {
2817 if there is a DLCX in a call To an Endpoint and the call was not connected, we use
2818 the DLCX as the end of the call
2820 if (!tmp_mgcpinfo->fromEndpoint) {
2821 if ((callsinfo->call_state == VOIP_CALL_SETUP) || (callsinfo->call_state == VOIP_RINGING)) {
2822 callsinfo->call_state = VOIP_CANCELLED;
2827 if (frame_label == NULL) frame_label = g_strdup(pi->code);
2828 break;
2829 case MGCP_RESPONSE:
2830 frame_label = ws_strdup_printf("%u (%s)",pi->rspcode, pi->code);
2831 break;
2832 case MGCP_OTHERS:
2833 /* XXX what to do? */
2834 break;
2837 comment = ws_strdup_printf("MGCP %s %s%s", tmp_mgcpinfo->endpointId, (pi->mgcp_type == MGCP_REQUEST)?"Request":"Response", pi->is_duplicate?" Duplicate":"");
2839 callsinfo->stop_fd = pinfo->fd;
2840 callsinfo->stop_rel_ts = pinfo->rel_ts;
2841 ++(callsinfo->npackets);
2842 /* increment the packets counter of all calls */
2843 ++(tapinfo->npackets);
2845 /* add to the graph */
2846 add_to_graph(tapinfo, pinfo, edt, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
2847 g_free(comment);
2848 g_free(frame_label);
2850 /* add SDP info if apply */
2851 if ( (tapinfo->sdp_summary != NULL) && (tapinfo->sdp_frame_num == pinfo->num) ) {
2852 append_to_frame_graph(tapinfo, pinfo->num, tapinfo->sdp_summary, NULL);
2853 g_free(tapinfo->sdp_summary);
2854 tapinfo->sdp_summary = NULL;
2857 tapinfo->redraw |= REDRAW_MGCP;
2859 return TAP_PACKET_REDRAW; /* refresh output */
2862 /****************************************************************************/
2863 static void
2864 mgcp_calls_draw(void *tap_offset_ptr)
2866 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_mgcp_);
2868 if (tapinfo->tap_draw && (tapinfo->redraw & REDRAW_MGCP)) {
2869 tapinfo->tap_draw(tapinfo);
2870 tapinfo->redraw &= ~REDRAW_MGCP;
2874 /****************************************************************************/
2875 /* TAP INTERFACE */
2876 /****************************************************************************/
2877 void
2878 mgcp_calls_init_tap(voip_calls_tapinfo_t *tap_id_base)
2880 GString *error_string;
2883 * We set TL_REQUIRES_PROTO_TREE to force a non-null "tree"
2884 * in the MGCP dissector; otherwise, the dissector
2885 * doesn't fill in the info passed to the tap's packet
2886 * routine.
2888 error_string = register_tap_listener("mgcp",
2889 tap_base_to_id(tap_id_base, tap_id_offset_mgcp_),
2890 NULL,
2891 TL_REQUIRES_PROTO_TREE,
2892 NULL,
2893 mgcp_calls_packet,
2894 mgcp_calls_draw,
2895 NULL
2897 if (error_string != NULL) {
2898 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2899 "%s", error_string->str);
2900 g_string_free(error_string, TRUE);
2904 /****************************************************************************/
2905 void
2906 remove_tap_listener_mgcp_calls(voip_calls_tapinfo_t *tap_id_base)
2908 remove_tap_listener(tap_base_to_id(tap_id_base, tap_id_offset_mgcp_));
2911 /****************************************************************************/
2912 /****************************TAP for ACTRACE (AudioCodes trace)**************/
2913 /****************************************************************************/
2915 /* whenever a ACTRACE packet is seen by the tap listener */
2916 static tap_packet_status
2917 actrace_calls_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt, const void *ACTRACEinfo, tap_flags_t flags _U_)
2919 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_actrace_);
2920 const actrace_info_t *pi = (const actrace_info_t *)ACTRACEinfo;
2921 GList *list;
2922 actrace_cas_calls_info_t *tmp_actrace_cas_info;
2923 voip_calls_info_t *tmp_listinfo;
2924 voip_calls_info_t *callsinfo = NULL;
2926 /* if display filtering activated and packet do not match, ignore it */
2927 if (tapinfo->apply_display_filter && (pinfo->fd->passed_dfilter == 0)) {
2928 return TAP_PACKET_DONT_REDRAW;
2931 tapinfo->actrace_frame_num = pinfo->num;
2932 tapinfo->actrace_trunk = pi->trunk;
2933 tapinfo->actrace_direction = pi->direction;
2935 if (pi->type == 1) { /* is CAS protocol */
2936 address pstn_add;
2937 char *comment = NULL;
2939 callsinfo = NULL;
2940 list = g_queue_peek_nth_link(tapinfo->callsinfos, 0);
2941 while (list)
2943 tmp_listinfo=(voip_calls_info_t *)list->data;
2944 if ( tmp_listinfo->protocol == VOIP_AC_CAS ) {
2945 tmp_actrace_cas_info = (actrace_cas_calls_info_t *)tmp_listinfo->prot_info;
2946 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
2947 if ( (tmp_actrace_cas_info->bchannel == pi->cas_bchannel) && (tmp_actrace_cas_info->trunk == tapinfo->actrace_trunk) ) {
2948 callsinfo = (voip_calls_info_t*)(list->data);
2949 break;
2952 list = g_list_next (list);
2955 set_address(&pstn_add, AT_STRINGZ, 5, "PSTN");
2957 /* if it is a new call, add it to the list */
2958 if (!callsinfo) {
2959 callsinfo = g_new0(voip_calls_info_t, 1);
2960 callsinfo->call_active_state = VOIP_ACTIVE;
2961 callsinfo->call_state = VOIP_CALL_SETUP;
2962 callsinfo->from_identity=g_strdup("N/A");
2963 callsinfo->to_identity=g_strdup("N/A");
2964 copy_address(&(callsinfo->initial_speaker),tapinfo->actrace_direction?&pstn_add:&(pinfo->src));
2965 callsinfo->start_fd=pinfo->fd;
2966 callsinfo->start_rel_ts=pinfo->rel_ts;
2967 callsinfo->protocol=VOIP_AC_CAS;
2968 callsinfo->prot_info=g_new(actrace_cas_calls_info_t, 1);
2969 callsinfo->free_prot_info = g_free;
2971 tmp_actrace_cas_info=(actrace_cas_calls_info_t *)callsinfo->prot_info;
2972 tmp_actrace_cas_info->bchannel=pi->cas_bchannel;
2973 tmp_actrace_cas_info->trunk=tapinfo->actrace_trunk;
2974 callsinfo->npackets = 0;
2975 callsinfo->call_num = tapinfo->ncalls++;
2976 g_queue_push_tail(tapinfo->callsinfos, callsinfo);
2979 callsinfo->stop_fd = pinfo->fd;
2980 callsinfo->stop_rel_ts = pinfo->rel_ts;
2981 ++(callsinfo->npackets);
2982 /* increment the packets counter of all calls */
2983 ++(tapinfo->npackets);
2985 comment = ws_strdup_printf("AC_CAS trunk:%u", tapinfo->actrace_trunk);
2987 add_to_graph(tapinfo, pinfo, edt, pi->cas_frame_label, comment, callsinfo->call_num,
2988 tapinfo->actrace_direction?&pstn_add:&(pinfo->src),
2989 tapinfo->actrace_direction?&(pinfo->src):&pstn_add,
2990 1 );
2992 g_free(comment);
2995 tapinfo->redraw |= REDRAW_ACTRACE;
2997 return TAP_PACKET_REDRAW; /* refresh output */
3000 /****************************************************************************/
3001 static void
3002 actrace_calls_draw(void *tap_offset_ptr)
3004 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_actrace_);
3006 if (tapinfo->tap_draw && (tapinfo->redraw & REDRAW_ACTRACE)) {
3007 tapinfo->tap_draw(tapinfo);
3008 tapinfo->redraw &= ~REDRAW_ACTRACE;
3012 /****************************************************************************/
3013 /* TAP INTERFACE */
3014 /****************************************************************************/
3015 void
3016 actrace_calls_init_tap(voip_calls_tapinfo_t *tap_id_base)
3018 GString *error_string;
3020 error_string = register_tap_listener("actrace", tap_base_to_id(tap_id_base, tap_id_offset_actrace_), NULL,
3022 NULL,
3023 actrace_calls_packet,
3024 actrace_calls_draw,
3025 NULL
3028 if (error_string != NULL) {
3029 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3030 "%s", error_string->str);
3031 g_string_free(error_string, TRUE);
3035 /****************************************************************************/
3036 void
3037 remove_tap_listener_actrace_calls(voip_calls_tapinfo_t *tap_id_base)
3039 remove_tap_listener(tap_base_to_id(tap_id_base, tap_id_offset_actrace_));
3043 /****************************************************************************/
3044 /**************************** TAP for H248/MEGACO **********************************/
3045 /****************************************************************************/
3047 #define gcp_is_req(type) ( type == GCP_CMD_ADD_REQ || type == GCP_CMD_MOVE_REQ || type == GCP_CMD_MOD_REQ || \
3048 type == GCP_CMD_SUB_REQ || type == GCP_CMD_AUDITCAP_REQ || type == GCP_CMD_AUDITVAL_REQ || \
3049 type == GCP_CMD_NOTIFY_REQ || type == GCP_CMD_SVCCHG_REQ || type == GCP_CMD_TOPOLOGY_REQ || \
3050 type == GCP_CMD_CTX_ATTR_AUDIT_REQ )
3053 static tap_packet_status
3054 h248_calls_packet_common(voip_calls_tapinfo_t *tapinfo, packet_info *pinfo, epan_dissect_t *edt, const void *prot_info, uint32_t redraw_bit) {
3055 const gcp_cmd_t *cmd = (const gcp_cmd_t *)prot_info;
3056 GList *list;
3057 voip_calls_info_t *callsinfo = NULL;
3058 address *mgw;
3059 address *mgc;
3060 char mgw_addr[128];
3062 if (cmd->ctx->id == NULL_CONTEXT || cmd->ctx->id == ALL_CONTEXTS ) {
3063 return TAP_PACKET_DONT_REDRAW;
3066 if ( gcp_is_req(cmd->type) ) {
3067 mgw = &(pinfo->dst);
3068 mgc = &(pinfo->src);
3069 } else {
3070 mgc = &(pinfo->dst);
3071 mgw = &(pinfo->src);
3074 address_to_str_buf(mgw, mgw_addr, 128);
3076 /* check whether we already have this context in the list */
3077 list = g_queue_peek_nth_link(tapinfo->callsinfos, 0);
3078 while (list)
3080 voip_calls_info_t* tmp_listinfo = (voip_calls_info_t *)list->data;
3082 if (tmp_listinfo->protocol == TEL_H248) {
3083 if (tmp_listinfo->prot_info == cmd->ctx) {
3084 callsinfo = (voip_calls_info_t*)(list->data);
3085 break;
3088 list = g_list_next (list);
3091 if (callsinfo==NULL) {
3093 callsinfo = g_new0(voip_calls_info_t, 1);
3094 callsinfo->call_state = VOIP_NO_STATE;
3095 callsinfo->call_active_state = VOIP_ACTIVE;
3096 callsinfo->from_identity = ws_strdup_printf("%s : %.8x", mgw_addr, cmd->ctx->id);
3097 callsinfo->to_identity = g_strdup("");
3098 callsinfo->prot_info = cmd->ctx;
3099 callsinfo->free_prot_info = NULL;
3101 callsinfo->npackets = 1;
3103 copy_address(&(callsinfo->initial_speaker), mgc);
3105 callsinfo->protocol = TEL_H248;
3106 callsinfo->call_num = tapinfo->ncalls++;
3107 callsinfo->start_fd = pinfo->fd;
3108 callsinfo->start_rel_ts = pinfo->rel_ts;
3109 callsinfo->stop_fd = pinfo->fd;
3110 callsinfo->stop_rel_ts = pinfo->rel_ts;
3112 g_queue_push_tail(tapinfo->callsinfos, callsinfo);
3114 } else {
3115 GString *s = g_string_new("");
3116 gcp_terms_t *ctx_term;
3118 g_free(callsinfo->from_identity);
3119 callsinfo->from_identity = ws_strdup_printf("%s : %.8x", mgw_addr, ((gcp_ctx_t*)callsinfo->prot_info)->id);
3121 g_free(callsinfo->to_identity);
3123 for (ctx_term = ((gcp_ctx_t*)callsinfo->prot_info)->terms.next;
3124 ctx_term;
3125 ctx_term = ctx_term->next ) {
3126 if ( ctx_term->term && ctx_term->term->str) {
3127 g_string_append_printf(s," %s",ctx_term->term->str);
3131 callsinfo->to_identity = g_string_free(s,FALSE);
3133 callsinfo->stop_fd = pinfo->fd;
3134 callsinfo->stop_rel_ts = pinfo->rel_ts;
3135 ++(callsinfo->npackets);
3138 add_to_graph(tapinfo, pinfo, edt, cmd->str ? cmd->str : "unknown Msg",
3139 wmem_strdup_printf(pinfo->pool, "TrxId = %u, CtxId = %.8x",cmd->trx->id,cmd->ctx->id),
3140 callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3142 ++(tapinfo->npackets);
3144 tapinfo->redraw |= redraw_bit;
3146 return TAP_PACKET_REDRAW;
3149 static tap_packet_status
3150 h248_calls_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt, const void *prot_info, tap_flags_t flags _U_) {
3151 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_h248_);
3153 /* if display filtering activated and packet do not match, ignore it */
3154 if (tapinfo->apply_display_filter && (pinfo->fd->passed_dfilter == 0)) {
3155 return TAP_PACKET_DONT_REDRAW;
3157 return h248_calls_packet_common(tapinfo, pinfo, edt, prot_info, REDRAW_H248);
3160 static void
3161 h248_calls_draw(void *tap_offset_ptr)
3163 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_h248_);
3165 if (tapinfo->tap_draw && (tapinfo->redraw & REDRAW_H248)) {
3166 tapinfo->tap_draw(tapinfo);
3167 tapinfo->redraw &= ~REDRAW_H248;
3171 static tap_packet_status
3172 megaco_calls_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt, const void *prot_info, tap_flags_t flags _U_) {
3173 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_megaco_);
3175 /* if display filtering activated and packet do not match, ignore it */
3176 if (tapinfo->apply_display_filter && (pinfo->fd->passed_dfilter == 0)) {
3177 return TAP_PACKET_DONT_REDRAW;
3179 return h248_calls_packet_common(tapinfo, pinfo, edt, prot_info, REDRAW_MEGACO);
3182 static void
3183 megaco_calls_draw(void *tap_offset_ptr)
3185 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_megaco_);
3187 if (tapinfo->tap_draw && (tapinfo->redraw & REDRAW_MEGACO)) {
3188 tapinfo->tap_draw(tapinfo);
3189 tapinfo->redraw &= ~REDRAW_MEGACO;
3193 void
3194 h248_calls_init_tap(voip_calls_tapinfo_t *tap_id_base)
3196 GString *error_string;
3198 error_string = register_tap_listener("megaco", tap_base_to_id(tap_id_base, tap_id_offset_megaco_),
3199 NULL,
3201 NULL,
3202 megaco_calls_packet,
3203 megaco_calls_draw,
3204 NULL);
3206 if (error_string != NULL) {
3207 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3208 "%s", error_string->str);
3209 g_string_free(error_string, TRUE);
3212 error_string = register_tap_listener("h248", tap_base_to_id(tap_id_base, tap_id_offset_h248_),
3213 NULL,
3215 NULL,
3216 h248_calls_packet,
3217 h248_calls_draw,
3218 NULL);
3220 if (error_string != NULL) {
3221 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3222 "%s", error_string->str);
3223 g_string_free(error_string, TRUE);
3227 void
3228 remove_tap_listener_h248_calls(voip_calls_tapinfo_t *tap_id_base)
3230 remove_tap_listener(tap_base_to_id(tap_id_base, tap_id_offset_h248_));
3231 remove_tap_listener(tap_base_to_id(tap_id_base, tap_id_offset_megaco_));
3234 /****************************************************************************/
3235 /**************************** TAP for SCCP and SUA **********************************/
3236 /**************************** ( RANAP and BSSAP ) **********************************/
3237 /****************************************************************************/
3239 static const voip_protocol sccp_proto_map[] = {
3240 TEL_SCCP,
3241 TEL_BSSMAP,
3242 TEL_RANAP
3244 #define SP2VP(ap) ((ap) < SCCP_PLOAD_NUM_PLOADS ? sccp_proto_map[(ap)] : TEL_SCCP)
3245 const value_string* sccp_payload_values;
3247 static tap_packet_status
3248 sccp_calls(voip_calls_tapinfo_t *tapinfo, packet_info *pinfo, epan_dissect_t *edt, const void *prot_info, uint32_t redraw_bit) {
3249 const sccp_msg_info_t* msg = (const sccp_msg_info_t *)prot_info;
3250 sccp_assoc_info_t* assoc = msg->data.co.assoc;
3251 GList *list;
3252 voip_calls_info_t *callsinfo = NULL;
3253 char *label = NULL;
3254 const char *comment = NULL;
3255 /* check whether we already have this assoc in the list */
3257 for(list = g_queue_peek_nth_link(tapinfo->callsinfos, 0) ; list ; list = g_list_next (list) ) {
3258 if ( ((voip_calls_info_t*)(list->data))->prot_info == assoc ) {
3259 callsinfo = (voip_calls_info_t*)(list->data);
3260 break;
3264 if (callsinfo==NULL) {
3265 callsinfo = g_new0(voip_calls_info_t, 1);
3266 callsinfo->call_state = VOIP_CALL_SETUP;
3267 callsinfo->call_active_state = VOIP_ACTIVE;
3268 if ( assoc->calling_party ) {
3269 callsinfo->from_identity = g_strdup(assoc->calling_party);
3270 } else {
3271 callsinfo->from_identity = g_strdup("Unknown");
3274 if ( assoc->called_party ) {
3275 callsinfo->to_identity = g_strdup(assoc->called_party);
3276 } else {
3277 callsinfo->to_identity = g_strdup("Unknown");
3280 callsinfo->prot_info = (void*)assoc;
3281 callsinfo->free_prot_info = NULL;
3283 callsinfo->npackets = 1;
3285 copy_address(&(callsinfo->initial_speaker), &(pinfo->src));
3287 callsinfo->protocol = SP2VP(assoc->payload);
3288 /* Store frame data which holds time and frame number */
3289 callsinfo->start_fd = pinfo->fd;
3290 callsinfo->start_rel_ts = pinfo->rel_ts;
3291 callsinfo->stop_fd = pinfo->fd;
3292 callsinfo->stop_rel_ts = pinfo->rel_ts;
3294 callsinfo->call_num = tapinfo->ncalls++;
3296 g_queue_push_tail(tapinfo->callsinfos, callsinfo);
3297 } else {
3299 if ( assoc->calling_party ) {
3300 g_free(callsinfo->from_identity);
3301 callsinfo->from_identity = g_strdup(assoc->calling_party);
3304 if ( assoc->called_party ) {
3305 g_free(callsinfo->to_identity);
3306 callsinfo->to_identity = g_strdup(assoc->called_party);
3309 callsinfo->protocol = SP2VP(assoc->payload);
3310 /* Store frame data which holds stop time and frame number */
3311 callsinfo->stop_fd = pinfo->fd;
3312 callsinfo->stop_rel_ts = pinfo->rel_ts;
3313 ++(callsinfo->npackets);
3315 switch (msg->type) {
3316 case SCCP_MSG_TYPE_CC:
3317 callsinfo->call_state = VOIP_IN_CALL;
3318 break;
3319 case SCCP_MSG_TYPE_RLC:
3320 callsinfo->call_state = VOIP_COMPLETED;
3321 callsinfo->call_active_state = VOIP_INACTIVE;
3322 break;
3323 default:
3324 break;
3328 if (msg->data.co.label) {
3329 label = wmem_strdup(NULL, msg->data.co.label);
3330 } else {
3331 label = val_to_str_wmem(NULL, msg->type, sccp_payload_values, "Unknown(%d)");
3334 if (msg->data.co.comment) {
3335 comment = msg->data.co.comment;
3336 } else {
3337 comment = NULL;
3340 add_to_graph(tapinfo, pinfo, edt, label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3341 wmem_free(NULL, label);
3343 ++(tapinfo->npackets);
3345 tapinfo->redraw |= redraw_bit;
3347 return TAP_PACKET_REDRAW;
3350 static tap_packet_status
3351 sccp_calls_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt, const void *prot_info, tap_flags_t flags _U_) {
3352 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_sccp_);
3354 /* if display filtering activated and packet do not match, ignore it */
3355 if (tapinfo->apply_display_filter && (pinfo->fd->passed_dfilter == 0)) {
3356 return TAP_PACKET_DONT_REDRAW;
3358 sccp_payload_values = sccp_message_type_acro_values;
3359 return sccp_calls(tapinfo, pinfo, edt, prot_info, REDRAW_SCCP);
3362 static void
3363 sccp_calls_draw(void *tap_offset_ptr)
3365 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_sccp_);
3367 if (tapinfo->tap_draw && (tapinfo->redraw & REDRAW_SCCP)) {
3368 tapinfo->tap_draw(tapinfo);
3369 tapinfo->redraw &= ~REDRAW_SCCP;
3373 static tap_packet_status
3374 sua_calls_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt, const void *prot_info, tap_flags_t flags _U_) {
3375 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_sua_);
3377 /* if display filtering activated and packet do not match, ignore it */
3378 if (tapinfo->apply_display_filter && (pinfo->fd->passed_dfilter == 0)) {
3379 return TAP_PACKET_DONT_REDRAW;
3381 sccp_payload_values = sua_co_class_type_acro_values;
3382 return sccp_calls(tapinfo, pinfo, edt, prot_info, REDRAW_SUA);
3385 static void
3386 sua_calls_draw(void *tap_offset_ptr)
3388 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_sua_);
3390 if (tapinfo->tap_draw && (tapinfo->redraw & REDRAW_SUA)) {
3391 tapinfo->tap_draw(tapinfo);
3392 tapinfo->redraw &= ~REDRAW_SUA;
3396 void sccp_calls_init_tap(voip_calls_tapinfo_t *tap_id_base)
3398 GString *error_string;
3400 error_string = register_tap_listener("sccp", tap_base_to_id(tap_id_base, tap_id_offset_sccp_),
3401 NULL,
3403 NULL,
3404 sccp_calls_packet,
3405 sccp_calls_draw,
3406 NULL);
3408 if (error_string != NULL) {
3409 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3410 "%s", error_string->str);
3411 g_string_free(error_string, TRUE);
3414 error_string = register_tap_listener("sua", tap_base_to_id(tap_id_base, tap_id_offset_sua_),
3415 NULL,
3417 NULL,
3418 sua_calls_packet,
3419 sua_calls_draw,
3420 NULL);
3422 if (error_string != NULL) {
3423 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3424 "%s", error_string->str);
3425 g_string_free(error_string, TRUE);
3429 void
3430 remove_tap_listener_sccp_calls(voip_calls_tapinfo_t *tap_id_base)
3432 remove_tap_listener(tap_base_to_id(tap_id_base, tap_id_offset_sccp_));
3433 remove_tap_listener(tap_base_to_id(tap_id_base, tap_id_offset_sua_));
3437 /****************************************************************************/
3438 /****************************TAP for UNISTIM ********************************/
3439 /****************************************************************************/
3441 static tap_packet_status
3442 unistim_calls_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt, const void *unistim_info, tap_flags_t flags _U_)
3444 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_unistim_);
3445 voip_calls_info_t *tmp_listinfo;
3446 voip_calls_info_t *callsinfo = NULL;
3447 unistim_info_t *tmp_unistim_info = NULL;
3448 GList *list = NULL;
3449 GString *g_tmp = NULL;
3450 const char *frame_label = NULL;
3451 char *comment = NULL;
3453 /* Fetch specific packet infos */
3454 const unistim_info_t *pi = (const unistim_info_t *)unistim_info;
3456 /* if display filtering activated and packet do not match, ignore it */
3457 if (tapinfo->apply_display_filter && (pinfo->fd->passed_dfilter == 0)) {
3458 return TAP_PACKET_DONT_REDRAW;
3461 /* Init gstring */
3462 g_tmp = g_string_new(NULL);
3464 /* Check to see if this is a dup */
3465 list = g_queue_peek_nth_link(tapinfo->callsinfos, 0);
3467 while(list)
3469 tmp_listinfo = (voip_calls_info_t *)list->data;
3471 if(tmp_listinfo->protocol == VOIP_UNISTIM) {
3473 tmp_unistim_info = (unistim_info_t *)tmp_listinfo->prot_info;
3475 /* Search by termid if possible, otherwise use ni/it ip + port.. */
3476 if(pi->termid != 0) {
3477 if(tmp_unistim_info->termid == pi->termid) {
3478 /* If the call has ended, then we can reuse it.. */
3479 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN) {
3480 /* Do nothing */
3481 } else {
3482 callsinfo = (voip_calls_info_t*)(list->data);
3483 break;
3486 } else {
3487 /* If no term id use ips / port to find entry */
3488 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)) {
3489 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN) {
3490 /* Do nothing previous call */
3491 } else {
3492 callsinfo = (voip_calls_info_t*)(list->data);
3493 break;
3496 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)) {
3497 if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN) {
3498 /* Do nothing, it ain't our call.. */
3499 } else {
3500 callsinfo = (voip_calls_info_t*)(list->data);
3501 break;
3507 /* Otherwise, go to the next one.. */
3508 list = g_list_next(list);
3511 if(pi->payload_type == 2 || pi->payload_type == 1) {
3513 if(pi->key_state == 1 || pi->hook_state == 1) {
3515 /* If the user hits a button,
3516 Session will be SETUP */
3518 /* If new add to list */
3519 if (callsinfo==NULL) {
3521 callsinfo = g_new0(voip_calls_info_t, 1);
3522 callsinfo->call_active_state = VOIP_ACTIVE;
3523 callsinfo->call_state = VOIP_CALL_SETUP;
3524 callsinfo->from_identity=ws_strdup_printf("%x",pi->termid);
3525 callsinfo->to_identity=g_strdup("UNKNOWN");
3526 copy_address(&(callsinfo->initial_speaker),&(pinfo->src));
3528 /* Set this on init of struct so in case the call doesn't complete, we'll have a ref. */
3529 /* Otherwise if the call is completed we'll have the open/close streams to ref actual call duration */
3530 /* Store frame data which holds time and frame number */
3531 callsinfo->start_fd=pinfo->fd;
3532 callsinfo->start_rel_ts=pinfo->rel_ts;
3534 callsinfo->protocol=VOIP_UNISTIM;
3535 callsinfo->prot_info=g_new(unistim_info_t, 1);
3537 tmp_unistim_info = (unistim_info_t *)callsinfo->prot_info;
3539 /* Clear tap struct */
3540 tmp_unistim_info->rudp_type = 0;
3541 tmp_unistim_info->payload_type = 0;
3542 tmp_unistim_info->sequence = pi->sequence;
3543 tmp_unistim_info->termid = pi->termid;
3544 tmp_unistim_info->key_val = -1;
3545 tmp_unistim_info->key_state = -1;
3546 tmp_unistim_info->hook_state = -1;
3547 tmp_unistim_info->stream_connect = -1;
3548 tmp_unistim_info->trans_connect = -1;
3549 tmp_unistim_info->set_termid = -1;
3550 tmp_unistim_info->string_data = NULL;
3551 tmp_unistim_info->key_buffer = NULL;
3553 copy_address(&(tmp_unistim_info->it_ip),&(pi->it_ip));
3554 copy_address(&(tmp_unistim_info->ni_ip),&(pi->ni_ip));
3555 tmp_unistim_info->it_port = pi->it_port;
3557 callsinfo->free_prot_info = g_free;
3558 callsinfo->npackets = 0;
3559 callsinfo->call_num = tapinfo->ncalls++;
3560 g_queue_push_tail(tapinfo->callsinfos, callsinfo);
3562 } else {
3564 /* Set up call wide info struct */
3565 tmp_unistim_info = (unistim_info_t *)callsinfo->prot_info;
3566 tmp_unistim_info->sequence = pi->sequence;
3569 /* Each packet COULD BE OUR LAST!!!! */
3570 /* Store frame data which holds time and frame number */
3571 callsinfo->stop_fd = pinfo->fd;
3572 callsinfo->stop_rel_ts = pinfo->rel_ts;
3574 /* This is a valid packet so increment counter */
3575 ++(callsinfo->npackets);
3577 /* increment the packets counter of all calls */
3578 ++(tapinfo->npackets);
3580 /* Key was depressed.. update key buffer.. */
3581 if(pi->key_val >= 0 && pi->key_val <= 11) {
3583 if(tmp_unistim_info->key_buffer != NULL) {
3585 /* assign to temp variable */
3586 g_string_assign(g_tmp,tmp_unistim_info->key_buffer);
3588 /* Manipulate the data */
3589 if(pi->key_val == 10) {
3590 tmp_unistim_info->key_buffer = ws_strdup_printf("%s*",g_tmp->str);
3591 } else if(pi->key_val == 11) {
3592 tmp_unistim_info->key_buffer = ws_strdup_printf("%s#",g_tmp->str);
3593 } else {
3594 tmp_unistim_info->key_buffer = ws_strdup_printf("%s%d",g_tmp->str,pi->key_val);
3597 } else {
3599 /* Create new string */
3600 if(pi->key_val == 10) {
3601 tmp_unistim_info->key_buffer = g_strdup("*");
3602 } else if(pi->key_val == 11) {
3603 tmp_unistim_info->key_buffer = g_strdup("#");
3604 } else {
3605 tmp_unistim_info->key_buffer = ws_strdup_printf("%d",pi->key_val);
3610 /* Select for non-digit characters */
3611 if(pi->key_val == 10) {
3612 comment = ws_strdup_printf("Key Input Sent: * (%d)", pi->sequence);
3613 } else if(pi->key_val == 11) {
3614 comment = ws_strdup_printf("Key Input Sent: # (%d)", pi->sequence);
3615 } else {
3616 comment = ws_strdup_printf("Key Input Sent: %d (%d)",pi->key_val, pi->sequence);
3618 } else if(pi->key_val == 12) {
3619 /* Set label and comment for graph */
3620 comment = ws_strdup_printf("Key Input Sent: UP (%d)", pi->sequence);
3621 } else if(pi->key_val == 13) {
3622 /* Set label and comment for graph */
3623 comment = ws_strdup_printf("Key Input Sent: DOWN (%d)", pi->sequence);
3624 } else if(pi->key_val == 14) {
3625 /* Set label and comment for graph */
3626 comment = ws_strdup_printf("Key Input Sent: RIGHT (%d)", pi->sequence);
3627 } else if(pi->key_val == 15) {
3628 if(pi->key_buffer != NULL) {
3629 /* Get data */
3630 g_string_assign(g_tmp,pi->key_buffer);
3632 /* Manipulate the data */
3633 g_string_truncate(g_tmp,g_tmp->len-1);
3635 /* Insert new data */
3636 tmp_unistim_info->key_buffer = g_strdup(g_tmp->str);
3639 /* Set label and comment for graph */
3640 comment = ws_strdup_printf("Key Input Sent: LEFT (%d)", pi->sequence);
3641 } else if(pi->key_val == 20) {
3642 /* User pressed the soft key 0 probably dial */
3643 comment = ws_strdup_printf("Key Input Sent: S0 (%d)", pi->sequence);
3644 } else if(pi->key_val == 21) {
3645 /* User pressed the soft key 1 */
3646 comment = ws_strdup_printf("Key Input Sent: S1 (%d)", pi->sequence);
3647 } else if(pi->key_val == 22) {
3648 /* User pressed the soft key 2 */
3649 /* On cs2k phones, soft key 2 is backspace. */
3650 if(pi->key_buffer != NULL) {
3652 /* Get data */
3653 g_string_assign(g_tmp,pi->key_buffer);
3655 /* Manipulate the data */
3656 g_string_truncate(g_tmp,g_tmp->len-1);
3658 /* Insert new data */
3659 tmp_unistim_info->key_buffer = g_strdup(g_tmp->str);
3662 /* add label and comment */
3663 comment = ws_strdup_printf("Key Input Sent: S2 (%d)", pi->sequence);
3664 } else if(pi->key_val == 28) {
3665 /* User pressed something */
3666 comment = ws_strdup_printf("Key Input Sent: Release (%d)", pi->sequence);
3667 } else if(pi->key_val == 23) {
3668 /* User pressed the soft key 3 */
3669 /* Cancel on cs2k so clear buffer */
3670 /* On mcs it's config which will clear the buffer too */
3671 tmp_unistim_info->key_buffer = g_strdup("\n");
3673 /* User pressed something, set labels*/
3674 comment = ws_strdup_printf("Key Input Sent: S3 (%d)", pi->sequence);
3675 } else if(pi->key_val == 27) {
3676 /* User pressed something */
3677 comment = ws_strdup_printf("Key Input Sent: Hold (%d)", pi->sequence);
3678 } else if(pi->key_val == 29) {
3679 /* User pressed something */
3680 comment = ws_strdup_printf("Key Input Sent: Mute (%d)", pi->sequence);
3681 } else if(pi->key_val == 30) {
3682 /* User pressed something */
3683 comment = ws_strdup_printf("Key Input Sent: Headset (%d)", pi->sequence);
3684 } else if(pi->key_val == 31) {
3685 /* Handsfree button */
3686 comment = ws_strdup_printf("Key Input Sent: Handsfree (%d)", pi->sequence);
3687 } else if(pi->key_val >= 32 && pi->key_val <= 56) {
3688 /* Prog. Key X */
3689 comment = ws_strdup_printf("Key Input Sent: Prog%d (%d)", (pi->key_val & 31), pi->sequence);
3692 if(pi->key_val != -1) {
3694 frame_label = "KEY INPUT";
3696 if (comment == NULL)
3697 /* Ouch! What do you do!? */
3698 /* User pressed something */
3699 comment = ws_strdup_printf("Key Input Sent: UNKNOWN - %d (%d)", pi->key_val, pi->sequence);
3701 /* add to the graph */
3702 add_to_graph(tapinfo, pinfo, edt, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3704 g_free(comment);
3707 if(pi->hook_state == 1) {
3709 /* Phone is off hook */
3710 frame_label = "OFF HOOK";
3711 comment = ws_strdup_printf("Off Hook (%d)", pi->sequence);
3713 /* add to the graph */
3714 add_to_graph(tapinfo, pinfo, edt, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3716 g_free(comment);
3717 } else if(pi->hook_state == 0) {
3719 /* Phone is on hook */
3720 frame_label = "ON HOOK";
3721 comment = ws_strdup_printf("On Hook (%d)", pi->sequence);
3723 /* add to the graph */
3724 add_to_graph(tapinfo, pinfo, edt, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3726 g_free(comment);
3730 /* Open stream was sent from server */
3731 if(pi->stream_connect == 1 && callsinfo != NULL) {
3733 /* Open stream */
3734 /* Signifies the start of the call so set start_sec & start_usec */
3735 /* Frame data holds the time info */
3736 callsinfo->start_fd=pinfo->fd;
3737 callsinfo->start_rel_ts=pinfo->rel_ts;
3738 /* Each packet COULD BE OUR LAST!!!! */
3739 /* Store frame data which holds time and frame number */
3740 callsinfo->stop_fd = pinfo->fd;
3741 callsinfo->stop_rel_ts = pinfo->rel_ts;
3743 /* Local packets too */
3744 ++(callsinfo->npackets);
3746 /* increment the packets counter of all calls */
3747 ++(tapinfo->npackets);
3749 /* ?? means we're not quite sure if this is accurate. Since Unistim isn't a true
3750 Call control protocol, we can only guess at the destination by messing with
3751 key buffers. */
3752 if(tmp_unistim_info->key_buffer != NULL) {
3753 callsinfo->to_identity = ws_strdup_printf("?? %s",tmp_unistim_info->key_buffer);
3756 /* change sequence number for ACK detection */
3757 tmp_unistim_info->sequence = pi->sequence;
3759 /* State changes too */
3760 callsinfo->call_active_state = VOIP_ACTIVE;
3761 callsinfo->call_state = VOIP_IN_CALL;
3763 /* Add graph data */
3764 frame_label = "STREAM OPENED";
3765 comment = ws_strdup_printf("Stream Opened (%d)",pi->sequence);
3767 /* add to the graph */
3768 add_to_graph(tapinfo, pinfo, edt, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3770 } else if(pi->stream_connect == 1 && callsinfo == NULL) {
3772 /* Research indicates some nortel products initiate stream first
3773 * without keypresses, therefore creating this solely on a keypress is
3774 * ineffective.
3775 * Sometimes calls start immediately with open stream.
3777 callsinfo = g_new0(voip_calls_info_t, 1);
3778 callsinfo->call_active_state = VOIP_ACTIVE;
3779 callsinfo->call_state = VOIP_CALL_SETUP;
3780 callsinfo->from_identity=g_strdup("UNKNOWN");
3781 callsinfo->to_identity=g_strdup("UNKNOWN");
3782 copy_address(&(callsinfo->initial_speaker),&(pinfo->src));
3784 /* Set this on init of struct so in case the call doesn't complete, we'll have a ref. */
3785 /* Otherwise if the call is completed we'll have the open/close streams to ref actual call duration */
3786 callsinfo->start_fd=pinfo->fd;
3787 callsinfo->start_rel_ts=pinfo->rel_ts;
3789 callsinfo->protocol=VOIP_UNISTIM;
3790 callsinfo->prot_info=g_new(unistim_info_t, 1);
3792 tmp_unistim_info = (unistim_info_t *)callsinfo->prot_info;
3794 /* Clear tap struct */
3795 tmp_unistim_info->rudp_type = 0;
3796 tmp_unistim_info->payload_type = 0;
3797 tmp_unistim_info->sequence = 0;
3798 tmp_unistim_info->termid = 0;
3799 tmp_unistim_info->key_val = -1;
3800 tmp_unistim_info->key_state = -1;
3801 tmp_unistim_info->hook_state = -1;
3802 tmp_unistim_info->stream_connect = -1;
3803 tmp_unistim_info->trans_connect = -1;
3804 tmp_unistim_info->set_termid = -1;
3805 tmp_unistim_info->string_data = NULL;
3806 tmp_unistim_info->key_buffer = NULL;
3808 copy_address(&(tmp_unistim_info->it_ip),&(pi->it_ip));
3809 copy_address(&(tmp_unistim_info->ni_ip),&(pi->ni_ip));
3810 tmp_unistim_info->it_port = pi->it_port;
3812 callsinfo->free_prot_info = g_free;
3813 callsinfo->npackets = 0;
3814 callsinfo->call_num = tapinfo->ncalls++;
3815 g_queue_push_tail(tapinfo->callsinfos, callsinfo);
3817 /* Open stream */
3818 /* Each packet COULD BE OUR LAST!!!! */
3819 /* Store frame data which holds time and frame number */
3820 callsinfo->stop_fd = pinfo->fd;
3821 callsinfo->stop_rel_ts = pinfo->rel_ts;
3822 /* Local packets too */
3823 ++(callsinfo->npackets);
3825 /* increment the packets counter of all calls */
3826 ++(tapinfo->npackets);
3828 /* ?? means we're not quite sure if this is accurate. Since Unistim isn't a true
3829 Call control protocol, we can only guess at the destination by messing with
3830 key buffers. */
3831 if(tmp_unistim_info->key_buffer != NULL) {
3832 callsinfo->to_identity = ws_strdup_printf("?? %s",tmp_unistim_info->key_buffer);
3835 /* change sequence number for ACK detection */
3836 tmp_unistim_info->sequence = pi->sequence;
3838 /* State changes too */
3839 callsinfo->call_active_state = VOIP_ACTIVE;
3840 callsinfo->call_state = VOIP_IN_CALL;
3842 /* Add graph data */
3843 frame_label = "STREAM OPENED";
3844 comment = ws_strdup_printf("Stream Opened (%d)",pi->sequence);
3846 /* add to the graph */
3847 add_to_graph(tapinfo, pinfo, edt, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3849 } else if(pi->stream_connect == 0 && callsinfo != NULL) {
3850 /* Close Stream */
3852 /* Set stop seconds + usec */
3853 /* frame_data holds the time info */
3854 callsinfo->stop_fd = pinfo->fd;
3855 callsinfo->stop_rel_ts = pinfo->rel_ts;
3857 tmp_unistim_info->sequence = pi->sequence;
3859 if(callsinfo->call_state == VOIP_IN_CALL) {
3860 callsinfo->call_active_state = VOIP_INACTIVE;
3861 callsinfo->call_state = VOIP_COMPLETED;
3862 } else {
3863 callsinfo->call_state = VOIP_UNKNOWN;
3864 callsinfo->call_active_state = VOIP_INACTIVE;
3867 frame_label = "STREAM CLOSED";
3868 comment = ws_strdup_printf("Stream Closed (%d)",pi->sequence);
3870 /* add to the graph */
3871 add_to_graph(tapinfo, pinfo, edt, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3873 } else
3874 comment = NULL;
3876 } else if(pi->rudp_type == 1 && callsinfo != NULL) {
3877 /* ACK */
3878 /* Only show acks for processed seq #s */
3879 if(tmp_unistim_info->sequence == pi->sequence) {
3881 frame_label = "ACK";
3882 comment = ws_strdup_printf("ACK for sequence %d",pi->sequence);
3884 /* add to the graph */
3885 add_to_graph(tapinfo, pinfo, edt, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3889 } else if(pi->rudp_type == 0 && callsinfo != NULL) {
3891 /* NAK */
3892 frame_label = "NAK";
3893 comment = ws_strdup_printf("NAK for sequence %d",pi->sequence);
3895 /* add to the graph */
3896 add_to_graph(tapinfo, pinfo, edt, frame_label, comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
3900 /* free data */
3901 g_free(comment);
3902 g_string_free(g_tmp, TRUE);
3904 tapinfo->redraw |= REDRAW_UNISTIM;
3906 return TAP_PACKET_REDRAW;
3909 /****************************************************************************/
3910 static void
3911 unistim_calls_draw(void *tap_offset_ptr)
3913 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_unistim_);
3915 if (tapinfo->tap_draw && (tapinfo->redraw & REDRAW_UNISTIM)) {
3916 tapinfo->tap_draw(tapinfo);
3917 tapinfo->redraw &= ~REDRAW_UNISTIM;
3921 /****************************************************************************/
3922 /* TAP INTERFACE */
3923 /****************************************************************************/
3924 void
3925 unistim_calls_init_tap(voip_calls_tapinfo_t *tap_id_base) {
3927 GString *error_string;
3929 error_string = register_tap_listener("unistim", tap_base_to_id(tap_id_base, tap_id_offset_unistim_),
3930 NULL,
3932 NULL,
3933 unistim_calls_packet,
3934 unistim_calls_draw,
3935 NULL
3938 if (error_string != NULL) {
3939 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3940 "%s", error_string->str);
3941 g_string_free(error_string, TRUE);
3945 /****************************************************************************/
3946 void
3947 remove_tap_listener_unistim_calls(voip_calls_tapinfo_t *tap_id_base)
3949 remove_tap_listener(tap_base_to_id(tap_id_base, tap_id_offset_unistim_));
3952 /****************************************************************************/
3953 /* ***************************TAP for SKINNY **********************************/
3954 /****************************************************************************/
3956 /* Telecaster to tap-voip call state mapping */
3957 static const voip_call_state skinny_tap_voip_state[] = {
3958 VOIP_NO_STATE,
3959 VOIP_CALL_SETUP,
3960 VOIP_COMPLETED,
3961 VOIP_RINGING,
3962 VOIP_RINGING,
3963 VOIP_IN_CALL,
3964 VOIP_REJECTED,
3965 VOIP_REJECTED,
3966 VOIP_IN_CALL,
3967 VOIP_IN_CALL,
3968 VOIP_COMPLETED,
3969 VOIP_COMPLETED,
3970 VOIP_CALL_SETUP,
3971 VOIP_UNKNOWN,
3972 VOIP_REJECTED
3975 static tap_packet_status
3976 skinny_calls_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt, const void *skinny_info, tap_flags_t flags _U_)
3978 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_skinny_);
3979 GList* list;
3980 voip_calls_info_t *callsinfo = NULL;
3981 address* phone;
3982 const skinny_info_t *si = (const skinny_info_t *)skinny_info;
3983 skinny_calls_info_t *tmp_skinnyinfo;
3984 char *comment;
3986 /* if display filtering activated and packet do not match, ignore it */
3987 if (tapinfo->apply_display_filter && (pinfo->fd->passed_dfilter == 0)) {
3988 return TAP_PACKET_DONT_REDRAW;
3991 if (si == NULL || (si->callId == 0 && si->passThroughPartyId == 0))
3992 return TAP_PACKET_DONT_REDRAW;
3993 /* check whether we already have this context in the list */
3994 list = g_queue_peek_nth_link(tapinfo->callsinfos, 0);
3995 while (list)
3997 voip_calls_info_t* tmp_listinfo = (voip_calls_info_t *)list->data;
3998 if (tmp_listinfo->protocol == VOIP_SKINNY) {
3999 tmp_skinnyinfo = (skinny_calls_info_t *)tmp_listinfo->prot_info;
4000 if (tmp_skinnyinfo->callId == si->callId ||
4001 tmp_skinnyinfo->callId == si->passThroughPartyId) {
4002 callsinfo = (voip_calls_info_t*)(list->data);
4003 break;
4006 list = g_list_next (list);
4009 if (si->messId >= 256)
4010 phone = &(pinfo->dst);
4011 else
4012 phone = &(pinfo->src);
4014 if (callsinfo==NULL) {
4015 callsinfo = g_new0(voip_calls_info_t, 1);
4016 callsinfo->call_state = VOIP_NO_STATE;
4017 callsinfo->call_active_state = VOIP_ACTIVE;
4018 /* callsinfo->from_identity = ws_strdup_printf("%s : %.8x", "Skinny", 1); */
4019 callsinfo->from_identity = g_strdup("");
4020 callsinfo->to_identity = g_strdup("");
4021 callsinfo->prot_info = g_new(skinny_calls_info_t, 1);
4022 callsinfo->free_prot_info = g_free;
4023 tmp_skinnyinfo = (skinny_calls_info_t *)callsinfo->prot_info;
4024 tmp_skinnyinfo->callId = si->callId ? si->callId : si->passThroughPartyId;
4025 callsinfo->npackets = 1;
4027 copy_address(&(callsinfo->initial_speaker), phone);
4029 callsinfo->protocol = VOIP_SKINNY;
4030 callsinfo->call_num = tapinfo->ncalls++;
4031 callsinfo->start_fd = pinfo->fd;
4032 callsinfo->start_rel_ts = pinfo->rel_ts;
4033 callsinfo->stop_fd = pinfo->fd;
4034 callsinfo->stop_rel_ts = pinfo->rel_ts;
4036 g_queue_push_tail(tapinfo->callsinfos, callsinfo);
4037 } else {
4038 if (si->callingParty) {
4039 g_free(callsinfo->from_identity);
4040 callsinfo->from_identity = g_strdup(si->callingParty);
4042 if (si->calledParty) {
4043 g_free(callsinfo->to_identity);
4044 callsinfo->to_identity = g_strdup(si->calledParty);
4046 if ((si->callState > 0) && (si->callState < array_length(skinny_tap_voip_state)))
4047 callsinfo->call_state = skinny_tap_voip_state[si->callState];
4049 callsinfo->stop_fd = pinfo->fd;
4050 callsinfo->stop_rel_ts = pinfo->rel_ts;
4051 ++(callsinfo->npackets);
4054 if (si->callId) {
4055 if (si->passThroughPartyId)
4056 comment = ws_strdup_printf("CallId = %u, PTId = %u", si->callId, si->passThroughPartyId);
4057 else
4058 comment = ws_strdup_printf("CallId = %u, LineId = %u", si->callId, si->lineId);
4059 } else {
4060 if (si->passThroughPartyId)
4061 comment = ws_strdup_printf("PTId = %u", si->passThroughPartyId);
4062 else
4063 comment = NULL;
4066 add_to_graph(tapinfo, pinfo, edt, si->messageName, comment,
4067 callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
4068 g_free(comment);
4069 append_to_frame_graph(tapinfo, pinfo->num, si->additionalInfo, NULL);
4071 tapinfo->redraw |= REDRAW_SKINNY;
4073 return TAP_PACKET_REDRAW;
4076 /****************************************************************************/
4077 static void
4078 skinny_calls_draw(void *tap_offset_ptr)
4080 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_skinny_);
4082 if (tapinfo->tap_draw && (tapinfo->redraw & REDRAW_SKINNY)) {
4083 tapinfo->tap_draw(tapinfo);
4084 tapinfo->redraw &= ~REDRAW_SKINNY;
4088 /****************************************************************************/
4089 /* TAP INTERFACE */
4090 /****************************************************************************/
4091 void
4092 skinny_calls_init_tap(voip_calls_tapinfo_t *tap_id_base)
4094 GString *error_string;
4097 * We set TL_REQUIRES_PROTO_TREE to force a non-null "tree"
4098 * in the SKINNY dissector; otherwise, the dissector
4099 * doesn't fill in the info passed to the tap's packet
4100 * routine.
4102 error_string = register_tap_listener("skinny",
4103 tap_base_to_id(tap_id_base, tap_id_offset_skinny_),
4104 NULL,
4105 TL_REQUIRES_PROTO_TREE,
4106 NULL,
4107 skinny_calls_packet,
4108 skinny_calls_draw,
4109 NULL
4111 if (error_string != NULL) {
4112 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4113 "%s", error_string->str);
4114 g_string_free(error_string, TRUE);
4118 /****************************************************************************/
4119 void
4120 remove_tap_listener_skinny_calls(voip_calls_tapinfo_t *tap_id_base)
4122 remove_tap_listener(tap_base_to_id(tap_id_base, tap_id_offset_skinny_));
4125 /****************************************************************************/
4126 /* ***************************TAP for IAX2 **********************************/
4127 /****************************************************************************/
4129 static void free_iax2_info(void *p) {
4130 iax2_info_t *ii = (iax2_info_t *)p;
4132 g_free(ii);
4136 /****************************************************************************/
4137 /* whenever a IAX2 packet is seen by the tap listener */
4138 static tap_packet_status
4139 iax2_calls_packet( void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt, const void *iax2_info, tap_flags_t flags _U_)
4141 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_iax2_);
4142 GList* list;
4143 voip_calls_info_t *callsinfo = NULL;
4144 address *phone;
4145 const iax2_info_t *ii = (const iax2_info_t *)iax2_info;
4146 iax2_info_t *tmp_iax2info;
4148 /* if display filtering activated and packet do not match, ignore it */
4149 if (tapinfo->apply_display_filter && (pinfo->fd->passed_dfilter == 0)) {
4150 return TAP_PACKET_DONT_REDRAW;
4153 if (ii == NULL || ii->ptype != IAX2_FULL_PACKET || (ii->scallno == 0 && ii->dcallno == 0))
4154 return TAP_PACKET_DONT_REDRAW;
4155 /* check whether we already have this context in the list */
4156 list = g_queue_peek_nth_link(tapinfo->callsinfos, 0);
4157 while (list)
4159 voip_calls_info_t* tmp_listinfo = (voip_calls_info_t *)list->data;
4160 if (tmp_listinfo->protocol == VOIP_IAX2) {
4161 tmp_iax2info = (iax2_info_t *)tmp_listinfo->prot_info;
4162 if (tmp_iax2info->scallno == ii->scallno ||
4163 tmp_iax2info->scallno == ii->dcallno) {
4164 callsinfo = (voip_calls_info_t*)(list->data);
4165 break;
4168 list = g_list_next (list);
4170 phone = &(pinfo->src);
4173 if (callsinfo==NULL) {
4174 /* We only care about real calls, i.e., no registration stuff */
4175 if (ii->ftype != AST_FRAME_IAX || ii->csub != IAX_COMMAND_NEW)
4176 return TAP_PACKET_DONT_REDRAW;
4177 callsinfo = g_new0(voip_calls_info_t, 1);
4178 callsinfo->call_state = VOIP_NO_STATE;
4179 callsinfo->call_active_state = VOIP_ACTIVE;
4180 callsinfo->prot_info=g_new(iax2_info_t, 1);
4181 callsinfo->free_prot_info = free_iax2_info;
4182 tmp_iax2info = (iax2_info_t *)callsinfo->prot_info;
4184 tmp_iax2info->scallno = ii->scallno;
4185 if (tmp_iax2info->scallno == 0) tmp_iax2info->scallno = ii->dcallno;
4186 tmp_iax2info->callState = ii->callState;
4188 callsinfo->npackets = 1;
4190 copy_address(&(callsinfo->initial_speaker), phone);
4191 callsinfo->from_identity = g_strdup(ii->callingParty);
4192 callsinfo->to_identity = g_strdup(ii->calledParty);
4194 callsinfo->protocol = VOIP_IAX2;
4195 callsinfo->call_num = tapinfo->ncalls++;
4196 callsinfo->start_fd=pinfo->fd;
4197 callsinfo->start_rel_ts=pinfo->rel_ts;
4198 callsinfo->stop_fd = pinfo->fd;
4199 callsinfo->stop_rel_ts = pinfo->rel_ts;
4201 g_queue_push_tail(tapinfo->callsinfos, callsinfo);
4203 } else {
4204 callsinfo->call_state = ii->callState;
4206 callsinfo->stop_fd = pinfo->fd;
4207 callsinfo->stop_rel_ts = pinfo->rel_ts;
4208 ++(callsinfo->npackets);
4211 add_to_graph(tapinfo, pinfo, edt, ii->messageName, "",
4212 callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
4214 tapinfo->redraw |= REDRAW_IAX2;
4216 return TAP_PACKET_REDRAW;
4220 /****************************************************************************/
4221 static void
4222 iax2_calls_draw(void *tap_offset_ptr)
4224 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_iax2_);
4226 if (tapinfo->tap_draw && (tapinfo->redraw & REDRAW_IAX2)) {
4227 tapinfo->tap_draw(tapinfo);
4228 tapinfo->redraw &= ~REDRAW_IAX2;
4232 /****************************************************************************/
4233 /* TAP INTERFACE */
4234 /****************************************************************************/
4235 void
4236 iax2_calls_init_tap(voip_calls_tapinfo_t *tap_id_base)
4238 GString *error_string;
4241 * We set TL_REQUIRES_PROTO_TREE to force a non-null "tree"
4242 * in the IAX2 dissector; otherwise, the dissector
4243 * doesn't fill in the info passed to the tap's packet
4244 * routine.
4245 * XXX - that appears to be true of the MGCP and SKINNY
4246 * dissectors, but, unless I've missed something, it doesn't
4247 * appear to be true of the IAX2 dissector.
4249 error_string = register_tap_listener("IAX2",
4250 tap_base_to_id(tap_id_base, tap_id_offset_iax2_),
4251 NULL,
4252 TL_REQUIRES_PROTO_TREE,
4253 NULL,
4254 iax2_calls_packet,
4255 iax2_calls_draw,
4256 NULL
4258 if (error_string != NULL) {
4259 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s",
4260 error_string->str);
4261 g_string_free(error_string, TRUE);
4265 /****************************************************************************/
4266 void
4267 remove_tap_listener_iax2_calls(voip_calls_tapinfo_t *tap_id_base)
4269 remove_tap_listener(tap_base_to_id(tap_id_base, tap_id_offset_iax2_));
4272 /****************************************************************************/
4273 /* ***************************TAP for OTHER PROTOCOL **********************************/
4274 /****************************************************************************/
4276 /* voip_calls_packet and voip_calls_init_tap appear to be dead code. We don't have a "voip" tap. */
4277 static tap_packet_status
4278 voip_calls_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt, const void *VoIPinfo, tap_flags_t flags _U_)
4280 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_voip_);
4281 voip_calls_info_t *callsinfo = NULL;
4282 voip_calls_info_t *tmp_listinfo;
4283 GList *list = NULL;
4284 const voip_packet_info_t *pi = (const voip_packet_info_t *)VoIPinfo;
4286 /* if display filtering activated and packet do not match, ignore it */
4287 if (tapinfo->apply_display_filter && (pinfo->fd->passed_dfilter == 0)) {
4288 return TAP_PACKET_DONT_REDRAW;
4291 /* VOIP_CALLS_DEBUG("num %u", pinfo->num); */
4292 if (pi->call_id)
4293 list = g_queue_peek_nth_link(tapinfo->callsinfos, 0);
4294 while (list) {
4295 tmp_listinfo = (voip_calls_info_t *)list->data;
4296 if ( tmp_listinfo->protocol == VOIP_COMMON ) {
4297 if (!strcmp(pi->call_id, tmp_listinfo->call_id)) {
4298 callsinfo = (voip_calls_info_t*)(list->data);
4299 break;
4302 list = g_list_next(list);
4305 if (callsinfo == NULL) {
4306 callsinfo = g_new0(voip_calls_info_t, 1);
4307 callsinfo->call_active_state = pi->call_active_state;
4308 callsinfo->call_state = pi->call_state;
4309 callsinfo->call_id=g_strdup((pi->call_id)?pi->call_id:"");
4310 callsinfo->from_identity = g_strdup((pi->from_identity)?pi->from_identity:"");
4311 callsinfo->to_identity = g_strdup((pi->to_identity)?pi->to_identity:"");
4312 copy_address(&(callsinfo->initial_speaker),&(pinfo->src));
4313 callsinfo->start_fd=pinfo->fd;
4314 callsinfo->start_rel_ts=pinfo->rel_ts;
4315 callsinfo->protocol=VOIP_COMMON;
4316 callsinfo->protocol_name=g_strdup((pi->protocol_name)?pi->protocol_name:"");
4317 callsinfo->call_comment=g_strdup((pi->call_comment)?pi->call_comment:"");
4318 callsinfo->prot_info=NULL;
4319 callsinfo->free_prot_info = NULL;
4321 callsinfo->call_num = tapinfo->ncalls++;
4322 callsinfo->npackets = 0;
4324 g_queue_push_tail(tapinfo->callsinfos, callsinfo);
4327 callsinfo->call_active_state = pi->call_active_state;
4328 if ((callsinfo->call_state != VOIP_COMPLETED) && (pi->call_state == VOIP_COMPLETED))
4329 tapinfo->completed_calls++;
4330 if (pi->call_state != VOIP_NO_STATE)
4331 callsinfo->call_state = pi->call_state;
4332 if (pi->call_comment) {
4333 g_free(callsinfo->call_comment);
4334 callsinfo->call_comment=g_strdup(pi->call_comment);
4336 callsinfo->stop_fd = pinfo->fd;
4337 callsinfo->stop_rel_ts = pinfo->rel_ts;
4338 ++(callsinfo->npackets);
4339 ++(tapinfo->npackets);
4341 /* add to the graph */
4342 add_to_graph(tapinfo, pinfo, edt, (pi->frame_label)?pi->frame_label:"VoIP msg", pi->frame_comment, callsinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
4344 tapinfo->redraw |= REDRAW_VOIP;
4346 return TAP_PACKET_REDRAW;
4349 /****************************************************************************/
4350 static void
4351 voip_calls_draw(void *tap_offset_ptr)
4353 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_voip_);
4355 if (tapinfo->tap_draw && (tapinfo->redraw & REDRAW_VOIP)) {
4356 tapinfo->tap_draw(tapinfo);
4357 tapinfo->redraw &= ~REDRAW_VOIP;
4361 /****************************************************************************/
4363 void
4364 voip_calls_init_tap(voip_calls_tapinfo_t *tap_id_base)
4366 GString *error_string;
4368 error_string = register_tap_listener("voip", tap_base_to_id(tap_id_base, tap_id_offset_voip_),
4369 NULL,
4371 NULL,
4372 voip_calls_packet,
4373 voip_calls_draw,
4374 NULL
4377 if (error_string != NULL) {
4378 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4379 "%s", error_string->str);
4380 g_string_free(error_string, TRUE);
4384 /****************************************************************************/
4385 void
4386 remove_tap_listener_voip_calls(voip_calls_tapinfo_t *tap_id_base)
4388 remove_tap_listener(tap_base_to_id(tap_id_base, tap_id_offset_voip_));
4391 /****************************************************************************/
4392 /* ***************************TAP for OTHER PROTOCOL **********************************/
4393 /****************************************************************************/
4395 /****************************************************************************/
4396 /* whenever a prot_ packet is seen by the tap listener */
4397 #if 0
4398 static tap_packet_status
4399 prot_calls_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info _U_, tap_flags_t flags _U_)
4401 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_prot_);
4403 /* if display filtering activated and packet do not match, ignore it */
4404 if (tapinfo->apply_display_filter && (pinfo->fd->passed_dfilter == 0)) {
4405 return TAP_PACKET_DONT_REDRAW;
4408 if (callsinfo!=NULL) {
4409 callsinfo->stop_abs = pinfo->abs_ts;
4410 callsinfo->stop_rel = pinfo->rel_ts;
4411 callsinfo->last_frame_num=pinfo->num;
4412 ++(callsinfo->npackets);
4413 ++(tapinfo->npackets);
4416 tapinfo->redraw = REDRAW_PROT;
4418 return TAP_PACKET_REDRAW;
4421 /****************************************************************************/
4422 static void
4423 prot_calls_draw(void *tap_offset_ptr)
4425 voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_prot_);
4427 if (tapinfo->tap_draw && (tapinfo->redraw & REDRAW_PROT)) {
4428 tapinfo->tap_draw(tapinfo);
4429 tapinfo->redraw &= ~REDRAW_PROT;
4433 /****************************************************************************/
4434 void
4435 prot_calls_init_tap(voip_calls_tapinfo_t *tap_id_base)
4437 GString *error_string;
4439 error_string = register_tap_listener("prot_", tap_base_to_id(tap_id_base, tap_id_offset_prot_),
4440 NULL,
4442 NULL,
4443 prot_calls_packet,
4444 prot_calls_draw,
4445 NULL
4448 if (error_string != NULL) {
4449 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4450 "%s", error_string->str);
4451 g_string_free(error_string, TRUE);
4455 /****************************************************************************/
4456 void
4457 remove_tap_listener_prot__calls(voip_calls_tapinfo_t *tap_id_base)
4459 remove_tap_listener(tap_base_to_id(tap_id_base, tap_id_offset_prot_));
4461 #endif