Skip to content

refactor(toolkit): revert dpkt's agreement-only code (#1708) - #1727

Merged
JarryShaw merged 1 commit into
mainfrom
refactor/1708-dpkt-revert-agreement
Oct 14, 2026
Merged

JarryShaw merged 1 commit into
mainfrom
refactor/1708-dpkt-revert-agreement

Conversation

@JarryShaw

Copy link
Copy Markdown
Owner

Please follow the guide below

What is the purpose of your pull request?

Tick the commit type your subject line carries.

  • fix — corrects a defect
  • feat — adds a feature
  • perf — changes performance, not behaviour
  • refactor — changes neither behaviour nor performance
  • test — tests only
  • docs — documentation only
  • ci — workflows or build tooling
  • release — bumps the version or rolls up a distribution
  • chore — anything else

Description of your pull request and other information

Phase 2 of #1708, for dpkt, per the plan on #1687.

Decision needed (#1646). dpkt's own lengths can misplace a layer, after 802.1Q then 802.1ad, or ISL then 802.1Q. This PR then re-serialises that layer from dpkt's fields, so the frame's data is kept, but those octets are dpkt's rather than the capture's. A zero checksum or length is recomputed. The alternative is to return None and drop the frame from reassembly and tracing. Re-serialising is recommended. Which do you want?

Tests:

  • The dpkt modules, the shared modules that run dpkt, and tests/foundation/engines:
    • 3.14: 272 passed;
    • 3.11 with dpkt 1.9.8: 286 passed.
  • Every guard mutation is caught.
  • Sphinx gives 63 warnings, the same as main.

@JarryShaw JarryShaw added refactor Restructuring for its own sake — neither a fix nor a new capability (refactor: prefix) review: good-to-go Cross-review at the current head says ready; CI state is separate labels Oct 14, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Verdict: GOOD TO GO at 3ab380768. Sonnet cross-reviews (author: Opus) checked two rounds. Round 1 confirmed the content and blocked only on #1721 merging. Round 2 checked the rebase.

  • Plan coverage: every row of the plan is reverted and nothing on the keep list is. toolkit/dpkt.py is byte-identical to round 1's, and its diff from 6c17c7e1b^ shows only the kept hunks plus the guards.
  • Guards: removing each one makes its test fail.
  • Rebase: nothing from refactor(toolkit): revert pypcapfile's agreement-only code (#1708) #1721 is undone. Main's pypcapfile sentences are kept and dpkt's are appended. VLAN_TAGS, VLAN_TAG_LEN and _Agreement have no readers left.
  • Prose against behaviour: crafted frames confirm each new sentence, with warnings turned into errors:
    • TCP in IP-in-IP or behind headers carried in IPv4 is dropped silently;
    • 4in6 and 6in4 give no IP input;
    • TCP is read past 40 extension headers and 70 nested tunnels, so dpkt applies neither bound.
  • Sphinx: 63 warnings, the same set as main.
  • For you: the fix(toolkit): dpkt ends the extraction with ProtocolError on 802.1Q then 802.1ad, two 802.1ad, or three VLAN tags #1646 choice in the description.

@JarryShaw JarryShaw moved this to In review in PyPCAPKit Oct 14, 2026
@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Coverage: 89.55% (unit tier, Python 3.15, e79bd2659, Unit Tests run success)

Package Statements Missed Branches Partial Cover
pcapkit (top level) 104 3 20 3 95.16%
pcapkit/const 18860 954 2368 868 91.06%
pcapkit/corekit 2384 67 764 35 96.51%
pcapkit/dumpkit 275 3 100 3 98.40%
pcapkit/foundation 2884 144 1010 34 94.20%
pcapkit/interface 138 7 52 5 93.68%
pcapkit/protocols 17174 226 4590 191 98.07%
pcapkit/toolkit 865 198 298 6 74.38%
pcapkit/utilities 508 4 154 4 98.79%
pcapkit/vendor 4417 2342 1010 157 43.38%

Per-file detail: the coverage-html artifact of this run.

@JarryShaw

Copy link
Copy Markdown
Owner Author

Resolve conflicts.

@JarryShaw

Copy link
Copy Markdown
Owner Author

Rebasing onto main now, after #1723 and #1724. The conflicts are in five docs files and two shared tests, where #1724 and this PR rewrote the same engine sentences and ENGINES lists. A Sonnet check runs on the result before I push it.

@JarryShaw

Copy link
Copy Markdown
Owner Author

And what exactly is re-serialising? I cannot make the decision without knowing the exact difference there.

@JarryShaw

Copy link
Copy Markdown
Owner Author

On an 802.1Q-then-802.1ad frame (the #1646 shape), dpkt's own header lengths put the IPv4 header at the wrong offset in the captured octets. The adapter then cannot slice that layer from the capture. "Re-serialising" means handing over bytes(copy(layer)) instead: dpkt packs back the fields it parsed (packet2bytes, toolkit/dpkt.py:258).

I measured the difference on the PR head (3ab380768) with hand-built frames, comparing the captured IPv4 octets with what is handed over:

Frame Handed over vs captured
Checksums set, no trailer identical
IPv4 Total Length 0 (TSO) identical (dpkt does not fill in the length)
Ethernet padding after the datagram the padding is dropped; the captured path trims it by Total Length anyway, so the datagram is the same
IPv4 or TCP checksum 0 differs: dpkt computes and fills in the checksum (0000 becomes 66c8 and 32d0), and everything else is identical

So the only observable change is a zero checksum arriving filled in. The other option, returning None, drops the whole frame from IP reassembly, TCP reassembly and flow tracing. I recommend re-serialising, because it keeps the data and changes only checksums that were zero.

@JarryShaw

Copy link
Copy Markdown
Owner Author

okay, go with re-serialising

@JarryShaw

Copy link
Copy Markdown
Owner Author

Recorded: re-serialising stays, which is what this PR already does. A layer that dpkt's own lengths misplace is handed over as dpkt's packing of it, and a zero checksum arrives filled in. The rebase onto main is in progress, and its Sonnet check follows before the push.

@JarryShaw

Copy link
Copy Markdown
Owner Author

resolve conflicts

@JarryShaw

Copy link
Copy Markdown
Owner Author

Conflicts are resolved locally: rebased onto fb7027b25 as 6418bdb14. Its narrow tests and the Sonnet check on the result are running now, and I push once the check comes back. #1728, which merged just now, does not touch this branch's files.

Third-party engines are best effort (#1687), so the dpkt code that exists
only to match the default engine comes out:

- revert #1662, #1655, #1624, #1622, #1614 and the dpkt hunks of #1605:
  the octet walk and its link-type stash, IPv6 in IPv4 and IPv4 in IPv6,
  refusing MPLS and ISL, the tunnel and extension-header walks, the IPv4
  header checks and the layer bounds
- keep #1690's timestamps, #1594's parser choice, #1621 and #1653
- re-land as guards: a layer dpkt's own lengths misplace (#1646) is
  re-serialised, not refused with ProtocolError; a Total Length below the
  IHL keeps the header whole (#1616), and a header the capture cuts is no
  input; packet2dict and packet2chain take a str payload and a raw frame
- delete the modules #1662 and #1655 added; the 1615/1616 module keeps
  only what its #1616 tests use, as no scapy test imports it now; dpkt's
  comparisons with the default engine assert constants or the capture's
  octets, or are dropped
- drop pypcapfile's VLAN_TAGS, VLAN_TAG_LEN and IPV6_EXTENSION_HEADERS,
  which only dpkt imported, and the 1668 module's _Agreement base, which
  nothing subclasses now
- the docs drop the depth claims and name what dpkt leaves out silently

The dpkt modules, the shared modules that run dpkt, tests/foundation/engines
and the project guards pass on 3.14 and 3.11 (dpkt 1.9.8, pypcapfile 0.12.0).
@JarryShaw JarryShaw removed the review: good-to-go Cross-review at the current head says ready; CI state is separate label Oct 14, 2026
@JarryShaw
JarryShaw force-pushed the refactor/1708-dpkt-revert-agreement branch from 3ab3807 to e79bd26 Compare October 14, 2026 16:34
@JarryShaw JarryShaw added the review: running A cross-review is in flight against the current head - no verdict yet label Oct 14, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Pushed: rebased onto 59dd2613d as e79bd2659, and conflict-free with main.

The Sonnet check on this head is still running, so the label reads review: running until it lands.

@JarryShaw JarryShaw added review: good-to-go Cross-review at the current head says ready; CI state is separate and removed review: running A cross-review is in flight against the current head - no verdict yet labels Oct 14, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Verdict: GOOD TO GO at e79bd2659. A Sonnet cross-review checked the rebase (author: Opus).

  • Unchanged parts: the patch bodies of the 10 files main did not touch are byte-identical to 3ab380768, including toolkit/dpkt.py and engines/dpkt.py.
  • Earlier merges intact: fix(protocols): reject an IPv6 header whose Version is not 6 (#1680) #1723 and refactor(toolkit): revert scapy's agreement-only code (#1708) #1724 are not undone. toolkit/scapy.py and the IPv6 Version check are as main has them.
  • Resolved sentences: each one is true of main's scapy and pypcapfile adapters and of this dpkt adapter. A 14-frame probe on 3.11 confirms the dpkt wording.
  • The two forced cleanups are correct: pypcapfile's IPV6_EXTENSION_HEADERS has no importer left, and the trimmed 1615/1616 helpers had none either.
  • Tests and Sphinx: tests pass on 3.14 and 3.11, and Sphinx gives 63 warnings, the same as main.

@JarryShaw
JarryShaw merged commit e0acacc into main Oct 14, 2026
54 checks passed
@github-project-automation github-project-automation Bot moved this from In review to Done in PyPCAPKit Oct 14, 2026
@JarryShaw
JarryShaw deleted the refactor/1708-dpkt-revert-agreement branch October 14, 2026 17:25
@JarryShaw JarryShaw removed the review: good-to-go Cross-review at the current head says ready; CI state is separate label Oct 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactor Restructuring for its own sake — neither a fix nor a new capability (refactor: prefix)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant