l2tp

package
v0.366.0 Latest Latest
Warning

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

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

Documentation

Overview

Package l2tp decodes L2TPv3 packets per RFC 3931 (UDP- encapsulated mode on UDP port 1701). L2TPv3 is the pseudowire encapsulation that pairs with PPPoE (covered by `pppoe_decode`) to complete the broadband subscriber- management story: PPPoE handles the access-side session from the customer modem to the BNG; L2TPv3 handles the backhaul/aggregation tunnel from the BNG to a Layer-2 VPN concentrator (LAC → LNS in classic deployments).

L2TPv3 is also the dominant transport for:

  • **Lawful intercept (LI) at every ISP** — voice + data captures are funnelled through L2TPv3 tunnels from edge LACs to a centralised LI mediation function.

  • **L2 VPN services** — Ethernet, ATM, Frame Relay, PPP, and HDLC pseudowires across MPLS or IP cores.

  • **Subscriber backhaul** — wholesale broadband resellers tunnel customers from CLEC LACs to their LNS for centralised AAA + IP allocation.

Wrap-vs-native judgement

Native. RFC 3931 is fully public. L2TPv3 has a tight
bit-packed common header that dispatches between
Control Messages (T=1) and Data Messages (T=0) via
the high bit. Control Messages carry an AVP
(Attribute-Value Pair) list with a small set of
well-defined Attribute Types; Data Messages carry an
opaque L2 frame after a small Session ID + Cookie
envelope. No crypto at the parse layer.

What this package covers

  • **16-bit common header** (RFC 3931 §3.2.1): bit 0 = **T** (Type: 0 Data, 1 Control); bit 1 = L (Length present); bits 2-3 reserved; bit 4 = S (Ns/Nr present); bits 5-7 reserved; bits 8-11 reserved; bits 12-15 = **Version** (must be 3 for L2TPv3).

  • **Control Message** (T=1; RFC 3931 §3.2.2): Length (uint16 BE; total bytes including this field's position) + Control Connection ID (uint32 BE; the peer-end's connection identifier) + Ns (uint16 BE; send sequence number) + Nr (uint16 BE; expected receive sequence number) + AVP list.

  • **AVP walker** (RFC 3931 §5.2) — each AVP:

  • 2 bytes: 1-bit Mandatory + 1-bit Hidden + 1-bit Reserved + 10-bit Length + 3 reserved bits packed into the high 6 bits + 10-bit Length in low 10 bits. (The bit-pack is `M H r r r r LLLLLLLLLL`.)

  • 2 bytes: Vendor ID (uint16 BE; 0 = IETF, others = SMI Private Enterprise Number).

  • 2 bytes: Attribute Type (uint16 BE).

  • Length-6 bytes: Value. **~15-entry IETF AVP name table** (when Vendor ID = 0): Message Type / Result Code / Protocol Version / Framing Capabilities / Bearer Capabilities / Tie Breaker / Firmware Revision / Host Name / Vendor Name / Assigned Tunnel ID / Receive Window Size / Challenge / Challenge Response / Cause Code / Q.931 Cause Code / Assigned Session ID / Call Serial Number / Local Session ID / Remote Session ID / Random Vector.

  • **Message Type AVP** (Attribute 0) — first AVP in every Control Message; its 2-byte value names the control message kind via a **16-entry name table** (RFC 3931 §5.4): 1 SCCRQ (Start-Control-Connection- Request) / 2 SCCRP (Start-Control-Connection-Reply) / 3 SCCCN (Start-Control-Connection-Connected) / 4 StopCCN (Stop-Control-Connection-Notification) / 6 HELLO (Keepalive) / 7 OCRQ (Outgoing-Call-Request) / 8 OCRP (Outgoing-Call-Reply) / 9 OCCN (Outgoing- Call-Connected) / 10 ICRQ (Incoming-Call-Request) / 11 ICRP (Incoming-Call-Reply) / 12 ICCN (Incoming- Call-Connected) / 14 CDN (Call-Disconnect-Notify) / 15 WEN (WAN-Error-Notify) / 16 SLI (Set-Link-Info) / 20 ACK (Acknowledgement, RFC 3931 addition).

  • **Data Message** (T=0): Session ID (uint32 BE; the peer-end's session identifier) + optional Cookie (4 or 8 bytes, negotiated during ICRQ/ICRP via "Assigned Cookie" AVP) + L2-Specific Sublayer (varies by encap; default L2SS is empty) + L2 Frame (opaque; surfaced as hex preview). The decoder surfaces the Session ID and the rest as raw hex pending operator-provided framing context.

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

  • UDP framing — feed L2TPv3 bytes after the UDP header strip. UDP-mode L2TPv3 runs on destination port 1701; IP-mode runs as IP protocol 115.

  • IP-mode L2TPv3 (IP protocol 115) — different envelope (no UDP header; Session ID 0 indicates a Control Message). Could share most decoder logic; deferred.

  • Per-AVP value type-aware decoding beyond Message Type and a few well-known integer/string AVPs — values are surfaced as hex with plausibly-text UTF-8 surfacing for Host Name / Vendor Name.

  • Hidden (encrypted) AVPs — the H bit is surfaced but decryption requires the shared secret + RFC 3931 §4.3 procedure; deferred.

  • PPP / HDLC / Ethernet / ATM / FR frame dissection inside Data Message payload — operator pulls bytes out of the payload preview and feeds into the appropriate L2 decoder.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AVP

type AVP struct {
	Mandatory     bool   `json:"mandatory"`
	Hidden        bool   `json:"hidden"`
	Length        int    `json:"length"`
	VendorID      int    `json:"vendor_id"`
	AttributeType int    `json:"attribute_type"`
	AttributeName string `json:"attribute_name,omitempty"`
	ValueHex      string `json:"value_hex,omitempty"`
	ValueText     string `json:"value_text,omitempty"`
}

AVP is one (Mandatory, Hidden, Length, Vendor ID, Attribute Type, Value) record from the AVP walker.

type ControlMessage

type ControlMessage struct {
	Length              int    `json:"length"`
	ControlConnectionID uint32 `json:"control_connection_id"`
	Ns                  int    `json:"send_sequence"`
	Nr                  int    `json:"expected_receive_sequence"`
	MessageType         int    `json:"message_type,omitempty"`
	MessageTypeName     string `json:"message_type_name,omitempty"`
	AVPs                []AVP  `json:"avps"`
}

ControlMessage is the decoded body of an L2TPv3 control message (T=1).

type DataMessage

type DataMessage struct {
	SessionID         uint32 `json:"session_id"`
	PayloadBytes      int    `json:"payload_bytes"`
	PayloadBytesShown int    `json:"payload_bytes_shown,omitempty"`
	PayloadHex        string `json:"payload_hex,omitempty"`
}

DataMessage is the decoded body of an L2TPv3 data message (T=0).

type DecodeOpts

type DecodeOpts struct {
	// MaxPayloadBytes caps the Data Message payload hex
	// preview. Zero surfaces the full payload.
	MaxPayloadBytes int
}

DecodeOpts tunes the walker for output size.

func DefaultDecodeOpts

func DefaultDecodeOpts() DecodeOpts

DefaultDecodeOpts returns a 256-byte payload preview cap.

type Result

type Result struct {
	Type            int    `json:"type"`
	TypeName        string `json:"type_name"`
	LengthPresent   bool   `json:"length_present"`
	SequencePresent bool   `json:"sequence_present"`
	Version         int    `json:"version"`

	Control *ControlMessage `json:"control_message,omitempty"`
	Data    *DataMessage    `json:"data_message,omitempty"`

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

Result is the top-level decoded view of an L2TPv3 packet.

func Decode

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

Decode parses a single L2TPv3 packet from hex.

Jump to

Keyboard shortcuts

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