Skip to content

fix(protocols): reject a jumbogram RFC 2675 calls an error (#1687) - #1713

Merged
JarryShaw merged 1 commit into
mainfrom
fix/1687-jumbo-payload-rfc2675
Oct 14, 2026
Merged

JarryShaw merged 1 commit into
mainfrom
fix/1687-jumbo-payload-rfc2675

Conversation

@JarryShaw

@JarryShaw JarryShaw commented Oct 14, 2026 •

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

RFC 2675 §3 lists four errors a receiver must detect: Payload Length 0 with a Hop-by-Hop header and no Jumbo Payload option; a non-zero Payload Length with the option; a Jumbo Payload Length below 65,536; the option with a Fragment header. IPv6.read now raises ProtocolError for each, as IPv4.read rejects a bad version, so behind a link layer the frame stops at IPv6 and rebuilds byte for byte. jumbogram_error() in schema/internet/ipv6.py defines all four. A capture cut before the Jumbo Payload option is rejected too (the first error), as the RFC has it. A capture cut after the option but short of its Jumbo Payload Length is still read as a jumbogram.

This changes the default engine only. The dpkt, scapy, pyshark and pypcapfile adapters are untouched; they are best effort and need not match.

IPv6.make with payload_length unset now writes 0 when the payload's leading Hop-by-Hop header carries a Jumbo Payload option, so a genuine Jumbo Payload Length builds a jumbogram, and make->parse round-trips byte for byte. Input the caller made invalid still raises on construction: a Jumbo Payload Length ≤ 65,535, an explicit non-zero payload_length, or a Fragment header. HOPOPT alone and in IPv4 is unchanged.

examples/generators/options.py built HOPOPT's Jumbo Payload frame in options-ipv6.pcap with Jumbo Payload Length 0 behind a non-zero Payload Length, now rejected, so the frame stopped at IPv6. It is now a genuine jumbogram: Payload Length 0, Jumbo Payload Length 65,536, filled out by a UDP datagram with a valid checksum, in a capture whose snaplen (262,144) lets libpcap readers take the 65,590-octet frame whole. The scapy engine reads only its first 65,535 octets (scapy's MTU, in PcapReader.recv); third-party engines are best effort.

Tests: a new class in test_ipv6_jumbogram_unit.py, tests/toolkit/test_pcap_jumbogram_rfc2675_1687_unit.py (default-engine extraction inputs) and tests/protocols/test_option_generator_jumbogram_1687_unit.py (the generator's jumbogram); all fail on origin/main. test_option_coverage_runtime.py checks the capture's jumbogram is read whole. Adapter tests drop the rows that compared an adapter with the default engine on a now-invalid jumbogram (#1708 cleans those files up). Only the related suites were run, on 3.14.8 and 3.11.15, not the whole suite.

Closes #1687

@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 14, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Verdict: GOOD TO GO at 191460715. A Sonnet cross-review covered two rounds.

@JarryShaw

Copy link
Copy Markdown
Owner Author

CI is red on 191460715, and the cause is a real test failure. The Integration legs (3.11–3.15) and the PyPCAP/PyPCAPFile parity leg fail one subtest:

  • tests/protocols/test_option_coverage_runtime.py, capture options-ipv6.pcap, frame 12: expected a Ethernet:IPv6 envelope, got Ethernet:Internet_Protocol_version_6.
  • examples/generators/options.py:1593 puts the Jumbo Payload option in an IPv6 envelope with a non-zero Payload Length. That is RFC 2675's second error, so this PR now rejects the frame. The narrow runs in both rounds missed this runtime-tier test.

Round 3 fixes the generator or the test, keeping coverage of the Jumbo option, and re-runs every test that reads these captures. The verdict resets on the new head.

@JarryShaw JarryShaw added review: needs-changes Cross-review at the current head says changes are required; see the verdict comment and removed review: good-to-go Cross-review at the current head says ready; CI state is separate labels Oct 14, 2026
@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Coverage: 89.47% (unit tier, Python 3.15, f927e8df7, 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 2372 67 762 35 96.49%
pcapkit/dumpkit 275 3 100 3 98.40%
pcapkit/foundation 3035 151 1076 34 94.28%
pcapkit/interface 138 7 52 5 93.68%
pcapkit/protocols 17181 226 4590 190 98.07%
pcapkit/toolkit 1437 281 592 6 77.97%
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 force-pushed the fix/1687-jumbo-payload-rfc2675 branch from 1914607 to a4cf408 Compare October 14, 2026 04:21
@JarryShaw JarryShaw added review: good-to-go Cross-review at the current head says ready; CI state is separate and removed review: needs-changes Cross-review at the current head says changes are required; see the verdict comment labels Oct 14, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Verdict: GOOD TO GO at a4cf408ff. A Sonnet cross-review checked round 3, which fixes the red Integration and parity legs.

  • The fix: examples/generators/options.py now emits the HOPOPT Jumbo Payload frame of options-ipv6.pcap as a genuine jumbogram: Payload Length 0, Jumbo Payload Length 65,536 carried in full, and a UDP datagram whose RFC 1071 checksum the reviewer recomputed independently.
  • Snaplen: the capture's snaplen is 262,144, so readers don't cut the 65,590-octet frame. The other four option captures are byte-identical.
  • The failing test: test_option_coverage_runtime.py fails at 191460715 and passes here on 3.14 and 3.11. Every test reading the option captures passes: 27 tests, 31,961 subtests.
  • Known limit: the scapy engine delivers only the first 65,535 octets of that frame; that is filed separately.

@JarryShaw

Copy link
Copy Markdown
Owner Author

CI is red on a4cf408ff, from a real failure. On the unit legs (3.11–3.15), the new tests/protocols/test_option_generator_jumbogram_1687_unit.py fails 4 tests with ModuleNotFoundError: No module named 'scapy'. _jumbogram_datagram (examples/generators/options.py:1933) imports scapy.utils.checksum, and the unit tier installs no scapy. The local runs had scapy, so they missed it. Round 4 computes the RFC 1071 checksum without scapy, so the test keeps running on the unit tier. The verdict resets on the new head.

@JarryShaw JarryShaw added review: needs-changes Cross-review at the current head says changes are required; see the verdict comment and removed review: good-to-go Cross-review at the current head says ready; CI state is separate labels Oct 14, 2026
RFC 2675 section 3 lists four errors a receiver must detect. The default
engine dissected each as a jumbogram, or warned and went on.

- schema/internet/ipv6.py: jumbogram_error() names the error, if any: a
  Payload Length of 0 with a Hop-by-Hop header and no Jumbo Payload option;
  a non-zero Payload Length with the option; a Jumbo Payload Length below
  65,536; the option with a Fragment header (asked of the caller's walk).
- IPv6.read raises ProtocolError for the first three, and the extension
  header walk for the fourth, as IPv4.read rejects a bad version, so behind
  a link layer the frame stops at IPv6 and rebuilds as captured.
- IPv6.make with no payload_length writes 0 when the payload's leading
  Hop-by-Hop header carries a Jumbo Payload option, so a genuine Jumbo
  Payload Length builds a jumbogram the parser accepts.
- examples/generators/options.py: HOPOPT's Jumbo Payload frame, one of those
  errors, is a genuine jumbogram, Jumbo Payload Length 65,536 filled out by a
  UDP datagram whose RFC 1071 checksum it sums without scapy, in a capture
  whose snaplen does not cut it.
- tests: each error on IPv6, behind Ethernet and at extraction; make->parse
  of a jumbogram; the generator's jumbogram, its datagram built with scapy
  blocked; adapter-test rows on now-invalid jumbograms dropped.
@JarryShaw JarryShaw removed the review: needs-changes Cross-review at the current head says changes are required; see the verdict comment label Oct 14, 2026
@JarryShaw
JarryShaw force-pushed the fix/1687-jumbo-payload-rfc2675 branch from a4cf408 to f927e8d Compare October 14, 2026 05:11
@JarryShaw JarryShaw added the review: good-to-go Cross-review at the current head says ready; CI state is separate label Oct 14, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Verdict: GOOD TO GO at f927e8df7. A Sonnet cross-review checked round 4.

  • The fix: _jumbogram_datagram now computes the UDP checksum with a pure-Python RFC 1071 sum over the IPv6 pseudo-header (RFC 8200 §8.1). It equals scapy.utils.checksum on 46 datagram sizes, and the receiver sum comes to 0xFFFF.
  • Captures unchanged: options-ipv6.pcap is byte-identical to round 3's.
  • The failing tests: they failed on a4cf408ff in a venv without scapy and pass here.
  • New test: test_the_datagram_needs_no_scapy blocks every scapy module, so the unit test cannot regress even where scapy is installed.

@JarryShaw
JarryShaw merged commit 0b9c508 into main Oct 14, 2026
50 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 fix/1687-jumbo-payload-rfc2675 branch October 14, 2026 13:06
@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 added this to the PyPCAPKit v1.5 milestone Oct 26, 2026
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(protocols): the default engine accepts an IPv6 Jumbo Payload option of 65535 octets or less, against RFC 2675

1 participant