package packet
import "tailscale.com/net/packet"
Package packet contains packet parsing and marshaling utilities.
Parsed provides allocation-free minimal packet header decoding, for use in packet filtering. The other types in the package are for constructing and marshaling packets into []bytes.
To support allocation-free parsing, this package defines IPv4 and IPv6 address types. You should prefer to use netaddr's types, except where you absolutely need allocation-free IP handling (i.e. in the tunnel datapath) and are willing to implement all codepaths and data structures twice, once per IP family.
Index ¶
- Constants
- func Generate(h Header, payload []byte) []byte
- func Hexdump(b []byte) string
- func ICMPEchoPayload(payload []byte) (idSeq uint32, buf []byte)
- type CaptureCallback
- type CaptureMeta
- type CapturePath
- type CaptureSink
- type GeneveHeader
- type Header
- type HeaderChecksummer
- type ICMP4Code
- type ICMP4Header
- func (h ICMP4Header) Len() int
- func (h ICMP4Header) Marshal(buf []byte) error
- func (h *ICMP4Header) ToResponse()
- type ICMP4Type
- type ICMP6Code
- type ICMP6Header
- func (h ICMP6Header) Len() int
- func (h ICMP6Header) Marshal(buf []byte) error
- func (h *ICMP6Header) ToResponse()
- func (h ICMP6Header) WriteChecksum(p []byte)
- type ICMP6Type
- type IP4Header
- func (h IP4Header) Len() int
- func (h IP4Header) Marshal(buf []byte) error
- func (h *IP4Header) ToResponse()
- type IP6Header
- func (h IP6Header) Len() int
- func (h IP6Header) Marshal(buf []byte) error
- func (h *IP6Header) ToResponse()
- type Parsed
- func (pp *Parsed) AsTSMPPing() (h TSMPPingRequest, ok bool)
- func (pp *Parsed) AsTSMPPong() (pong TSMPPongReply, ok bool)
- func (pp *Parsed) AsTailscaleRejectedHeader() (h TailscaleRejectedHeader, ok bool)
- func (q *Parsed) Buffer() []byte
- func (q *Parsed) Decode(b []byte)
- func (q *Parsed) EchoIDSeq() uint32
- func (q *Parsed) ICMP4Header() ICMP4Header
- func (q *Parsed) ICMP6Header() ICMP6Header
- func (q *Parsed) IP4Header() IP4Header
- func (q *Parsed) IP6Header() IP6Header
- func (q *Parsed) IsEchoRequest() bool
- func (q *Parsed) IsEchoResponse() bool
- func (q *Parsed) IsError() bool
- func (q *Parsed) IsTCPSyn() bool
- func (q *Parsed) Payload() []byte
- func (p *Parsed) String() string
- func (q *Parsed) StuffForTesting(len int)
- func (p *Parsed) Transport() []byte
- func (q *Parsed) UDP4Header() UDP4Header
- type TCPFlag
- type TSMPPingRequest
- type TSMPPongReply
- type TSMPType
- type TailscaleRejectReason
- type TailscaleRejectedHeader
- func (rh TailscaleRejectedHeader) Flow() flowtrack.Tuple
- func (h TailscaleRejectedHeader) Len() int
- func (h TailscaleRejectedHeader) Marshal(buf []byte) error
- func (rh TailscaleRejectedHeader) String() string
- type UDP4Header
- func (h UDP4Header) Len() int
- func (h UDP4Header) Marshal(buf []byte) error
- func (h *UDP4Header) ToResponse()
- type UDP6Header
Constants ¶
const ( // GeneveProtocolDisco is the IEEE 802 Ethertype number used to represent // the Tailscale Disco protocol in a Geneve header. GeneveProtocolDisco uint16 = 0x7A11 // GeneveProtocolWireGuard is the IEEE 802 Ethertype number used to represent the // WireGuard protocol in a Geneve header. GeneveProtocolWireGuard uint16 = 0x7A12 )
const ( // GeneveFixedHeaderLength is the length of the fixed size portion of the // Geneve header, in bytes. GeneveFixedHeaderLength = 8 )
Functions ¶
func Generate ¶
Generate generates a new packet with the given Header and payload. This function allocates memory, see Header.Marshal for an allocation-free option.
func Hexdump ¶
func ICMPEchoPayload ¶
ICMPEchoPayload generates a new random ID/Sequence pair, and returns a uint32 derived from them, along with the id, sequence and given payload in a buffer. It returns an error if the random source could not be read.
Types ¶
type CaptureCallback ¶
type CaptureCallback func(CapturePath, time.Time, []byte, CaptureMeta)
Callback describes a function which is called to record packets when debugging packet-capture. Such callbacks must not take ownership of the provided data slice: it may only copy out of it within the lifetime of the function.
type CaptureMeta ¶
type CaptureMeta struct { DidSNAT bool // SNAT was performed & the address was updated. OriginalSrc netip.AddrPort // The source address before SNAT was performed. DidDNAT bool // DNAT was performed & the address was updated. OriginalDst netip.AddrPort // The destination address before DNAT was performed. }
CaptureMeta contains metadata that is used when debugging.
type CapturePath ¶
type CapturePath uint8
CapturePath describes where in the data path the packet was captured.
const ( // FromLocal indicates the packet was logged as it traversed the FromLocal path: // i.e.: A packet from the local system into the TUN. FromLocal CapturePath = 0 // FromPeer indicates the packet was logged upon reception from a remote peer. FromPeer CapturePath = 1 // SynthesizedToLocal indicates the packet was generated from within tailscaled, // and is being routed to the local machine's network stack. SynthesizedToLocal CapturePath = 2 // SynthesizedToPeer indicates the packet was generated from within tailscaled, // and is being routed to a remote Wireguard peer. SynthesizedToPeer CapturePath = 3 // PathDisco indicates the packet is information about a disco frame. PathDisco CapturePath = 254 )
CapturePath values
type CaptureSink ¶
type CaptureSink interface { // Close closes Close() error // NumOutputs returns the number of outputs registered with the sink. NumOutputs() int // CaptureCallback returns a callback which can be used to // write packets to the sink. CaptureCallback() CaptureCallback // WaitCh returns a channel which blocks until // the sink is closed. WaitCh() <-chan struct{} // RegisterOutput connects an output to this sink, which // will be written to with a pcap stream as packets are logged. // A function is returned which unregisters the output when // called. // // If w implements io.Closer, it will be closed upon error // or when the sink is closed. If w implements http.Flusher, // it will be flushed periodically. RegisterOutput(w io.Writer) (unregister func()) }
CaptureSink is the minimal interface from tailscale.com/feature/capture's Sink type that is needed by the core (magicsock/LocalBackend/wgengine/etc). This lets the relativel heavy feature/capture package be optionally linked.
type GeneveHeader ¶
type GeneveHeader struct { // Ver (2 bits): The current version number is 0. Packets received by a // tunnel endpoint with an unknown version MUST be dropped. Transit devices // interpreting Geneve packets with an unknown version number MUST treat // them as UDP packets with an unknown payload. Version uint8 // Protocol Type (16 bits): The type of protocol data unit appearing after // the Geneve header. This follows the Ethertype [ETYPES] convention, with // Ethernet itself being represented by the value 0x6558. Protocol uint16 // Virtual Network Identifier (VNI) (24 bits): An identifier for a unique // element of a virtual network. In many situations, this may represent an // L2 segment; however, the control plane defines the forwarding semantics // of decapsulated packets. The VNI MAY be used as part of ECMP forwarding // decisions or MAY be used as a mechanism to distinguish between // overlapping address spaces contained in the encapsulated packet when load // balancing across CPUs. VNI uint32 // O (1 bit): Control packet. This packet contains a control message. // Control messages are sent between tunnel endpoints. Tunnel endpoints MUST // NOT forward the payload, and transit devices MUST NOT attempt to // interpret it. Since control messages are less frequent, it is RECOMMENDED // that tunnel endpoints direct these packets to a high-priority control // queue (for example, to direct the packet to a general purpose CPU from a // forwarding Application-Specific Integrated Circuit (ASIC) or to separate // out control traffic on a NIC). Transit devices MUST NOT alter forwarding // behavior on the basis of this bit, such as ECMP link selection. Control bool }
GeneveHeader represents the fixed size Geneve header from RFC8926. TLVs/options are not implemented/supported.
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Ver| Opt Len |O|C| Rsvd. | Protocol Type | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Virtual Network Identifier (VNI) | Reserved | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
func (*GeneveHeader) Decode ¶
func (h *GeneveHeader) Decode(b []byte) error
Decode decodes GeneveHeader from b. If len(b) < GeneveFixedHeaderLength an io.ErrShortBuffer error is returned.
func (*GeneveHeader) Encode ¶
func (h *GeneveHeader) Encode(b []byte) error
Encode encodes GeneveHeader into b. If len(b) < GeneveFixedHeaderLength an io.ErrShortBuffer error is returned.
type Header ¶
type Header interface { // Len returns the length of the marshaled packet. Len() int // Marshal serializes the header into buf, which must be at // least Len() bytes long. Implementations of Marshal assume // that bytes after the first Len() are payload bytes for the // purpose of computing length and checksum fields. Marshal // implementations must not allocate memory. Marshal(buf []byte) error }
Header is a packet header capable of marshaling itself into a byte buffer.
type HeaderChecksummer ¶
type HeaderChecksummer interface { Header // WriteCheck writes the correct checksum into buf, which should // be be the already-marshalled header and payload. WriteChecksum(buf []byte) }
HeaderChecksummer is implemented by Header implementations that need to do a checksum over their payloads.
type ICMP4Code ¶
type ICMP4Code uint8
ICMP4Code is an ICMPv4 code, as specified in https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml
const ( ICMP4NoCode ICMP4Code = 0 )
type ICMP4Header ¶
ICMP4Header is an IPv4+ICMPv4 header.
func (ICMP4Header) Len ¶
func (h ICMP4Header) Len() int
Len implements Header.
func (ICMP4Header) Marshal ¶
func (h ICMP4Header) Marshal(buf []byte) error
Marshal implements Header.
func (*ICMP4Header) ToResponse ¶
func (h *ICMP4Header) ToResponse()
ToResponse implements Header. TODO: it doesn't implement it correctly, instead it statically generates an ICMP Echo Reply packet.
type ICMP4Type ¶
type ICMP4Type uint8
ICMP4Type is an ICMPv4 type, as specified in https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml
const ( ICMP4EchoReply ICMP4Type = 0x00 ICMP4EchoRequest ICMP4Type = 0x08 ICMP4Unreachable ICMP4Type = 0x03 ICMP4TimeExceeded ICMP4Type = 0x0b ICMP4ParamProblem ICMP4Type = 0x12 )
func (ICMP4Type) String ¶
type ICMP6Code ¶
type ICMP6Code uint8
ICMP6Code is an ICMPv6 code, as specified in https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xhtml
const ( ICMP6NoCode ICMP6Code = 0 )
type ICMP6Header ¶
ICMP6Header is an IPv4+ICMPv4 header.
func (ICMP6Header) Len ¶
func (h ICMP6Header) Len() int
Len implements Header.
func (ICMP6Header) Marshal ¶
func (h ICMP6Header) Marshal(buf []byte) error
Marshal implements Header.
func (*ICMP6Header) ToResponse ¶
func (h *ICMP6Header) ToResponse()
ToResponse implements Header. TODO: it doesn't implement it correctly, instead it statically generates an ICMP Echo Reply packet.
func (ICMP6Header) WriteChecksum ¶
func (h ICMP6Header) WriteChecksum(p []byte)
WriteChecksum implements HeaderChecksummer, writing just the checksum bytes into the otherwise fully marshaled ICMP6 packet p (which should include the IPv6 header, ICMPv6 header, and payload).
type ICMP6Type ¶
type ICMP6Type uint8
ICMP6Type is an ICMPv6 type, as specified in https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xhtml
const ( ICMP6Unreachable ICMP6Type = 1 ICMP6PacketTooBig ICMP6Type = 2 ICMP6TimeExceeded ICMP6Type = 3 ICMP6ParamProblem ICMP6Type = 4 ICMP6EchoRequest ICMP6Type = 128 ICMP6EchoReply ICMP6Type = 129 )
func (ICMP6Type) String ¶
type IP4Header ¶
IP4Header represents an IPv4 packet header.
func (IP4Header) Len ¶
Len implements Header.
func (IP4Header) Marshal ¶
Marshal implements Header.
func (*IP4Header) ToResponse ¶
func (h *IP4Header) ToResponse()
ToResponse implements Header.
type IP6Header ¶
type IP6Header struct { IPProto ipproto.Proto IPID uint32 // only lower 20 bits used Src netip.Addr Dst netip.Addr }
IP6Header represents an IPv6 packet header.
func (IP6Header) Len ¶
Len implements Header.
func (IP6Header) Marshal ¶
Marshal implements Header.
func (*IP6Header) ToResponse ¶
func (h *IP6Header) ToResponse()
ToResponse implements Header.
type Parsed ¶
type Parsed struct { // IPVersion is the IP protocol version of the packet (4 or // 6), or 0 if the packet doesn't look like IPv4 or IPv6. IPVersion uint8 // IPProto is the IP subprotocol (UDP, TCP, etc.). Valid iff IPVersion != 0. IPProto ipproto.Proto // SrcIP4 is the source address. Family matches IPVersion. Port is // valid iff IPProto == TCP || IPProto == UDP. Src netip.AddrPort // DstIP4 is the destination address. Family matches IPVersion. Dst netip.AddrPort // TCPFlags is the packet's TCP flag bits. Valid iff IPProto == TCP. TCPFlags TCPFlag // CaptureMeta contains metadata that is used when debugging. CaptureMeta CaptureMeta // contains filtered or unexported fields }
Parsed is a minimal decoding of a packet suitable for use in filters.
func (*Parsed) AsTSMPPing ¶
func (pp *Parsed) AsTSMPPing() (h TSMPPingRequest, ok bool)
func (*Parsed) AsTSMPPong ¶
func (pp *Parsed) AsTSMPPong() (pong TSMPPongReply, ok bool)
AsTSMPPong returns pp as a TSMPPongReply and whether it is one. The pong.IPHeader field is not populated.
func (*Parsed) AsTailscaleRejectedHeader ¶
func (pp *Parsed) AsTailscaleRejectedHeader() (h TailscaleRejectedHeader, ok bool)
AsTailscaleRejectedHeader parses pp as an incoming rejection connection TSMP message.
ok reports whether pp was a valid TSMP rejection packet.
func (*Parsed) Buffer ¶
Buffer returns the entire packet buffer. This is a read-only view; that is, q retains the ownership of the buffer.
func (*Parsed) Decode ¶
Decode extracts data from the packet in b into q. It performs extremely simple packet decoding for basic IPv4 and IPv6 packet types. It extracts only the subprotocol id, IP addresses, and (if any) ports, and shouldn't need any memory allocation.
func (*Parsed) EchoIDSeq ¶
EchoIDSeq extracts the identifier/sequence bytes from an ICMP Echo response, and returns them as a uint32, used to lookup internally routed ICMP echo responses. This function is intentionally lightweight as it is called on every incoming ICMP packet.
func (*Parsed) ICMP4Header ¶
func (q *Parsed) ICMP4Header() ICMP4Header
func (*Parsed) ICMP6Header ¶
func (q *Parsed) ICMP6Header() ICMP6Header
func (*Parsed) IP4Header ¶
func (*Parsed) IP6Header ¶
func (*Parsed) IsEchoRequest ¶
IsEchoRequest reports whether q is an ICMP Echo Request.
func (*Parsed) IsEchoResponse ¶
IsEchoResponse reports whether q is an IPv4 ICMP Echo Response.
func (*Parsed) IsError ¶
IsError reports whether q is an ICMP "Error" packet.
func (*Parsed) IsTCPSyn ¶
IsTCPSyn reports whether q is a TCP SYN packet, without ACK set. (i.e. the first packet in a new connection)
func (*Parsed) Payload ¶
Payload returns the payload of the IP subprotocol section. This is a read-only view; that is, q retains the ownership of the buffer.
func (*Parsed) String ¶
func (*Parsed) StuffForTesting ¶
StuffForTesting makes Parsed contain a len-bytes buffer. Used in tests to build up a synthetic parse result with a non-zero buffer.
func (*Parsed) Transport ¶
Transport returns the transport header and payload (IP subprotocol, such as TCP or UDP). This is a read-only view; that is, p retains the ownership of the buffer.
func (*Parsed) UDP4Header ¶
func (q *Parsed) UDP4Header() UDP4Header
type TCPFlag ¶
type TCPFlag uint8
const ( TCPFin TCPFlag = 0x01 TCPSyn TCPFlag = 0x02 TCPRst TCPFlag = 0x04 TCPPsh TCPFlag = 0x08 TCPAck TCPFlag = 0x10 TCPUrg TCPFlag = 0x20 TCPECNEcho TCPFlag = 0x40 TCPCWR TCPFlag = 0x80 TCPSynAck TCPFlag = TCPSyn | TCPAck TCPECNBits TCPFlag = TCPECNEcho | TCPCWR )
type TSMPPingRequest ¶
type TSMPPingRequest struct { Data [8]byte }
TSMPPingRequest is a TSMP message that's like an ICMP ping request.
On the wire, after the IP header, it's currently 9 bytes:
- 'p' (TSMPTypePing)
- 8 opaque ping bytes to copy back in the response
type TSMPPongReply ¶
func (TSMPPongReply) Len ¶
func (h TSMPPongReply) Len() int
func (TSMPPongReply) Marshal ¶
func (h TSMPPongReply) Marshal(buf []byte) error
type TSMPType ¶
type TSMPType uint8
const ( // TSMPTypeRejectedConn is the type byte for a TailscaleRejectedHeader. TSMPTypeRejectedConn TSMPType = '!' // TSMPTypePing is the type byte for a TailscalePingRequest. TSMPTypePing TSMPType = 'p' // TSMPTypePong is the type byte for a TailscalePongResponse. TSMPTypePong TSMPType = 'o' )
type TailscaleRejectReason ¶
type TailscaleRejectReason byte
const ( // TailscaleRejectReasonNone is the TailscaleRejectReason zero value. TailscaleRejectReasonNone TailscaleRejectReason = 0 // RejectedDueToACLs means that the host rejected the connection due to ACLs. RejectedDueToACLs TailscaleRejectReason = 'A' // RejectedDueToShieldsUp means that the host rejected the connection due to shields being up. RejectedDueToShieldsUp TailscaleRejectReason = 'S' // RejectedDueToIPForwarding means that the relay node's IP // forwarding is disabled. RejectedDueToIPForwarding TailscaleRejectReason = 'F' // RejectedDueToHostFirewall means that the target host's // firewall is blocking the traffic. RejectedDueToHostFirewall TailscaleRejectReason = 'W' )
func (TailscaleRejectReason) IsZero ¶
func (r TailscaleRejectReason) IsZero() bool
IsZero reports whether r is the zero value, representing no rejection.
func (TailscaleRejectReason) String ¶
func (r TailscaleRejectReason) String() string
type TailscaleRejectedHeader ¶
type TailscaleRejectedHeader struct { IPSrc netip.Addr // IPv4 or IPv6 header's src IP IPDst netip.Addr // IPv4 or IPv6 header's dst IP Src netip.AddrPort // rejected flow's src Dst netip.AddrPort // rejected flow's dst Proto ipproto.Proto // proto that was rejected (TCP or UDP) Reason TailscaleRejectReason // why the connection was rejected // MaybeBroken is whether the rejection is non-terminal (the // client should not fail immediately). This is sent by a // target when it's not sure whether it's totally broken, but // it might be. For example, the target tailscaled might think // its host firewall or IP forwarding aren't configured // properly, but tailscaled might be wrong (not having enough // visibility into what the OS is doing). When true, the // message is simply an FYI as a potential reason to use for // later when the pendopen connection tracking timer expires. MaybeBroken bool }
TailscaleRejectedHeader is a TSMP message that says that one Tailscale node has rejected the connection from another. Unlike a TCP RST, this includes a reason.
On the wire, after the IP header, it's currently 7 or 8 bytes:
- '!'
- IPProto byte (IANA protocol number: TCP or UDP)
- 'A' or 'S' (RejectedDueToACLs, RejectedDueToShieldsUp)
- srcPort big endian uint16
- dstPort big endian uint16
- [optional] byte of flag bits: lowest bit (0x1): MaybeBroken
In the future it might also accept 16 byte IP flow src/dst IPs after the header, if they're different than the IP-level ones.
func (TailscaleRejectedHeader) Flow ¶
func (rh TailscaleRejectedHeader) Flow() flowtrack.Tuple
func (TailscaleRejectedHeader) Len ¶
func (h TailscaleRejectedHeader) Len() int
func (TailscaleRejectedHeader) Marshal ¶
func (h TailscaleRejectedHeader) Marshal(buf []byte) error
func (TailscaleRejectedHeader) String ¶
func (rh TailscaleRejectedHeader) String() string
type UDP4Header ¶
UDP4Header is an IPv4+UDP header.
func (UDP4Header) Len ¶
func (h UDP4Header) Len() int
Len implements Header.
func (UDP4Header) Marshal ¶
func (h UDP4Header) Marshal(buf []byte) error
Marshal implements Header.
func (*UDP4Header) ToResponse ¶
func (h *UDP4Header) ToResponse()
ToResponse implements Header.
type UDP6Header ¶
UDP6Header is an IPv6+UDP header.
func (UDP6Header) Len ¶
func (h UDP6Header) Len() int
Len implements Header.
func (UDP6Header) Marshal ¶
func (h UDP6Header) Marshal(buf []byte) error
Marshal implements Header.
func (*UDP6Header) ToResponse ¶
func (h *UDP6Header) ToResponse()
ToResponse implements Header.
Source Files ¶
capture.go doc.go geneve.go header.go icmp.go icmp4.go icmp6.go ip4.go ip6.go packet.go tsmp.go udp4.go udp6.go
Directories ¶
Path | Synopsis |
---|---|
net/packet/checksum | Package checksum provides functions for updating checksums in parsed packets. |
- Version
- v1.84.0 (latest)
- Published
- May 21, 2025
- Platform
- linux/amd64
- Imports
- 13 packages
- Last checked
- 1 day ago –
Tools for package owners.