or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

bpf.mdcontext-ctxhttp.mdcontext.mddict.mddns-dnsmessage.mdhtml-atom.mdhtml-charset.mdhtml.mdhttp-httpguts.mdhttp-httpproxy.mdhttp2-h2c.mdhttp2-hpack.mdhttp2.mdicmp.mdidna.mdindex.mdipv4.mdipv6.mdnettest.mdnetutil.mdproxy.mdpublicsuffix.mdquic-qlog.mdquic.mdtrace.mdwebdav.mdwebsocket.mdxsrftoken.md
tile.json

icmp.mddocs/

ICMP Protocol Handling

Package icmp provides basic functions for the manipulation of messages used in the Internet Control Message Protocols, ICMPv4 and ICMPv6.

ICMPv4 and ICMPv6 are defined in RFC 792 and RFC 4443. Multi-part message support for ICMP is defined in RFC 4884. ICMP extensions for MPLS are defined in RFC 4950. ICMP extensions for interface and next-hop identification are defined in RFC 5837.

Import

import "golang.org/x/net/icmp"

Functions

// IPv6PseudoHeader returns an IPv6 pseudo header for checksum calculation
func IPv6PseudoHeader(src, dst net.IP) []byte

// ParseIPv4Header returns the IPv4 header of the IPv4 packet that triggered an ICMP error
func ParseIPv4Header(b []byte) (*ipv4.Header, error)

Message

// Message represents an ICMP message
type Message struct {
    Type     Type        // type (ipv4.ICMPType or ipv6.ICMPType)
    Code     int         // code
    Checksum int         // checksum
    Body     MessageBody // body
}

func ParseMessage(proto int, b []byte) (*Message, error)
func (m *Message) Marshal(psh []byte) ([]byte, error)

ParseMessage

ParseMessage parses b as an ICMP message. The provided proto must be either the ICMPv4 or ICMPv6 protocol number.

Marshal

Marshal returns the binary encoding of the ICMP message. For ICMPv4, always contains calculated checksum. For ICMPv6, contains calculated checksum when psh is not nil (must be IPv6 pseudo header), otherwise kernel computes it.

MessageBody Interface

// MessageBody represents an ICMP message body
type MessageBody interface {
    Len(proto int) int
    Marshal(proto int) ([]byte, error)
}

// Type represents an ICMP message type
type Type interface {
    Protocol() int
}

PacketConn

// PacketConn represents a packet network endpoint for ICMPv4 or ICMPv6
type PacketConn struct {
    // Has unexported fields
}

func ListenPacket(network, address string) (*PacketConn, error)

func (c *PacketConn) Close() error
func (c *PacketConn) IPv4PacketConn() *ipv4.PacketConn
func (c *PacketConn) IPv6PacketConn() *ipv6.PacketConn
func (c *PacketConn) LocalAddr() net.Addr
func (c *PacketConn) ReadFrom(b []byte) (int, net.Addr, error)
func (c *PacketConn) SetDeadline(t time.Time) error
func (c *PacketConn) SetReadDeadline(t time.Time) error
func (c *PacketConn) SetWriteDeadline(t time.Time) error
func (c *PacketConn) WriteTo(b []byte, dst net.Addr) (int, error)

ListenPacket

For non-privileged datagram-oriented ICMP endpoints, network must be "udp4" or "udp6". For privileged raw ICMP endpoints, network must be "ip4" or "ip6" followed by colon and ICMP protocol number or name.

Examples:

  • ListenPacket("udp4", "192.168.0.1")
  • ListenPacket("udp6", "::")
  • ListenPacket("ip4:icmp", "0.0.0.0")
  • ListenPacket("ip6:58", "fe80::1%en0")

Message Body Types

Echo

// Echo represents an ICMP echo request or reply message body
type Echo struct {
    ID   int    // identifier
    Seq  int    // sequence number
    Data []byte // data
}

func (p *Echo) Len(proto int) int
func (p *Echo) Marshal(proto int) ([]byte, error)

DstUnreach

// DstUnreach represents an ICMP destination unreachable message body
type DstUnreach struct {
    Data       []byte      // original datagram field
    Extensions []Extension // extensions
}

func (p *DstUnreach) Len(proto int) int
func (p *DstUnreach) Marshal(proto int) ([]byte, error)

TimeExceeded

// TimeExceeded represents an ICMP time exceeded message body
type TimeExceeded struct {
    Data       []byte      // original datagram field
    Extensions []Extension // extensions
}

func (p *TimeExceeded) Len(proto int) int
func (p *TimeExceeded) Marshal(proto int) ([]byte, error)

ParamProb

// ParamProb represents an ICMP parameter problem message body
type ParamProb struct {
    Pointer    uintptr     // offset where error was detected
    Data       []byte      // original datagram field
    Extensions []Extension // extensions
}

func (p *ParamProb) Len(proto int) int
func (p *ParamProb) Marshal(proto int) ([]byte, error)

PacketTooBig

// PacketTooBig represents an ICMP packet too big message body
type PacketTooBig struct {
    MTU  int    // maximum transmission unit of nexthop link
    Data []byte // original datagram field
}

func (p *PacketTooBig) Len(proto int) int
func (p *PacketTooBig) Marshal(proto int) ([]byte, error)

ExtendedEchoRequest

// ExtendedEchoRequest represents an ICMP extended echo request message body
type ExtendedEchoRequest struct {
    ID         int         // identifier
    Seq        int         // sequence number
    Local      bool        // must be true when identifying by name or index
    Extensions []Extension // extensions
}

func (p *ExtendedEchoRequest) Len(proto int) int
func (p *ExtendedEchoRequest) Marshal(proto int) ([]byte, error)

ExtendedEchoReply

// ExtendedEchoReply represents an ICMP extended echo reply message body
type ExtendedEchoReply struct {
    ID     int  // identifier
    Seq    int  // sequence number
    State  int  // 3-bit state working with Message.Code
    Active bool // probed interface is active
    IPv4   bool // probed interface runs IPv4
    IPv6   bool // probed interface runs IPv6
}

func (p *ExtendedEchoReply) Len(proto int) int
func (p *ExtendedEchoReply) Marshal(proto int) ([]byte, error)

RawBody

// RawBody represents a raw message body
type RawBody struct {
    Data []byte // data
}

func (p *RawBody) Len(proto int) int
func (p *RawBody) Marshal(proto int) ([]byte, error)

// DefaultMessageBody is deprecated, use RawBody
type DefaultMessageBody = RawBody

Extensions

// Extension represents an ICMP extension
type Extension interface {
    Len(proto int) int
    Marshal(proto int) ([]byte, error)
}

MPLSLabelStack

// MPLSLabelStack represents an MPLS label stack
type MPLSLabelStack struct {
    Class  int         // extension object class number
    Type   int         // extension object sub-type
    Labels []MPLSLabel
}

func (ls *MPLSLabelStack) Len(proto int) int
func (ls *MPLSLabelStack) Marshal(proto int) ([]byte, error)

// MPLSLabel represents an MPLS label stack entry
type MPLSLabel struct {
    Label int  // label value
    TC    int  // traffic class
    S     bool // bottom of stack
    TTL   int  // time to live
}

InterfaceIdent

// InterfaceIdent represents interface identification
type InterfaceIdent struct {
    Class int    // extension object class number
    Type  int    // extension object sub-type
    Name  string // interface name
    Index int    // interface index
    AFI   int    // address family identifier
    Addr  []byte // address
}

func (ifi *InterfaceIdent) Len(_ int) int
func (ifi *InterfaceIdent) Marshal(proto int) ([]byte, error)

InterfaceInfo

// InterfaceInfo represents interface and next-hop identification
type InterfaceInfo struct {
    Class     int            // extension object class number
    Type      int            // extension object sub-type
    Interface *net.Interface
    Addr      *net.IPAddr
}

func (ifi *InterfaceInfo) Len(proto int) int
func (ifi *InterfaceInfo) Marshal(proto int) ([]byte, error)

RawExtension

// RawExtension represents a raw extension
type RawExtension struct {
    Data []byte // data
}

func (p *RawExtension) Len(proto int) int
func (p *RawExtension) Marshal(proto int) ([]byte, error)

Usage Examples

Sending ICMP Echo Request (Ping)

import (
    "golang.org/x/net/icmp"
    "golang.org/x/net/ipv4"
    "net"
    "time"
)

func ping(addr string) error {
    conn, err := icmp.ListenPacket("udp4", "0.0.0.0")
    if err != nil {
        return err
    }
    defer conn.Close()

    // Create echo request
    msg := icmp.Message{
        Type: ipv4.ICMPTypeEcho,
        Code: 0,
        Body: &icmp.Echo{
            ID:   1,
            Seq:  1,
            Data: []byte("PING"),
        },
    }

    // Marshal message
    msgBytes, err := msg.Marshal(nil)
    if err != nil {
        return err
    }

    // Send to destination
    dst, err := net.ResolveUDPAddr("udp4", addr)
    if err != nil {
        return err
    }

    _, err = conn.WriteTo(msgBytes, dst)
    if err != nil {
        return err
    }

    // Wait for reply
    conn.SetReadDeadline(time.Now().Add(3 * time.Second))
    reply := make([]byte, 1500)
    n, peer, err := conn.ReadFrom(reply)
    if err != nil {
        return err
    }

    // Parse reply
    replyMsg, err := icmp.ParseMessage(1, reply[:n])
    if err != nil {
        return err
    }

    fmt.Printf("Reply from %v: %+v\n", peer, replyMsg)
    return nil
}

IPv6 Ping

import "golang.org/x/net/ipv6"

func ping6(addr string) error {
    conn, err := icmp.ListenPacket("udp6", "::")
    if err != nil {
        return err
    }
    defer conn.Close()

    msg := icmp.Message{
        Type: ipv6.ICMPTypeEchoRequest,
        Code: 0,
        Body: &icmp.Echo{
            ID:   1,
            Seq:  1,
            Data: []byte("PING6"),
        },
    }

    dst, err := net.ResolveUDPAddr("udp6", addr)
    if err != nil {
        return err
    }

    msgBytes, err := msg.Marshal(nil)
    if err != nil {
        return err
    }

    _, err = conn.WriteTo(msgBytes, dst)
    return err
}

Privileged Raw ICMP

func rawPing(addr string) error {
    conn, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
    if err != nil {
        return err
    }
    defer conn.Close()

    msg := icmp.Message{
        Type: ipv4.ICMPTypeEcho,
        Code: 0,
        Body: &icmp.Echo{
            ID:   os.Getpid() & 0xffff,
            Seq:  1,
            Data: []byte("RAWPING"),
        },
    }

    msgBytes, err := msg.Marshal(nil)
    if err != nil {
        return err
    }

    dst, err := net.ResolveIPAddr("ip4", addr)
    if err != nil {
        return err
    }

    _, err = conn.WriteTo(msgBytes, dst)
    return err
}