Skip to content

Detect 802.3 length-field / LLC framing in Ethernet.decode() #188

Description

@EONRaider

Target: 2.5.0 (Tier 3 — L2 discovery & tunneling) — blocks the
STP and CDP issues in this same tier.

Context

layer2/ethernet.py
unconditionally reads bytes 12–13 as an EtherType and hands them
straight to _ethertype_class(). Real Ethernet frames are ambiguous
at that offset: IEEE 802.3 says a value ≤ 1500 is a frame length,
not an EtherType, and it's followed by an 802.2 LLC header (DSAP,
SSAP, Control) rather than whatever the length value would otherwise
be misread as. STP (LLC DSAP 0x42, no SNAP) and CDP (LLC DSAP 0xAA
with a SNAP header carrying its own EtherType-like PID) both ride this
framing. Today, a frame like that either raises as an unrecognized
"ethertype" or — worse — collides with a real EtherType numerically
below 1500 (none currently assigned, but nothing stops one from being
registered later without noticing the collision).

This is the one issue in the roadmap that isn't a drop-in
registration.
It changes what Ethernet.next_protocol() does for
an entire class of frames that decode "successfully" today (as an
unrecognized ethertype, silently) and will decode differently once
this lands.

Deliverable

  • In Ethernet.decode()/next_protocol(), branch on the bytes-12–13
    value: <= 1500 is 802.3 length (IEEE 802.3 §3.2.6); >= 1536
    (0x0600) is EtherType (values 1501–1535 are reserved/undefined by
    the standard and can raise or fall back, whichever this library's
    existing "unknown" convention prefers).
  • On the 802.3-length branch, decode the following 802.2 LLC header
    (DSAP 1 byte, SSAP 1 byte, Control 1 or 2 bytes depending on the
    low bits of Control) and add a new dispatch table (llc.dsap,
    following the ip.proto / ethertype naming convention in
    registry.py) keyed on DSAP.
  • SNAP (DSAP/SSAP = 0xAA/0xAA, used by CDP among others) is LLC's own
    extension: a 3-byte OUI plus a 2-byte PID sits after the LLC header,
    and the PID plays the same role an EtherType does. Decide whether
    SNAP dispatch reuses the existing ethertype table (since most
    SNAP PIDs mirror real EtherTypes) or gets its own llc.snap_pid
    table — recommend reusing ethertype, since that's what SNAP's PID
    field is defined to mean, and avoids a third near-duplicate table
    for something that already has one.
  • Register a Protocol for the raw LLC header itself (analogous to
    how VLAN is a thin layer that chains onward) so STP/CDP (their
    own issues, this tier) have something to dispatch from.

Design questions to settle first

  • Does this change Ethernet.ethertype's type or meaning at all? It
    shouldn't — keep ethertype as the raw 16-bit field exactly as
    today; the length/EtherType distinction lives in
    next_protocol()'s behavior, not in a new field, so nothing in
    the public dataclass shape changes.
  • What happens to frames in the 1501–1535 reserved gap? Recommend:
    same as any other unrecognized value today — next_protocol()
    returns None, no exception.

Acceptance criteria

  • Ethernet.next_protocol() correctly branches length-vs-EtherType
    at the 1500/1536 boundary.
  • A new llc.dsap table (or equivalent) dispatches on 802.2 LLC
    DSAP; SNAP's PID reuses (or clearly extends) the ethertype
    table per the design decision above.
  • Every existing EtherType-dispatched test still passes unchanged
    — this must be additive, not a behavior change for any frame
    that decodes correctly today.
  • Fixture with a real 802.3+LLC frame (a captured STP BPDU or CDP
    frame from the sibling issues works) and one in the
    1501–1535 reserved gap.
  • CHANGELOG entry; full ladder green.

References

IEEE 802.3 §3.2.6 (length field), IEEE 802.2 (LLC), RFC 1042 / IEEE
802.1H (SNAP) · blocks the STP and CDP issues, this tier (#173)

Part of #173

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions