diff options
author | James Coleman <jamesc@dspsrv.com> | 2014-06-19 17:47:49 +0100 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2014-06-25 16:14:58 +0000 |
commit | 8ac87dccde4544e5397f0d741d2ec9f230971b43 (patch) | |
tree | 0646a55352122a71d41113c6de55c50bbc15c260 | |
parent | 03f7a4bedc046651e82cb49d26e4fb75cc7af26b (diff) |
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>
-rw-r--r-- | ui/gtk/gui_stat_menu.h | 1 | ||||
-rw-r--r-- | ui/gtk/main_menubar.c | 2 | ||||
-rw-r--r-- | ui/gtk/voip_calls.c | 69 | ||||
-rw-r--r-- | ui/gtk/voip_calls.h | 9 | ||||
-rw-r--r-- | ui/gtk/voip_calls_dlg.c | 23 |
5 files changed, 91 insertions, 13 deletions
diff --git a/ui/gtk/gui_stat_menu.h b/ui/gtk/gui_stat_menu.h index 992193b3c1..03beef2a2d 100644 --- a/ui/gtk/gui_stat_menu.h +++ b/ui/gtk/gui_stat_menu.h @@ -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); diff --git a/ui/gtk/main_menubar.c b/ui/gtk/main_menubar.c index 6b85dd19a9..1ab235250e 100644 --- a/ui/gtk/main_menubar.c +++ b/ui/gtk/main_menubar.c @@ -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) }, diff --git a/ui/gtk/voip_calls.c b/ui/gtk/voip_calls.c index ea150c3a87..29ee319de5 100644 --- a/ui/gtk/voip_calls.c +++ b/ui/gtk/voip_calls.c @@ -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 **********************************/ diff --git a/ui/gtk/voip_calls.h b/ui/gtk/voip_calls.h index 625e3801ad..f478c56aab 100644 --- a/ui/gtk/voip_calls.h +++ b/ui/gtk/voip_calls.h @@ -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 { diff --git a/ui/gtk/voip_calls_dlg.c b/ui/gtk/voip_calls_dlg.c index 14ddbbc1a7..78bb0eaf21 100644 --- a/ui/gtk/voip_calls_dlg.c +++ b/ui/gtk/voip_calls_dlg.c @@ -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) @@ -379,6 +377,13 @@ on_graph_bt_clicked(GtkButton *button _U_, gpointer user_data _U_) } /****************************************************************************/ +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 on_player_bt_clicked(GtkButton *button _U_, gpointer user_data _U_) @@ -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); } |