aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEugène Adell <eugene.adell@gmail.com>2023-07-27 07:34:52 +0000
committerJohn Thacker <johnthacker@gmail.com>2023-07-27 07:34:52 +0000
commit939a9fb0a7cfdbe10f0e901a2b009cd28e4b41c6 (patch)
treea66016437b04232d801fe38e15a06be5fa136529
parent5218affca51271f3e49ddd8f32ec6711cffd4fe0 (diff)
TCP: Summarize the completeness bitmask as a string
-rw-r--r--docbook/wsug_src/wsug_advanced.adoc5
-rw-r--r--epan/dissectors/packet-tcp.c123
-rw-r--r--epan/dissectors/packet-tcp.h3
3 files changed, 103 insertions, 28 deletions
diff --git a/docbook/wsug_src/wsug_advanced.adoc b/docbook/wsug_src/wsug_advanced.adoc
index e28a416775..9ca624ab66 100644
--- a/docbook/wsug_src/wsug_advanced.adoc
+++ b/docbook/wsug_src/wsug_advanced.adoc
@@ -720,6 +720,11 @@ data transfer will be found with a longer filter as closing a connection can be
associated with FIN or RST packets, or even both :
'tcp.completeness==31 or tcp.completeness==47 or tcp.completeness==63'
+Another way to select specific conversation values is to filter on the
+tcp.completeness.str field. Thus, 'tcp.completeness.str matches "(R.*|F)[^D]ASS"'
+will find all 'Complete, NO_DATA' conversations, while the 'Complete, WITH_DATA'
+ones will be found with 'tcp.completeness.str matches "(R.*|F)DASS"'.
+
[#ChAdvTimestamps]
=== Time Stamps
diff --git a/epan/dissectors/packet-tcp.c b/epan/dissectors/packet-tcp.c
index 73e168a951..83cee13151 100644
--- a/epan/dissectors/packet-tcp.c
+++ b/epan/dissectors/packet-tcp.c
@@ -179,6 +179,7 @@ static int hf_tcp_completeness_ack = -1;
static int hf_tcp_completeness_data = -1;
static int hf_tcp_completeness_fin = -1;
static int hf_tcp_completeness_rst = -1;
+static int hf_tcp_completeness_str = -1;
static int hf_tcp_seq = -1;
static int hf_tcp_seq_abs = -1;
static int hf_tcp_nxtseq = -1;
@@ -841,6 +842,7 @@ tcp_flags_to_str(wmem_allocator_t *scope, const struct tcpheader *tcph)
return buf;
}
+
static char *
tcp_flags_to_str_first_letter(wmem_allocator_t *scope, const struct tcpheader *tcph)
{
@@ -870,6 +872,47 @@ tcp_flags_to_str_first_letter(wmem_allocator_t *scope, const struct tcpheader *t
return wmem_strbuf_finalize(buf);
}
+/*
+ * Print the first letter of each flag set, or the dot character otherwise
+ */
+static char *
+completeness_flags_to_str_first_letter(wmem_allocator_t *scope, guint8 flags)
+{
+ wmem_strbuf_t *buf = wmem_strbuf_new(scope, "");
+
+ if( flags & TCP_COMPLETENESS_RST )
+ wmem_strbuf_append(buf, "R");
+ else
+ wmem_strbuf_append(buf, UTF8_MIDDLE_DOT);
+
+ if( flags & TCP_COMPLETENESS_FIN )
+ wmem_strbuf_append(buf, "F");
+ else
+ wmem_strbuf_append(buf, UTF8_MIDDLE_DOT);
+
+ if( flags & TCP_COMPLETENESS_DATA )
+ wmem_strbuf_append(buf, "D");
+ else
+ wmem_strbuf_append(buf, UTF8_MIDDLE_DOT);
+
+ if( flags & TCP_COMPLETENESS_ACK )
+ wmem_strbuf_append(buf, "A");
+ else
+ wmem_strbuf_append(buf, UTF8_MIDDLE_DOT);
+
+ if( flags & TCP_COMPLETENESS_SYNACK )
+ wmem_strbuf_append(buf, "S");
+ else
+ wmem_strbuf_append(buf, UTF8_MIDDLE_DOT);
+
+ if( flags & TCP_COMPLETENESS_SYNSENT )
+ wmem_strbuf_append(buf, "S");
+ else
+ wmem_strbuf_append(buf, UTF8_MIDDLE_DOT);
+
+ return wmem_strbuf_finalize(buf);
+}
+
static void
tcp_src_prompt(packet_info *pinfo, gchar *result)
{
@@ -7783,17 +7826,23 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
/* Display the completeness of this TCP conversation */
static int* const completeness_fields[] = {
- &hf_tcp_completeness_syn,
- &hf_tcp_completeness_syn_ack,
- &hf_tcp_completeness_ack,
- &hf_tcp_completeness_data,
- &hf_tcp_completeness_fin,
&hf_tcp_completeness_rst,
+ &hf_tcp_completeness_fin,
+ &hf_tcp_completeness_data,
+ &hf_tcp_completeness_ack,
+ &hf_tcp_completeness_syn_ack,
+ &hf_tcp_completeness_syn,
NULL};
+
item = proto_tree_add_bitmask_value_with_flags(tcp_tree, NULL, 0,
hf_tcp_completeness, ett_tcp_completeness, completeness_fields,
tcpd->conversation_completeness, BMT_NO_APPEND);
proto_item_set_generated(item);
+ field_tree = proto_item_add_subtree(item, ett_tcp_completeness);
+
+ flags_str_first_letter = tcpd->conversation_completeness_str;
+ item = proto_tree_add_string(field_tree, hf_tcp_completeness_str, tvb, 0, 0, flags_str_first_letter);
+ proto_item_set_generated(item);
/* Copy the stream index into the header as well to make it available
* to tap listeners.
@@ -8013,37 +8062,51 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
}
conversation_completeness = tcpd->conversation_completeness ;
+ }
- /* SYN-ACK */
- if((tcph->th_flags&(TH_SYN|TH_ACK))==(TH_SYN|TH_ACK)) {
- conversation_completeness |= TCP_COMPLETENESS_SYNACK;
- }
+ /* SYN-ACK */
+ if((tcph->th_flags&(TH_SYN|TH_ACK))==(TH_SYN|TH_ACK)) {
+ conversation_completeness |= TCP_COMPLETENESS_SYNACK;
+ }
- /* ACKs */
- if((tcph->th_flags&(TH_SYN|TH_ACK))==(TH_ACK)) {
- if(tcph->th_seglen>0) { /* transporting some data */
- conversation_completeness |= TCP_COMPLETENESS_DATA;
- }
- else { /* pure ACK */
- conversation_completeness |= TCP_COMPLETENESS_ACK;
- }
+ /* ACKs */
+ if((tcph->th_flags&(TH_SYN|TH_ACK))==(TH_ACK)) {
+ if(tcph->th_seglen>0) { /* transporting some data */
+ conversation_completeness |= TCP_COMPLETENESS_DATA;
}
-
- /* FIN-ACK */
- if((tcph->th_flags&(TH_FIN|TH_ACK))==(TH_FIN|TH_ACK)) {
- conversation_completeness |= TCP_COMPLETENESS_FIN;
+ else { /* pure ACK */
+ conversation_completeness |= TCP_COMPLETENESS_ACK;
}
+ }
- /* RST */
- /* XXX: A RST segment should be validated (RFC 9293 3.5.3),
- * and if not valid should not change the conversation state.
- */
- if(tcph->th_flags&(TH_RST)) {
- conversation_completeness |= TCP_COMPLETENESS_RST;
+ /* FIN-ACK */
+ if((tcph->th_flags&(TH_FIN|TH_ACK))==(TH_FIN|TH_ACK)) {
+ conversation_completeness |= TCP_COMPLETENESS_FIN;
+ }
+
+ /* RST */
+ /* XXX: A RST segment should be validated (RFC 9293 3.5.3),
+ * and if not valid should not change the conversation state.
+ */
+ if(tcph->th_flags&(TH_RST)) {
+ conversation_completeness |= TCP_COMPLETENESS_RST;
+ }
+
+ /* Store the completeness at the conversation level,
+ * both as numerical and as Flag First Letters string, to avoid
+ * computing many times the same thing.
+ */
+ if (tcpd->conversation_completeness) {
+ if (tcpd->conversation_completeness != conversation_completeness) {
+ tcpd->conversation_completeness = conversation_completeness;
+ tcpd->conversation_completeness_str = completeness_flags_to_str_first_letter(wmem_file_scope(), tcpd->conversation_completeness) ;
}
}
+ else {
+ tcpd->conversation_completeness = conversation_completeness;
+ tcpd->conversation_completeness_str = completeness_flags_to_str_first_letter(wmem_file_scope(), tcpd->conversation_completeness) ;
+ }
}
- tcpd->conversation_completeness = conversation_completeness;
if (tcp_summary_in_tree) {
if(tcph->th_flags&TH_ACK) {
@@ -8674,6 +8737,10 @@ proto_register_tcp(void)
TFS(&tfs_present_absent), TCP_COMPLETENESS_RST,
"Conversation has a RST packet", HFILL}},
+ { &hf_tcp_completeness_str,
+ { "Completeness Flags", "tcp.completeness.str", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+
{ &hf_tcp_seq,
{ "Sequence Number", "tcp.seq", FT_UINT32, BASE_DEC, NULL, 0x0,
NULL, HFILL }},
diff --git a/epan/dissectors/packet-tcp.h b/epan/dissectors/packet-tcp.h
index f7ff247a2b..5220505133 100644
--- a/epan/dissectors/packet-tcp.h
+++ b/epan/dissectors/packet-tcp.h
@@ -494,6 +494,9 @@ struct tcp_analysis {
*/
guint8 conversation_completeness;
+ /* Stores the value as a String to be displayed in the appropriate field */
+ gchar *conversation_completeness_str;
+
/* Track AccECN support */
gboolean had_acc_ecn_setup_syn;
gboolean had_acc_ecn_setup_syn_ack;