pim

package
v0.331.0 Latest Latest
Warning

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

Go to latest
Published: May 21, 2026 License: AGPL-3.0 Imports: 5 Imported by: 0

Documentation

Overview

Package pim decodes Protocol Independent Multicast (PIM) version 2 packets per RFC 7761 (PIM-SM v2; the dominant multicast routing protocol). PIM Sparse-Mode is the de-facto multicast routing protocol in every enterprise + ISP + cloud fabric that carries multicast traffic; the Dense-Mode + BIDIR variants share the same packet envelope and the same type space.

Wrap-vs-native judgement

Native. RFC 7761 is fully public; PIM uses a tight 4-byte
common header (Version + Type + Reserved + Checksum)
followed by a per-type body. Bodies use a small set of
well-defined "Encoded Address" formats (Unicast / Group /
Source — RFC 7761 §4.9) plus typed TLV options for Hello.
No crypto, no compression — operators paste PIM bytes (IP
protocol number 103, multicast to 224.0.0.13 for Hello /
Bootstrap / Assert / Join-Prune, unicast to RPs for
Register) from a `tcpdump -X proto 103` line, a Wireshark
Follow-IP-Stream view, or any PIM-speaking router's
tcpdump and get the documented header + per-type body
breakdown.

What this package covers

  • **4-byte common header** (RFC 7761 §4.9):

  • byte 0: Version (4 bits; always 2) + Type (4 bits).

  • byte 1: Reserved (0; some PIM variants use this byte as a subtype — surfaced as a Note when non-zero).

  • bytes 2-3: Checksum (uint16 BE, hex-formatted).

  • **11-entry Type name table** (RFC 7761 §4.9 + the older PIM-DM / BIDIR / PIM-MIB registries): 0 Hello, 1 Register, 2 Register-Stop, 3 Join/Prune, 4 Bootstrap, 5 Assert, 6 Graft (PIM-DM only), 7 Graft-Ack (PIM-DM only), 8 Candidate-RP-Advertisement, 9 State Refresh (PIM-DM only), 10 DF Election (PIM-BIDIR).

  • **Hello body** (Type 0; RFC 7761 §4.3) — TLV option walker over (Type uint16 BE, Length uint16 BE, Value) records. **5-entry option type table**: 1 Holdtime (uint16 seconds; 0xFFFF = never timeout), 2 LAN Prune Delay (uint16 propagation_delay + uint16 override_interval with T-bit in the high bit of propagation_delay), 19 DR Priority (uint32 — higher wins; absence = treat as priority 0 per RFC 7761 §4.3.2), 20 Generation ID (uint32 — changes on neighbor reset; a change is the canonical detection of a PIM neighbor reboot), 24 Address List (encoded-address list of secondary addresses the router owns on the LAN).

  • **Register body** (Type 1; RFC 7761 §4.4) — 4-byte flags (B = Border-bit, N = Null-Register-bit) + encapsulated multicast IP datagram (surfaced as raw hex; first nibble heuristic for inner IPv4 vs IPv6).

  • **Register-Stop body** (Type 2; RFC 7761 §4.4) — Encoded Group Address + Encoded Unicast Source Address.

  • **Join/Prune body** (Type 3; RFC 7761 §4.5) — Encoded Unicast Upstream Neighbor + Reserved + Num Groups + Hold Time (uint16 seconds) + N × Group records:

  • Multicast Group Address (Encoded Group)

  • Number of Joined Sources (uint16)

  • Number of Pruned Sources (uint16)

  • Joined Source Addresses (N × Encoded Source)

  • Pruned Source Addresses (N × Encoded Source)

  • **Bootstrap body** (Type 4; RFC 5059) — Fragment Tag + Hash Mask Len + BSR Priority + Encoded Unicast BSR Address + per-group RP-Set records (decoded structurally, including the RP records inside each group).

  • **Assert body** (Type 5; RFC 7761 §4.6) — Encoded Group Address + Encoded Unicast Source Address + 1-bit R (RPT bit, high bit of byte 0) + 31-bit Metric Preference + 32-bit Metric. Used for tie-breaking when multiple PIM routers see the same multicast forwarder candidate on a LAN.

  • **Encoded Address parsing** (RFC 7761 §4.9.1):

  • **Encoded Unicast** — Addr Family (1 byte: 1 IPv4 / 2 IPv6) + Encoding Type (1 byte; 0 native) + Address (4 bytes IPv4 / 16 bytes IPv6).

  • **Encoded Group** — Addr Family + Encoding Type + Flags byte (B-bit + Z-bit) + Mask Length + Group Address.

  • **Encoded Source** — Addr Family + Encoding Type + Flags byte (S/W/R bits in the low 3 bits of byte 2) + Mask Length + Source Address.

What this package does NOT cover (deliberately out of scope)

  • IP framing — feed PIM bytes after the IPv4/IPv6 header strip. PIM runs over IP protocol 103.

  • PIMv1 — the pre-RFC 2117 "DVMRP-like" form is obsolete (no production deployments since the late 1990s); the Version field will be flagged in a Note if it is not 2.

  • Multicast routing-table reasoning — RPF check, (*,G) and (S,G) tree state — that's higher-level analysis.

  • PIM checksum verification — surfaced as a hex string but not recomputed (the IPv4 pseudo-header dependency would require the operator to provide the IP src/dst).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AssertBody

type AssertBody struct {
	Group            EncodedGroup   `json:"group"`
	Source           EncodedUnicast `json:"source"`
	RPTBit           bool           `json:"rpt_bit"`
	MetricPreference uint32         `json:"metric_preference"`
	Metric           uint32         `json:"metric"`
}

AssertBody is a PIM Assert with the (group, source) tuple and the metric.

type BootstrapBody

type BootstrapBody struct {
	FragmentTag    uint16         `json:"fragment_tag"`
	HashMaskLen    int            `json:"hash_mask_length"`
	BSRPriority    int            `json:"bsr_priority"`
	BSRAddress     EncodedUnicast `json:"bsr_address"`
	RemainderHex   string         `json:"remainder_hex,omitempty"`
	RemainderBytes int            `json:"remainder_bytes"`
}

BootstrapBody is a PIM-BSR Bootstrap message.

type EncodedGroup

type EncodedGroup struct {
	AddressFamily int    `json:"address_family"`
	EncodingType  int    `json:"encoding_type"`
	BBit          bool   `json:"b_bit_bidir"`
	ZBit          bool   `json:"z_bit_admin_scope_zone"`
	MaskLength    int    `json:"mask_length"`
	Address       string `json:"address"`
}

EncodedGroup is RFC 7761 §4.9.1 Encoded-Group-Address.

type EncodedSource

type EncodedSource struct {
	AddressFamily int    `json:"address_family"`
	EncodingType  int    `json:"encoding_type"`
	SBit          bool   `json:"s_bit_sparse"`
	WBit          bool   `json:"w_bit_wildcard"`
	RBit          bool   `json:"r_bit_rpt"`
	MaskLength    int    `json:"mask_length"`
	Address       string `json:"address"`
}

EncodedSource is RFC 7761 §4.9.1 Encoded-Source-Address.

type EncodedUnicast

type EncodedUnicast struct {
	AddressFamily int    `json:"address_family"`
	EncodingType  int    `json:"encoding_type"`
	Address       string `json:"address"`
}

EncodedUnicast is RFC 7761 §4.9.1 Encoded-Unicast-Address.

type HelloBody

type HelloBody struct {
	Options []HelloOption `json:"options"`
}

HelloBody is the TLV option list from a PIM Hello.

type HelloOption

type HelloOption struct {
	Type     int    `json:"type"`
	TypeName string `json:"type_name"`
	Length   int    `json:"length"`
	ValueHex string `json:"value_hex,omitempty"`

	// Decoded forms (populated for known types).
	HoldtimeSeconds       *int     `json:"holdtime_seconds,omitempty"`
	HoldtimeNote          string   `json:"holdtime_note,omitempty"`
	DRPriority            *uint32  `json:"dr_priority,omitempty"`
	GenerationID          *uint32  `json:"generation_id,omitempty"`
	LANPropagationDelayMs *uint16  `json:"lan_propagation_delay_ms,omitempty"`
	LANOverrideIntervalMs *uint16  `json:"lan_override_interval_ms,omitempty"`
	LANTBit               *bool    `json:"lan_t_bit,omitempty"`
	AddressList           []string `json:"address_list,omitempty"`
}

HelloOption is one TLV record from a PIM Hello.

type JoinPruneBody

type JoinPruneBody struct {
	UpstreamNeighbor EncodedUnicast   `json:"upstream_neighbor"`
	NumGroups        int              `json:"num_groups"`
	HoldTimeSeconds  int              `json:"hold_time_seconds"`
	Groups           []JoinPruneGroup `json:"groups"`
}

JoinPruneBody is the Join/Prune state for one upstream neighbor.

type JoinPruneGroup

type JoinPruneGroup struct {
	Group         EncodedGroup    `json:"group"`
	NumJoined     int             `json:"num_joined_sources"`
	NumPruned     int             `json:"num_pruned_sources"`
	JoinedSources []EncodedSource `json:"joined_sources,omitempty"`
	PrunedSources []EncodedSource `json:"pruned_sources,omitempty"`
}

JoinPruneGroup is one group record inside a Join/Prune.

type RegisterBody

type RegisterBody struct {
	FlagBorder   bool   `json:"flag_border"`
	FlagNull     bool   `json:"flag_null_register"`
	FlagsHex     string `json:"flags_hex"`
	EncapHex     string `json:"encapsulated_datagram_hex,omitempty"`
	EncapBytes   int    `json:"encapsulated_datagram_bytes"`
	EncapVersion int    `json:"encapsulated_ip_version,omitempty"`
}

RegisterBody is the unicast-tunnelled multicast datagram body.

type RegisterStopBody

type RegisterStopBody struct {
	Group  EncodedGroup   `json:"group"`
	Source EncodedUnicast `json:"source"`
}

RegisterStopBody is the stop signal for a Register tunnel.

type Result

type Result struct {
	Version     int    `json:"version"`
	Type        int    `json:"type"`
	TypeName    string `json:"type_name"`
	Reserved    int    `json:"reserved"`
	ChecksumHex string `json:"checksum_hex"`
	TotalBytes  int    `json:"total_bytes"`

	Hello        *HelloBody        `json:"hello,omitempty"`
	Register     *RegisterBody     `json:"register,omitempty"`
	RegisterStop *RegisterStopBody `json:"register_stop,omitempty"`
	JoinPrune    *JoinPruneBody    `json:"join_prune,omitempty"`
	Assert       *AssertBody       `json:"assert,omitempty"`
	Bootstrap    *BootstrapBody    `json:"bootstrap,omitempty"`

	Notes []string `json:"notes,omitempty"`
}

Result is the top-level decoded view.

func Decode

func Decode(hexStr string) (*Result, error)

Decode parses a single PIMv2 packet from hex.

Jump to

Keyboard shortcuts

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