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 "golang.org/x/net/icmp"// 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 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 parses b as an ICMP message. The provided proto must be either the ICMPv4 or ICMPv6 protocol number.
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 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 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)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")// 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 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 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 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 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 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 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 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// Extension represents an ICMP extension
type Extension interface {
Len(proto int) int
Marshal(proto int) ([]byte, error)
}// 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 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 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 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)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
}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
}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
}