Skip to content

ICMP: embedded_chain, and document when lax=True is the right default - #132

Merged
EONRaider merged 1 commit into
masterfrom
claude/decoder-depth-polish-8m54to
Sep 4, 2026
Merged

ICMP: embedded_chain, and document when lax=True is the right default#132
EONRaider merged 1 commit into
masterfrom
claude/decoder-depth-polish-8m54to

Conversation

@EONRaider

Copy link
Copy Markdown
Owner

Summary

Closes#92. decode_frame(lax=True, start=IPv4) already solved this issue's core problem with zero new code — verified before writing anything: an RFC-792 ICMP error message quotes only the invoking IP header plus 8 bytes of what follows, never a full TCP/UDP header, so decoding it needs the lax path, not a try/except. Of the issue's four acceptance criteria, three were already true on master; the fourth — the distinction is documented, so nobody reaches for lax by default — is the actual work here, plus a small pre-wired convenience accessor.

What's included

  • ICMPv4/ICMPv6 (via the shared _ICMP base) gain embedded_chain: decode_frame(icmp.embedded_packet, lax=True, start=IPv4-or-IPv6), next to the existing raw embedded_packet — same shape as this codebase's other accessor-plus-typed-view pairs. None for the same cases embedded_packet degrades to (non-error message types, an empty body).
  • icmp.py now imports IPv4/IPv6 (from layer3.ip) and decode_frame (from walk) at module level. Verified no import cycle before committing to that (rather than deferring, per with_checksums()'s pattern): neither ip.py nor walk.py imports icmp.py, directly or transitively — checked via python -c "import netprotocols" and two isolated import paths (from netprotocols.layer3.icmp import ..., from netprotocols.layer3 import icmp).
  • The module docstring and a new README section explain the actual distinction: embedded_chain's lax=True is the right default here only because the truncation is RFC-mandated, expected input — not a general license to reach for lax=True on a complete frame that fails to decode, which is still a bug to raise on.
  • tests/test_icmp.py: embedded_chain decodes a truncated embedded packet cleanly with stopped_by set (ICMPv4 → IPv4, ICMPv6 → IPv6); returns None for non-error types and an empty body, mirroring embedded_packet's existing tests.
  • CHANGELOG.md entry under ## [Unreleased].

Verification

  • uv run --frozen ruff check . and uv run --frozen ruff format --check . are clean
  • uv run --frozen mypy is clean (strict)
  • uv run --frozen pytest passes locally
  • uv run --frozen python scripts/benchmark.py --check --threshold 15 — within threshold (+14.0% vs. baseline)
  • CHANGELOG.md has an entry under ## [Unreleased]

No new protocol/dispatch change, so that checklist block doesn't apply.

Notes

Last of the three remaining Tier 2 issues (#90#89#92, per the roadmap's #107 working agreement). Once this merges, Tier 2 (#104) is fully closed — the version bump to 2.0.0 and CHANGELOG heading change are a release-cut decision left to the repo owner.


🤖 Generated with Claude Code

https://claude.ai/code/session_01SVCFe7B1U5VeJRoUbx24vb


Generated by Claude Code

decode_frame(lax=True, start=IPv4) already solves #92's core problem
with zero new code: an RFC-792 error message quotes only the invoking
IP header plus 8 bytes of what follows, never a full TCP/UDP header,
so decoding it needs the lax path, not a try/except. Verified against
a real embedded-packet fixture before writing anything.
embedded_chain is the pre-wired convenience next to the existing raw
embedded_packet -- same shape as this codebase's other accessor-plus-
typed-view pairs. Starts at IPv4 for ICMPv4, IPv6 for ICMPv6. None for
the same cases embedded_packet degrades to (non-error types, an empty
body).
No import cycle: icmp.py importing ip.py and walk.py at module level
was verified clean (neither imports icmp.py, directly or transitively)
via `python -c "import netprotocols"` and two isolated import paths
before committing to top-level imports over deferred ones.
The remaining acceptance criterion -- the distinction documented, so
nobody reaches for lax by default -- is the actual work here: the
module docstring and a new README section explain that embedded_chain's
lax=True is the right default only because the truncation is
RFC-mandated, expected input, not a general license for lax=True on a
complete frame that fails to decode.
Closes#92.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SVCFe7B1U5VeJRoUbx24vb
@EONRaider
EONRaider merged commit 701bf48 into masterSep 4, 2026
7 checks passed
This was referenced Sep 4, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A named lax decode mode for deliberately truncated input

2 participants

@EONRaider@claude