TCP: Report reassembled in for more PDUs where we know it

In the case where the beginning of a TCP segment does not continue
a higher-level PDU, but the end of the segment is the beginning of
another PDU, we don't need to create the MSP for the second PDU
after the first time we visit the packet. However, we do want to
retrieve that MSP for determining in which frame the second PDU
was reassembled.

Make "Reassembled PDU in frame:" messages be added in that case
like it already is for other frames with MSPs.
This commit is contained in:
John Thacker 2022-05-29 10:52:39 -04:00
parent 717e4c47ee
commit ec12d0c530
1 changed files with 58 additions and 49 deletions

View File

@ -4103,13 +4103,10 @@ again:
/* Did the subdissector ask us to desegment some more data
* before it could handle the packet?
* If so we have to create some structures in our table but
* this is something we only do the first time we see this
* packet.
* If so we'll have to handle that later.
*/
if(pinfo->desegment_len) {
if (!PINFO_FD_VISITED(pinfo))
must_desegment = TRUE;
must_desegment = TRUE;
/*
* Set "deseg_offset" to the offset in "tvb"
@ -4331,15 +4328,6 @@ again:
}
if (must_desegment) {
/* If the dissector requested "reassemble until FIN"
* just set this flag for the flow and let reassembly
* proceed at normal. We will check/pick up these
* reassembled PDUs later down in dissect_tcp() when checking
* for the FIN flag.
*/
if (tcpd && pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
tcpd->fwd->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN;
}
/*
* The sequence number at which the stuff to be desegmented
* starts is the sequence number of the byte at an offset
@ -4352,43 +4340,64 @@ again:
*/
deseg_seq = seq + (deseg_offset - offset);
if (tcpd && ((nxtseq - deseg_seq) <= 1024*1024)
&& (!PINFO_FD_VISITED(pinfo))) {
if(pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
/* The subdissector asked to reassemble using the
* entire next segment.
* Just ask reassembly for one more byte
* but set this msp flag so we can pick it up
* above.
*/
msp = pdu_store_sequencenumber_of_next_pdu(pinfo, deseg_seq,
nxtseq+1, tcpd->fwd->multisegment_pdus);
msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
} else if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
/*
* The subdissector asked to reassemble at the end of the
* connection. That will be done in dissect_tcp, but here we
* have to ask reassembly to collect all future segments.
* Note that TCP_FLOW_REASSEMBLE_UNTIL_FIN was set before, this
* ensures that OoO detection is skipped.
* The exact nxtpdu offset does not matter, but it should be
* smaller than half of the maximum 32-bit unsigned integer to
* allow detection of sequence number wraparound, and larger
* than the largest possible stream size. Hopefully 1GiB
* (0x40000000 bytes) should be enough.
*/
msp = pdu_store_sequencenumber_of_next_pdu(pinfo, deseg_seq,
nxtseq+0x40000000, tcpd->fwd->multisegment_pdus);
} else {
msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
deseg_seq, nxtseq+pinfo->desegment_len, tcpd->fwd->multisegment_pdus);
/* We have to create some structures in our table but
* this is something we only do the first time we see this
* packet. */
if (!PINFO_FD_VISITED(pinfo)) {
/* If the dissector requested "reassemble until FIN"
* just set this flag for the flow and let reassembly
* proceed at normal. We will check/pick up these
* reassembled PDUs later down in dissect_tcp() when checking
* for the FIN flag.
*/
if (tcpd && pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
tcpd->fwd->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN;
}
if (tcpd && ((nxtseq - deseg_seq) <= 1024*1024)) {
if(pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
/* The subdissector asked to reassemble using the
* entire next segment.
* Just ask reassembly for one more byte
* but set this msp flag so we can pick it up
* above.
*/
msp = pdu_store_sequencenumber_of_next_pdu(pinfo, deseg_seq,
nxtseq+1, tcpd->fwd->multisegment_pdus);
msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
} else if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
/*
* The subdissector asked to reassemble at the end of the
* connection. That will be done in dissect_tcp, but here we
* have to ask reassembly to collect all future segments.
* Note that TCP_FLOW_REASSEMBLE_UNTIL_FIN was set before,
* this ensures that OoO detection is skipped.
* The exact nxtpdu offset does not matter, but it should be
* smaller than half of the maximum 32-bit unsigned integer
* to allow detection of sequence number wraparound, and
* larger than the largest possible stream size. Hopefully
* 1GiB (0x40000000 bytes) should be enough.
*/
msp = pdu_store_sequencenumber_of_next_pdu(pinfo, deseg_seq,
nxtseq+0x40000000, tcpd->fwd->multisegment_pdus);
} else {
msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
deseg_seq, nxtseq+pinfo->desegment_len, tcpd->fwd->multisegment_pdus);
}
/* add this segment as the first one for this new pdu */
fragment_add(&tcp_reassembly_table, tvb, deseg_offset,
pinfo, msp->first_frame, msp,
0, nxtseq - deseg_seq,
LT_SEQ(nxtseq, msp->nxtpdu));
/* add this segment as the first one for this new pdu */
fragment_add(&tcp_reassembly_table, tvb, deseg_offset,
pinfo, msp->first_frame, msp,
0, nxtseq - deseg_seq,
LT_SEQ(nxtseq, msp->nxtpdu));
}
} else {
/* If this is not the first time we have seen the packet, then
* the MSP should already be created. Retrieve it to see if we
* know what later frame the PDU is reassembled in.
*/
if (tcpd && (msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32(tcpd->fwd->multisegment_pdus, deseg_seq))) {
ipfd_head = fragment_get(&tcp_reassembly_table, pinfo, msp->first_frame, msp);
}
}
}