From 3fea3c3709a039958cbe2fcb6c87d3f4d5049f11 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Mon, 27 Aug 2018 15:31:03 +0200 Subject: [PATCH] tcp: fix OoO reassembly when the first data packet is OoO OoO reassembly assumed that the stream starts with the first data segment, but this can already be OoO. Use the hint from SYN instead. The test capture is based on a local capture, post-processed with scapy to introduce an OoO condition and fixup the frame time. Bug: 15078 Change-Id: Id0e312bb3d0e7c7f8f1b243a2be9f15c9851c501 Fixes: v2.9.0rc0-1097-gca42331437 ("tcp: add support for reassembling out-of-order segments") Reviewed-on: https://code.wireshark.org/review/29305 Petri-Dish: Peter Wu Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman --- epan/dissectors/packet-tcp.c | 10 ++++++++-- test/captures/dns-ooo.pcap | Bin 0 -> 418 bytes test/suite_dissection.py | 11 +++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 test/captures/dns-ooo.pcap diff --git a/epan/dissectors/packet-tcp.c b/epan/dissectors/packet-tcp.c index 73f4a2647a..e25f18a487 100644 --- a/epan/dissectors/packet-tcp.c +++ b/epan/dissectors/packet-tcp.c @@ -3179,8 +3179,8 @@ again: * the MSP is not complete yet. */ } if (tcpd->fwd->maxnextseq == 0 || LT_SEQ(tcpd->fwd->maxnextseq, nxtseq)) { - /* Update the maximum expected seqno if unknown or if the new - * segment succeeds previous segments. */ + /* Update the maximum expected seqno if no SYN packet was seen + * before, or if the new segment succeeds previous segments. */ tcpd->fwd->maxnextseq = nxtseq; } } @@ -6308,6 +6308,12 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) tcpd->server_port = tcph->th_dport; tcpd->ts_mru_syn = pinfo->abs_ts; } + /* Remember where the next segment will start. */ + if (tcp_desegment && tcp_reassemble_out_of_order && tcpd && !PINFO_FD_VISITED(pinfo)) { + if (tcpd->fwd->maxnextseq == 0) { + tcpd->fwd->maxnextseq = tcph->th_seq + 1; + } + } } if(tcph->th_flags & TH_FIN) { /* XXX - find a way to know the server port and output only that one */ diff --git a/test/captures/dns-ooo.pcap b/test/captures/dns-ooo.pcap new file mode 100644 index 0000000000000000000000000000000000000000..594b925f7c977fabbf879fb7c9213533c8666420 GIT binary patch literal 418 zcmca|c+)~A1{MYw`2U}Qff2}g@v}L4b}t))7my9Ylgcdj9c=8Xb(j|<&B5Txz+l6` z;J{$dmdAZy1=Bw+P6j3h)3faffj9l+KcpX7ASAZHoS%V#iG_6w3lj&|??CqZ@0P4y z%gD^k1Tr~iDjS0n&{Pn{FxlkZdXUNe$!I3~15N(bAi%n!Yzokgj9^nA0!>{HGEpj= zgP|H|8VF;Un0s#{*hCF969d2|O0ce|xB)YfBlz8tHS!h@<~KF~!vPc$jO?iuiMa(i zsm#gwxj-%h;{hIslxR5vOYDvtN(>B|OhAPo0CLJypi`WIY!Jq9is`)#V5cOaIR)Z5 Ppi|0Z;ZE@fd5!@9c6)$f literal 0 HcmV?d00001 diff --git a/test/suite_dissection.py b/test/suite_dissection.py index cfec7c4c66..540fe5a2ef 100644 --- a/test/suite_dissection.py +++ b/test/suite_dissection.py @@ -79,3 +79,14 @@ class case_dissect_tcp(subprocesstest.SubprocessTestCase): self.assertTrue(self.grepOutput(r'^\s*11\s.*PUT /3 HTTP/1.1')) self.assertTrue(self.grepOutput(r'^\s*11\s.*PUT /4 HTTP/1.1')) self.assertTrue(self.grepOutput(r'^\s*15\s.*PUT /5 HTTP/1.1')) + + def test_tcp_out_of_order_data_after_syn(self): + '''Test when the first non-empty segment is OoO.''' + capture_file = os.path.join(config.capture_dir, 'dns-ooo.pcap') + proc = self.runProcess((config.cmd_tshark, + '-r', capture_file, + '-otcp.reassemble_out_of_order:TRUE', + '-Y', 'dns', '-Tfields', '-edns.qry.name', + ), + env=config.test_env) + self.assertEqual(proc.stdout_str.strip(), 'example.com')