fix_bug_10199: enhancement Telephony VoIP Call add ability to show all SIP Flows.

Add SIP Flows menu option beside VoIP Calls.
Flow for all SIP message types (which have a call-id) is shown in SIP Flow.
Add useful info(original flow method, response code, cseq) to comment field in conversation and flow dialogs.

Change-Id: I4801a633ed9b6594b2d89629c9d6fec6352da150
Reviewed-on: https://code.wireshark.org/review/2479
Reviewed-by: Evan Huus <eapache@gmail.com>
Reviewed-by: James Coleman <gaoithe@gmail.com>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
James Coleman 2014-06-19 17:47:49 +01:00 committed by Anders Broman
parent 03f7a4bedc
commit 8ac87dccde
5 changed files with 91 additions and 13 deletions

View File

@ -136,6 +136,7 @@ void sctp_stat_start(GtkAction *action, gpointer user_data);
void gui_iostat_cb(GtkAction *action, gpointer user_data);
void voip_calls_launch(GtkAction *action, gpointer user_data);
void voip_flows_launch(GtkAction *action, gpointer user_data);
void ansi_a_stat_gtk_bsmap_cb(GtkAction *action, gpointer user_data);
void ansi_a_stat_gtk_dtap_cb(GtkAction *action, gpointer user_data);

View File

@ -1324,6 +1324,7 @@ static const char *ui_desc_menubar =
" <menuitem name='SMPP' action='/Telephony/smpp_commands'/>\n"
" <menuitem name='UCP' action='/Telephony/ucp_messages'/>\n"
" <menuitem name='VoIPCalls' action='/Telephony/VoIPCalls'/>\n"
" <menuitem name='VoIPFlows' action='/Telephony/VoIPFlows'/>\n"
" </menu>\n"
" <menu name= 'ToolsMenu' action='/Tools'>\n"
" <menuitem name='FirewallACLRules' action='/Tools/FirewallACLRules'/>\n"
@ -1789,6 +1790,7 @@ static const GtkActionEntry main_menu_bar_entries[] = {
{ "/Telephony/smpp_commands", NULL, "SM_PPOperations", NULL, NULL, G_CALLBACK(gtk_stats_tree_cb) },
{ "/Telephony/ucp_messages", NULL, "_UCP Messages", NULL, NULL, G_CALLBACK(gtk_stats_tree_cb) },
{ "/Telephony/VoIPCalls", WIRESHARK_STOCK_TELEPHONE, "_VoIP Calls", NULL, NULL, G_CALLBACK(voip_calls_launch) },
{ "/Telephony/VoIPFlows", WIRESHARK_STOCK_TELEPHONE, "SIP _Flows", NULL, NULL, G_CALLBACK(voip_flows_launch) },
{ "/Tools/FirewallACLRules", NULL, "Firewall ACL Rules", NULL, NULL, G_CALLBACK(firewall_rule_cb) },

View File

@ -994,6 +994,7 @@ SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
address tmp_src, tmp_dst;
gchar *frame_label = NULL;
gchar *comment = NULL;
gchar *old_comment = NULL;
gchar *key=NULL;
const sip_info_value_t *pi = (const sip_info_value_t *)SIPinfo;
@ -1014,9 +1015,17 @@ SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
/* search the call information in the SIP_HASH */
callsinfo = (voip_calls_info_t *)g_hash_table_lookup(tapinfo->callsinfo_hashtable[SIP_HASH], key);
/* not in the hash? then create a new entry if the message is INVITE -i.e. if this session is a call*/
if ((callsinfo==NULL) &&(pi->request_method!=NULL)) {
if (strcmp(pi->request_method,"INVITE")==0) {
/* Create a new flow entry if the message is INVITE in case of FLOW_ONLY_INVITES,
Create a new flow entry for all messages which have a method in case of FLOW_ALL.
Flows for REGISTER, OPTIONS, MESSAGE and other SIP methods can be seen. */
if ((callsinfo==NULL) && (pi->request_method!=NULL)) {
/* check VoIPcalls_get_flow_show_option() == FLOW_ALL or FLOW_ONLY_INVITES */
if (VoIPcalls_get_flow_show_option() == FLOW_ALL ||
(VoIPcalls_get_flow_show_option() == FLOW_ONLY_INVITES &&
strcmp(pi->request_method,"INVITE")==0)) {
callsinfo = (voip_calls_info_t *)g_malloc0(sizeof(voip_calls_info_t));
callsinfo->call_active_state = VOIP_ACTIVE;
callsinfo->call_state = VOIP_CALL_SETUP;
@ -1029,16 +1038,21 @@ SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
callsinfo->protocol=VOIP_SIP;
callsinfo->prot_info=g_malloc(sizeof(sip_calls_info_t));
callsinfo->free_prot_info = free_sip_info;
callsinfo->call_id = g_strdup(pi->tap_call_id);
tmp_sipinfo = (sip_calls_info_t *)callsinfo->prot_info;
tmp_sipinfo->call_identifier = g_strdup(pi->tap_call_id);
tmp_sipinfo->sip_state = SIP_INVITE_SENT;
tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
callsinfo->npackets = 0;
callsinfo->call_num = tapinfo->ncalls++;
/* show method in comment in conversation list dialog, user can discern different conversation types */
callsinfo->call_comment=g_strdup(pi->request_method);
tapinfo->callsinfo_list = g_list_prepend(tapinfo->callsinfo_list, callsinfo);
/* insert the call information in the SIP_HASH */
g_hash_table_insert(tapinfo->callsinfo_hashtable[SIP_HASH],
tmp_sipinfo->call_identifier, callsinfo);
tmp_sipinfo->call_identifier, callsinfo);
}
}
@ -1052,7 +1066,7 @@ SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
if (pi->request_method == NULL) {
frame_label = g_strdup_printf("%u %s", pi->response_code, pi->reason_phrase );
comment = g_strdup("SIP Status");
comment = g_strdup_printf("SIP Status %u %s", pi->response_code, pi->reason_phrase );
if ((tmp_sipinfo && pi->tap_cseq_number == tmp_sipinfo->invite_cseq)&&(ADDRESSES_EQUAL(&tmp_dst,&(callsinfo->initial_speaker)))) {
if ((pi->response_code > 199) && (pi->response_code<300) && (tmp_sipinfo->sip_state == SIP_INVITE_SENT)) {
@ -1062,6 +1076,19 @@ SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
callsinfo->call_state = VOIP_REJECTED;
tapinfo->rejected_calls++;
}
/* UPDATE comment in conversation list dialog with response code and reason.
Multiple code(+reason) may be appended, so skip over intermediate codes (100 trying, 183 ringing, e.t.c.)
TODO: is useful but not perfect, what is appended is truncated when displayed in dialog window */
if (pi->response_code >= 200) {
old_comment = callsinfo->call_comment;
callsinfo->call_comment=g_strdup_printf("%s %u",
callsinfo->call_comment,
pi->response_code/*, pi->reason_phrase*/);
g_free(old_comment);
}
}
}
@ -1071,26 +1098,35 @@ SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
if ((strcmp(pi->request_method,"INVITE")==0)&&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))) {
tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
callsinfo->call_state = VOIP_CALL_SETUP;
comment = g_strdup_printf("SIP From: %s To:%s", callsinfo->from_identity, callsinfo->to_identity);
/* TODO: sometimes truncated when displayed in dialog window */
comment = g_strdup_printf("SIP INVITE From: %s To:%s Call-ID:%s CSeq:%d",
callsinfo->from_identity, callsinfo->to_identity,
callsinfo->call_id, pi->tap_cseq_number);
}
else if ((strcmp(pi->request_method,"ACK")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
&&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))&&(tmp_sipinfo->sip_state==SIP_200_REC)
&&(callsinfo->call_state == VOIP_CALL_SETUP)) {
callsinfo->call_state = VOIP_IN_CALL;
comment = g_strdup("SIP Request");
comment = g_strdup_printf("SIP Request INVITE ACK 200 CSeq:%d", pi->tap_cseq_number);
}
else if (strcmp(pi->request_method,"BYE")==0) {
callsinfo->call_state = VOIP_COMPLETED;
tapinfo->completed_calls++;
comment = g_strdup("SIP Request");
comment = g_strdup_printf("SIP Request BYE CSeq:%d", pi->tap_cseq_number);
}
else if ((strcmp(pi->request_method,"CANCEL")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
&&(ADDRESSES_EQUAL(&tmp_src,&(callsinfo->initial_speaker)))&&(callsinfo->call_state==VOIP_CALL_SETUP)) {
callsinfo->call_state = VOIP_CANCELLED;
tmp_sipinfo->sip_state = SIP_CANCEL_SENT;
comment = g_strdup("SIP Request");
comment = g_strdup_printf("SIP Request CANCEL CSeq:%d", pi->tap_cseq_number);
} else {
comment = g_strdup("SIP Request");
/* comment = g_strdup_printf("SIP %s", pi->request_method); */
tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
callsinfo->call_state = VOIP_CALL_SETUP;
comment = g_strdup_printf("SIP %s From: %s To:%s CSeq:%d",
pi->request_method,
callsinfo->from_identity,
callsinfo->to_identity, pi->tap_cseq_number);
}
}
@ -1113,6 +1149,7 @@ SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, con
g_free(sdp_summary);
sdp_summary = NULL;
}
}
tapinfo->redraw = TRUE;
@ -4069,6 +4106,18 @@ remove_tap_listener_voip_calls(void)
have_voip_tap_listener=FALSE;
}
/****************************************************************************/
static flow_show_options flow_show_option=FLOW_ALL;
flow_show_options VoIPcalls_get_flow_show_option(void)
{
return flow_show_option;
}
void VoIPcalls_set_flow_show_option(flow_show_options option)
{
flow_show_option = option;
}
/****************************************************************************/
/* ***************************TAP for OTHER PROTOCOL **********************************/

View File

@ -67,6 +67,15 @@ typedef enum _hash_indexes {
extern const char *voip_protocol_name[];
typedef enum _flow_show_options
{
FLOW_ALL,
FLOW_ONLY_INVITES
} flow_show_options;
flow_show_options VoIPcalls_get_flow_show_option(void);
void VoIPcalls_set_flow_show_option(flow_show_options option);
/** defines specific SIP data */
typedef enum _sip_call_state {

View File

@ -312,8 +312,6 @@ voip_calls_on_select_all(GtkButton *button _U_, gpointer user_data _U_)
gtk_tree_selection_select_all(selection);
}
/* compare two list entries by packet no */
static gint
graph_analysis_sort_compare(gconstpointer a, gconstpointer b)
@ -378,6 +376,13 @@ on_graph_bt_clicked(GtkButton *button _U_, gpointer user_data _U_)
graph_analysis_update(graph_analysis_data); /* refresh it */
}
/****************************************************************************/
static void
on_flow_bt_clicked(GtkButton *button _U_, gpointer user_data _U_)
{
on_graph_bt_clicked(button,user_data);
}
/****************************************************************************/
#ifdef HAVE_LIBPORTAUDIO
static void
@ -470,6 +475,8 @@ add_to_list_store(voip_calls_info_t* strinfo)
break;
default:
field[CALL_COL_COMMENTS][0]='\0';
if (strinfo->call_comment)
g_snprintf(field[CALL_COL_COMMENTS],30, "%s", strinfo->call_comment);
}
/* Acquire an iterator */
@ -719,7 +726,7 @@ voip_calls_dlg_create(void)
bt_graph = ws_gtk_button_new_from_stock(WIRESHARK_STOCK_VOIP_FLOW);
gtk_container_add(GTK_CONTAINER(hbuttonbox), bt_graph);
gtk_widget_show(bt_graph);
g_signal_connect(bt_graph, "clicked", G_CALLBACK(on_graph_bt_clicked), NULL);
g_signal_connect(bt_graph, "clicked", G_CALLBACK(on_flow_bt_clicked), NULL);
gtk_widget_set_tooltip_text(bt_graph, "Show a flow graph of the selected calls.");
#ifdef HAVE_LIBPORTAUDIO
@ -906,6 +913,16 @@ voip_calls_init_tap(const char *dummy _U_, void* userdata _U_)
void
voip_calls_launch(GtkAction *action _U_, gpointer user_data _U_)
{
VoIPcalls_set_flow_show_option(FLOW_ONLY_INVITES);
voip_calls_init_tap("", NULL);
}
/****************************************************************************/
/* entry point when called via the GTK menu */
void
voip_flows_launch(GtkAction *action _U_, gpointer user_data _U_)
{
VoIPcalls_set_flow_show_option(FLOW_ALL);
voip_calls_init_tap("", NULL);
}