Packets Reassembly

pcapkit.foundation.reassembly bases on algorithms described in RFC 791 and RFC 815, implements datagram reassembly of IP and TCP packets.

See also

For more information on customisation and extension, please refer to Customisation & Extensions.

All reassembly classes are implemented as ReassemblyBase subclasses, which are responsible for processing extracted packets and reassemble the datagrams to a nonfragmented packet. Below is a brief diagram of the class hierarchy of pcapkit.foundation.reassembly:

        flowchart LR
    A{{ReassemblyMeta}} -.->|metaclass| B(ReassemblyBase)

    B --> IP & TCP
    IP --> IPv4 & IPv6

    B --> C(Reassembly)
    C --> D([user customisation ...])

    click A "/pcapkit/foundation/reassembly/reassembly.html#pcapkit.foundation.reassembly.reassembly.ReassemblyMeta"
    click B "/pcapkit/foundation/reassembly/reassembly.html#pcapkit.foundation.reassembly.reassembly.ReassemblyBase"
    click C "/pcapkit/foundation/reassembly/reassembly.html#pcapkit.foundation.reassembly.reassembly.Reassembly"
    click D "/ext.html#reassembly-and-flow-tracing"

    click IP "/pcapkit/foundation/reassembly/ip/ip.html#pcapkit.foundation.reassembly.ip.IP"
    click IPv4 "/pcapkit/foundation/reassembly/ip/ipv4.html#pcapkit.foundation.reassembly.ipv4.IPv4"
    click IPv6 "/pcapkit/foundation/reassembly/ip/ipv6.html#pcapkit.foundation.reassembly.ipv6.IPv6"
    click TCP "/pcapkit/foundation/reassembly/tcp.html#pcapkit.foundation.reassembly.tcp.TCP"
    

Auxiliary Data

class pcapkit.foundation.reassembly.ReassemblyManager(*args: VT, **kwargs: VT)[source]

Bases: Info

Reassembly Manager.

ipv4: IPv4

IPv4 reassembly.

ipv6: IPv6

IPv6 reassembly.

tcp: TCP

TCP reassembly.

class pcapkit.foundation.reassembly.data.data.ReassemblyData(*args: VT, **kwargs: VT)[source]

Bases: Info

Data storage for reassembly.

ipv4: tuple[Datagram, ...]

IPv4 reassembled data.

ipv6: tuple[Datagram, ...]

IPv6 reassembled data.

tcp: tuple[Datagram, ...]

TCP reassembled data.

class pcapkit.foundation.reassembly.data.data.Deferred(analyze, proto, payload)[source]

Bases: object

A postponed analysis of a reassembled payload.

A reassembled datagram’s packet is a second, full parse of the payload the datagram just reassembled. Nothing about postponing it is specific to any one reassembler, which is why this lives beside ReassemblyData rather than in either protocol’s data module.

IP reassembly is the case that made it necessary. It submits a datagram for every frame – not only the fragmented ones, since a frame that is not fragmented in any sense still reaches IP.reassembly and is submitted there as a trivially complete datagram – so the eager parse re-parsed captures holding no fragments at all: http.pcap has 1117 IPv4 frames, none of them fragmented, and the parse was 86% of the cost of IP reassembly over it.

TCP reassembly builds its packet eagerly too (TCP.submit). It is a far smaller cost there, being FIN/RST-driven rather than per-frame – 222 submits per http.pcap pass against 1117 – so it is left for its own change, but it can use this unmodified when someone gets to it.

Holding the call here defers it to the first read of Datagram.packet, so a caller that wants the parsed payload still gets exactly the object the eager call produced, and one that does not never pays for it.

Parameters:
__call__()[source]

Run the postponed analysis.

Return type:

ProtocolBase

Returns:

Parsed payload.

class pcapkit.foundation.reassembly.data.data.DeferredPacket[source]

Bases: object

Resolves a Deferred packet field on first read.

A reassembled datagram’s packet is the parsed form of the payload it just reassembled, and both reassemblers can hand a Deferred in its place. This carries the reading half of that arrangement, so the two Datagram models share it rather than each declaring it.

A subclass has to list packet in its __additional__. That is what makes the field lazy at all: Info stores a field whose name is a builtin name under a mangled key and maps it back on the way out, so packet never lands in __dict__ itself – which routes reading it through __getattr__(), where the deferred analysis can run, while dict(datagram), to_dict() and iteration still report the field under its own name.

__analyse__()[source]

Resolve a deferred analysis, at most once.

Return type:

ProtocolBase | None

Returns:

Parsed IP payload, or None for an incomplete datagram.

to_dict()[source]

Convert Datagram into dict.

Return type:

dict[str, Any]

Returns:

The datagram’s fields, with packet analysed if it had not been read yet – a dict holding a Deferred would leak an implementation detail into what is meant to be plain data.