diff --git a/docs/source/pcapkit/foundation/reassembly/ip/index.rst b/docs/source/pcapkit/foundation/reassembly/ip/index.rst index bd721eff1b..87e90ccb14 100644 --- a/docs/source/pcapkit/foundation/reassembly/ip/index.rst +++ b/docs/source/pcapkit/foundation/reassembly/ip/index.rst @@ -89,3 +89,7 @@ Algorithm flush all reassembly with this BUFID; DONE. } + +Because completion frees the buffer (:rfc:`791#section-3.2`), a fragment that +arrives after its datagram has completed opens a new buffer, which is later +reported as a separate incomplete datagram; this is intended (:issue:`1507`). diff --git a/pcapkit/foundation/reassembly/ip.py b/pcapkit/foundation/reassembly/ip.py index bef1acc096..81400f394a 100644 --- a/pcapkit/foundation/reassembly/ip.py +++ b/pcapkit/foundation/reassembly/ip.py @@ -87,6 +87,16 @@ def reassembly(self, info: 'Packet[_AT]') -> 'None': Arguments: info: info dict of packets to be reassembled + Note: + A completed datagram's buffer is freed, as in the + :rfc:`791#section-3.2` reassembly procedure, so a fragment of it + that arrives afterwards -- a late duplicate, say -- opens a new + buffer. The caller sees that buffer as a separate incomplete + datagram, ``PARTIAL`` at the end of the capture or ``TIMEOUT`` if + it expires first. This is intended, is permitted by + :rfc:`8200#section-4.5`, and matches Linux, Zeek and Wireshark + (:issue:`1507`). + """ # clear cache self._flag_n = False