aboutsummaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorMikio Hara <mikioh.mikioh@gmail.com>2014-12-03 12:32:52 +0900
committerMikio Hara <mikioh.mikioh@gmail.com>2014-12-03 12:32:52 +0900
commitb745b482fe97df07c8c3a25247731f0141ac864b (patch)
tree2410116b463d4e09bfc29c96ee686b13fe512cfe /internal
parentfc168c3c5cfd0f4237144c6863b9585cc5d9a24f (diff)
downloadnet-b745b482fe97df07c8c3a25247731f0141ac864b.tar.gz
x/net/icmp: new package
This CL makes icmp an external package. LGTM=iant R=iant CC=golang-codereviews https://golang.org/cl/182370043
Diffstat (limited to 'internal')
-rw-r--r--internal/icmp/dstunreach.go41
-rw-r--r--internal/icmp/echo.go43
-rw-r--r--internal/icmp/endpoint.go108
-rw-r--r--internal/icmp/example_test.go54
-rw-r--r--internal/icmp/helper_unix.go87
-rw-r--r--internal/icmp/ipv4.go61
-rw-r--r--internal/icmp/ipv4_test.go71
-rw-r--r--internal/icmp/ipv6.go23
-rw-r--r--internal/icmp/listen_stub.go33
-rw-r--r--internal/icmp/listen_unix.go98
-rw-r--r--internal/icmp/message.go135
-rw-r--r--internal/icmp/message_test.go134
-rw-r--r--internal/icmp/messagebody.go39
-rw-r--r--internal/icmp/packettoobig.go41
-rw-r--r--internal/icmp/paramprob.go41
-rw-r--r--internal/icmp/ping_test.go130
-rw-r--r--internal/icmp/sys_freebsd.go11
-rw-r--r--internal/icmp/timeexceeded.go39
18 files changed, 0 insertions, 1189 deletions
diff --git a/internal/icmp/dstunreach.go b/internal/icmp/dstunreach.go
deleted file mode 100644
index 8241017..0000000
--- a/internal/icmp/dstunreach.go
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package icmp
-
-// A DstUnreach represents an ICMP destination unreachable message
-// body.
-type DstUnreach struct {
- Data []byte // data
-}
-
-// Len implements the Len method of MessageBody interface.
-func (p *DstUnreach) Len() int {
- if p == nil {
- return 0
- }
- return 4 + len(p.Data)
-}
-
-// Marshal implements the Marshal method of MessageBody interface.
-func (p *DstUnreach) Marshal() ([]byte, error) {
- b := make([]byte, 4+len(p.Data))
- copy(b[4:], p.Data)
- return b, nil
-}
-
-// parseDstUnreach parses b as an ICMP destination unreachable message
-// body.
-func parseDstUnreach(b []byte) (MessageBody, error) {
- bodyLen := len(b)
- if bodyLen < 4 {
- return nil, errMessageTooShort
- }
- p := &DstUnreach{}
- if bodyLen > 4 {
- p.Data = make([]byte, bodyLen-4)
- copy(p.Data, b[4:])
- }
- return p, nil
-}
diff --git a/internal/icmp/echo.go b/internal/icmp/echo.go
deleted file mode 100644
index dfac9cb..0000000
--- a/internal/icmp/echo.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package icmp
-
-// An Echo represents an ICMP echo request or reply message body.
-type Echo struct {
- ID int // identifier
- Seq int // sequence number
- Data []byte // data
-}
-
-// Len implements the Len method of MessageBody interface.
-func (p *Echo) Len() int {
- if p == nil {
- return 0
- }
- return 4 + len(p.Data)
-}
-
-// Marshal implements the Marshal method of MessageBody interface.
-func (p *Echo) Marshal() ([]byte, error) {
- b := make([]byte, 4+len(p.Data))
- b[0], b[1] = byte(p.ID>>8), byte(p.ID)
- b[2], b[3] = byte(p.Seq>>8), byte(p.Seq)
- copy(b[4:], p.Data)
- return b, nil
-}
-
-// parseEcho parses b as an ICMP echo request or reply message body.
-func parseEcho(b []byte) (MessageBody, error) {
- bodyLen := len(b)
- if bodyLen < 4 {
- return nil, errMessageTooShort
- }
- p := &Echo{ID: int(b[0])<<8 | int(b[1]), Seq: int(b[2])<<8 | int(b[3])}
- if bodyLen > 4 {
- p.Data = make([]byte, bodyLen-4)
- copy(p.Data, b[4:])
- }
- return p, nil
-}
diff --git a/internal/icmp/endpoint.go b/internal/icmp/endpoint.go
deleted file mode 100644
index 5bf2cfe..0000000
--- a/internal/icmp/endpoint.go
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package icmp
-
-import (
- "net"
- "syscall"
- "time"
-
- "golang.org/x/net/ipv4"
- "golang.org/x/net/ipv6"
-)
-
-var _ net.PacketConn = &PacketConn{}
-
-type ipc interface{}
-
-// A PacketConn represents a packet network endpoint that uses either
-// ICMPv4 or ICMPv6.
-type PacketConn struct {
- c net.PacketConn
- ipc // either ipv4.PacketConn or ipv6.PacketConn
-}
-
-func (c *PacketConn) ok() bool { return c != nil && c.c != nil }
-
-// IPv4PacketConn returns the ipv4.PacketConn of c.
-// It returns nil when c is not created as the endpoint for ICMPv4.
-func (c *PacketConn) IPv4PacketConn() *ipv4.PacketConn {
- if !c.ok() {
- return nil
- }
- p, _ := c.ipc.(*ipv4.PacketConn)
- return p
-}
-
-// IPv6PacketConn returns the ipv6.PacketConn of c.
-// It returns nil when c is not created as the endpoint for ICMPv6.
-func (c *PacketConn) IPv6PacketConn() *ipv6.PacketConn {
- if !c.ok() {
- return nil
- }
- p, _ := c.ipc.(*ipv6.PacketConn)
- return p
-}
-
-// ReadFrom reads an ICMP message from the connection.
-func (c *PacketConn) ReadFrom(b []byte) (int, net.Addr, error) {
- if !c.ok() {
- return 0, nil, syscall.EINVAL
- }
- return c.c.ReadFrom(b)
-}
-
-// WriteTo writes the ICMP message b to dst.
-// Dst must be net.UDPAddr when c is a non-privileged
-// datagram-oriented ICMP endpoint. Otherwise it must be net.IPAddr.
-func (c *PacketConn) WriteTo(b []byte, dst net.Addr) (int, error) {
- if !c.ok() {
- return 0, syscall.EINVAL
- }
- return c.c.WriteTo(b, dst)
-}
-
-// Close closes the endpoint.
-func (c *PacketConn) Close() error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return c.c.Close()
-}
-
-// LocalAddr returns the local network address.
-func (c *PacketConn) LocalAddr() net.Addr {
- if !c.ok() {
- return nil
- }
- return c.c.LocalAddr()
-}
-
-// SetDeadline sets the read and write deadlines associated with the
-// endpoint.
-func (c *PacketConn) SetDeadline(t time.Time) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return c.c.SetDeadline(t)
-}
-
-// SetReadDeadline sets the read deadline associated with the
-// endpoint.
-func (c *PacketConn) SetReadDeadline(t time.Time) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return c.c.SetReadDeadline(t)
-}
-
-// SetWriteDeadline sets the write deadline associated with the
-// endpoint.
-func (c *PacketConn) SetWriteDeadline(t time.Time) error {
- if !c.ok() {
- return syscall.EINVAL
- }
- return c.c.SetWriteDeadline(t)
-}
diff --git a/internal/icmp/example_test.go b/internal/icmp/example_test.go
deleted file mode 100644
index 0ef839c..0000000
--- a/internal/icmp/example_test.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package icmp_test
-
-import (
- "log"
- "net"
- "os"
-
- "golang.org/x/net/internal/iana"
- "golang.org/x/net/internal/icmp"
- "golang.org/x/net/ipv6"
-)
-
-func ExamplePacketConn_nonPrivilegedPing() {
- c, err := icmp.ListenPacket("udp6", "fe80::1%en0")
- if err != nil {
- log.Fatal(err)
- }
- defer c.Close()
-
- wm := icmp.Message{
- Type: ipv6.ICMPTypeEchoRequest, Code: 0,
- Body: &icmp.Echo{
- ID: os.Getpid() & 0xffff, Seq: 1,
- Data: []byte("HELLO-R-U-THERE"),
- },
- }
- wb, err := wm.Marshal(nil)
- if err != nil {
- log.Fatal(err)
- }
- if _, err := c.WriteTo(wb, &net.UDPAddr{IP: net.ParseIP("ff02::1"), Zone: "en0"}); err != nil {
- log.Fatal(err)
- }
-
- rb := make([]byte, 1500)
- n, peer, err := c.ReadFrom(rb)
- if err != nil {
- log.Fatal(err)
- }
- rm, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, rb[:n])
- if err != nil {
- log.Fatal(err)
- }
- switch rm.Type {
- case ipv6.ICMPTypeEchoReply:
- log.Printf("got reflection from %v", peer)
- default:
- log.Printf("got %+v; want echo reply", rm)
- }
-}
diff --git a/internal/icmp/helper_unix.go b/internal/icmp/helper_unix.go
deleted file mode 100644
index d3c5529..0000000
--- a/internal/icmp/helper_unix.go
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
-
-package icmp
-
-import (
- "net"
- "syscall"
-)
-
-func sockaddr(family int, address string) (syscall.Sockaddr, error) {
- switch family {
- case syscall.AF_INET:
- a, err := net.ResolveIPAddr("ip4", address)
- if err != nil {
- return nil, err
- }
- if len(a.IP) == 0 {
- a.IP = net.IPv4zero
- }
- if a.IP = a.IP.To4(); a.IP == nil {
- return nil, net.InvalidAddrError("non-ipv4 address")
- }
- sa := &syscall.SockaddrInet4{}
- copy(sa.Addr[:], a.IP)
- return sa, nil
- case syscall.AF_INET6:
- a, err := net.ResolveIPAddr("ip6", address)
- if err != nil {
- return nil, err
- }
- if len(a.IP) == 0 {
- a.IP = net.IPv6unspecified
- }
- if a.IP.Equal(net.IPv4zero) {
- a.IP = net.IPv6unspecified
- }
- if a.IP = a.IP.To16(); a.IP == nil || a.IP.To4() != nil {
- return nil, net.InvalidAddrError("non-ipv6 address")
- }
- sa := &syscall.SockaddrInet6{ZoneId: zoneToUint32(a.Zone)}
- copy(sa.Addr[:], a.IP)
- return sa, nil
- default:
- return nil, net.InvalidAddrError("unexpected family")
- }
-}
-
-func zoneToUint32(zone string) uint32 {
- if zone == "" {
- return 0
- }
- if ifi, err := net.InterfaceByName(zone); err == nil {
- return uint32(ifi.Index)
- }
- n, _, _ := dtoi(zone, 0)
- return uint32(n)
-}
-
-func last(s string, b byte) int {
- i := len(s)
- for i--; i >= 0; i-- {
- if s[i] == b {
- break
- }
- }
- return i
-}
-
-const big = 0xFFFFFF
-
-func dtoi(s string, i0 int) (n int, i int, ok bool) {
- n = 0
- for i = i0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
- n = n*10 + int(s[i]-'0')
- if n >= big {
- return 0, i, false
- }
- }
- if i == i0 {
- return 0, i, false
- }
- return n, i, true
-}
diff --git a/internal/icmp/ipv4.go b/internal/icmp/ipv4.go
deleted file mode 100644
index a252d73..0000000
--- a/internal/icmp/ipv4.go
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package icmp
-
-import (
- "net"
- "runtime"
- "unsafe"
-
- "golang.org/x/net/ipv4"
-)
-
-// See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html.
-var freebsdVersion uint32
-
-// ParseIPv4Header parses b as an IPv4 header of ICMP error message
-// invoking packet, which is contained in ICMP error message.
-func ParseIPv4Header(b []byte) (*ipv4.Header, error) {
- if len(b) < ipv4.HeaderLen {
- return nil, errHeaderTooShort
- }
- hdrlen := int(b[0]&0x0f) << 2
- if hdrlen > len(b) {
- return nil, errBufferTooShort
- }
- h := &ipv4.Header{
- Version: int(b[0] >> 4),
- Len: hdrlen,
- TOS: int(b[1]),
- ID: int(b[4])<<8 | int(b[5]),
- FragOff: int(b[6])<<8 | int(b[7]),
- TTL: int(b[8]),
- Protocol: int(b[9]),
- Checksum: int(b[10])<<8 | int(b[11]),
- Src: net.IPv4(b[12], b[13], b[14], b[15]),
- Dst: net.IPv4(b[16], b[17], b[18], b[19]),
- }
- switch runtime.GOOS {
- case "darwin":
- // TODO(mikio): fix potential misaligned memory access
- h.TotalLen = int(*(*uint16)(unsafe.Pointer(&b[2:3][0])))
- case "freebsd":
- if freebsdVersion >= 1000000 {
- h.TotalLen = int(b[2])<<8 | int(b[3])
- } else {
- // TODO(mikio): fix potential misaligned memory access
- h.TotalLen = int(*(*uint16)(unsafe.Pointer(&b[2:3][0])))
- }
- default:
- h.TotalLen = int(b[2])<<8 | int(b[3])
- }
- h.Flags = ipv4.HeaderFlags(h.FragOff&0xe000) >> 13
- h.FragOff = h.FragOff & 0x1fff
- if hdrlen-ipv4.HeaderLen > 0 {
- h.Options = make([]byte, hdrlen-ipv4.HeaderLen)
- copy(h.Options, b[ipv4.HeaderLen:])
- }
- return h, nil
-}
diff --git a/internal/icmp/ipv4_test.go b/internal/icmp/ipv4_test.go
deleted file mode 100644
index b05c697..0000000
--- a/internal/icmp/ipv4_test.go
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package icmp
-
-import (
- "net"
- "reflect"
- "runtime"
- "testing"
-
- "golang.org/x/net/ipv4"
-)
-
-var (
- wireHeaderFromKernel = [ipv4.HeaderLen]byte{
- 0x45, 0x01, 0xbe, 0xef,
- 0xca, 0xfe, 0x45, 0xdc,
- 0xff, 0x01, 0xde, 0xad,
- 172, 16, 254, 254,
- 192, 168, 0, 1,
- }
- wireHeaderFromTradBSDKernel = [ipv4.HeaderLen]byte{
- 0x45, 0x01, 0xef, 0xbe,
- 0xca, 0xfe, 0x45, 0xdc,
- 0xff, 0x01, 0xde, 0xad,
- 172, 16, 254, 254,
- 192, 168, 0, 1,
- }
- // TODO(mikio): Add platform dependent wire header formats when
- // we support new platforms.
-
- testHeader = &ipv4.Header{
- Version: ipv4.Version,
- Len: ipv4.HeaderLen,
- TOS: 1,
- TotalLen: 0xbeef,
- ID: 0xcafe,
- Flags: ipv4.DontFragment,
- FragOff: 1500,
- TTL: 255,
- Protocol: 1,
- Checksum: 0xdead,
- Src: net.IPv4(172, 16, 254, 254),
- Dst: net.IPv4(192, 168, 0, 1),
- }
-)
-
-func TestParseIPv4Header(t *testing.T) {
- var wh []byte
- switch runtime.GOOS {
- case "darwin":
- wh = wireHeaderFromTradBSDKernel[:]
- case "freebsd":
- if freebsdVersion >= 1000000 {
- wh = wireHeaderFromKernel[:]
- } else {
- wh = wireHeaderFromTradBSDKernel[:]
- }
- default:
- wh = wireHeaderFromKernel[:]
- }
- h, err := ParseIPv4Header(wh)
- if err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(h, testHeader) {
- t.Fatalf("got %#v; want %#v", h, testHeader)
- }
-}
diff --git a/internal/icmp/ipv6.go b/internal/icmp/ipv6.go
deleted file mode 100644
index fe4031a..0000000
--- a/internal/icmp/ipv6.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package icmp
-
-import (
- "net"
-
- "golang.org/x/net/internal/iana"
-)
-
-const ipv6PseudoHeaderLen = 2*net.IPv6len + 8
-
-// IPv6PseudoHeader returns an IPv6 pseudo header for checkusm
-// calculation.
-func IPv6PseudoHeader(src, dst net.IP) []byte {
- b := make([]byte, ipv6PseudoHeaderLen)
- copy(b, src.To16())
- copy(b[net.IPv6len:], dst.To16())
- b[len(b)-1] = byte(iana.ProtocolIPv6ICMP)
- return b
-}
diff --git a/internal/icmp/listen_stub.go b/internal/icmp/listen_stub.go
deleted file mode 100644
index 1a9be6a..0000000
--- a/internal/icmp/listen_stub.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build nacl plan9 windows
-
-package icmp
-
-// ListenPacket listens for incoming ICMP packets addressed to
-// address. See net.Dial for the syntax of address.
-//
-// For non-privileged datagram-oriented ICMP endpoints, network must
-// be "udp4" or "udp6". The endpoint allows to read, write a few
-// limited ICMP messages such as echo request and echo reply.
-// Currently only Dariwn and Linux support this.
-//
-// Examples:
-// ListenPacket("udp4", "192.168.0.1")
-// ListenPacket("udp4", "0.0.0.0")
-// ListenPacket("udp6", "fe80::1%en0")
-// ListenPacket("udp6", "::")
-//
-// For privileged raw ICMP endpoints, network must be "ip4" or "ip6"
-// followed by a colon and an ICMP protocol number or name.
-//
-// Examples:
-// ListenPacket("ip4:icmp", "192.168.0.1")
-// ListenPacket("ip4:1", "0.0.0.0")
-// ListenPacket("ip6:ipv6-icmp", "fe80::1%en0")
-// ListenPacket("ip6:58", "::")
-func ListenPacket(network, address string) (*PacketConn, error) {
- return nil, errOpNoSupport
-}
diff --git a/internal/icmp/listen_unix.go b/internal/icmp/listen_unix.go
deleted file mode 100644
index 5ae9c39..0000000
--- a/internal/icmp/listen_unix.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
-
-package icmp
-
-import (
- "net"
- "os"
- "runtime"
- "syscall"
-
- "golang.org/x/net/internal/iana"
- "golang.org/x/net/ipv4"
- "golang.org/x/net/ipv6"
-)
-
-const sysIP_STRIPHDR = 0x17 // for now only darwin supports this option
-
-// ListenPacket listens for incoming ICMP packets addressed to
-// address. See net.Dial for the syntax of address.
-//
-// For non-privileged datagram-oriented ICMP endpoints, network must
-// be "udp4" or "udp6". The endpoint allows to read, write a few
-// limited ICMP messages such as echo request and echo reply.
-// Currently only Dariwn and Linux support this.
-//
-// Examples:
-// ListenPacket("udp4", "192.168.0.1")
-// ListenPacket("udp4", "0.0.0.0")
-// ListenPacket("udp6", "fe80::1%en0")
-// ListenPacket("udp6", "::")
-//
-// For privileged raw ICMP endpoints, network must be "ip4" or "ip6"
-// followed by a colon and an ICMP protocol number or name.
-//
-// Examples:
-// ListenPacket("ip4:icmp", "192.168.0.1")
-// ListenPacket("ip4:1", "0.0.0.0")
-// ListenPacket("ip6:ipv6-icmp", "fe80::1%en0")
-// ListenPacket("ip6:58", "::")
-func ListenPacket(network, address string) (*PacketConn, error) {
- var family, proto int
- switch network {
- case "udp4":
- family, proto = syscall.AF_INET, iana.ProtocolICMP
- case "udp6":
- family, proto = syscall.AF_INET6, iana.ProtocolIPv6ICMP
- default:
- i := last(network, ':')
- switch network[:i] {
- case "ip4":
- proto = iana.ProtocolICMP
- case "ip6":
- proto = iana.ProtocolIPv6ICMP
- }
- }
- var err error
- var c net.PacketConn
- switch family {
- case syscall.AF_INET, syscall.AF_INET6:
- s, err := syscall.Socket(family, syscall.SOCK_DGRAM, proto)
- if err != nil {
- return nil, os.NewSyscallError("socket", err)
- }
- defer syscall.Close(s)
- if runtime.GOOS == "darwin" && family == syscall.AF_INET {
- if err := syscall.SetsockoptInt(s, iana.ProtocolIP, sysIP_STRIPHDR, 1); err != nil {
- return nil, os.NewSyscallError("setsockopt", err)
- }
- }
- sa, err := sockaddr(family, address)
- if err != nil {
- return nil, err
- }
- if err := syscall.Bind(s, sa); err != nil {
- return nil, os.NewSyscallError("bind", err)
- }
- f := os.NewFile(uintptr(s), "datagram-oriented icmp")
- defer f.Close()
- c, err = net.FilePacketConn(f)
- default:
- c, err = net.ListenPacket(network, address)
- }
- if err != nil {
- return nil, err
- }
- switch proto {
- case iana.ProtocolICMP:
- return &PacketConn{c: c, ipc: ipv4.NewPacketConn(c)}, nil
- case iana.ProtocolIPv6ICMP:
- return &PacketConn{c: c, ipc: ipv6.NewPacketConn(c)}, nil
- default:
- return &PacketConn{c: c}, nil
- }
-}
diff --git a/internal/icmp/message.go b/internal/icmp/message.go
deleted file mode 100644
index 2023dbe..0000000
--- a/internal/icmp/message.go
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package icmp provides basic functions for the manipulation of ICMP
-// message.
-package icmp
-
-import (
- "errors"
- "net"
- "syscall"
-
- "golang.org/x/net/internal/iana"
- "golang.org/x/net/ipv4"
- "golang.org/x/net/ipv6"
-)
-
-var (
- errMessageTooShort = errors.New("message too short")
- errHeaderTooShort = errors.New("header too short")
- errBufferTooShort = errors.New("buffer too short")
- errOpNoSupport = errors.New("operation not supported")
-)
-
-// A Type represents an ICMP message type.
-type Type interface {
- Protocol() int
-}
-
-// A Message represents an ICMP message.
-type Message struct {
- Type Type // type, either ipv4.ICMPType or ipv6.ICMPType
- Code int // code
- Checksum int // checksum
- Body MessageBody // body
-}
-
-// Marshal returns the binary enconding of the ICMP message m.
-//
-// For ICMP for IPv4 message, the returned message always contains the
-// calculated checksum field.
-//
-// For ICMP for IPv6 message, the returned message contains the
-// calculated checksum field when psh is not nil, otherwise the kernel
-// will compute the checksum field during the message transmission.
-// When psh is not nil, it must be the pseudo header for IPv6.
-func (m *Message) Marshal(psh []byte) ([]byte, error) {
- var mtype int
- switch typ := m.Type.(type) {
- case ipv4.ICMPType:
- mtype = int(typ)
- case ipv6.ICMPType:
- mtype = int(typ)
- default:
- return nil, syscall.EINVAL
- }
- b := []byte{byte(mtype), byte(m.Code), 0, 0}
- if m.Type.Protocol() == iana.ProtocolIPv6ICMP && psh != nil {
- b = append(psh, b...)
- }
- if m.Body != nil && m.Body.Len() != 0 {
- mb, err := m.Body.Marshal()
- if err != nil {
- return nil, err
- }
- b = append(b, mb...)
- }
- if m.Type.Protocol() == iana.ProtocolIPv6ICMP {
- if psh == nil { // cannot calculate checksum here
- return b, nil
- }
- off, l := 2*net.IPv6len, len(b)-len(psh)
- b[off], b[off+1], b[off+2], b[off+3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
- }
- csumcv := len(b) - 1 // checksum coverage
- s := uint32(0)
- for i := 0; i < csumcv; i += 2 {
- s += uint32(b[i+1])<<8 | uint32(b[i])
- }
- if csumcv&1 == 0 {
- s += uint32(b[csumcv])
- }
- s = s>>16 + s&0xffff
- s = s + s>>16
- // Place checksum back in header; using ^= avoids the
- // assumption the checksum bytes are zero.
- b[len(psh)+2] ^= byte(^s)
- b[len(psh)+3] ^= byte(^s >> 8)
- return b[len(psh):], nil
-}
-
-var parseFns = map[Type]func([]byte) (MessageBody, error){
- ipv4.ICMPTypeDestinationUnreachable: parseDstUnreach,
- ipv4.ICMPTypeTimeExceeded: parseTimeExceeded,
- ipv4.ICMPTypeParameterProblem: parseParamProb,
-
- ipv4.ICMPTypeEcho: parseEcho,
- ipv4.ICMPTypeEchoReply: parseEcho,
-
- ipv6.ICMPTypeDestinationUnreachable: parseDstUnreach,
- ipv6.ICMPTypePacketTooBig: parsePacketTooBig,
- ipv6.ICMPTypeTimeExceeded: parseTimeExceeded,
- ipv6.ICMPTypeParameterProblem: parseParamProb,
-
- ipv6.ICMPTypeEchoRequest: parseEcho,
- ipv6.ICMPTypeEchoReply: parseEcho,
-}
-
-// ParseMessage parses b as an ICMP message.
-// Proto must be either the ICMPv4 or ICMPv6 protocol number.
-func ParseMessage(proto int, b []byte) (*Message, error) {
- if len(b) < 4 {
- return nil, errMessageTooShort
- }
- var err error
- m := &Message{Code: int(b[1]), Checksum: int(b[2])<<8 | int(b[3])}
- switch proto {
- case iana.ProtocolICMP:
- m.Type = ipv4.ICMPType(b[0])
- case iana.ProtocolIPv6ICMP:
- m.Type = ipv6.ICMPType(b[0])
- default:
- return nil, syscall.EINVAL
- }
- if fn, ok := parseFns[m.Type]; !ok {
- m.Body, err = parseDefaultMessageBody(b[4:])
- } else {
- m.Body, err = fn(b[4:])
- }
- if err != nil {
- return nil, err
- }
- return m, nil
-}
diff --git a/internal/icmp/message_test.go b/internal/icmp/message_test.go
deleted file mode 100644
index cd643e2..0000000
--- a/internal/icmp/message_test.go
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package icmp_test
-
-import (
- "net"
- "reflect"
- "testing"
-
- "golang.org/x/net/internal/iana"
- "golang.org/x/net/internal/icmp"
- "golang.org/x/net/ipv4"
- "golang.org/x/net/ipv6"
-)
-
-var marshalAndParseMessageForIPv4Tests = []icmp.Message{
- {
- Type: ipv4.ICMPTypeDestinationUnreachable, Code: 15,
- Body: &icmp.DstUnreach{
- Data: []byte("ERROR-INVOKING-PACKET"),
- },
- },
- {
- Type: ipv4.ICMPTypeTimeExceeded, Code: 1,
- Body: &icmp.TimeExceeded{
- Data: []byte("ERROR-INVOKING-PACKET"),
- },
- },
- {
- Type: ipv4.ICMPTypeParameterProblem, Code: 2,
- Body: &icmp.ParamProb{
- Pointer: 8,
- Data: []byte("ERROR-INVOKING-PACKET"),
- },
- },
- {
- Type: ipv4.ICMPTypeEcho, Code: 0,
- Body: &icmp.Echo{
- ID: 1, Seq: 2,
- Data: []byte("HELLO-R-U-THERE"),
- },
- },
- {
- Type: ipv4.ICMPTypePhoturis,
- Body: &icmp.DefaultMessageBody{
- Data: []byte{0x80, 0x40, 0x20, 0x10},
- },
- },
-}
-
-func TestMarshalAndParseMessageForIPv4(t *testing.T) {
- for _, tt := range marshalAndParseMessageForIPv4Tests {
- b, err := tt.Marshal(nil)
- if err != nil {
- t.Fatal(err)
- }
- m, err := icmp.ParseMessage(iana.ProtocolICMP, b)
- if err != nil {
- t.Fatal(err)
- }
- if m.Type != tt.Type || m.Code != tt.Code {
- t.Errorf("got %v; want %v", m, &tt)
- }
- if !reflect.DeepEqual(m.Body, tt.Body) {
- t.Errorf("got %v; want %v", m.Body, tt.Body)
- }
- }
-}
-
-var marshalAndParseMessageForIPv6Tests = []icmp.Message{
- {
- Type: ipv6.ICMPTypeDestinationUnreachable, Code: 6,
- Body: &icmp.DstUnreach{
- Data: []byte("ERROR-INVOKING-PACKET"),
- },
- },
- {
- Type: ipv6.ICMPTypePacketTooBig, Code: 0,
- Body: &icmp.PacketTooBig{
- MTU: 1<<16 - 1,
- Data: []byte("ERROR-INVOKING-PACKET"),
- },
- },
- {
- Type: ipv6.ICMPTypeTimeExceeded, Code: 1,
- Body: &icmp.TimeExceeded{
- Data: []byte("ERROR-INVOKING-PACKET"),
- },
- },
- {
- Type: ipv6.ICMPTypeParameterProblem, Code: 2,
- Body: &icmp.ParamProb{
- Pointer: 8,
- Data: []byte("ERROR-INVOKING-PACKET"),
- },
- },
- {
- Type: ipv6.ICMPTypeEchoRequest, Code: 0,
- Body: &icmp.Echo{
- ID: 1, Seq: 2,
- Data: []byte("HELLO-R-U-THERE"),
- },
- },
- {
- Type: ipv6.ICMPTypeDuplicateAddressConfirmation,
- Body: &icmp.DefaultMessageBody{
- Data: []byte{0x80, 0x40, 0x20, 0x10},
- },
- },
-}
-
-func TestMarshalAndParseMessageForIPv6(t *testing.T) {
- pshicmp := icmp.IPv6PseudoHeader(net.ParseIP("fe80::1"), net.ParseIP("ff02::1"))
- for _, tt := range marshalAndParseMessageForIPv6Tests {
- for _, psh := range [][]byte{pshicmp, nil} {
- b, err := tt.Marshal(psh)
- if err != nil {
- t.Fatal(err)
- }
- m, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, b)
- if err != nil {
- t.Fatal(err)
- }
- if m.Type != tt.Type || m.Code != tt.Code {
- t.Errorf("got %v; want %v", m, &tt)
- }
- if !reflect.DeepEqual(m.Body, tt.Body) {
- t.Errorf("got %v; want %v", m.Body, tt.Body)
- }
- }
- }
-}
diff --git a/internal/icmp/messagebody.go b/internal/icmp/messagebody.go
deleted file mode 100644
index f653ab6..0000000
--- a/internal/icmp/messagebody.go
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package icmp
-
-// A MessageBody represents an ICMP message body.
-type MessageBody interface {
- // Len returns the length of ICMP message body.
- Len() int
-
- // Marshal returns the binary enconding of ICMP message body.
- Marshal() ([]byte, error)
-}
-
-// A DefaultMessageBody represents the default message body.
-type DefaultMessageBody struct {
- Data []byte // data
-}
-
-// Len implements the Len method of MessageBody interface.
-func (p *DefaultMessageBody) Len() int {
- if p == nil {
- return 0
- }
- return len(p.Data)
-}
-
-// Marshal implements the Marshal method of MessageBody interface.
-func (p *DefaultMessageBody) Marshal() ([]byte, error) {
- return p.Data, nil
-}
-
-// parseDefaultMessageBody parses b as an ICMP message body.
-func parseDefaultMessageBody(b []byte) (MessageBody, error) {
- p := &DefaultMessageBody{Data: make([]byte, len(b))}
- copy(p.Data, b)
- return p, nil
-}
diff --git a/internal/icmp/packettoobig.go b/internal/icmp/packettoobig.go
deleted file mode 100644
index fc10192..0000000
--- a/internal/icmp/packettoobig.go
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package icmp
-
-// A PacketTooBig represents an ICMP packet too big message body.
-type PacketTooBig struct {
- MTU int // maximum transmission unit of the nexthop link
- Data []byte // data
-}
-
-// Len implements the Len method of MessageBody interface.
-func (p *PacketTooBig) Len() int {
- if p == nil {
- return 0
- }
- return 4 + len(p.Data)
-}
-
-// Marshal implements the Marshal method of MessageBody interface.
-func (p *PacketTooBig) Marshal() ([]byte, error) {
- b := make([]byte, 4+len(p.Data))
- b[0], b[1], b[2], b[3] = byte(p.MTU>>24), byte(p.MTU>>16), byte(p.MTU>>8), byte(p.MTU)
- copy(b[4:], p.Data)
- return b, nil
-}
-
-// parsePacketTooBig parses b as an ICMP packet too big message body.
-func parsePacketTooBig(b []byte) (MessageBody, error) {
- bodyLen := len(b)
- if bodyLen < 4 {
- return nil, errMessageTooShort
- }
- p := &PacketTooBig{MTU: int(b[0])<<24 | int(b[1])<<16 | int(b[2])<<8 | int(b[3])}
- if bodyLen > 4 {
- p.Data = make([]byte, bodyLen-4)
- copy(p.Data, b[4:])
- }
- return p, nil
-}
diff --git a/internal/icmp/paramprob.go b/internal/icmp/paramprob.go
deleted file mode 100644
index be32ce0..0000000
--- a/internal/icmp/paramprob.go
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package icmp
-
-// A ParamProb represents an ICMP parameter problem message body.
-type ParamProb struct {
- Pointer uintptr // offset within the data where the error was detected
- Data []byte // data
-}
-
-// Len implements the Len method of MessageBody interface.
-func (p *ParamProb) Len() int {
- if p == nil {
- return 0
- }
- return 4 + len(p.Data)
-}
-
-// Marshal implements the Marshal method of MessageBody interface.
-func (p *ParamProb) Marshal() ([]byte, error) {
- b := make([]byte, 4+len(p.Data))
- b[0], b[1], b[2], b[3] = byte(p.Pointer>>24), byte(p.Pointer>>16), byte(p.Pointer>>8), byte(p.Pointer)
- copy(b[4:], p.Data)
- return b, nil
-}
-
-// parseParamProb parses b as an ICMP parameter problem message body.
-func parseParamProb(b []byte) (MessageBody, error) {
- bodyLen := len(b)
- if bodyLen < 4 {
- return nil, errMessageTooShort
- }
- p := &ParamProb{Pointer: uintptr(b[0])<<24 | uintptr(b[1])<<16 | uintptr(b[2])<<8 | uintptr(b[3])}
- if bodyLen > 4 {
- p.Data = make([]byte, bodyLen-4)
- copy(p.Data, b[4:])
- }
- return p, nil
-}
diff --git a/internal/icmp/ping_test.go b/internal/icmp/ping_test.go
deleted file mode 100644
index 8d71d6c..0000000
--- a/internal/icmp/ping_test.go
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package icmp_test
-
-import (
- "errors"
- "net"
- "os"
- "runtime"
- "testing"
-
- "golang.org/x/net/internal/iana"
- "golang.org/x/net/internal/icmp"
- "golang.org/x/net/ipv4"
- "golang.org/x/net/ipv6"
-)
-
-func googleAddr(c *icmp.PacketConn, protocol int) (net.Addr, error) {
- const host = "www.google.com"
- ips, err := net.LookupIP(host)
- if err != nil {
- return nil, err
- }
- netaddr := func(ip net.IP) (net.Addr, error) {
- switch c.LocalAddr().(type) {
- case *net.UDPAddr:
- return &net.UDPAddr{IP: ip}, nil
- case *net.IPAddr:
- return &net.IPAddr{IP: ip}, nil
- default:
- return nil, errors.New("neither UDPAddr nor IPAddr")
- }
- }
- for _, ip := range ips {
- switch protocol {
- case iana.ProtocolICMP:
- if ip.To4() != nil {
- return netaddr(ip)
- }
- case iana.ProtocolIPv6ICMP:
- if ip.To16() != nil && ip.To4() == nil {
- return netaddr(ip)
- }
- }
- }
- return nil, errors.New("no A or AAAA record")
-}
-
-var pingGoogleTests = []struct {
- network, address string
- protocol int
- mtype icmp.Type
-}{
- {"udp4", "0.0.0.0", iana.ProtocolICMP, ipv4.ICMPTypeEcho},
- {"ip4:icmp", "0.0.0.0", iana.ProtocolICMP, ipv4.ICMPTypeEcho},
-
- {"udp6", "::", iana.ProtocolIPv6ICMP, ipv6.ICMPTypeEchoRequest},
- {"ip6:ipv6-icmp", "::", iana.ProtocolIPv6ICMP, ipv6.ICMPTypeEchoRequest},
-}
-
-func TestPingGoogle(t *testing.T) {
- if testing.Short() {
- t.Skip("to avoid external network")
- }
- switch runtime.GOOS {
- case "darwin":
- case "linux":
- t.Log("you may need to adjust the net.ipv4.ping_group_range kernel state")
- default:
- t.Skipf("not supported on %q", runtime.GOOS)
- }
-
- for i, tt := range pingGoogleTests {
- if tt.network[:2] == "ip" && os.Getuid() != 0 {
- continue
- }
- c, err := icmp.ListenPacket(tt.network, tt.address)
- if err != nil {
- t.Error(err)
- continue
- }
- defer c.Close()
-
- dst, err := googleAddr(c, tt.protocol)
- if err != nil {
- t.Error(err)
- continue
- }
-
- wm := icmp.Message{
- Type: tt.mtype, Code: 0,
- Body: &icmp.Echo{
- ID: os.Getpid() & 0xffff, Seq: 1 << uint(i),
- Data: []byte("HELLO-R-U-THERE"),
- },
- }
- wb, err := wm.Marshal(nil)
- if err != nil {
- t.Error(err)
- continue
- }
- if n, err := c.WriteTo(wb, dst); err != nil {
- t.Error(err, dst)
- continue
- } else if n != len(wb) {
- t.Errorf("got %v; want %v", n, len(wb))
- continue
- }
-
- rb := make([]byte, 1500)
- n, peer, err := c.ReadFrom(rb)
- if err != nil {
- t.Error(err)
- continue
- }
- rm, err := icmp.ParseMessage(tt.protocol, rb[:n])
- if err != nil {
- t.Error(err)
- continue
- }
- switch rm.Type {
- case ipv4.ICMPTypeEchoReply, ipv6.ICMPTypeEchoReply:
- t.Logf("got reflection from %v", peer)
- default:
- t.Errorf("got %+v; want echo reply", rm)
- }
- }
-}
diff --git a/internal/icmp/sys_freebsd.go b/internal/icmp/sys_freebsd.go
deleted file mode 100644
index c75f3dd..0000000
--- a/internal/icmp/sys_freebsd.go
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package icmp
-
-import "syscall"
-
-func init() {
- freebsdVersion, _ = syscall.SysctlUint32("kern.osreldate")
-}
diff --git a/internal/icmp/timeexceeded.go b/internal/icmp/timeexceeded.go
deleted file mode 100644
index 993a150..0000000
--- a/internal/icmp/timeexceeded.go
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package icmp
-
-// A TimeExceeded represents an ICMP time exceeded message body.
-type TimeExceeded struct {
- Data []byte // data
-}
-
-// Len implements the Len method of MessageBody interface.
-func (p *TimeExceeded) Len() int {
- if p == nil {
- return 0
- }
- return 4 + len(p.Data)
-}
-
-// Marshal implements the Marshal method of MessageBody interface.
-func (p *TimeExceeded) Marshal() ([]byte, error) {
- b := make([]byte, 4+len(p.Data))
- copy(b[4:], p.Data)
- return b, nil
-}
-
-// parseTimeExceeded parses b as an ICMP time exceeded message body.
-func parseTimeExceeded(b []byte) (MessageBody, error) {
- bodyLen := len(b)
- if bodyLen < 4 {
- return nil, errMessageTooShort
- }
- p := &TimeExceeded{}
- if bodyLen > 4 {
- p.Data = make([]byte, bodyLen-4)
- copy(p.Data, b[4:])
- }
- return p, nil
-}