forked from osmocom/wireshark
QUIC: Add Follow QUIC Stream support to Qt and tshark
The QUIC transport protocol provides a stream, similar to HTTP/2. Make it possible to look at the stream contents. This can be helpful while HTTP/3 support is not yet complete. Known issues that will be addressed in the future: - If a single packet contains multiple streams, then Follow QUIC Stream will wrongly include data from streams other than the selected one. This is tracked by bug 16093 and affects HTTP/2 as well. - The Substream index menu does not properly filter for available stream numbers. If a non-existing stream is selected, then changing to another (potentially valid) index results in the "Capture file invalid." error. As workaround, clear the display filter first. - Follow Stream always selects Stream ID 0 instead of the first or currently selected stream field in a packet. Users should manually update the stream index as needed. Change-Id: I5866be380d58c96f0a71a29abdbd1be20ae3534a Ping-Bug: 13881 Reviewed-on: https://code.wireshark.org/review/34694 Petri-Dish: Peter Wu <peter@lekensteyn.nl> Tested-by: Petri Dish Buildbot Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com> Reviewed-by: Anders Broman <a.broman58@gmail.com>osmith/wip
parent
750ffac7b6
commit
d2a660d805
|
@ -852,6 +852,7 @@ libwireshark.so.0 libwireshark0 #MINVER#
|
|||
get_utf_16_string@Base 1.12.0~rc1
|
||||
get_vlan_hash_table@Base 2.1.0
|
||||
get_wka_hashtable@Base 1.12.0~rc1
|
||||
get_quic_connections_count@Base 3.1.1
|
||||
giop_add_CDR_string@Base 3.0.1
|
||||
golay_decode@Base 1.9.1
|
||||
golay_encode@Base 1.9.1
|
||||
|
|
|
@ -1228,6 +1228,8 @@ I<prot> specifies the transport protocol. It can be one of:
|
|||
tcp TCP
|
||||
udp UDP
|
||||
tls TLS or SSL
|
||||
http2 HTTP/2 streams
|
||||
quic QUIC streams
|
||||
|
||||
I<mode> specifies the output mode. It can be one of:
|
||||
|
||||
|
@ -1296,6 +1298,10 @@ stream on the first TCP session (index 0) with HTTP/2 Stream ID 1.
|
|||
00000020 34 a0 5b b8 21 5c 0b ea 62 d1 bf 4.[.!\.. b..
|
||||
0000002B 00 40 00 00 00 00 00 00 01 89 50 4e 47 0d 0a 1a .@...... ..PNG...
|
||||
|
||||
QUIC streams can be selected through B<-z "follow,quic,hex,3,0">, the first
|
||||
number indicates the UDP stream index whereas the second number selects the QUIC
|
||||
Stream ID.
|
||||
|
||||
=item B<-z> h225,counter[I<,filter>]
|
||||
|
||||
Count ITU-T H.225 messages and their reasons. In the first column you get a
|
||||
|
|
|
@ -110,6 +110,9 @@ a HTTP/2 Stream Index (field name `http2.streamid`) which are unique within a
|
|||
TCP connection. The “Stream” selector determines the TCP connection whereas the
|
||||
“Substream” selector is used to pick the HTTP/2 Stream ID.
|
||||
|
||||
The QUIC protocol is similar, the first number selects the UDP stream index
|
||||
while the "Substream" field selects the QUIC Stream ID.
|
||||
|
||||
[[ChAdvShowPacketBytes]]
|
||||
|
||||
=== Show Packet Bytes
|
||||
|
|
|
@ -501,6 +501,7 @@ set(DISSECTOR_PUBLIC_HEADERS
|
|||
packet-q931.h
|
||||
packet-q932.h
|
||||
packet-qsig.h
|
||||
packet-quic.h
|
||||
packet-radius.h
|
||||
packet-raknet.h
|
||||
packet-ranap.h
|
||||
|
|
|
@ -34,9 +34,14 @@
|
|||
#include <epan/to_str.h>
|
||||
#include "packet-tls-utils.h"
|
||||
#include "packet-tls.h"
|
||||
#include "packet-quic.h"
|
||||
#include <epan/prefs.h>
|
||||
#include <wsutil/pint.h>
|
||||
|
||||
#include <epan/tap.h>
|
||||
#include <epan/follow.h>
|
||||
#include <epan/addr_resolv.h>
|
||||
|
||||
#if GCRYPT_VERSION_NUMBER >= 0x010600 /* 1.6.0 */
|
||||
/* Whether to provide support for authentication in addition to decryption. */
|
||||
#define HAVE_LIBGCRYPT_AEAD
|
||||
|
@ -50,6 +55,8 @@
|
|||
void proto_reg_handoff_quic(void);
|
||||
void proto_register_quic(void);
|
||||
|
||||
static int quic_follow_tap = -1;
|
||||
|
||||
/* Initialize the protocol and registered fields */
|
||||
static int proto_quic = -1;
|
||||
static int hf_quic_connection_number = -1;
|
||||
|
@ -228,6 +235,17 @@ struct quic_cid_item {
|
|||
quic_cid_t data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Per-STREAM state, identified by QUIC Stream ID.
|
||||
*
|
||||
* Assume that every QUIC Short Header packet has no STREAM frames that overlap
|
||||
* each other in the same QUIC packet (identified by "frame_num"). Thus, the
|
||||
* Stream ID and offset uniquely identifies the STREAM Frame info in per packet.
|
||||
*/
|
||||
typedef struct _quic_stream_state {
|
||||
guint64 stream_id;
|
||||
} quic_stream_state;
|
||||
|
||||
/**
|
||||
* State for a single QUIC connection, identified by one or more Destination
|
||||
* Connection IDs (DCID).
|
||||
|
@ -253,6 +271,8 @@ typedef struct quic_info_data {
|
|||
quic_cid_item_t client_cids; /**< SCID of client from first Initial Packet. */
|
||||
quic_cid_item_t server_cids; /**< SCID of server from first Retry/Handshake. */
|
||||
quic_cid_t client_dcid_initial; /**< DCID from Initial Packet. */
|
||||
wmem_map_t *client_streams; /**< Map from Stream ID -> STREAM info (guint64 -> quic_stream_state), sent by the client. */
|
||||
wmem_map_t *server_streams; /**< Map from Stream ID -> STREAM info (guint64 -> quic_stream_state), sent by the server. */
|
||||
} quic_info_data_t;
|
||||
|
||||
/** Per-packet information about QUIC, populated on the first pass. */
|
||||
|
@ -641,6 +661,21 @@ quic_cids_is_known_length(const quic_cid_t *cid)
|
|||
return (quic_cid_lengths & (1ULL << cid->len)) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the QUIC connection for the current UDP stream. This may return NULL
|
||||
* after connection migration if the new UDP association was not properly linked
|
||||
* via a match based on the Connection ID.
|
||||
*/
|
||||
static quic_info_data_t *
|
||||
quic_connection_from_conv(packet_info *pinfo)
|
||||
{
|
||||
conversation_t *conv = find_conversation_pinfo(pinfo, 0);
|
||||
if (conv) {
|
||||
return (quic_info_data_t *)conversation_get_proto_data(conv, proto_quic);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to lookup a matching connection (Connection ID is optional).
|
||||
* If connection is found, "from_server" is set accordingly.
|
||||
|
@ -676,10 +711,9 @@ quic_connection_find_dcid(packet_info *pinfo, const quic_cid_t *dcid, gboolean *
|
|||
}
|
||||
}
|
||||
} else {
|
||||
conversation_t *conv = find_conversation_pinfo(pinfo, 0);
|
||||
if (conv) {
|
||||
conn = (quic_info_data_t *)conversation_get_proto_data(conv, proto_quic);
|
||||
check_ports = !!conn;
|
||||
conn = quic_connection_from_conv(pinfo);
|
||||
if (conn) {
|
||||
check_ports = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1087,6 +1121,9 @@ dissect_quic_frame_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *quic_tree
|
|||
proto_item_append_text(ti_ft, " len=%" G_GINT64_MODIFIER "u uni=%d", length, !!(stream_id & 2U));
|
||||
|
||||
proto_tree_add_item(ft_tree, hf_quic_stream_data, tvb, offset, (int)length, ENC_NA);
|
||||
if (have_tap_listener(quic_follow_tap)) {
|
||||
tap_queue_packet(quic_follow_tap, pinfo, tvb_new_subset_length(tvb, offset, (int)length));
|
||||
}
|
||||
offset += (int)length;
|
||||
}
|
||||
break;
|
||||
|
@ -2417,6 +2454,58 @@ quic_cleanup(void)
|
|||
quic_server_connections = NULL;
|
||||
}
|
||||
|
||||
/* Follow QUIC Stream functionality {{{ */
|
||||
|
||||
static gchar *
|
||||
quic_follow_conv_filter(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))) {
|
||||
gboolean from_server;
|
||||
quic_info_data_t *conn = quic_connection_find_dcid(pinfo, NULL, &from_server);
|
||||
if (!conn) {
|
||||
return NULL;
|
||||
}
|
||||
// XXX Look up stream ID for the current packet.
|
||||
guint stream_id = 0;
|
||||
*stream = conn->number;
|
||||
*sub_stream = stream_id;
|
||||
return g_strdup_printf("quic.connection.number eq %u and quic.stream.stream_id eq %u", conn->number, stream_id);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
quic_follow_index_filter(guint stream, guint sub_stream)
|
||||
{
|
||||
return g_strdup_printf("quic.connection.number eq %u and quic.stream.stream_id eq %u", stream, sub_stream);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
quic_follow_address_filter(address *src_addr _U_, address *dst_addr _U_, int src_port _U_, int dst_port _U_)
|
||||
{
|
||||
// This appears to be solely used for tshark. Let's not support matching by
|
||||
// IP addresses and UDP ports for now since that fails after connection
|
||||
// migration. If necessary, use udp_follow_address_filter.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static tap_packet_status
|
||||
follow_quic_tap_listener(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *data)
|
||||
{
|
||||
// TODO fix filtering for multiple streams, see
|
||||
// https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=16093
|
||||
follow_tvb_tap_listener(tapdata, pinfo, NULL, data);
|
||||
return TAP_PACKET_DONT_REDRAW;
|
||||
}
|
||||
|
||||
guint32 get_quic_connections_count(void)
|
||||
{
|
||||
return quic_connections_count;
|
||||
}
|
||||
/* Follow QUIC Stream functionality }}} */
|
||||
|
||||
void
|
||||
proto_register_quic(void)
|
||||
{
|
||||
|
@ -2885,6 +2974,9 @@ proto_register_quic(void)
|
|||
|
||||
register_init_routine(quic_init);
|
||||
register_cleanup_routine(quic_cleanup);
|
||||
|
||||
register_follow_stream(proto_quic, "quic_follow", quic_follow_conv_filter, quic_follow_index_filter, quic_follow_address_filter,
|
||||
udp_port_to_display, follow_quic_tap_listener);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2893,6 +2985,7 @@ proto_reg_handoff_quic(void)
|
|||
tls13_handshake_handle = find_dissector("tls13-handshake");
|
||||
dissector_add_uint_with_preference("udp.port", 0, quic_handle);
|
||||
heur_dissector_add("udp", dissect_quic_heur, "QUIC", "quic", proto_quic, HEURISTIC_ENABLE);
|
||||
quic_follow_tap = register_tap("quic_follow");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/* packet-quic.h
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef __PACKET_QUIC_H__
|
||||
#define __PACKET_QUIC_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include "ws_symbol_export.h"
|
||||
|
||||
/** Returns the number of items for quic.connection.number. */
|
||||
WS_DLL_PUBLIC guint32 get_quic_connections_count(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __PACKET_QUIC_H__ */
|
|
@ -43,7 +43,8 @@ typedef enum {
|
|||
FOLLOW_TLS,
|
||||
FOLLOW_UDP,
|
||||
FOLLOW_HTTP,
|
||||
FOLLOW_HTTP2
|
||||
FOLLOW_HTTP2,
|
||||
FOLLOW_QUIC,
|
||||
} follow_type_t;
|
||||
|
||||
/* Show Type */
|
||||
|
|
|
@ -340,7 +340,7 @@ follow_arg_filter(const char **opt_argp, follow_info_t *follow_info)
|
|||
{
|
||||
*opt_argp += len;
|
||||
|
||||
/* if it's HTTP2 protocol we should read substream id otherwise it's a range parameter from follow_arg_range */
|
||||
/* if it's HTTP2 or QUIC protocol we should read substream id otherwise it's a range parameter from follow_arg_range */
|
||||
if (cli_follow_info->sub_stream_index == -1 && sscanf(*opt_argp, ",%d%n", &cli_follow_info->sub_stream_index, &len) == 1 &&
|
||||
((*opt_argp)[len] == 0 || (*opt_argp)[len] == ','))
|
||||
{
|
||||
|
@ -454,8 +454,9 @@ static void follow_stream(const char *opt_argp, void *userdata)
|
|||
|
||||
cli_follow_info = g_new0(cli_follow_info_t, 1);
|
||||
cli_follow_info->stream_index = -1;
|
||||
/* use second parameter only for HTTP2 substream */
|
||||
if (strncmp(proto_filter_name, "http2", 5) == 0) {
|
||||
/* use second parameter only for HTTP2 or QUIC substream */
|
||||
if (g_str_equal(proto_filter_name, "http2") ||
|
||||
g_str_equal(proto_filter_name, "quic")) {
|
||||
cli_follow_info->sub_stream_index = -1;
|
||||
} else {
|
||||
cli_follow_info->sub_stream_index = 0;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "epan/dissectors/packet-tcp.h"
|
||||
#include "epan/dissectors/packet-udp.h"
|
||||
#include "epan/dissectors/packet-http2.h"
|
||||
#include "epan/dissectors/packet-quic.h"
|
||||
#include "epan/prefs.h"
|
||||
#include "epan/addr_resolv.h"
|
||||
#include "epan/charsets.h"
|
||||
|
@ -99,6 +100,9 @@ FollowStreamDialog::FollowStreamDialog(QWidget &parent, CaptureFile &cf, follow_
|
|||
case FOLLOW_HTTP2:
|
||||
follower_ = get_follow_by_name("HTTP2");
|
||||
break;
|
||||
case FOLLOW_QUIC:
|
||||
follower_ = get_follow_by_name("QUIC");
|
||||
break;
|
||||
default :
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
@ -405,10 +409,18 @@ void FollowStreamDialog::on_subStreamNumberSpinBox_valueChanged(int sub_stream_n
|
|||
// Stream ID 0 should always exist as it is used for control messages.
|
||||
sub_stream_num_new = 0;
|
||||
ok = TRUE;
|
||||
} else if (previous_sub_stream_num_ < sub_stream_num){
|
||||
ok = http2_get_stream_id_ge(static_cast<guint>(stream_num), sub_stream_num_new, &sub_stream_num_new);
|
||||
} else if (follow_type_ == FOLLOW_HTTP2) {
|
||||
if (previous_sub_stream_num_ < sub_stream_num){
|
||||
ok = http2_get_stream_id_ge(static_cast<guint>(stream_num), sub_stream_num_new, &sub_stream_num_new);
|
||||
} else {
|
||||
ok = http2_get_stream_id_le(static_cast<guint>(stream_num), sub_stream_num_new, &sub_stream_num_new);
|
||||
}
|
||||
} else if (follow_type_ == FOLLOW_QUIC) {
|
||||
// TODO clamp the stream IDs correctly for QUIC
|
||||
ok = TRUE;
|
||||
} else {
|
||||
ok = http2_get_stream_id_le(static_cast<guint>(stream_num), sub_stream_num_new, &sub_stream_num_new);
|
||||
// Should not happen, this field is only visible for suitable protocols.
|
||||
return;
|
||||
}
|
||||
sub_stream_num = static_cast<gint>(sub_stream_num_new);
|
||||
|
||||
|
@ -502,6 +514,7 @@ FollowStreamDialog::readStream()
|
|||
case FOLLOW_UDP :
|
||||
case FOLLOW_HTTP :
|
||||
case FOLLOW_HTTP2:
|
||||
case FOLLOW_QUIC:
|
||||
case FOLLOW_TLS :
|
||||
ret = readFollowStream();
|
||||
break;
|
||||
|
@ -891,7 +904,7 @@ bool FollowStreamDialog::follow(QString previous_filter, bool use_stream_index,
|
|||
return false;
|
||||
}
|
||||
|
||||
/* disable substream spin box for all protocols except HTTP2 */
|
||||
/* disable substream spin box for all protocols except HTTP2 and QUIC */
|
||||
ui->subStreamNumberSpinBox->blockSignals(true);
|
||||
ui->subStreamNumberSpinBox->setEnabled(false);
|
||||
ui->subStreamNumberSpinBox->setValue(0);
|
||||
|
@ -951,6 +964,30 @@ bool FollowStreamDialog::follow(QString previous_filter, bool use_stream_index,
|
|||
|
||||
break;
|
||||
}
|
||||
case FOLLOW_QUIC:
|
||||
{
|
||||
int stream_count = get_quic_connections_count();
|
||||
ui->streamNumberSpinBox->blockSignals(true);
|
||||
ui->streamNumberSpinBox->setMaximum(stream_count-1);
|
||||
ui->streamNumberSpinBox->setValue(stream_num);
|
||||
ui->streamNumberSpinBox->blockSignals(false);
|
||||
ui->streamNumberSpinBox->setToolTip(tr("%Ln total stream(s).", "", stream_count));
|
||||
ui->streamNumberLabel->setToolTip(ui->streamNumberSpinBox->toolTip());
|
||||
|
||||
// TODO extract number of QUIC streams?
|
||||
stream_count = G_MAXINT32;
|
||||
ui->subStreamNumberSpinBox->blockSignals(true);
|
||||
ui->subStreamNumberSpinBox->setEnabled(true);
|
||||
ui->subStreamNumberSpinBox->setMaximum(stream_count);
|
||||
ui->subStreamNumberSpinBox->setValue(sub_stream_num);
|
||||
ui->subStreamNumberSpinBox->blockSignals(false);
|
||||
ui->subStreamNumberSpinBox->setToolTip(tr("%Ln total sub stream(s).", "", stream_count));
|
||||
ui->subStreamNumberSpinBox->setToolTip(ui->subStreamNumberSpinBox->toolTip());
|
||||
ui->subStreamNumberSpinBox->setVisible(true);
|
||||
ui->subStreamNumberLabel->setVisible(true);
|
||||
|
||||
break;
|
||||
}
|
||||
case FOLLOW_TLS:
|
||||
case FOLLOW_HTTP:
|
||||
/* No extra handling */
|
||||
|
|
|
@ -554,6 +554,7 @@ private slots:
|
|||
void on_actionAnalyzeFollowTLSStream_triggered();
|
||||
void on_actionAnalyzeFollowHTTPStream_triggered();
|
||||
void on_actionAnalyzeFollowHTTP2Stream_triggered();
|
||||
void on_actionAnalyzeFollowQUICStream_triggered();
|
||||
|
||||
void statCommandExpertInfo(const char *, void *);
|
||||
void on_actionAnalyzeExpertInfo_triggered();
|
||||
|
|
|
@ -416,6 +416,7 @@
|
|||
<addaction name="actionAnalyzeFollowTLSStream"/>
|
||||
<addaction name="actionAnalyzeFollowHTTPStream"/>
|
||||
<addaction name="actionAnalyzeFollowHTTP2Stream"/>
|
||||
<addaction name="actionAnalyzeFollowQUICStream"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuConversationFilter">
|
||||
<property name="title">
|
||||
|
@ -1720,6 +1721,14 @@
|
|||
<string>HTTP/2 Stream</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAnalyzeFollowQUICStream">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>QUIC Stream</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionStatisticsTcpStreamTcptrace">
|
||||
<property name="text">
|
||||
<string>Time Sequence (tcptrace)</string>
|
||||
|
|
|
@ -1115,7 +1115,8 @@ void MainWindow::recentActionTriggered() {
|
|||
|
||||
void MainWindow::setMenusForSelectedPacket()
|
||||
{
|
||||
gboolean is_ip = FALSE, is_tcp = FALSE, is_udp = FALSE, is_sctp = FALSE, is_tls = FALSE, is_rtp = FALSE, is_lte_rlc = FALSE, is_http = FALSE, is_http2 = FALSE;
|
||||
gboolean is_ip = FALSE, is_tcp = FALSE, is_udp = FALSE, is_sctp = FALSE, is_tls = FALSE, is_rtp = FALSE, is_lte_rlc = FALSE,
|
||||
is_http = FALSE, is_http2 = FALSE, is_quic = FALSE;
|
||||
|
||||
/* Making the menu context-sensitive allows for easier selection of the
|
||||
desired item and has the added benefit, with large captures, of
|
||||
|
@ -1175,6 +1176,7 @@ void MainWindow::setMenusForSelectedPacket()
|
|||
&is_tls, &is_rtp, &is_lte_rlc);
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1208,6 +1210,7 @@ void MainWindow::setMenusForSelectedPacket()
|
|||
main_ui_->actionAnalyzeFollowTLSStream->setEnabled(is_tls);
|
||||
main_ui_->actionAnalyzeFollowHTTPStream->setEnabled(is_http);
|
||||
main_ui_->actionAnalyzeFollowHTTP2Stream->setEnabled(is_http2);
|
||||
main_ui_->actionAnalyzeFollowQUICStream->setEnabled(is_quic);
|
||||
|
||||
foreach(QAction *cc_action, cc_actions) {
|
||||
cc_action->setEnabled(frame_selected);
|
||||
|
@ -2774,6 +2777,11 @@ void MainWindow::on_actionAnalyzeFollowHTTP2Stream_triggered()
|
|||
openFollowStreamDialogForType(FOLLOW_HTTP2);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionAnalyzeFollowQUICStream_triggered()
|
||||
{
|
||||
openFollowStreamDialogForType(FOLLOW_QUIC);
|
||||
}
|
||||
|
||||
void MainWindow::openSCTPAllAssocsDialog()
|
||||
{
|
||||
SCTPAllAssocsDialog *sctp_dialog = new SCTPAllAssocsDialog(this, capture_file_.capFile());
|
||||
|
|
|
@ -544,6 +544,7 @@ void PacketList::contextMenuEvent(QContextMenuEvent *event)
|
|||
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeFollowTLSStream"));
|
||||
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeFollowHTTPStream"));
|
||||
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeFollowHTTP2Stream"));
|
||||
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeFollowQUICStream"));
|
||||
|
||||
ctx_menu->addSeparator();
|
||||
|
||||
|
|
|
@ -286,6 +286,7 @@ void ProtoTree::contextMenuEvent(QContextMenuEvent *event)
|
|||
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeFollowTLSStream"));
|
||||
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeFollowHTTPStream"));
|
||||
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeFollowHTTP2Stream"));
|
||||
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeFollowQUICStream"));
|
||||
ctx_menu.addSeparator();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue