diff options
author | Mikio Hara <mikioh.mikioh@gmail.com> | 2014-12-03 12:32:52 +0900 |
---|---|---|
committer | Mikio Hara <mikioh.mikioh@gmail.com> | 2014-12-03 12:32:52 +0900 |
commit | b745b482fe97df07c8c3a25247731f0141ac864b (patch) | |
tree | 2410116b463d4e09bfc29c96ee686b13fe512cfe /internal | |
parent | fc168c3c5cfd0f4237144c6863b9585cc5d9a24f (diff) | |
download | net-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.go | 41 | ||||
-rw-r--r-- | internal/icmp/echo.go | 43 | ||||
-rw-r--r-- | internal/icmp/endpoint.go | 108 | ||||
-rw-r--r-- | internal/icmp/example_test.go | 54 | ||||
-rw-r--r-- | internal/icmp/helper_unix.go | 87 | ||||
-rw-r--r-- | internal/icmp/ipv4.go | 61 | ||||
-rw-r--r-- | internal/icmp/ipv4_test.go | 71 | ||||
-rw-r--r-- | internal/icmp/ipv6.go | 23 | ||||
-rw-r--r-- | internal/icmp/listen_stub.go | 33 | ||||
-rw-r--r-- | internal/icmp/listen_unix.go | 98 | ||||
-rw-r--r-- | internal/icmp/message.go | 135 | ||||
-rw-r--r-- | internal/icmp/message_test.go | 134 | ||||
-rw-r--r-- | internal/icmp/messagebody.go | 39 | ||||
-rw-r--r-- | internal/icmp/packettoobig.go | 41 | ||||
-rw-r--r-- | internal/icmp/paramprob.go | 41 | ||||
-rw-r--r-- | internal/icmp/ping_test.go | 130 | ||||
-rw-r--r-- | internal/icmp/sys_freebsd.go | 11 | ||||
-rw-r--r-- | internal/icmp/timeexceeded.go | 39 |
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 -} |