Linux cooked capture v1 (DLT_LINUX_SLL) header encoding and decoding.
SLL ("Simple Linux Layer to describe the format") is the pseudo link
layer libpcap synthesizes when a capture is taken on a Linux "any" device,
or on an interface whose real link layer doesn't fit an Ethernet-shaped
header (PPP, tunnels, nlmon, ...). It replaces the real link-layer
header with a fixed 16-byte header, followed by the payload as understood
by protocol:
0 7 8 15 16 23 24 31 +--------+--------+--------+--------+ | Packet Type | ARPHRD Type | +--------+--------+--------+--------+ | Addr Length | Link-Layer | +-----------------+ Address | | Address (cont.) | +-----------------+-----------------+ | Addr (cont.) | Protocol | +-----------------+-----------------+ | Payload (variable) | +-----------------------------------+
linkLayerAddress is always 8 bytes on the wire regardless of the actual
address length — only the first linkLayerAddressLength bytes are
meaningful, the rest is padding. This coder surfaces the field verbatim
(all 8 bytes); trim it with linkLayerAddress.subarray(0, linkLayerAddressLength) if you only want the meaningful prefix.
arphrdType is a Linux ARPHRD_* constant (include/uapi/linux/if_arp.h)
identifying the real link layer of the captured interface, and protocol
is an EtherType-space value (the same numbering Ethernet II uses)
identifying the payload, e.g. 0x0800 for IPv4.
See the tcpdump link-layer header type registry for the authoritative layout: https://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL.html.
Scope for 0.0.1: the 16-byte header only, shallow and sane. No
deep-parsing of payload by protocol, no v2 (DLT_LINUX_SLL2) support.
Round-trip an IPv4-carrying SLL header
Round-trip an IPv4-carrying SLL header
import { assertEquals } from "@std/assert"; import { sllHeader, SLL_PACKET_TYPE } from "@binstruct/sll"; const coder = sllHeader(); const frame = { packetType: SLL_PACKET_TYPE.HOST, arphrdType: 1, linkLayerAddressLength: 6, linkLayerAddress: new Uint8Array([0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x00, 0x00]), protocol: 0x0800, payload: new Uint8Array([0x45, 0x00, 0x00, 0x14]), }; const buffer = new Uint8Array(64); const written = coder.encode(frame, buffer); const [decoded, read] = coder.decode(buffer.subarray(0, written)); assertEquals(written, read); assertEquals(decoded.packetType, SLL_PACKET_TYPE.HOST); assertEquals(decoded.protocol, 0x0800); assertEquals(decoded.payload, frame.payload);