Skip to content

fix(toolkit): pypcapfile reads IP over loopback and raw-IP link types, up to the frame layer bound (#1609, #1667) - #1682

Merged
JarryShaw merged 2 commits into
mainfrom
fix/1609-1667-pypcapfile-linktypes-and-layer-bound
Oct 13, 2026
Merged

JarryShaw merged 2 commits into
mainfrom
fix/1609-1667-pypcapfile-linktypes-and-layer-bound

Conversation

@JarryShaw

Copy link
Copy Markdown
Owner

Please follow the guide below

  • You will be asked some questions, please read them carefully and answer honestly

  • Put an x into all the boxes [ ] relevant to your pull request (like that [x])

  • Use Preview tab to see how your pull request will actually look like

  • Searched for similar pull requests

  • Followed the coding style (make pylint, make mypy, make isort)

  • make test passes, and a test case covers the change — tests cover it; only the toolkit, engine and pypcapfile-related selections were run, not the whole suite

  • Added a changelog entry under docs/source/changelog/ and regenerated CHANGELOG.md, if the change is user-visible — N/A — centralised in docs(changelog): shared 1.5.0 changelog — long-lived, merges last (#610, #616, #617, #618, #620) #657

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

The pypcapfile adapters now read what the default engine reads:

Cells as in the issues (3.11) default pypcapfile before pypcapfile after
#1667: NULL, LOOP, RAW 1/1 · 1/1 · 2,0 · 0,2 · 1/1 · 2 0/0 · 0/0 · 0,0 · 0,0 · 0/0 · 0 1/1 · 0/0 · 2,0 · 0,0 · 1/1 · 2
#1667: IPV4 1/1 · – · 2,0 · – · – · – 0/0 · – · 0,0 · – · – · – 1/1 · – · 2,0 · – · – · –
#1667: IPV6 – · 1/1 · – · 0,2 · 1/1 · 2 – · 0/0 · – · 0,0 · 0/0 · 0 – · 0/0 · – · 0,0 · 1/1 · 2
#1609: TCP in 63 IPv4, behind 62 tags or 32 (IPv4, AH) pairs; 4in6 TCP at layer 65 0/0 1/1 0/0
#1609: two IPv4 fragments in 63 IPv6 0 2 0

I measured 154 captures (the issue rows, the #1609 depth rows on Ethernet and on the new link types, controls, and the sample corpus) with every engine on 3.11.15 and default, dpkt and scapy on 3.14.8, on 4673cffa9. The branch is rebased onto 2025da5e5; 257580444 and 2025da5e5 touch the Conda workflow and its release-gate test, the version, and HIP/MH constant enumerations only, and were not re-measured. 94 pypcapfile cells changed, and no cell of any other engine did. pypcapfile now matches default field for field on every PCAP capture, and its TCP-over-IPv6 warning fires exactly where default finds TCP over IPv6. The six PCAP-NG refusals are unchanged, by design.

Two new test files, plus one engine test, which also checks PPP, 105 and 147 still warn. All 10 new test methods fail on main (the agreement module's two inherited RoundTripBase table checks pass anywhere) and pass with the fix, on 3.11 and on 3.14, where the real-engine comparison is skipped. Under the pypcapfile tests on 3.14, coverage of pcapkit/toolkit/pypcapfile.py goes from 98.93% to 100.00%.

Closes #1667
Part of #1609

…, up to the frame layer bound (#1609, #1667)

- pypcapfile decodes Ethernet only, so the adapters handed no TCP, trace
  or IPv4 input over on NULL, LOOP, RAW, IPV4 and IPV6. They now read the
  IP packet there themselves (READ_LINKTYPES): the loopback family by
  Loopback's table and family_byteorder, RAW by its version nibble.
  TCP over IPv6 stays declined with the per-capture warning; 12 and
  LINUX_SLL stay unread, and only those still get the engine's
  "unrecognised link layer protocol" warning.
- The VLAN, tunnel and extension-header walks ran past FRAME_LAYER_LIMIT.
  Each VLAN tag, IP header, AH and IPv6 extension header now counts one
  layer, as in the default engine, and nothing past layer 64 is read or
  warned of. _upper_layer, which pyshark imports, is unchanged.
- packet2dict reported an unread frame's hex text (raw_len 94 for 47
  octets); it now reports the octets.

New tests fail on main and pass here on 3.11 and 3.14.

Closes #1667
Part of #1609
… frame layer bound (#1609, #1667)

- protocol.rst listed pypcapfile with pyshark as not applying
  FRAME_LAYER_LIMIT. It now stands with dpkt and scapy; pyshark's
  sentence is otherwise unchanged.
- The toolkit note names the link types the adapters read and the
  layer bound, and documents READ_LINKTYPES. The engine note says the
  toolkit reads the IP packet of loopback and raw-IP frames.
- The previous commit's message says 12 and LINUX_SLL are the only
  link types still warned of. Every link type but Ethernet and the
  five READ_LINKTYPES still is; the engine test now checks PPP (9),
  105 and 147 as well.

The pypcapfile tests pass on 3.11 and the touched tests on 3.14; the
engine test still fails on main on both.

Closes #1667
Part of #1609
@JarryShaw JarryShaw added fix Pull requests that fix a defect (fix: subject prefix) review: good-to-go Cross-review at the current head says ready; CI state is separate labels Oct 13, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Verdict: GOOD TO GO at 53f1c1564. This passed a Sonnet cross-review on round 2; round 1 had come back NEEDS CHANGES for prose only. I re-ran the new link-type and layer-bound test, the engine test and the 1604 agreement test on 3.11 with pypcapfile 0.12.0, and they pass.

What it does. The pypcapfile adapters now read the IP packet on NULL, LOOP, RAW, IPV4 and IPV6 link types (#1667). They read it with pypcapfile's own IP(data, 0), choosing the family by Loopback's table and family_byteorder. They also stop at the 64-layer frame bound, counting each tag, IP header, AH and extension header as the default engine does. That is pypcapfile's part of #1609.

What the reviewer measured. 481 of its own captures: 307 disagreements with the default engine on main, 3 on the branch, none caused by this PR. Two were the default-engine crash that #1675 has since fixed.

Round 2. protocol.rst now groups pypcapfile with dpkt and scapy as stopping at the bound. 3rdparty.rst documents the five link types, with an autodata entry for READ_LINKTYPES. The body now says correctly that every other link type still warns.

Left as you may want them: these five link types now give no engine warning, and an undecodable IPv4 packet on them does not warn either.

@github-actions

Copy link
Copy Markdown
Contributor

Coverage: 89.48% (unit tier, Python 3.14, 53f1c1564, Unit Tests run success)

Package Statements Missed Branches Partial Cover
pcapkit (top level) 104 3 20 3 95.16%
pcapkit/const 18858 954 2366 868 91.06%
pcapkit/corekit 2366 67 760 35 96.48%
pcapkit/dumpkit 275 3 100 3 98.40%
pcapkit/foundation 3033 152 1076 35 94.23%
pcapkit/interface 138 7 52 5 93.68%
pcapkit/protocols 17166 226 4580 190 98.07%
pcapkit/toolkit 1407 271 578 5 78.34%
pcapkit/utilities 494 4 146 4 98.75%
pcapkit/vendor 4417 2342 1010 157 43.38%

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

@JarryShaw
JarryShaw merged commit cd90688 into main Oct 13, 2026
50 checks passed
@github-project-automation github-project-automation Bot moved this from In review to Done in PyPCAPKit Oct 13, 2026
@JarryShaw
JarryShaw deleted the fix/1609-1667-pypcapfile-linktypes-and-layer-bound branch October 13, 2026 21:53
@JarryShaw JarryShaw removed the review: good-to-go Cross-review at the current head says ready; CI state is separate label Oct 13, 2026
JarryShaw added a commit that referenced this pull request Oct 14, 2026
…1721)

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

- revert #1682, #1600, #1575 and #1535, and the pypcapfile hunks of #1655,
  #1608 and #1605: reading loopback and raw-IP link types, the frame layer
  bound, the VLAN and tunnel walks, keying tunnelled TCP by the innermost
  header, stepping over AH and extension headers, and checking options
  with the default engine's parsers
- keep the helpers the dpkt and scapy adapters import, unchanged, until
  their own reverts drop them; their docstrings no longer say pypcapfile
  asks the default engine's parsers too
- re-land #1576, #1577, #1590 and #1591 as guards in _network and
  _transport, #1513's once-per-capture warning for TCP straight over
  IPv6, and #1667's packet2dict fix: an undecoded frame is reported as
  its octets, not as hex text twice as long
- keep #1569's record reader and #1690's packet2timestamp
- delete the three test modules those reverts added, the pypcapfile
  timestamp agreement class, and #1682's link-type warning test; the
  re-landed guards' tests assert constants
- drop what the reverts removed from the docs, READ_LINKTYPES included,
  and say that TCP behind a VLAN tag, in a tunnel or behind an
  extension header (an IPv6 one, or AH in IPv4) is now left out
  without a warning

The pypcapfile modules, test_new_engine_parity_runtime.py,
test_engine_runtime.py, the timestamp module and the project guards pass
on 3.11 (pypcapfile 0.12.0) and 3.14.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

fix(toolkit): the pypcapfile engine hands no TCP or IPv4 input over on the NULL, LOOP, RAW, IPV4 and IPV6 link types

1 participant