From e75e1fb580f3a496309ae1d65c1865fa98262ec5 Mon Sep 17 00:00:00 2001 From: Jirka Novak Date: Fri, 26 Mar 2021 18:24:38 +0100 Subject: [PATCH] Follow SIP Call: Added Follow SIP Call to Follow menu Changes: - epan/follow.c: follow_conv_filter_func has new parameter epan_dissect_t *edt, so filter can be generated based on decoded tree of packet below the cursor - menu Follow/SIP Call is enabled when sip packet is selected - value of sip.Call-ID is used as filter for SIP call - for sharkd it generates filter just 'sip.Call-ID' with no value --- epan/dissectors/packet-dccp.c | 2 +- epan/dissectors/packet-http2.c | 2 +- epan/dissectors/packet-quic.c | 2 +- epan/dissectors/packet-sip.c | 41 ++++++++++++++++++++++++++++++++++ epan/dissectors/packet-tcp.c | 2 +- epan/dissectors/packet-tcp.h | 2 +- epan/dissectors/packet-udp.c | 2 +- epan/follow.h | 3 ++- sharkd_session.c | 2 +- ui/qt/follow_stream_dialog.cpp | 20 ++++++++++++++++- ui/qt/main_window.h | 1 + ui/qt/main_window.ui | 9 ++++++++ ui/qt/main_window_slots.cpp | 9 +++++++- ui/qt/packet_list.cpp | 1 + ui/qt/proto_tree.cpp | 1 + 15 files changed, 89 insertions(+), 10 deletions(-) diff --git a/epan/dissectors/packet-dccp.c b/epan/dissectors/packet-dccp.c index d7446c9b34..53b8355543 100644 --- a/epan/dissectors/packet-dccp.c +++ b/epan/dissectors/packet-dccp.c @@ -538,7 +538,7 @@ dccp_build_filter(packet_info *pinfo) return NULL; } -static gchar *dccp_follow_conv_filter(packet_info *pinfo, guint *stream, guint *sub_stream _U_) +static gchar *dccp_follow_conv_filter(epan_dissect_t *edt _U_, packet_info *pinfo, guint *stream, guint *sub_stream _U_) { conversation_t *conv; struct dccp_analysis *dccpd; diff --git a/epan/dissectors/packet-http2.c b/epan/dissectors/packet-http2.c index 0f404584d0..9496426b72 100644 --- a/epan/dissectors/packet-http2.c +++ b/epan/dissectors/packet-http2.c @@ -2058,7 +2058,7 @@ inflate_http2_header_block(tvbuff_t *tvb, packet_info *pinfo, guint offset, prot #endif static gchar* -http2_follow_conv_filter(packet_info *pinfo, guint *stream, guint *sub_stream) +http2_follow_conv_filter(epan_dissect_t *edt _U_, packet_info *pinfo, guint *stream, guint *sub_stream) { http2_session_t *h2session; struct tcp_analysis *tcpd; diff --git a/epan/dissectors/packet-quic.c b/epan/dissectors/packet-quic.c index 2580632e47..10908df3b9 100644 --- a/epan/dissectors/packet-quic.c +++ b/epan/dissectors/packet-quic.c @@ -3747,7 +3747,7 @@ quic_cleanup(void) /* Follow QUIC Stream functionality {{{ */ static gchar * -quic_follow_conv_filter(packet_info *pinfo, guint *stream, guint *sub_stream) +quic_follow_conv_filter(epan_dissect_t *edt _U_, packet_info *pinfo, guint *stream, guint *sub_stream) { if (((pinfo->net_src.type == AT_IPv4 && pinfo->net_dst.type == AT_IPv4) || (pinfo->net_src.type == AT_IPv6 && pinfo->net_dst.type == AT_IPv6))) { diff --git a/epan/dissectors/packet-sip.c b/epan/dissectors/packet-sip.c index 745d02e80d..4acc7f4195 100644 --- a/epan/dissectors/packet-sip.c +++ b/epan/dissectors/packet-sip.c @@ -35,6 +35,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -61,6 +65,7 @@ void proto_register_sip(void); static gint sip_tap = -1; +static gint sip_follow_tap = -1; static gint exported_pdu_tap = -1; static dissector_handle_t sip_handle; static dissector_handle_t sip_tcp_handle; @@ -3586,6 +3591,9 @@ dissect_sip_common(tvbuff_t *tvb, int offset, int remaining_length, packet_info proto_item_set_text(th, "Message Header"); hdr_tree = proto_item_add_subtree(th, ett_sip_hdr); + if (have_tap_listener(sip_follow_tap)) + tap_queue_packet(sip_follow_tap, pinfo, tvb); + /* * Process the headers - if we're not building a protocol tree, * we just do this to find the blank line separating the @@ -6007,6 +6015,36 @@ sip_stat_free_table_item(stat_tap_table* table _U_, guint row _U_, guint column, field_data->value.string_value = NULL; } +static gchar *sip_follow_conv_filter(epan_dissect_t *edt, packet_info *pinfo _U_, guint *stream _U_, guint *sub_stream _U_) +{ + gchar *filter = NULL; + + /* Extract si.Call-ID from decoded tree in edt */ + if (edt != NULL) { + int hfid = proto_registrar_get_id_byname("sip.Call-ID"); + GPtrArray *gp = proto_find_first_finfo(edt->tree, hfid); + if (gp != NULL && gp->len != 0) { + filter = g_strdup_printf("sip.Call-ID == \"%s\"", (gchar *)fvalue_get(&((field_info *)gp->pdata[0])->value)); + } + g_ptr_array_free(gp, TRUE); + } else { + filter = g_strdup_printf("sip.Call-ID"); + } + + return filter; +} + +static gchar *sip_follow_index_filter(guint stream _U_, guint sub_stream _U_) +{ + return NULL; +} + +static gchar *sip_follow_address_filter(address *src_addr _U_, address *dst_addr _U_, int src_port _U_, int dst_port _U_) +{ + return NULL; +} + + /* Register the protocol with Wireshark */ void proto_register_sip(void) { @@ -7617,6 +7655,7 @@ void proto_register_sip(void) heur_subdissector_list = register_heur_dissector_list("sip", proto_sip); /* Register for tapping */ sip_tap = register_tap("sip"); + sip_follow_tap = register_tap("sip_follow"); ext_hdr_subdissector_table = register_dissector_table("sip.hdr", "SIP Extension header", proto_sip, FT_STRING, BASE_NONE); @@ -7632,6 +7671,8 @@ void proto_register_sip(void) ws_mempbrk_compile(&pbrk_addr_end, "[] \t:;"); ws_mempbrk_compile(&pbrk_via_param_end, "\t;, "); + register_follow_stream(proto_sip, "sip_follow", sip_follow_conv_filter, sip_follow_index_filter, sip_follow_address_filter, + udp_port_to_display, follow_tvb_tap_listener); } void diff --git a/epan/dissectors/packet-tcp.c b/epan/dissectors/packet-tcp.c index 0532a63feb..4132e1a966 100644 --- a/epan/dissectors/packet-tcp.c +++ b/epan/dissectors/packet-tcp.c @@ -947,7 +947,7 @@ tcp_seq_analysis_packet( void *ptr, packet_info *pinfo, epan_dissect_t *edt _U_, } -gchar *tcp_follow_conv_filter(packet_info *pinfo, guint *stream, guint *sub_stream _U_) +gchar *tcp_follow_conv_filter(epan_dissect_t *edt _U_, packet_info *pinfo, guint *stream, guint *sub_stream _U_) { conversation_t *conv; struct tcp_analysis *tcpd; diff --git a/epan/dissectors/packet-tcp.h b/epan/dissectors/packet-tcp.h index 9411aa5962..abec8f6c70 100644 --- a/epan/dissectors/packet-tcp.h +++ b/epan/dissectors/packet-tcp.h @@ -539,7 +539,7 @@ WS_DLL_PUBLIC guint32 get_tcp_stream_count(void); WS_DLL_PUBLIC guint32 get_mptcp_stream_count(void); /* Follow Stream functionality shared with HTTP (and SSL?) */ -extern gchar *tcp_follow_conv_filter(packet_info *pinfo, guint *stream, guint *sub_stream); +extern gchar *tcp_follow_conv_filter(epan_dissect_t *edt, packet_info *pinfo, guint *stream, guint *sub_stream); extern gchar *tcp_follow_index_filter(guint stream, guint sub_stream); extern gchar *tcp_follow_address_filter(address *src_addr, address *dst_addr, int src_port, int dst_port); diff --git a/epan/dissectors/packet-udp.c b/epan/dissectors/packet-udp.c index 60048150df..7572969969 100644 --- a/epan/dissectors/packet-udp.c +++ b/epan/dissectors/packet-udp.c @@ -434,7 +434,7 @@ udp_build_filter(packet_info *pinfo) return NULL; } -static gchar *udp_follow_conv_filter(packet_info *pinfo, guint *stream, guint *sub_stream _U_) +static gchar *udp_follow_conv_filter(epan_dissect_t *edt _U_, packet_info *pinfo, guint *stream, guint *sub_stream _U_) { conversation_t *conv; struct udp_analysis *udpd; diff --git a/epan/follow.h b/epan/follow.h index 25e9f85492..58d075f4fa 100644 --- a/epan/follow.h +++ b/epan/follow.h @@ -46,6 +46,7 @@ typedef enum { FOLLOW_HTTP, FOLLOW_HTTP2, FOLLOW_QUIC, + FOLLOW_SIP, } follow_type_t; /* Show Type */ @@ -101,7 +102,7 @@ typedef struct _follow_info { struct register_follow; typedef struct register_follow register_follow_t; -typedef gchar* (*follow_conv_filter_func)(packet_info *pinfo, guint *stream, guint *sub_stream); +typedef gchar* (*follow_conv_filter_func)(epan_dissect_t *edt, packet_info *pinfo, guint *stream, guint *sub_stream); typedef gchar* (*follow_index_filter_func)(guint stream, guint sub_stream); typedef gchar* (*follow_address_filter_func)(address* src_addr, address* dst_addr, int src_port, int dst_port); typedef gchar* (*follow_port_to_display_func)(wmem_allocator_t *allocator, guint port); diff --git a/sharkd_session.c b/sharkd_session.c index 6e578cb4ad..be322061fe 100644 --- a/sharkd_session.c +++ b/sharkd_session.c @@ -2749,7 +2749,7 @@ sharkd_follower_visit_layers_cb(const void *key _U_, void *value, void *user_dat const char *layer_proto = proto_get_protocol_short_name(find_protocol_by_id(proto_id)); char *follow_filter; - follow_filter = get_follow_conv_func(follower)(pi, &ignore_stream, &ignore_sub_stream); + follow_filter = get_follow_conv_func(follower)(NULL, pi, &ignore_stream, &ignore_sub_stream); json_dumper_begin_array(&dumper); json_dumper_value_string(&dumper, layer_proto); diff --git a/ui/qt/follow_stream_dialog.cpp b/ui/qt/follow_stream_dialog.cpp index 961c22dc63..ceaef1dded 100644 --- a/ui/qt/follow_stream_dialog.cpp +++ b/ui/qt/follow_stream_dialog.cpp @@ -13,6 +13,7 @@ #include "main_window.h" #include "wireshark_application.h" +#include "frame_tvbuff.h" #include "epan/follow.h" #include "epan/dissectors/packet-tcp.h" #include "epan/dissectors/packet-udp.h" @@ -106,6 +107,9 @@ FollowStreamDialog::FollowStreamDialog(QWidget &parent, CaptureFile &cf, follow_ case FOLLOW_QUIC: follower_ = get_follow_by_name("QUIC"); break; + case FOLLOW_SIP: + follower_ = get_follow_by_name("SIP"); + break; default : g_assert_not_reached(); } @@ -528,6 +532,7 @@ FollowStreamDialog::readStream() case FOLLOW_HTTP2: case FOLLOW_QUIC: case FOLLOW_TLS : + case FOLLOW_SIP : ret = readFollowStream(); break; @@ -884,7 +889,7 @@ bool FollowStreamDialog::follow(QString previous_filter, bool use_stream_index, if (use_stream_index) { follow_filter = gchar_free_to_qstring(get_follow_index_func(follower_)(stream_num, sub_stream_num)); } else { - follow_filter = gchar_free_to_qstring(get_follow_conv_func(follower_)(&cap_file_.capFile()->edt->pi, &stream_num, &sub_stream_num)); + follow_filter = gchar_free_to_qstring(get_follow_conv_func(follower_)(cap_file_.capFile()->edt, &cap_file_.capFile()->edt->pi, &stream_num, &sub_stream_num)); } if (follow_filter.isEmpty()) { QMessageBox::warning(this, @@ -1011,6 +1016,19 @@ bool FollowStreamDialog::follow(QString previous_filter, bool use_stream_index, case FOLLOW_HTTP: /* No extra handling */ break; + case FOLLOW_SIP: + { + /* There are no more streams */ + ui->streamNumberSpinBox->setEnabled(false); + ui->streamNumberSpinBox->blockSignals(true); + ui->streamNumberSpinBox->setMaximum(0); + ui->streamNumberSpinBox->setValue(0); + ui->streamNumberSpinBox->blockSignals(false); + ui->streamNumberSpinBox->setToolTip(tr("No streams")); + ui->streamNumberLabel->setToolTip(ui->streamNumberSpinBox->toolTip()); + + break; + } } beginRetapPackets(); diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index 699e719ed1..57a16aa25b 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -579,6 +579,7 @@ private slots: void on_actionAnalyzeFollowHTTPStream_triggered(); void on_actionAnalyzeFollowHTTP2Stream_triggered(); void on_actionAnalyzeFollowQUICStream_triggered(); + void on_actionAnalyzeFollowSIPCall_triggered(); void statCommandExpertInfo(const char *, void *); void on_actionAnalyzeExpertInfo_triggered(); diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui index 4c1f1eaaf1..c748efcace 100644 --- a/ui/qt/main_window.ui +++ b/ui/qt/main_window.ui @@ -418,6 +418,7 @@ + @@ -1759,6 +1760,14 @@ QUIC Stream + + + false + + + SIP Call + + Time Sequence (tcptrace) diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index fc68849265..71b33967c3 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -1124,7 +1124,7 @@ void MainWindow::recentActionTriggered() { void MainWindow::setMenusForSelectedPacket() { gboolean is_ip = FALSE, is_tcp = FALSE, is_udp = FALSE, is_dccp = FALSE, is_sctp = FALSE, is_tls = FALSE, is_rtp = FALSE, is_lte_rlc = FALSE, - is_http = FALSE, is_http2 = FALSE, is_quic = FALSE; + is_http = FALSE, is_http2 = FALSE, is_quic = FALSE, is_sip = FALSE; /* Making the menu context-sensitive allows for easier selection of the desired item and has the added benefit, with large captures, of @@ -1197,6 +1197,7 @@ void MainWindow::setMenusForSelectedPacket() is_http = proto_is_frame_protocol(capture_file_.capFile()->edt->pi.layers, "http"); is_http2 = proto_is_frame_protocol(capture_file_.capFile()->edt->pi.layers, "http2"); is_quic = proto_is_frame_protocol(capture_file_.capFile()->edt->pi.layers, "quic"); + is_sip = proto_is_frame_protocol(capture_file_.capFile()->edt->pi.layers, "sip"); } } @@ -1243,6 +1244,7 @@ void MainWindow::setMenusForSelectedPacket() main_ui_->actionAnalyzeFollowHTTPStream->setEnabled(is_http); main_ui_->actionAnalyzeFollowHTTP2Stream->setEnabled(is_http2); main_ui_->actionAnalyzeFollowQUICStream->setEnabled(is_quic); + main_ui_->actionAnalyzeFollowSIPCall->setEnabled(is_sip); foreach(QAction *cc_action, cc_actions) { cc_action->setEnabled(frame_selected); @@ -2907,6 +2909,11 @@ void MainWindow::on_actionAnalyzeFollowQUICStream_triggered() openFollowStreamDialogForType(FOLLOW_QUIC); } +void MainWindow::on_actionAnalyzeFollowSIPCall_triggered() +{ + openFollowStreamDialogForType(FOLLOW_SIP); +} + void MainWindow::openSCTPAllAssocsDialog() { SCTPAllAssocsDialog *sctp_dialog = new SCTPAllAssocsDialog(this, capture_file_.capFile()); diff --git a/ui/qt/packet_list.cpp b/ui/qt/packet_list.cpp index d6196e6093..9ed453fa90 100644 --- a/ui/qt/packet_list.cpp +++ b/ui/qt/packet_list.cpp @@ -688,6 +688,7 @@ void PacketList::contextMenuEvent(QContextMenuEvent *event) submenu->addAction(window()->findChild("actionAnalyzeFollowHTTPStream")); submenu->addAction(window()->findChild("actionAnalyzeFollowHTTP2Stream")); submenu->addAction(window()->findChild("actionAnalyzeFollowQUICStream")); + submenu->addAction(window()->findChild("actionAnalyzeFollowSIPCall")); ctx_menu->addSeparator(); diff --git a/ui/qt/proto_tree.cpp b/ui/qt/proto_tree.cpp index fafdebd426..6697ab9674 100644 --- a/ui/qt/proto_tree.cpp +++ b/ui/qt/proto_tree.cpp @@ -309,6 +309,7 @@ void ProtoTree::contextMenuEvent(QContextMenuEvent *event) submenu->addAction(window()->findChild("actionAnalyzeFollowHTTPStream")); submenu->addAction(window()->findChild("actionAnalyzeFollowHTTP2Stream")); submenu->addAction(window()->findChild("actionAnalyzeFollowQUICStream")); + submenu->addAction(window()->findChild("actionAnalyzeFollowSIPCall")); ctx_menu.addSeparator(); }