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:
parent
03f7a4bedc
commit
8ac87dccde
|
@ -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);
|
||||
|
|
|
@ -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) },
|
||||
|
||||
|
|
|
@ -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 **********************************/
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue