Skip to content

fix(toolkit): dpkt ends the extraction with ProtocolError on 802.1Q then 802.1ad, two 802.1ad, or three VLAN tags #1646

Closed

Description

@JarryShaw

Describe the bug
With engine='dpkt' and TCP or IPv4 reassembly on, three tag stackings make extract() raise ProtocolError: 802.1Q then 802.1ad, 802.1ad twice, or three tags. The rest of the capture is never read. The error is TCP header not found at offset 38 of the 66-octet record; the frame cannot be sliced without re-serialising it, or, from IPv4 reassembly, IP header not found at offset 18 .... Tracing alone is unaffected. The default engine, scapy and pypcapfile read the same frames and carry on.

dpkt 1.9.8 decodes the IP packet but loses tags. Ethernet._unpack_data (dpkt/ethernet.py:90) reads two tags per pass, and __init__ runs a second pass over the leftover octets that resets vlan_tags. Only the last tag survives: 1 of 2, or 1 of 3. dpkt's re-serialisation is then 4 octets short for each lost tag. _layer2bytes (pcapkit/toolkit/dpkt.py:362, raised at :403) slices the record by that length, misses the header, and raises. tcp_reassembly (:975) and ipv4_reassembly (:781) both call it.

Reproduction on main (b375656e1): Python 3.14.8 and 3.11.15, dpkt 1.9.8, and pypcapfile 0.12.0 on 3.11 only. Each case is a two-frame capture extracted with reassembly=True, tcp=True, trace=True. The first frame is Ethernet, then the tags, then IPv4 and a TCP segment carrying 4 octets of data. The first TPID is the Ethernet type, each tag's next type is the following TPID, and the VLAN ids run 100, 101, and so on. The second frame is plain IPv4/TCP. Each cell is the first frame's TCP reassembly payload length / whether it is traced:

tags, then IPv4/TCP default dpkt scapy pypcapfile
802.1Q (control) 4 / yes 4 / yes 4 / yes 4 / yes
802.1ad, 802.1Q (control) 4 / yes 4 / yes 4 / yes 4 / yes
802.1Q, 802.1ad 4 / yes ProtocolError 4 / yes 4 / yes
802.1ad, 802.1ad 4 / yes ProtocolError 4 / yes 4 / yes
802.1Q, 802.1Q, 802.1Q 4 / yes ProtocolError 4 / yes 4 / yes
802.1ad, 802.1Q, 802.1Q 4 / yes ProtocolError 4 / yes 4 / yes

pyshark does no reassembly, so it is not compared.

Expected behavior
For each frame, dpkt hands over the same TCP, trace and IP reassembly inputs as the default engine, and the extraction continues.

Activity

  1. JarryShaw commented on Oct 13, 2026

    @JarryShaw
    OwnerAuthor

    Being fixed together with #1637 and #1638. Their fix makes this same _layer2bytes error reachable from IPv6 reassembly of a 6in4 fragment as well, so the root cause is fixed in that PR rather than disclosed.

  2. added
    fixPull requests that fix a defect (fix: subject prefix)
    wipWork in flight - a covering PR is open or an agent is actively on it
    on Oct 13, 2026
  3. removed
    wipWork in flight - a covering PR is open or an agent is actively on it
    on Oct 13, 2026
  4. added this to the PyPCAPKit v1.5 milestone on Oct 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    fixPull requests that fix a defect (fix: subject prefix)

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions