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.

JarryShaw added a commit that referenced this pull request Nov 1, 2026
- Added: one's-complement checksum verification and computation (#2543),
  and the IPX and SCTP registration wrappers (#2521).
- Folded into unreleased entries: LinuxSLL/FRAD/Netlink registries (#2527),
  the IGMP class names (#2542), TLS record chaining and the SSLv2 trial's
  warnings (#2537), DTLS reassembly via Extractor and toolkit (#2528), and
  IP_Pseudo's walk at any depth (#2543). ICMP drops its stale checksum line.
- Breaking: make() checksums, DRARP's module (#2540), IPv6 overlapping
  fragments (#2569), TCP_GAP_LIMIT replacing TCP.__window__ (#2579), and
  Extractor/extract's positional dtls (#2528).
- Changed: member order (#2490), conventions (#2542, #2521, #2570), CI -n
  logical (#2572). Fixed: AppType.get (#2568), trial warnings (#2519, #2577).
- CHANGELOG.md regenerated; util/changelog_md.py --check passes.
@github-actions github-actions Bot added this to the PyPCAPKit v1.6 milestone Nov 2, 2026
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