diff options
author | Eugène Adell <eugene.adell@gmail.com> | 2023-07-27 07:34:52 +0000 |
---|---|---|
committer | John Thacker <johnthacker@gmail.com> | 2023-07-27 07:34:52 +0000 |
commit | 939a9fb0a7cfdbe10f0e901a2b009cd28e4b41c6 (patch) | |
tree | a66016437b04232d801fe38e15a06be5fa136529 | |
parent | 5218affca51271f3e49ddd8f32ec6711cffd4fe0 (diff) |
TCP: Summarize the completeness bitmask as a string
-rw-r--r-- | docbook/wsug_src/wsug_advanced.adoc | 5 | ||||
-rw-r--r-- | epan/dissectors/packet-tcp.c | 123 | ||||
-rw-r--r-- | epan/dissectors/packet-tcp.h | 3 |
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; |