Skip to content

feat(protocols)!: verify and compute one's-complement checksums (#2470) - #2543

Merged
JarryShaw merged 10 commits into
mainfrom
feat/2470-checksum-wave
Nov 1, 2026
Merged

JarryShaw merged 10 commits into
mainfrom
feat/2470-checksum-wave

Conversation

@JarryShaw

Copy link
Copy Markdown
Owner

What is the purpose of your pull request?

  • 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
  • const — regenerates constant or registry tables, members keeping their numeric values

Description of your pull request and other information

Closes #2470, #2472, #2473, #2474, #2475 and #2513.

  • PCAPKIT_CHECKSUM_VERIFY (off) and PCAPKIT_CHECKSUM_COMPUTE (on), overridable per call. Each protocol records a ChecksumStatus, shaped like ESP's status, and warns on a mismatch. The pseudo-header comes from IP_Pseudo.
  • IPv4 header, TCP, UDP, ICMP/ICMPv6 and OSPFv2 checksums, each in its own commit. A fragment records NO_PSEUDO_HEADER without warning. The four offload shapes record NOT_COMPUTED, as documented in pep.rst.
  • Breaking: make() now computes checksums by default, so constructed bytes change.
  • fix(misc): IP_Pseudo misses a malformed IPv6 extension header past the first one #2513: IP_Pseudo detects an unparsed Destination Options or Routing header at any depth.
  • Follows: the owner's ruling 3 on ICMP/ICMPv6 checksum verification (deferred from #2446) #2470, a dedicated ChecksumWarning(ProtocolWarning), lands as a commit here.

Shared pieces of the one's-complement checksum work (#2470, #2472-#2475):

- utilities.config: CHECKSUM_VERIFY (PCAPKIT_CHECKSUM_VERIFY, off) and
  CHECKSUM_COMPUTE (PCAPKIT_CHECKSUM_COMPUTE, on), read with read_flag
- protocols.misc.checksum.checksum: ChecksumStatus, the RFC 1071 sum, and
  helpers to compute and verify a checksum over an optional pseudo-header;
  a payload being rebuilt does not warn a second time
- IPv4 and IPv6 verify their upper layer's pseudo-header checksum once
  parsed, and compute it for a payload whose make() left it pending,
  unless the IPv4 packet is a fragment
- docs: the flags on the config page, the module on the checksum page,
  and the rulings in pep.rst
- IPv4.read verifies the header checksum (RFC 791 section 3.1) under
  CHECKSUM_VERIFY and records checksum_status; a wrong one warns, a zero
  one (header checksum offload) is NOT_COMPUTED
- IPv4.make takes checksum=None by default and computes it over the header
  under CHECKSUM_COMPUTE; a given checksum is written as given, so a
  from_data rebuild stays byte-exact
- the enclosing IPv4 or IPv6 layer verifies the checksum over its
  pseudo-header (RFC 793 section 3.1) under CHECKSUM_VERIFY, recording
  checksum_status on the segment; a zero one or the pseudo-header's sum
  alone (checksum offload) is NOT_COMPUTED
- TCP.make takes checksum=None by default and a pseudo keyword; it computes
  the checksum over pseudo, or leaves it to the IP layer the segment is
  the payload of, under CHECKSUM_COMPUTE
- the enclosing IPv4 or IPv6 layer verifies the checksum over its
  pseudo-header and the datagram the Length field gives (RFC 768) under
  CHECKSUM_VERIFY; a zero one is NOT_COMPUTED over IPv4 but INVALID over
  IPv6 (RFC 8200 section 8.1), and the pseudo-header's sum alone (checksum
  offload) is NOT_COMPUTED
- UDP.make takes checksum=None by default and a pseudo keyword, computing
  the checksum as TCP.make does; a computed zero is sent as all ones
- OSPF.read verifies the OSPFv2 checksum over the packet but its
  Authentication field (RFC 2328 appendix A.3.1) under CHECKSUM_VERIFY and
  records checksum_status; under cryptographic authentication, where the
  field is unused (appendix D.4.3), it is NOT_COMPUTED
- OSPF.make takes checksum=None by default and computes it the same way
  under CHECKSUM_COMPUTE, leaving it zero under cryptographic
  authentication; other versions are neither verified nor computed
)

- ICMPv4.read verifies the checksum over the message (RFC 792) under
  CHECKSUM_VERIFY and records checksum_status; ICMPv4.make computes one it
  is not given under CHECKSUM_COMPUTE
- the enclosing IPv6 layer verifies the ICMPv6 checksum over its
  pseudo-header (RFC 4443 section 2.3), past any extension headers
- ICMPv6.make takes a pseudo keyword and computes the checksum as TCP.make
  does, or leaves it to the IPv6 layer the message is the payload of
- the data models no longer say the checksum is never verified
- ICMPv4 verified a first IPv4 fragment over the fragment alone and recorded
  INVALID with a ProtocolWarning; IPv4 and IPv6 now parse a fragment's payload
  under checksum.fragment_payload(), and ICMPv4 records NO_PSEUDO_HEADER there,
  as TCP, UDP and ICMPv6 do.
- ChecksumStatus.NO_PSEUDO_HEADER's doc names the paths that produce it, and
  no longer an upper layer behind ESP.
- tests/project RFC-constant sweep: list OSPF's Authentication offset 16 and
  the RFC 1071 word mask and carry shift as unrelated values.
- Drop counted and stale wording from the checksum docs, and a Sphinx role
  from a plain comment in ospf.py; pep.rst records the fragment ruling.
…eudo (#2513)

- IP_Pseudo._source and _destination tested only the header after the fixed
  one for the Destination Options or Routing header the walk stopped on, so
  one past a valid header lost its Home Address or final destination with no
  error. Both now ask the new _walk, which _upper shares, where the walk
  stopped, at any depth.
- _upper raises one error for an unparsed header, naming the protocol and
  upper_length it needs, instead of "give src" or "give dst".
- Tests cover a malformed header past the first one, _upper with src or dst
  given, and the header-limit case, whose 33rd header now raises from _source.
@JarryShaw JarryShaw added feat Pull requests that add a new capability (feat: subject prefix) breaking Breaks public-facing behaviour or API (apply alongside the type label) review: good-to-go Cross-review at the current head says ready; CI state is separate labels Nov 1, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Cross-review (Sonnet) at 74595a754: GOOD TO GO.

  • The RFC-constant exceptions are genuine: OSPF's Authentication offset, and the RFC 1071 mask and shift.
  • tests/project passes in both halves.
  • On independently built packets, ICMPv4 in an IPv4 or IPv6 first fragment, and behind AH, records NO_PSEUDO_HEADER with no warning, matching TCP/UDP/ICMPv6. A reassembled datagram verifies VALID.
  • fix(misc): IP_Pseudo misses a malformed IPv6 extension header past the first one #2513's detection works at any depth, and its tests fail before the fix.

The ChecksumWarning commit resets this verdict when it lands.

- verify_checksum warned with ProtocolWarning, so a filter could not silence
  mismatches without silencing every protocol warning. It now warns with
  ChecksumWarning, a ProtocolWarning subclass, so the IPv4 header, TCP, UDP,
  ICMP, ICMPv6 and OSPFv2 mismatches can be filtered on their own, and
  existing ProtocolWarning filters still match them.
- ChecksumWarning is exported from pcapkit.utilities.warnings and documented
  beside ProtocolWarning; pep.rst, the checksum docs and CHECKSUM_VERIFY name it.
- Tests re-pin each protocol's mismatch to ChecksumWarning and pin the
  subclass and the filters: ignoring ChecksumWarning keeps other
  ProtocolWarnings, and a ProtocolWarning filter still catches a mismatch.
- pep.rst named only #2471 and implementation as where the one's-complement
  rulings were settled; it now also cites the owner's acceptance of the two
  global flags and the offload heuristic on #2470.
@github-actions

github-actions Bot commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Coverage: 93.98% (unit tier, Python 3.15, 2da6786db, Unit Tests run success)

Package Statements Missed Branches Partial Cover
pcapkit (top level) 104 4 20 2 95.16%
pcapkit/const 20087 144 2710 125 98.78%
pcapkit/corekit 2605 74 818 37 96.52%
pcapkit/dumpkit 281 3 100 3 98.43%
pcapkit/foundation 3194 27 1112 31 98.65%
pcapkit/interface 138 4 52 3 96.32%
pcapkit/protocols 20085 209 5288 202 98.37%
pcapkit/toolkit 924 36 334 10 95.55%
pcapkit/utilities 505 7 144 5 98.15%
pcapkit/vendor 5009 2222 1148 182 52.31%

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

@JarryShaw

Copy link
Copy Markdown
Owner Author

Pushed 2da6786db, two commits on the reviewed head. They apply ruling 3 on #2470: ChecksumWarning(ProtocolWarning) is raised through verify_checksum, the single site the six protocols share, and pep.rst now cites the #2470 rulings. Cross-review (Sonnet) of the pair: GOOD TO GO.

  • Tests: two mutations (reverting the category, dropping the subclass) each turn the tests red.
  • Filters: ignore on ProtocolWarning still silences mismatches. ignore on ChecksumWarning silences only them.
  • Non-blocking: under an error filter, an ICMPv4 or OSPF mismatch reached as a next layer is absorbed by beholder into Raw(error=...). It behaved the same before this pair.

@JarryShaw
JarryShaw merged commit 47fac07 into main Nov 1, 2026
61 checks passed
@github-project-automation github-project-automation Bot moved this from In review to Done in PyPCAPKit Nov 1, 2026
@JarryShaw JarryShaw removed the review: good-to-go Cross-review at the current head says ready; CI state is separate label Nov 1, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

protocols.misc.checksum.checksum should go to foundation or corekit. And its module name should be clear that it's for internet protocols specifically, not a generic checksum name.

@JarryShaw

Copy link
Copy Markdown
Owner Author

Paraphrased: the checksum helpers leave protocols.misc for foundation or corekit, under a name that says Internet checksum. That is filed as #2580, with a recommendation: split, putting the protocol-independent part in pcapkit.corekit.internet_checksum. foundation would make protocol read code import foundation, which #2528 removed. The IP pseudo-header pieces stay beside IP_Pseudo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking Breaks public-facing behaviour or API (apply alongside the type label) feat Pull requests that add a new capability (feat: subject prefix)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

ICMP/ICMPv6 checksum verification (deferred from #2446)

1 participant