packet

package
v0.0.0-...-6b8ee43 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 25, 2026 License: AGPL-3.0 Imports: 11 Imported by: 0

Documentation

Overview

Package packet is the IS-IS PDU and TLV wire codec: the protocol's serialization boundary. It parses received frames into PDU views and serializes PDU structs back to bytes.

Layering (umbrella plan/spec-isis-0-umbrella.md): types (leaf) <- packet <- the IS-IS runtime (transport, circuit, adjacency, lsdb, spf). This package imports ONLY the domain types from internal/plugins/isis/types (plus the Go standard library and internal/core/textbuf for display). It contains no runtime, sockets, timers, LSDB, or FSM; those live in later children. It MUST NOT import the runtime, nor BGP-LS.

Decode is lazy and zero-copy (ISO/IEC 10589 clause 7.3.14 unknown-TLV propagation): a PDU view holds the caller's byte slice plus offsets, and TLVs are iterated on demand via TLVIterator yielding (type, value-slice) without copying. Unknown TLVs are retained as opaque spans so the LSDB can re-flood them verbatim. The lifetime contract: a decoded view is valid only while the caller's backing slice is stable; isis-6 copies LSP bytes it retains.

Encode is buffer-first (ai/rules/buffer-first.md): every PDU and TLV writes into a caller-owned buffer via WriteTo(buf []byte, off int) int. The PDU Length field and the LSP Fletcher checksum are written by skip-and-backfill, never a Len()-then-WriteTo() double traversal. Human-readable rendering uses textbuf/AppendTo, never fmt.Sprintf (ai/rules/no-sprintf-alloc.md).

The single highest-risk item is the ISO 8473 Fletcher checksum with its two-step adjustment (checksum.go): it is implemented and vector-tested before any runtime depends on this package.

Index

Constants

View Source
const (
	// CommonHeaderLen is the fixed length of the IS-IS common header in octets.
	CommonHeaderLen = 8

	// ProtocolDiscriminator is the Intra-domain Routeing Protocol Discriminator
	// (NLPID 0x83 for IS-IS) carried in octet 0 of every PDU.
	ProtocolDiscriminator = 0x83

	// VersionProtocolIDExtension is the "version/protocol ID extension" octet
	// (octet 2); always 1.
	VersionProtocolIDExtension = 0x01

	// Version is the "version" octet (octet 5); always 1.
	Version = 0x01

	// IDLength is the System ID length advertised in the common header (octet
	// 3). Ze fixes the System ID at 6 octets; on the wire the value 0 also
	// means "6 octets" (ISO/IEC 10589 clause 9.5), so both 0 and 6 are accepted
	// on receive and 6 is sent.
	IDLength = types.SystemIDLen
)

Common-header constants (ISO/IEC 10589 clause 9.5/9.6/9.7/9.8).

View Source
const (
	LSPFlagPartition = 0x80 // P: partition repair supported
	LSPFlagOverload  = 0x04 // OL: LSP database overload (RFC 3787)
	LSPFlagISTypeL1  = 0x01 // IS type low bit
	LSPFlagISTypeL2  = 0x02 // IS type high bit
	// LSPAttachedMask covers the four ATT bits (default/delay/expense/error
	// metric attached); set by an L1L2 router in its L1 LSP.
	LSPAttachedMask = 0x78
)

Type-block bit masks (ISO/IEC 10589 clause 9.8). The high bit P is the partition-repair flag; ATT are the four attached-metric bits; OL is the LSP-database-overload bit; the low two bits are the IS type.

View Source
const (
	TLVAreaAddresses        = 1   // ISO/IEC 10589 clause 9.2
	TLVISReachabilityNarrow = 2   // ISO/IEC 10589 clause 9.3 (decode-only)
	TLVISNeighbors          = 6   // ISO/IEC 10589 clause 9.4 (LAN SNPA list)
	TLVPadding              = 8   // ISO/IEC 10589 clause 9.10
	TLVLSPEntries           = 9   // ISO/IEC 10589 clause 9.14
	TLVAuthentication       = 10  // ISO/IEC 10589 clause 9.8 / RFC 5304
	TLVExtendedISReach      = 22  // RFC 5305 sec 3
	TLVProtocolsSupported   = 129 // RFC 1195
	TLVIPInterfaceAddress   = 132 // RFC 1195
	TLVExtendedIPReach      = 135 // RFC 5305 sec 4
	TLVDynamicHostname      = 137 // RFC 5301
	TLVIPv6InterfaceAddress = 232 // RFC 5308 sec 3
	TLVIPv6Reachability     = 236 // RFC 5308 sec 2
	TLVP2PThreeWay          = 240 // RFC 5303 sec 3.1
)

TLV type codes handled by this codec (ISO/IEC 10589 clause 9 and the extension RFCs). The umbrella TLV inventory enumerates the full set; this codec encodes/decodes 1, 6, 8, 9, 10, 22, 129, 132, 135, 137, 232, 236, 240 and decode-only TLV 2.

View Source
const (
	AuthTypeReserved      = 0   // ISO/IEC 10589 (reserved)
	AuthTypeCleartext     = 1   // ISO/IEC 10589: cleartext password
	AuthTypeGenericCrypto = 3   // RFC 5310: generic cryptographic authentication (HMAC-SHA)
	AuthTypeHMACMD5       = 54  // RFC 5304 sec 2 (0x36)
	AuthTypeDomainPrivate = 255 // ISO/IEC 10589: routeing domain private method
)

IS-IS authentication type codes carried as the first value octet of TLV 10 (RFC 5304 sec 1 / sec 4, RFC 5310). The codec treats everything after this octet as opaque.

View Source
const (
	NLPIDIPv4 = 0xCC // RFC 1195
	NLPIDIPv6 = 0x8E // RFC 5308 sec 4
)

NLPID values carried in TLV 129 (Protocols Supported, RFC 1195 / RFC 5308).

View Source
const (
	SubTLVLinkLocalRemoteID = 4 // RFC 5305 sec 5.2.1 / RFC 5307: link local/remote identifiers
	SubTLVIPv4InterfaceAddr = 6 // RFC 5305 sec 3.2: IPv4 interface address
	SubTLVIPv4NeighborAddr  = 8 // RFC 5305 sec 3.3: IPv4 neighbor address
)

Sub-TLV type codes for TLV 22 the spec calls out (RFC 5305 sec 3, sec 5.2.1). The codec round-trips ANY sub-TLV as an opaque SubTLV; these constants are provided for callers that build the in-scope set.

View Source
const IPv4AddrLen = 4

IPv4AddrLen is the length of one IPv4 address (TLV 132 entry).

View Source
const IPv6AddrLen = 16

IPv6AddrLen is the length of one IPv6 address (TLV 232 entry).

LSPEntryLen is the fixed size of one LSP Entries TLV record.

View Source
const (

	// MaxDISPriority is the largest DIS priority (LAN IIH).
	MaxDISPriority = 127
)

PDU-specific fixed-header lengths (the octets after the common header, before the TLVs). All assume the 6-octet System ID (Ze fixes ID length at 6).

View Source
const MaxIPv4PrefixLen = 32

MaxIPv4PrefixLen is the largest IPv4 prefix length.

View Source
const MaxIPv6PrefixLen = 128

MaxIPv6PrefixLen is the largest IPv6 prefix length.

View Source
const MaxTLVValueLen = 255

MaxTLVValueLen is the largest value a single TLV can carry: the length field is one octet (ISO/IEC 10589 clause 9). A value longer than this must be split across multiple TLVs by the caller (e.g. fragmentation in isis-6).

View Source
const SNPALen = 6

SNPALen is the length of a Subnetwork Point of Attachment address (a 48-bit IEEE 802 MAC) carried in TLV 6.

View Source
const TLVHeaderLen = 2

TLVHeaderLen is the fixed type+length framing of one TLV or sub-TLV.

Variables

View Source
var (
	// ErrAuthMissing reports that authentication is configured but the received
	// PDU carries no TLV 10 (downgrade resistance, RFC 5304 sec 2 / spec R-6).
	ErrAuthMissing = errors.New("isis auth: authentication TLV (10) missing")
	// ErrAuthNotFirst reports that TLV 10 is present but is not the first TLV
	// (RFC 5304 sec 1; AC-8).
	ErrAuthNotFirst = errors.New("isis auth: authentication TLV (10) not first")
	// ErrAuthTypeMismatch reports that the received auth type byte does not match
	// any candidate key's algorithm.
	ErrAuthTypeMismatch = errors.New("isis auth: authentication type mismatch")
	// ErrAuthMismatch reports that no candidate key produced a matching digest
	// (the PDU is rejected; the caller increments ze_isis_auth_failures_total).
	ErrAuthMismatch = errors.New("isis auth: authentication value mismatch")
	// ErrAuthUnsupported reports an algorithm this build cannot sign/verify.
	ErrAuthUnsupported = errors.New("isis auth: unsupported authentication algorithm")
	// ErrAuthMalformed reports a PDU that cannot be decoded for signing/verifying.
	ErrAuthMalformed = errors.New("isis auth: malformed PDU")
	// ErrAuthPurgeExtraTLV reports an authenticated purge that carries a TLV other
	// than the authentication TLV (RFC 5304 sec 2: MUST NOT accept such purges).
	ErrAuthPurgeExtraTLV = errors.New("isis auth: purge carries non-authentication TLV")
)

Errors returned by the auth backend. They are typed sentinels so callers can match without parsing strings; verify failures never echo key material or the received digest (security review: no leakage).

View Source
var (
	// ErrShortBuffer reports a buffer too short to hold the structure being
	// decoded or encoded.
	ErrShortBuffer = errors.New("isis packet: buffer too short")
	// ErrBadDiscriminator reports a common header whose protocol discriminator
	// is not 0x83.
	ErrBadDiscriminator = errors.New("isis packet: bad protocol discriminator")
	// ErrBadVersion reports a common header whose version octets are not 1.
	ErrBadVersion = errors.New("isis packet: unsupported version")
	// ErrBadIDLength reports a common header whose ID length is neither 0 nor 6
	// (Ze fixes the System ID at 6 octets).
	ErrBadIDLength = errors.New("isis packet: unsupported ID length")
	// ErrUnknownPDUType reports a PDU type code that is not one of the 9 known
	// types.
	ErrUnknownPDUType = errors.New("isis packet: unknown PDU type")
	// ErrTruncated reports a PDU body shorter than its fixed header requires.
	ErrTruncated = errors.New("isis packet: truncated PDU")
	// ErrLength reports a length field that is out of range (e.g. a TLV value
	// longer than 255 octets, or a sub-TLV block that overflows its TLV).
	ErrLength = errors.New("isis packet: invalid length")
)

Errors returned by the codec. They are typed sentinels so callers can match without parsing strings, and they never echo attacker-controlled bytes (security review: error leakage).

Functions

func AuthTLVIndex

func AuthTLVIndex(tlvs []TLV) int

AuthTLVIndex returns the index of the first Authentication TLV (type 10) in the slice, or -1 if absent. RFC 5304 sec 1 requires TLV 10 to be the first TLV when present; isis-10 uses this to enforce ordering on receive. (The codec itself does not reject misordered auth TLVs; it only surfaces the position, per the spec's separation of codec from enforcement.)

func Checksum

func Checksum(data []byte, checkOff int) (high, low byte)

Checksum computes the two ISO 8473 Fletcher checksum octets for the data region, where the checksum field itself sits at checkOff octets from the start of the region (0-based). The two checksum octets in data[checkOff] and data[checkOff+1] are treated as zero during the computation regardless of their current contents, exactly as required before placing the result.

It returns the (high, low) octets to store at data[checkOff] and data[checkOff+1] so that VerifyChecksum over the same region yields zero.

ISO/IEC 10589 clause 7.3.11: the checksum is computed "commencing with the Source ID field" (the octet after Remaining Lifetime) to the end of the PDU; for an LSP the checksum field is at the start+offset of the checksummed region. The classic adjustment (ISO 8473 annex C.3.4.2) is reproduced below.

func ReleaseTLVs

func ReleaseTLVs(tlvs []TLV)

ReleaseTLVs returns a TLV slice obtained from DecodeTLVs to the pool. Callers must not use the slice after this call. Nil and non-pool-sized slices (e.g. from a PDU with >64 TLVs that outgrew the pool array) are silently ignored.

func SignPDU

func SignPDU(pdu []byte, key Key) ([]byte, error)

SignPDU signs a fully-constructed PDU with key and returns the final on-wire bytes. The input pdu MUST be the complete PDU (common header + body + TLVs), already padded for an IIH (RFC 5304 sec 2 signs padded Hellos) and WITHOUT a TLV 10. SignPDU:

  • inserts TLV 10 as the FIRST TLV (RFC 5304 sec 1), sized to the algorithm, with a zero (placeholder) Authentication Value;
  • computes the digest over the PDU with the Authentication Value zeroed, and for LSPs with the Checksum and Remaining Lifetime fields also zeroed (RFC 5304 sec 2);
  • writes the digest into the TLV 10 value (and the Key ID for the generic- crypto family, RFC 5310 sec 3.1);
  • for an LSP, recomputes the Fletcher checksum LAST so the signing order is build -> sign -> checksum (spec AC-9, R-3); the Remaining Lifetime is restored to its original value before the checksum runs.

Cleartext (auth type 1) carries the password as the value and computes no digest (sanity only, not security; spec AC-5).

func VerifyChecksum

func VerifyChecksum(data []byte) bool

VerifyChecksum re-runs the Fletcher sums over the data region (with the checksum octets in place) and reports true iff both sums are zero, which is the ISO 8473 condition for a correct checksum (ISO/IEC 10589 clause 7.3.11). A region whose stored checksum field is all zero is treated as "checksum not present" and is NOT considered valid here (callers that allow disabled checksums check that separately); this function reports strict correctness.

func VerifyPDU

func VerifyPDU(pdu []byte, keys []Key) error

VerifyPDU verifies a received PDU against the candidate keys. It enforces the downgrade and ordering rules and, on a match, returns nil; on any failure it returns a typed error and the caller drops the PDU and increments ze_isis_auth_failures_total (spec AC-1, AC-2). The candidate keys are every currently-valid key in the relevant chain (the active signing key plus all accepted-on-receive keys, for hitless rotation -- spec AC-4).

Behavior:

  • No candidate keys: authentication is not configured for this PDU class; VerifyPDU returns nil (unauthenticated operation, the default).
  • TLV 10 absent under configured auth: ErrAuthMissing (R-6 downgrade).
  • TLV 10 present but not first: ErrAuthNotFirst (RFC 5304 sec 1, AC-8).
  • For each candidate key whose algorithm matches the received auth type, recompute the digest with the proper field zeroing and constant-time compare (AC-12); any match accepts.
  • For an LSP that is a purge (Remaining Lifetime 0), additionally enforce RFC 5304 sec 2: the purge MUST be authenticated (handled by the digest check) and MUST NOT carry any TLV other than TLV 10 (ErrAuthPurgeExtraTLV).

func WriteLSPEntriesTLV

func WriteLSPEntriesTLV(buf []byte, off int, t LSPEntriesTLV) int

WriteLSPEntriesTLV emits TLV 9 (type+length+value) into buf at off and returns the new offset. It is the exported entry point the flooding spec (isis-7) uses to build CSNP/PSNP bodies via the canonical isis-2 codec rather than re-encoding the entry layout. The caller ensures the entry count fits one TLV (255/16 = 15 entries); isis-7 splits larger lists across multiple TLV 9s.

func WritePaddingTLV

func WritePaddingTLV(buf []byte, off, n int) int

WritePaddingTLV emits one TLV 8 with n zero value octets (0 <= n <= 255) into buf at off and returns the new offset. The padding owner (isis-5) computes how many padding TLVs are needed to reach the interface MTU before authentication (ISO/IEC 10589 clause 8.2.3) and calls this per TLV; buffer-first, assumes room. Exported because the originator lives in a sibling package (isis-5), not this codec child.

Types

type AdjThreeWayState

type AdjThreeWayState uint8

AdjThreeWayState is the RFC 5303 three-way adjacency state (sec 2.1, 3.1).

const (
	AdjThreeWayUp           AdjThreeWayState = 0
	AdjThreeWayInitializing AdjThreeWayState = 1
	AdjThreeWayDown         AdjThreeWayState = 2
)

Three-way adjacency state values (RFC 5303 sec 3.1: 0 = Up, 1 = Initializing, 2 = Down).

type AreaAddressesTLV

type AreaAddressesTLV struct {
	Areas []types.AreaID
}

AreaAddressesTLV is the decoded TLV 1: the list of area addresses an IS belongs to. Originated in IIHs (isis-5) and LSPs (isis-6).

func DecodeAreaAddressesTLV

func DecodeAreaAddressesTLV(value []byte) (AreaAddressesTLV, error)

DecodeAreaAddressesTLV parses a TLV 1 value. Each entry is a 1-octet length followed by that many octets. Bound-checked (security review): a length that overruns the value terminates with ErrTruncated and no partial area leaks.

type AuthAlgorithm

type AuthAlgorithm uint8

AuthAlgorithm selects the digest algorithm carried in TLV 10. The values are internal identifiers; the on-wire authentication TYPE byte (1/3/54) is derived from the algorithm by authTypeFor, and for the generic-crypto family (type 3) the algorithm is NEVER sent on the wire (RFC 5310 sec 2: the algorithm is selected per-SA via the Key ID).

const (
	AuthAlgoNone       AuthAlgorithm = iota // no authentication configured
	AuthAlgoCleartext                       // ISO/IEC 10589 cleartext password (auth type 1)
	AuthAlgoHMACMD5                         // RFC 5304 HMAC-MD5 (auth type 54)
	AuthAlgoHMACSHA1                        // RFC 5310 HMAC-SHA-1 (auth type 3)
	AuthAlgoHMACSHA224                      // RFC 5310 HMAC-SHA-224 (auth type 3)
	AuthAlgoHMACSHA256                      // RFC 5310 HMAC-SHA-256 (auth type 3)
	AuthAlgoHMACSHA384                      // RFC 5310 HMAC-SHA-384 (auth type 3)
	AuthAlgoHMACSHA512                      // RFC 5310 HMAC-SHA-512 (auth type 3)
)

Authentication algorithms (spec-isis-10). Cleartext is sanity-only; HMAC-MD5 (RFC 5304) and the HMAC-SHA family (RFC 5310) provide integrity.

type AuthTLV

type AuthTLV struct {
	AuthType uint8
	Value    []byte // opaque; aliases the source buffer on decode
}

AuthTLV is the decoded TLV 10: the 1-octet authentication type followed by an opaque authentication value. The codec does not interpret the value (the digest / password / key-id structure is isis-10's concern); it only carries it so the TLV round-trips and isis-10 can verify/sign over the full PDU.

func DecodeAuthTLV

func DecodeAuthTLV(value []byte) (AuthTLV, error)

DecodeAuthTLV parses a TLV 10 value: the first octet is the authentication type, the remainder the opaque authentication value. A zero-length value is rejected (ErrLength): TLV 10 must carry at least the type octet (RFC 5304 sec 1). The codec does not reject unknown auth types or malformed digest lengths -- that is enforcement (isis-10) -- but it does require the structural minimum so a truncated TLV is not silently accepted as valid (security review: "must not silently accept malformed auth TLV structure").

type CSNP

type CSNP struct {
	PDUType          PDUType // PDUTypeL1CSNP or PDUTypeL2CSNP
	SourceID         types.SourceID
	StartLSPID       types.LSPID
	EndLSPID         types.LSPID
	MaxAreaAddresses uint8 // common-header field; 0 = the default 3
	TLVs             []TLV
}

CSNP is a decoded Level 1 or Level 2 Complete Sequence Numbers PDU (ISO/IEC 10589 clause 9.10). It summarizes the sender's LSDB over the LSP-ID range [Start, End] via TLV 9 (LSP Entries). The PDU type distinguishes L1 (0x18) from L2 (0x19).

func DecodeCSNP

func DecodeCSNP(pt PDUType, body []byte) (CSNP, error)

DecodeCSNP parses a CSNP body following the common header.

func (*CSNP) EncodedLen

func (c *CSNP) EncodedLen() int

EncodedLen returns the total on-wire size of the CSNP.

func (*CSNP) WriteTo

func (c *CSNP) WriteTo(buf []byte, off int) int

WriteTo serializes the CSNP into buf at off; PDU Length via skip-and-backfill. Buffer-first.

type CircuitType

type CircuitType uint8

CircuitType is the 1-octet circuit type field in an IIH (ISO/IEC 10589 clause 9.5): the low two bits select the level(s) the sender uses on this circuit.

const (
	CircuitL1   CircuitType = 1 // Level 1 only
	CircuitL2   CircuitType = 2 // Level 2 only
	CircuitL1L2 CircuitType = 3 // Level 1 and Level 2
)

Circuit type values (ISO/IEC 10589 clause 9.5: only the low two bits are defined; the rest are reserved and ignored on receipt).

type ExtIPReachEntry

type ExtIPReachEntry struct {
	Metric  types.PrefixMetric
	UpDown  bool // up/down bit from the control octet (set = leaked down a level)
	Prefix  netip.Prefix
	SubTLVs []SubTLV // present only when the S bit was set; retained verbatim
}

ExtIPReachEntry is one decoded TLV 135 prefix entry.

type ExtISReachEntry

type ExtISReachEntry struct {
	Neighbor types.SourceID
	Metric   types.Metric
	SubTLVs  []SubTLV
}

ExtISReachEntry is one decoded TLV 22 neighbor entry. The 24-bit metric is carried in types.Metric (which range-checks the 24-bit bound). SubTLVs are retained opaquely so the entry round-trips verbatim regardless of which sub-TLV types Ze understands.

type ExtendedIPReachTLV

type ExtendedIPReachTLV struct {
	Entries []ExtIPReachEntry
}

ExtendedIPReachTLV is the decoded TLV 135: a list of prefix entries.

func DecodeExtendedIPReachTLV

func DecodeExtendedIPReachTLV(value []byte) (ExtendedIPReachTLV, error)

DecodeExtendedIPReachTLV parses a TLV 135 value. Every length is bound-checked before slicing (security review, R-5): a prefix length > 32, a packed prefix or sub-TLV block that overruns the value, is rejected without reading out of bounds. The 32-bit metric is preserved as-is (never capped at 24-bit). The sub-TLV-length octet and sub-TLVs are read ONLY when the S bit is set.

func (ExtendedIPReachTLV) EncodedLen

func (t ExtendedIPReachTLV) EncodedLen() int

EncodedLen returns the full on-wire size of TLV 135 (type + length + value).

func (ExtendedIPReachTLV) WriteTo

func (t ExtendedIPReachTLV) WriteTo(buf []byte, off int) int

WriteTo emits TLV 135 into buf at off and returns the new offset. The S (sub-TLV-present) bit and the sub-TLV-length octet are written ONLY when the entry has sub-TLVs, exactly mirroring the decode (RFC 5305 sec 4.2). The up/down bit is placed in the control octet. Buffer-first; the originator (isis-6/9/11) lives in a sibling package.

type ExtendedISReachTLV

type ExtendedISReachTLV struct {
	Entries []ExtISReachEntry
}

ExtendedISReachTLV is the decoded TLV 22: a list of neighbor entries.

func DecodeExtendedISReachTLV

func DecodeExtendedISReachTLV(value []byte) (ExtendedISReachTLV, error)

DecodeExtendedISReachTLV parses a TLV 22 value. Every field is bound-checked before slicing (security review): an entry whose declared sub-TLV length overruns the value is rejected with ErrTruncated, and the 24-bit metric cannot overflow by construction (3 octets). It does NOT cap the metric at MAX_PATH_METRIC; that SPF clamp is isis-9's concern (the codec preserves the wire value).

type Header struct {
	// LengthIndicator is the length of this PDU's fixed header (common header
	// plus the PDU-specific fixed fields), as carried in octet 1.
	LengthIndicator uint8
	// IDLength is the System ID length octet as received (0 or 6).
	IDLength uint8
	// PDUType is the 5-bit PDU type code.
	PDUType PDUType
	// MaxAreaAddresses is the maximum number of area addresses (octet 7); 0
	// means the default of 3 (ISO/IEC 10589 clause 9.5).
	MaxAreaAddresses uint8
}

Header is the parsed common 8-octet IS-IS header (ISO/IEC 10589 clause 9.5). It is a small value copied out of the wire bytes; the body parsers take the remaining slice.

func DecodeHeader

func DecodeHeader(buf []byte) (Header, int, error)

DecodeHeader parses and validates the common 8-octet header at the start of buf. It is bound-checked before every read (security review: input validation) and rejects a bad discriminator, version, ID length, or unknown PDU type. On success it returns the parsed header and the offset at which the PDU-specific body begins (always CommonHeaderLen).

ISO/IEC 10589 clause 9.5: "Intradomain Routeing Protocol Discriminator" = 0x83, "Version/Protocol ID Extension" = 1, "Version" = 1.

type IPv4InterfaceAddrTLV

type IPv4InterfaceAddrTLV struct {
	Addresses []netip.Addr // each a 4-octet IPv4 address
}

IPv4InterfaceAddrTLV is the decoded TLV 132.

func DecodeIPv4InterfaceAddrTLV

func DecodeIPv4InterfaceAddrTLV(value []byte) (IPv4InterfaceAddrTLV, error)

DecodeIPv4InterfaceAddrTLV parses a TLV 132 value (one 4-octet address per entry). A value length that is not a multiple of 4 is rejected (ErrLength).

type IPv6InterfaceAddrTLV

type IPv6InterfaceAddrTLV struct {
	Addresses []netip.Addr // each a 16-octet IPv6 address
}

IPv6InterfaceAddrTLV is the decoded TLV 232.

func DecodeIPv6InterfaceAddrTLV

func DecodeIPv6InterfaceAddrTLV(value []byte) (IPv6InterfaceAddrTLV, error)

DecodeIPv6InterfaceAddrTLV parses a TLV 232 value (one 16-octet address per entry). A value length that is not a multiple of 16 is rejected (ErrLength).

type IPv6ReachEntry

type IPv6ReachEntry struct {
	Metric   types.PrefixMetric
	UpDown   bool // U flag (set = leaked down a level)
	External bool // X flag (set = redistributed from another protocol)
	Prefix   netip.Prefix
	SubTLVs  []SubTLV // present only when the S flag was set; retained verbatim
}

IPv6ReachEntry is one decoded TLV 236 prefix entry.

type IPv6ReachabilityTLV

type IPv6ReachabilityTLV struct {
	Entries []IPv6ReachEntry
}

IPv6ReachabilityTLV is the decoded TLV 236: a list of IPv6 prefix entries.

func DecodeIPv6ReachabilityTLV

func DecodeIPv6ReachabilityTLV(value []byte) (IPv6ReachabilityTLV, error)

DecodeIPv6ReachabilityTLV parses a TLV 236 value. Every length is bound-checked before slicing (security review, R-5): a prefix length > 128, a packed prefix or sub-TLV block that overruns the value, is rejected without reading out of bounds. The 32-bit metric is preserved as-is. The sub-TLV-length octet and sub-TLVs are read ONLY when the S flag is set.

func (IPv6ReachabilityTLV) EncodedLen

func (t IPv6ReachabilityTLV) EncodedLen() int

EncodedLen returns the full on-wire size of TLV 236 (type + length + value).

func (IPv6ReachabilityTLV) WriteTo

func (t IPv6ReachabilityTLV) WriteTo(buf []byte, off int) int

WriteTo emits TLV 236 into buf at off and returns the new offset. The S flag and the sub-TLV-length octet are written ONLY when the entry has sub-TLVs, mirroring the decode (RFC 5308 sec 2). The U and X bits go in the flags octet, the prefix length in its own octet. Buffer-first; the originator (isis-12) lives in a sibling package.

type ISNeighborsTLV

type ISNeighborsTLV struct {
	SNPAs [][SNPALen]byte
}

ISNeighborsTLV is the decoded TLV 6: the list of neighbor SNPAs (MACs).

func DecodeISNeighborsTLV

func DecodeISNeighborsTLV(value []byte) (ISNeighborsTLV, error)

DecodeISNeighborsTLV parses a TLV 6 value (one 6-octet SNPA per entry). A value length that is not a multiple of SNPALen is rejected (ErrLength) so a crafted partial address cannot be read past its bounds.

type JSONView

type JSONView struct {
	Type             string `json:"type"`               // PDU type token, e.g. "l2-lsp"
	MaxAreaAddresses uint8  `json:"max-area-addresses"` // common-header field

	LANHello *lanHelloJSON `json:"lan-hello,omitempty"`
	P2PHello *p2pHelloJSON `json:"p2p-hello,omitempty"`
	LSP      *lspJSON      `json:"lsp,omitempty"`
	CSNP     *csnpJSON     `json:"csnp,omitempty"`
	PSNP     *psnpJSON     `json:"psnp,omitempty"`
}

JSONView is a JSON-serializable rendering of a decoded PDU. Exactly one body field is non-nil, matching the header's PDU type. Field names are stable kebab/lower tokens for diagnostics and test assertions.

type Key

type Key struct {
	Algorithm AuthAlgorithm
	Secret    []byte //nolint:gosec // G117: field name describes key material, not a literal secret; never logged.
	KeyID     uint16
}

Key is one authentication key used to sign or verify. Secret is the raw key material (the $9$-decoded plaintext supplied by the component key store, held only in memory); the auth backend never logs it. KeyID is carried on the wire only for the generic-crypto family (type 3, RFC 5310); it is ignored for cleartext and HMAC-MD5.

type LANHello

type LANHello struct {
	PDUType          PDUType // PDUTypeL1LANHello or PDUTypeL2LANHello
	CircuitType      CircuitType
	SystemID         types.SystemID
	HoldingTime      types.HoldingTime
	Priority         uint8 // 0..127 (DIS election)
	LANID            types.SourceID
	MaxAreaAddresses uint8 // common-header field; 0 = the default 3
	TLVs             []TLV
}

LANHello is a decoded Level 1 or Level 2 LAN IS-IS Hello (ISO/IEC 10589 clause 9.5). The PDU type (set by the caller on encode, read on decode) distinguishes L1 (0x0f) from L2 (0x10). LANID is the System ID + pseudonode of the current DIS (zero when none elected). TLVs are retained in order.

func DecodeLANHello

func DecodeLANHello(pt PDUType, body []byte) (LANHello, error)

DecodeLANHello parses a LAN IIH body following the common header. body is the slice after the 8-octet common header. pt is the PDU type from the header (L1/L2). Every field is bound-checked before slicing (security review). The returned TLVs alias body; the caller copies any it retains.

func (*LANHello) EncodedLen

func (h *LANHello) EncodedLen() int

EncodedLen returns the total on-wire size of the LAN IIH.

func (*LANHello) WriteTo

func (h *LANHello) WriteTo(buf []byte, off int) int

WriteTo serializes the LAN IIH into buf at off and returns the new offset. The PDU Length field is filled by skip-and-backfill (ai/rules/buffer-first.md) rather than a Len()-then-WriteTo() double pass. Buffer-first: the caller guarantees room (>= EncodedLen()).

ISO/IEC 10589 clause 9.5: priority is a 7-bit field; the high bit is reserved and sent zero, so the priority is masked to 0..127.

type LSP

type LSP struct {
	PDUType           PDUType // PDUTypeL1LSP or PDUTypeL2LSP
	RemainingLifetime types.RemainingLifetime
	LSPID             types.LSPID
	SequenceNumber    types.SequenceNumber
	Checksum          uint16 // as decoded; recomputed and backfilled on WriteTo
	TypeBlock         uint8
	MaxAreaAddresses  uint8 // common-header field; 0 = the default 3
	TLVs              []TLV

	// RawBytes is the verbatim PDU as decoded (nil when the struct was built
	// for encoding). The LSDB retains this for re-flood.
	RawBytes []byte
}

LSP is a decoded Level 1 or Level 2 Link State PDU (ISO/IEC 10589 clause 9.8). The PDU type distinguishes L1 (0x12) from L2 (0x14). RawBytes, when set on a decode, is the full PDU slice (for the LSDB to store and re-flood verbatim); it is nil on a struct built for encoding. TLVs are retained in order so an unknown TLV re-floods verbatim (ISO/IEC 10589 clause 7.3.14).

func DecodeLSP

func DecodeLSP(pt PDUType, full, body []byte) (LSP, error)

DecodeLSP parses an LSP body following the common header. body is the slice after the common header; full is the entire PDU slice (common header + body) so RawBytes can be retained for verbatim re-flood. Every field is bound-checked before slicing (security review).

func StripPurgeBody

func StripPurgeBody(lsp *LSP) *LSP

StripPurgeBody returns the canonical authenticated-purge form of an LSP: the LSP with its body removed (RFC 5304 sec 2: "ISes that ... initiate LSP purges MUST remove the body of the LSP and add the authentication TLV"). The returned PDU has Remaining Lifetime 0, no TLVs (the caller signs it, which adds TLV 10 as the only TLV), and a recomputed length. The caller then SignPDUs it. seq is the purge sequence number the originator assigns.

func (*LSP) EncodedLen

func (l *LSP) EncodedLen() int

EncodedLen returns the total on-wire size of the LSP.

func (*LSP) IsOverloaded

func (l *LSP) IsOverloaded() bool

IsOverloaded reports whether the LSP-database-overload (OL) bit is set in the type block (RFC 3787); SPF (isis-9) treats an overloaded node as transit-only.

func (*LSP) VerifyChecksum

func (l *LSP) VerifyChecksum() bool

VerifyChecksum recomputes the Fletcher checksum over this LSP's raw bytes and reports whether it is valid (ISO/IEC 10589 clause 7.3.11). It requires RawBytes to be set (a decoded LSP); for an LSP built in memory the checksum is computed by WriteTo, so verify the encoded output instead. Returns false if RawBytes is too short to contain the checksum region.

func (*LSP) WriteTo

func (l *LSP) WriteTo(buf []byte, off int) int

WriteTo serializes the LSP into buf at off and returns the new offset. The PDU Length is written via skip-and-backfill, and the ISO 8473 Fletcher checksum is computed over the region from the octet after Remaining Lifetime to the end and backfilled LAST (ISO/IEC 10589 clause 7.3.11). The Checksum field of the struct is ignored on encode; the computed value is authoritative and is also stored back into l.Checksum for the caller. Buffer-first.

Note (RFC 5304 sec 2 / isis-10): when authentication is enabled, isis-10 signs the PDU with the Checksum and Remaining Lifetime fields zeroed, AFTER padding, and BEFORE this checksum is computed. This codec computes the checksum over whatever auth TLV bytes are present; the engine's send order (build -> sign TLV 10 -> Fletcher checksum) guarantees the auth value is in place when the checksum runs.

type LSPEntriesTLV

type LSPEntriesTLV struct {
	Entries []LSPEntry
}

LSPEntriesTLV is the decoded TLV 9: a list of LSP summaries.

func DecodeLSPEntriesTLV

func DecodeLSPEntriesTLV(value []byte) (LSPEntriesTLV, error)

DecodeLSPEntriesTLV parses a TLV 9 value into fixed-size entries. A value length that is not a multiple of LSPEntryLen is rejected (ErrLength) so a crafted partial entry cannot be read past its bounds.

func (LSPEntriesTLV) EncodedLen

func (t LSPEntriesTLV) EncodedLen() int

EncodedLen returns the on-wire size of TLV 9 (type+length+value) for this entry list: the 2-octet TLV header plus 16 octets per entry. The caller (the flooding spec, isis-7) sizes its build buffer with this. The entry count must fit one TLV (<= 15 entries); isis-7 chunks larger lists.

type LSPEntry

type LSPEntry struct {
	RemainingLifetime types.RemainingLifetime
	LSPID             types.LSPID
	SequenceNumber    types.SequenceNumber
	Checksum          uint16
}

LSPEntry summarizes one LSP for CSNP/PSNP synchronization. The checksum is the LSP's stored Fletcher checksum (opaque to a CSNP/PSNP, compared as a value). isis-7 builds these from the LSDB.

type NarrowISReachEntry

type NarrowISReachEntry struct {
	DefaultMetricValue    uint8 // low 6 bits of the default metric octet
	DefaultMetricExternal bool  // I/E bit of the default metric octet (set = external)
	DelayMetric           uint8
	ExpenseMetric         uint8
	ErrorMetric           uint8
	Neighbor              types.SourceID
}

NarrowISReachEntry is one decoded TLV 2 entry. Only the fields a wide-metric IS needs for interop are surfaced; the delay/expense/error metrics are kept raw. DefaultMetricValue is the 6-bit metric; DefaultMetricInternal reports the I/E bit (0 = internal, 1 = external) of the default metric octet.

type NarrowISReachTLV

type NarrowISReachTLV struct {
	VirtualFlag uint8
	Entries     []NarrowISReachEntry
}

NarrowISReachTLV is the decoded TLV 2 (decode-only). VirtualFlag is the leading octet preceding the entries (ISO/IEC 10589 clause 9.3).

func DecodeNarrowISReachTLV

func DecodeNarrowISReachTLV(value []byte) (NarrowISReachTLV, error)

DecodeNarrowISReachTLV parses a TLV 2 value (decode-only, AC-14). The value must be at least 1 octet (the virtual flag) and the remainder a whole number of 11-octet entries; anything else is rejected with ErrLength rather than reading past the buffer. This never panics on arbitrary input (R-3).

type P2PHello

type P2PHello struct {
	CircuitType      CircuitType
	SystemID         types.SystemID
	HoldingTime      types.HoldingTime
	LocalCircuitID   uint8
	MaxAreaAddresses uint8 // common-header field; 0 = the default 3
	TLVs             []TLV
}

P2PHello is a decoded Point-to-Point IS-IS Hello (ISO/IEC 10589 clause 9.6). It is level-agnostic (its circuit type carries the level). LocalCircuitID is the 1-octet circuit ID on the sender's side. TLVs are retained in order (notably TLV 240 for the RFC 5303 three-way handshake).

func DecodeP2PHello

func DecodeP2PHello(body []byte) (P2PHello, error)

DecodeP2PHello parses a P2P IIH body following the common header.

func (*P2PHello) EncodedLen

func (h *P2PHello) EncodedLen() int

EncodedLen returns the total on-wire size of the P2P IIH.

func (*P2PHello) WriteTo

func (h *P2PHello) WriteTo(buf []byte, off int) int

WriteTo serializes the P2P IIH into buf at off; PDU Length via skip-and-backfill. Buffer-first.

type P2PThreeWayTLV

type P2PThreeWayTLV struct {
	State           AdjThreeWayState
	HasCircuitID    bool
	LocalCircuitID  uint32
	HasNeighbor     bool
	NeighborID      types.SystemID
	NeighborCircuit uint32
}

P2PThreeWayTLV is the decoded TLV 240. HasNeighbor reports whether the neighbor fields are present (the 15-octet form); HasCircuitID whether the extended local circuit ID is present (the 5- or 15-octet form).

func DecodeP2PThreeWayTLV

func DecodeP2PThreeWayTLV(value []byte) (P2PThreeWayTLV, error)

DecodeP2PThreeWayTLV parses a TLV 240 value (length 1, 5, or 15). Any other length is rejected (ErrLength) per RFC 5303 sec 3.1; the codec does not validate the state value here (isis-5 discards an invalid state).

type PDU

type PDU struct {
	Header   Header
	LANHello *LANHello
	P2PHello *P2PHello
	LSP      *LSP
	CSNP     *CSNP
	PSNP     *PSNP
}

PDU is the decoded union returned by DecodePDU. Exactly one of the typed pointers is non-nil, selected by Header.PDUType. The runtime dispatcher (isis-4 server.go) keys off Header.PDUType; this struct lets a single decode call return both the parsed header and the typed body without the caller re-switching on the type. The IIH/LSP/SNP body parsers can also be called directly when the PDU type is already known.

func DecodePDU

func DecodePDU(buf []byte) (PDU, error)

DecodePDU parses a complete IS-IS PDU: the common header followed by the type-specific body. It validates the common header (discriminator, version, ID length, known PDU type), dispatches by the 5-bit PDU type to the matching body decoder, and threads the common-header Max Area Addresses field into the typed body. It never panics on arbitrary input (AC-11, R-3): a bad header or a truncated body returns a typed error.

buf is one whole PDU (the 802.3 + LLC framing already stripped by isis-3, or supplied directly by the offline decode CLI). Decoded TLV value slices alias buf; the caller copies any it retains.

func (*PDU) Release

func (p *PDU) Release()

Release returns the decoded TLV slice to the pool. Callers must not access the PDU's TLVs after this call.

func (PDU) ToJSON

func (p PDU) ToJSON() JSONView

ToJSON renders a decoded PDU to its JSON view. Cold path (CLI/diagnostics).

type PDUType

type PDUType uint8

PDUType is the 1-octet PDU type field of the IS-IS common header. Only the low 5 bits are the type code (ISO/IEC 10589 clause 9.5); the high 3 bits are reserved and MUST be zero on transmit.

const (
	PDUTypeL1LANHello PDUType = 0x0f // 15: Level 1 LAN IS-IS Hello
	PDUTypeL2LANHello PDUType = 0x10 // 16: Level 2 LAN IS-IS Hello
	PDUTypeP2PHello   PDUType = 0x11 // 17: Point-to-Point IS-IS Hello
	PDUTypeL1LSP      PDUType = 0x12 // 18: Level 1 Link State PDU
	PDUTypeL2LSP      PDUType = 0x14 // 20: Level 2 Link State PDU
	PDUTypeL1CSNP     PDUType = 0x18 // 24: Level 1 Complete Sequence Numbers PDU
	PDUTypeL2CSNP     PDUType = 0x19 // 25: Level 2 Complete Sequence Numbers PDU
	PDUTypeL1PSNP     PDUType = 0x1a // 26: Level 1 Partial Sequence Numbers PDU
	PDUTypeL2PSNP     PDUType = 0x1b // 27: Level 2 Partial Sequence Numbers PDU
)

PDU type code octets (ISO/IEC 10589 clause 9).

These are the AUTHORITATIVE values from ISO/IEC 10589 clause 9 and the umbrella contract. The research guide (docs/research/isis-implementation-guide.md sec 2) transcribes the L1 codes incorrectly (it lists L1 LSP 0x18, L1 CSNP 0x24, L1 PSNP 0x26); those are typos. TestISISPDUConstants pins these exact values so a regression cannot silently break interop (spec A-5).

func (PDUType) Level

func (t PDUType) Level() (level uint8, ok bool)

Level reports the IS-IS level (1 or 2) implied by a PDU type, and ok=false for the P2P Hello (which is level-agnostic; its circuit type carries the level) or an unknown type.

func (PDUType) String

func (t PDUType) String() string

String renders the PDU type as a stable short token (for CLI/JSON). Cold path; the small switch returns interned literals (no allocation).

type PSNP

type PSNP struct {
	PDUType          PDUType // PDUTypeL1PSNP or PDUTypeL2PSNP
	SourceID         types.SourceID
	MaxAreaAddresses uint8 // common-header field; 0 = the default 3
	TLVs             []TLV
}

PSNP is a decoded Level 1 or Level 2 Partial Sequence Numbers PDU (ISO/IEC 10589 clause 9.11). It carries TLV 9 (LSP Entries) to acknowledge or request individual LSPs. The PDU type distinguishes L1 (0x1a) from L2 (0x1b).

func DecodePSNP

func DecodePSNP(pt PDUType, body []byte) (PSNP, error)

DecodePSNP parses a PSNP body following the common header.

func (*PSNP) EncodedLen

func (p *PSNP) EncodedLen() int

EncodedLen returns the total on-wire size of the PSNP.

func (*PSNP) WriteTo

func (p *PSNP) WriteTo(buf []byte, off int) int

WriteTo serializes the PSNP into buf at off; PDU Length via skip-and-backfill. Buffer-first.

type ProtocolsSupportedTLV

type ProtocolsSupportedTLV struct {
	NLPIDs []uint8
}

ProtocolsSupportedTLV is the decoded TLV 129.

func DecodeProtocolsSupportedTLV

func DecodeProtocolsSupportedTLV(value []byte) ProtocolsSupportedTLV

DecodeProtocolsSupportedTLV parses a TLV 129 value (one NLPID per octet).

type SubTLV

type SubTLV struct {
	Type  uint8
	Value []byte
}

SubTLV is one sub-TLV (RFC 5305 sec 2): the same Type(1)+Length(1)+Value framing as a TLV, nested inside a TLV 22/135/236 entry. Value aliases the source buffer on decode. Unknown sub-TLVs are retained and re-emitted verbatim, matching the unknown-TLV passthrough contract one level down (RFC 5305 sec 2: "Unknown sub-TLVs are to be ignored and skipped upon receipt" -- the codec keeps them so the entry round-trips, and leaves the ignore policy to the consumer).

func (SubTLV) EncodedLen

func (s SubTLV) EncodedLen() int

EncodedLen returns the on-wire size of this sub-TLV.

type TLV

type TLV struct {
	Type  uint8
	Value []byte
}

TLV is one decoded TLV retained as a type plus its raw value bytes. It is the opaque carrier used both for unknown TLVs (re-flooded verbatim per ISO/IEC 10589 clause 7.3.14) and as a uniform encode unit for TLVs the caller has already serialized. Value aliases the source buffer on decode; callers that retain it past the buffer's lifetime must copy (see CopyValue).

func DecodeTLVs

func DecodeTLVs(buf []byte) ([]TLV, error)

DecodeTLVs walks the entire TLV region and returns every TLV in order, retaining each value as an opaque span (zero-copy: the values alias buf). Unknown types are kept identically to known ones, so re-encoding the slice reproduces the region byte-for-byte (AC-5, R-6). A truncated final TLV stops the walk and is reported via the error; the TLVs decoded before the truncation are still returned.

Allocation uses a fixed capacity so all TLV slices are the same size, enabling future pool reuse. The cap is the maximum TLV count that fits in a single MTU-bounded PDU; each TLV consumes at least TLVHeaderLen octets (security review: resource exhaustion).

func (TLV) CopyValue

func (t TLV) CopyValue() TLV

CopyValue returns a TLV whose Value is an independent copy, safe to retain after the source buffer is recycled (isis-6 LSDB retention).

func (TLV) EncodedLen

func (t TLV) EncodedLen() int

EncodedLen returns the number of octets this TLV occupies on the wire.

func (TLV) WriteTo

func (t TLV) WriteTo(buf []byte, off int) int

WriteTo serializes the TLV (type + length + value) into buf at off and returns the new offset. Buffer-first; the caller guarantees room. The value length is assumed valid (<= MaxTLVValueLen); DecodeTLVs cannot produce a longer value because the wire length field is a single octet.

type TLVIterator

type TLVIterator struct {
	// contains filtered or unexported fields
}

TLVIterator walks a TLV region lazily, yielding (type, value-slice) pairs without copying. Decode is zero-copy per ai/rules/buffer-first.md: the value slices alias the caller's buffer and are valid only while it is stable.

The iterator never panics on malformed input (spec R-3, AC-11): a TLV whose declared length runs past the end of the region terminates iteration and is reported via Err. The same type is used for sub-TLV regions (RFC 5305 sec 2).

func NewTLVIterator

func NewTLVIterator(buf []byte) TLVIterator

NewTLVIterator returns an iterator over the TLV region buf. The region is the raw TLV bytes only (no PDU header); callers slice it out of the PDU first.

func (*TLVIterator) Err

func (it *TLVIterator) Err() error

Err returns the first error encountered (nil on a clean walk to the region boundary). It is set when a TLV's declared length overruns the region.

func (*TLVIterator) Next

func (it *TLVIterator) Next() (typ uint8, value []byte, ok bool)

Next returns the next (type, value) pair and ok=true, or ok=false at the end of the region or on a truncated TLV. Every read is bound-checked before slicing (security review: input validation). When a TLV's declared length exceeds the remaining bytes, Next stops and records ErrTruncated; the partial bytes are not yielded.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL