vendor
This commit is contained in:
274
vendor/golang.org/x/net/icmp/diag_test.go
generated
vendored
Normal file
274
vendor/golang.org/x/net/icmp/diag_test.go
generated
vendored
Normal file
@ -0,0 +1,274 @@
|
||||
// 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"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/icmp"
|
||||
"golang.org/x/net/internal/iana"
|
||||
"golang.org/x/net/internal/nettest"
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
type diagTest struct {
|
||||
network, address string
|
||||
protocol int
|
||||
m icmp.Message
|
||||
}
|
||||
|
||||
func TestDiag(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("avoid external network")
|
||||
}
|
||||
|
||||
t.Run("Ping/NonPrivileged", func(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
case "linux":
|
||||
t.Log("you may need to adjust the net.ipv4.ping_group_range kernel state")
|
||||
default:
|
||||
t.Logf("not supported on %s", runtime.GOOS)
|
||||
return
|
||||
}
|
||||
for i, dt := range []diagTest{
|
||||
{
|
||||
"udp4", "0.0.0.0", iana.ProtocolICMP,
|
||||
icmp.Message{
|
||||
Type: ipv4.ICMPTypeEcho, Code: 0,
|
||||
Body: &icmp.Echo{
|
||||
ID: os.Getpid() & 0xffff,
|
||||
Data: []byte("HELLO-R-U-THERE"),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
"udp6", "::", iana.ProtocolIPv6ICMP,
|
||||
icmp.Message{
|
||||
Type: ipv6.ICMPTypeEchoRequest, Code: 0,
|
||||
Body: &icmp.Echo{
|
||||
ID: os.Getpid() & 0xffff,
|
||||
Data: []byte("HELLO-R-U-THERE"),
|
||||
},
|
||||
},
|
||||
},
|
||||
} {
|
||||
if err := doDiag(dt, i); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
t.Run("Ping/Privileged", func(t *testing.T) {
|
||||
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||
t.Skip(m)
|
||||
}
|
||||
for i, dt := range []diagTest{
|
||||
{
|
||||
"ip4:icmp", "0.0.0.0", iana.ProtocolICMP,
|
||||
icmp.Message{
|
||||
Type: ipv4.ICMPTypeEcho, Code: 0,
|
||||
Body: &icmp.Echo{
|
||||
ID: os.Getpid() & 0xffff,
|
||||
Data: []byte("HELLO-R-U-THERE"),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
"ip6:ipv6-icmp", "::", iana.ProtocolIPv6ICMP,
|
||||
icmp.Message{
|
||||
Type: ipv6.ICMPTypeEchoRequest, Code: 0,
|
||||
Body: &icmp.Echo{
|
||||
ID: os.Getpid() & 0xffff,
|
||||
Data: []byte("HELLO-R-U-THERE"),
|
||||
},
|
||||
},
|
||||
},
|
||||
} {
|
||||
if err := doDiag(dt, i); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
t.Run("Probe/Privileged", func(t *testing.T) {
|
||||
if m, ok := nettest.SupportsRawIPSocket(); !ok {
|
||||
t.Skip(m)
|
||||
}
|
||||
for i, dt := range []diagTest{
|
||||
{
|
||||
"ip4:icmp", "0.0.0.0", iana.ProtocolICMP,
|
||||
icmp.Message{
|
||||
Type: ipv4.ICMPTypeExtendedEchoRequest, Code: 0,
|
||||
Body: &icmp.ExtendedEchoRequest{
|
||||
ID: os.Getpid() & 0xffff,
|
||||
Local: true,
|
||||
Extensions: []icmp.Extension{
|
||||
&icmp.InterfaceIdent{
|
||||
Class: 3, Type: 1,
|
||||
Name: "doesnotexist",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
"ip6:ipv6-icmp", "::", iana.ProtocolIPv6ICMP,
|
||||
icmp.Message{
|
||||
Type: ipv6.ICMPTypeExtendedEchoRequest, Code: 0,
|
||||
Body: &icmp.ExtendedEchoRequest{
|
||||
ID: os.Getpid() & 0xffff,
|
||||
Local: true,
|
||||
Extensions: []icmp.Extension{
|
||||
&icmp.InterfaceIdent{
|
||||
Class: 3, Type: 1,
|
||||
Name: "doesnotexist",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} {
|
||||
if err := doDiag(dt, i); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func doDiag(dt diagTest, seq int) error {
|
||||
c, err := icmp.ListenPacket(dt.network, dt.address)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
dst, err := googleAddr(c, dt.protocol)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if dt.network != "udp6" && dt.protocol == iana.ProtocolIPv6ICMP {
|
||||
var f ipv6.ICMPFilter
|
||||
f.SetAll(true)
|
||||
f.Accept(ipv6.ICMPTypeDestinationUnreachable)
|
||||
f.Accept(ipv6.ICMPTypePacketTooBig)
|
||||
f.Accept(ipv6.ICMPTypeTimeExceeded)
|
||||
f.Accept(ipv6.ICMPTypeParameterProblem)
|
||||
f.Accept(ipv6.ICMPTypeEchoReply)
|
||||
f.Accept(ipv6.ICMPTypeExtendedEchoReply)
|
||||
if err := c.IPv6PacketConn().SetICMPFilter(&f); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
switch m := dt.m.Body.(type) {
|
||||
case *icmp.Echo:
|
||||
m.Seq = 1 << uint(seq)
|
||||
case *icmp.ExtendedEchoRequest:
|
||||
m.Seq = 1 << uint(seq)
|
||||
}
|
||||
wb, err := dt.m.Marshal(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n, err := c.WriteTo(wb, dst); err != nil {
|
||||
return err
|
||||
} else if n != len(wb) {
|
||||
return fmt.Errorf("got %v; want %v", n, len(wb))
|
||||
}
|
||||
|
||||
rb := make([]byte, 1500)
|
||||
if err := c.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil {
|
||||
return err
|
||||
}
|
||||
n, peer, err := c.ReadFrom(rb)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rm, err := icmp.ParseMessage(dt.protocol, rb[:n])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch {
|
||||
case dt.m.Type == ipv4.ICMPTypeEcho && rm.Type == ipv4.ICMPTypeEchoReply:
|
||||
fallthrough
|
||||
case dt.m.Type == ipv6.ICMPTypeEchoRequest && rm.Type == ipv6.ICMPTypeEchoReply:
|
||||
fallthrough
|
||||
case dt.m.Type == ipv4.ICMPTypeExtendedEchoRequest && rm.Type == ipv4.ICMPTypeExtendedEchoReply:
|
||||
fallthrough
|
||||
case dt.m.Type == ipv6.ICMPTypeExtendedEchoRequest && rm.Type == ipv6.ICMPTypeExtendedEchoReply:
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("got %+v from %v; want echo reply or extended echo reply", rm, peer)
|
||||
}
|
||||
}
|
||||
|
||||
func googleAddr(c *icmp.PacketConn, protocol int) (net.Addr, error) {
|
||||
host := "ipv4.google.com"
|
||||
if protocol == iana.ProtocolIPv6ICMP {
|
||||
host = "ipv6.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")
|
||||
}
|
||||
}
|
||||
if len(ips) > 0 {
|
||||
return netaddr(ips[0])
|
||||
}
|
||||
return nil, errors.New("no A or AAAA record")
|
||||
}
|
||||
|
||||
func TestConcurrentNonPrivilegedListenPacket(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("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 %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
network, address := "udp4", "127.0.0.1"
|
||||
if !nettest.SupportsIPv4() {
|
||||
network, address = "udp6", "::1"
|
||||
}
|
||||
const N = 1000
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(N)
|
||||
for i := 0; i < N; i++ {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
c, err := icmp.ListenPacket(network, address)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
c.Close()
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
41
vendor/golang.org/x/net/icmp/dstunreach.go
generated
vendored
Normal file
41
vendor/golang.org/x/net/icmp/dstunreach.go
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
// 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, known as original datagram field
|
||||
Extensions []Extension // extensions
|
||||
}
|
||||
|
||||
// Len implements the Len method of MessageBody interface.
|
||||
func (p *DstUnreach) Len(proto int) int {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
l, _ := multipartMessageBodyDataLen(proto, true, p.Data, p.Extensions)
|
||||
return 4 + l
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of MessageBody interface.
|
||||
func (p *DstUnreach) Marshal(proto int) ([]byte, error) {
|
||||
return marshalMultipartMessageBody(proto, true, p.Data, p.Extensions)
|
||||
}
|
||||
|
||||
// parseDstUnreach parses b as an ICMP destination unreachable message
|
||||
// body.
|
||||
func parseDstUnreach(proto int, typ Type, b []byte) (MessageBody, error) {
|
||||
if len(b) < 4 {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
p := &DstUnreach{}
|
||||
var err error
|
||||
p.Data, p.Extensions, err = parseMultipartMessageBody(proto, typ, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p, nil
|
||||
}
|
157
vendor/golang.org/x/net/icmp/echo.go
generated
vendored
Normal file
157
vendor/golang.org/x/net/icmp/echo.go
generated
vendored
Normal file
@ -0,0 +1,157 @@
|
||||
// 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
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
// 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(proto int) int {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
return 4 + len(p.Data)
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of MessageBody interface.
|
||||
func (p *Echo) Marshal(proto int) ([]byte, error) {
|
||||
b := make([]byte, 4+len(p.Data))
|
||||
binary.BigEndian.PutUint16(b[:2], uint16(p.ID))
|
||||
binary.BigEndian.PutUint16(b[2:4], uint16(p.Seq))
|
||||
copy(b[4:], p.Data)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// parseEcho parses b as an ICMP echo request or reply message body.
|
||||
func parseEcho(proto int, _ Type, b []byte) (MessageBody, error) {
|
||||
bodyLen := len(b)
|
||||
if bodyLen < 4 {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
p := &Echo{ID: int(binary.BigEndian.Uint16(b[:2])), Seq: int(binary.BigEndian.Uint16(b[2:4]))}
|
||||
if bodyLen > 4 {
|
||||
p.Data = make([]byte, bodyLen-4)
|
||||
copy(p.Data, b[4:])
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// An 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
|
||||
}
|
||||
|
||||
// Len implements the Len method of MessageBody interface.
|
||||
func (p *ExtendedEchoRequest) Len(proto int) int {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
l, _ := multipartMessageBodyDataLen(proto, false, nil, p.Extensions)
|
||||
return 4 + l
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of MessageBody interface.
|
||||
func (p *ExtendedEchoRequest) Marshal(proto int) ([]byte, error) {
|
||||
b, err := marshalMultipartMessageBody(proto, false, nil, p.Extensions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bb := make([]byte, 4)
|
||||
binary.BigEndian.PutUint16(bb[:2], uint16(p.ID))
|
||||
bb[2] = byte(p.Seq)
|
||||
if p.Local {
|
||||
bb[3] |= 0x01
|
||||
}
|
||||
bb = append(bb, b...)
|
||||
return bb, nil
|
||||
}
|
||||
|
||||
// parseExtendedEchoRequest parses b as an ICMP extended echo request
|
||||
// message body.
|
||||
func parseExtendedEchoRequest(proto int, typ Type, b []byte) (MessageBody, error) {
|
||||
if len(b) < 4+4 {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
p := &ExtendedEchoRequest{ID: int(binary.BigEndian.Uint16(b[:2])), Seq: int(b[2])}
|
||||
if b[3]&0x01 != 0 {
|
||||
p.Local = true
|
||||
}
|
||||
var err error
|
||||
_, p.Extensions, err = parseMultipartMessageBody(proto, typ, b[4:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// An 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 together with Message.Code
|
||||
Active bool // probed interface is active
|
||||
IPv4 bool // probed interface runs IPv4
|
||||
IPv6 bool // probed interface runs IPv6
|
||||
}
|
||||
|
||||
// Len implements the Len method of MessageBody interface.
|
||||
func (p *ExtendedEchoReply) Len(proto int) int {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
return 4
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of MessageBody interface.
|
||||
func (p *ExtendedEchoReply) Marshal(proto int) ([]byte, error) {
|
||||
b := make([]byte, 4)
|
||||
binary.BigEndian.PutUint16(b[:2], uint16(p.ID))
|
||||
b[2] = byte(p.Seq)
|
||||
b[3] = byte(p.State<<5) & 0xe0
|
||||
if p.Active {
|
||||
b[3] |= 0x04
|
||||
}
|
||||
if p.IPv4 {
|
||||
b[3] |= 0x02
|
||||
}
|
||||
if p.IPv6 {
|
||||
b[3] |= 0x01
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// parseExtendedEchoReply parses b as an ICMP extended echo reply
|
||||
// message body.
|
||||
func parseExtendedEchoReply(proto int, _ Type, b []byte) (MessageBody, error) {
|
||||
if len(b) < 4 {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
p := &ExtendedEchoReply{
|
||||
ID: int(binary.BigEndian.Uint16(b[:2])),
|
||||
Seq: int(b[2]),
|
||||
State: int(b[3]) >> 5,
|
||||
}
|
||||
if b[3]&0x04 != 0 {
|
||||
p.Active = true
|
||||
}
|
||||
if b[3]&0x02 != 0 {
|
||||
p.IPv4 = true
|
||||
}
|
||||
if b[3]&0x01 != 0 {
|
||||
p.IPv6 = true
|
||||
}
|
||||
return p, nil
|
||||
}
|
112
vendor/golang.org/x/net/icmp/endpoint.go
generated
vendored
Normal file
112
vendor/golang.org/x/net/icmp/endpoint.go
generated
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
// 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"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
var _ net.PacketConn = &PacketConn{}
|
||||
|
||||
// A PacketConn represents a packet network endpoint that uses either
|
||||
// ICMPv4 or ICMPv6.
|
||||
type PacketConn struct {
|
||||
c net.PacketConn
|
||||
p4 *ipv4.PacketConn
|
||||
p6 *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
|
||||
}
|
||||
return c.p4
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
return c.p6
|
||||
}
|
||||
|
||||
// ReadFrom reads an ICMP message from the connection.
|
||||
func (c *PacketConn) ReadFrom(b []byte) (int, net.Addr, error) {
|
||||
if !c.ok() {
|
||||
return 0, nil, errInvalidConn
|
||||
}
|
||||
// Please be informed that ipv4.NewPacketConn enables
|
||||
// IP_STRIPHDR option by default on Darwin.
|
||||
// See golang.org/issue/9395 for further information.
|
||||
if runtime.GOOS == "darwin" && c.p4 != nil {
|
||||
n, _, peer, err := c.p4.ReadFrom(b)
|
||||
return n, peer, err
|
||||
}
|
||||
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, errInvalidConn
|
||||
}
|
||||
return c.c.WriteTo(b, dst)
|
||||
}
|
||||
|
||||
// Close closes the endpoint.
|
||||
func (c *PacketConn) Close() error {
|
||||
if !c.ok() {
|
||||
return errInvalidConn
|
||||
}
|
||||
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 errInvalidConn
|
||||
}
|
||||
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 errInvalidConn
|
||||
}
|
||||
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 errInvalidConn
|
||||
}
|
||||
return c.c.SetWriteDeadline(t)
|
||||
}
|
63
vendor/golang.org/x/net/icmp/example_test.go
generated
vendored
Normal file
63
vendor/golang.org/x/net/icmp/example_test.go
generated
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
// 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"
|
||||
"runtime"
|
||||
|
||||
"golang.org/x/net/icmp"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
func ExamplePacketConn_nonPrivilegedPing() {
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
case "linux":
|
||||
log.Println("you may need to adjust the net.ipv4.ping_group_range kernel state")
|
||||
default:
|
||||
log.Println("not supported on", runtime.GOOS)
|
||||
return
|
||||
}
|
||||
|
||||
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(58, 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)
|
||||
}
|
||||
}
|
108
vendor/golang.org/x/net/icmp/extension.go
generated
vendored
Normal file
108
vendor/golang.org/x/net/icmp/extension.go
generated
vendored
Normal file
@ -0,0 +1,108 @@
|
||||
// Copyright 2015 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 (
|
||||
"encoding/binary"
|
||||
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
// An Extension represents an ICMP extension.
|
||||
type Extension interface {
|
||||
// Len returns the length of ICMP extension.
|
||||
// Proto must be either the ICMPv4 or ICMPv6 protocol number.
|
||||
Len(proto int) int
|
||||
|
||||
// Marshal returns the binary encoding of ICMP extension.
|
||||
// Proto must be either the ICMPv4 or ICMPv6 protocol number.
|
||||
Marshal(proto int) ([]byte, error)
|
||||
}
|
||||
|
||||
const extensionVersion = 2
|
||||
|
||||
func validExtensionHeader(b []byte) bool {
|
||||
v := int(b[0]&0xf0) >> 4
|
||||
s := binary.BigEndian.Uint16(b[2:4])
|
||||
if s != 0 {
|
||||
s = checksum(b)
|
||||
}
|
||||
if v != extensionVersion || s != 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// parseExtensions parses b as a list of ICMP extensions.
|
||||
// The length attribute l must be the length attribute field in
|
||||
// received icmp messages.
|
||||
//
|
||||
// It will return a list of ICMP extensions and an adjusted length
|
||||
// attribute that represents the length of the padded original
|
||||
// datagram field. Otherwise, it returns an error.
|
||||
func parseExtensions(typ Type, b []byte, l int) ([]Extension, int, error) {
|
||||
// Still a lot of non-RFC 4884 compliant implementations are
|
||||
// out there. Set the length attribute l to 128 when it looks
|
||||
// inappropriate for backwards compatibility.
|
||||
//
|
||||
// A minimal extension at least requires 8 octets; 4 octets
|
||||
// for an extension header, and 4 octets for a single object
|
||||
// header.
|
||||
//
|
||||
// See RFC 4884 for further information.
|
||||
switch typ {
|
||||
case ipv4.ICMPTypeExtendedEchoRequest, ipv6.ICMPTypeExtendedEchoRequest:
|
||||
if len(b) < 8 || !validExtensionHeader(b) {
|
||||
return nil, -1, errNoExtension
|
||||
}
|
||||
l = 0
|
||||
default:
|
||||
if 128 > l || l+8 > len(b) {
|
||||
l = 128
|
||||
}
|
||||
if l+8 > len(b) {
|
||||
return nil, -1, errNoExtension
|
||||
}
|
||||
if !validExtensionHeader(b[l:]) {
|
||||
if l == 128 {
|
||||
return nil, -1, errNoExtension
|
||||
}
|
||||
l = 128
|
||||
if !validExtensionHeader(b[l:]) {
|
||||
return nil, -1, errNoExtension
|
||||
}
|
||||
}
|
||||
}
|
||||
var exts []Extension
|
||||
for b = b[l+4:]; len(b) >= 4; {
|
||||
ol := int(binary.BigEndian.Uint16(b[:2]))
|
||||
if 4 > ol || ol > len(b) {
|
||||
break
|
||||
}
|
||||
switch b[2] {
|
||||
case classMPLSLabelStack:
|
||||
ext, err := parseMPLSLabelStack(b[:ol])
|
||||
if err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
exts = append(exts, ext)
|
||||
case classInterfaceInfo:
|
||||
ext, err := parseInterfaceInfo(b[:ol])
|
||||
if err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
exts = append(exts, ext)
|
||||
case classInterfaceIdent:
|
||||
ext, err := parseInterfaceIdent(b[:ol])
|
||||
if err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
exts = append(exts, ext)
|
||||
}
|
||||
b = b[ol:]
|
||||
}
|
||||
return exts, l, nil
|
||||
}
|
333
vendor/golang.org/x/net/icmp/extension_test.go
generated
vendored
Normal file
333
vendor/golang.org/x/net/icmp/extension_test.go
generated
vendored
Normal file
@ -0,0 +1,333 @@
|
||||
// Copyright 2015 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 (
|
||||
"fmt"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/internal/iana"
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
func TestMarshalAndParseExtension(t *testing.T) {
|
||||
fn := func(t *testing.T, proto int, typ Type, hdr, obj []byte, te Extension) error {
|
||||
b, err := te.Marshal(proto)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !reflect.DeepEqual(b, obj) {
|
||||
return fmt.Errorf("got %#v; want %#v", b, obj)
|
||||
}
|
||||
switch typ {
|
||||
case ipv4.ICMPTypeExtendedEchoRequest, ipv6.ICMPTypeExtendedEchoRequest:
|
||||
exts, l, err := parseExtensions(typ, append(hdr, obj...), 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if l != 0 {
|
||||
return fmt.Errorf("got %d; want 0", l)
|
||||
}
|
||||
if !reflect.DeepEqual(exts, []Extension{te}) {
|
||||
return fmt.Errorf("got %#v; want %#v", exts[0], te)
|
||||
}
|
||||
default:
|
||||
for i, wire := range []struct {
|
||||
data []byte // original datagram
|
||||
inlattr int // length of padded original datagram, a hint
|
||||
outlattr int // length of padded original datagram, a want
|
||||
err error
|
||||
}{
|
||||
{nil, 0, -1, errNoExtension},
|
||||
{make([]byte, 127), 128, -1, errNoExtension},
|
||||
|
||||
{make([]byte, 128), 127, -1, errNoExtension},
|
||||
{make([]byte, 128), 128, -1, errNoExtension},
|
||||
{make([]byte, 128), 129, -1, errNoExtension},
|
||||
|
||||
{append(make([]byte, 128), append(hdr, obj...)...), 127, 128, nil},
|
||||
{append(make([]byte, 128), append(hdr, obj...)...), 128, 128, nil},
|
||||
{append(make([]byte, 128), append(hdr, obj...)...), 129, 128, nil},
|
||||
|
||||
{append(make([]byte, 512), append(hdr, obj...)...), 511, -1, errNoExtension},
|
||||
{append(make([]byte, 512), append(hdr, obj...)...), 512, 512, nil},
|
||||
{append(make([]byte, 512), append(hdr, obj...)...), 513, -1, errNoExtension},
|
||||
} {
|
||||
exts, l, err := parseExtensions(typ, wire.data, wire.inlattr)
|
||||
if err != wire.err {
|
||||
return fmt.Errorf("#%d: got %v; want %v", i, err, wire.err)
|
||||
}
|
||||
if wire.err != nil {
|
||||
continue
|
||||
}
|
||||
if l != wire.outlattr {
|
||||
return fmt.Errorf("#%d: got %d; want %d", i, l, wire.outlattr)
|
||||
}
|
||||
if !reflect.DeepEqual(exts, []Extension{te}) {
|
||||
return fmt.Errorf("#%d: got %#v; want %#v", i, exts[0], te)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
t.Run("MPLSLabelStack", func(t *testing.T) {
|
||||
for _, et := range []struct {
|
||||
proto int
|
||||
typ Type
|
||||
hdr []byte
|
||||
obj []byte
|
||||
ext Extension
|
||||
}{
|
||||
// MPLS label stack with no label
|
||||
{
|
||||
proto: iana.ProtocolICMP,
|
||||
typ: ipv4.ICMPTypeDestinationUnreachable,
|
||||
hdr: []byte{
|
||||
0x20, 0x00, 0x00, 0x00,
|
||||
},
|
||||
obj: []byte{
|
||||
0x00, 0x04, 0x01, 0x01,
|
||||
},
|
||||
ext: &MPLSLabelStack{
|
||||
Class: classMPLSLabelStack,
|
||||
Type: typeIncomingMPLSLabelStack,
|
||||
},
|
||||
},
|
||||
// MPLS label stack with a single label
|
||||
{
|
||||
proto: iana.ProtocolIPv6ICMP,
|
||||
typ: ipv6.ICMPTypeDestinationUnreachable,
|
||||
hdr: []byte{
|
||||
0x20, 0x00, 0x00, 0x00,
|
||||
},
|
||||
obj: []byte{
|
||||
0x00, 0x08, 0x01, 0x01,
|
||||
0x03, 0xe8, 0xe9, 0xff,
|
||||
},
|
||||
ext: &MPLSLabelStack{
|
||||
Class: classMPLSLabelStack,
|
||||
Type: typeIncomingMPLSLabelStack,
|
||||
Labels: []MPLSLabel{
|
||||
{
|
||||
Label: 16014,
|
||||
TC: 0x4,
|
||||
S: true,
|
||||
TTL: 255,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// MPLS label stack with multiple labels
|
||||
{
|
||||
proto: iana.ProtocolICMP,
|
||||
typ: ipv4.ICMPTypeDestinationUnreachable,
|
||||
hdr: []byte{
|
||||
0x20, 0x00, 0x00, 0x00,
|
||||
},
|
||||
obj: []byte{
|
||||
0x00, 0x0c, 0x01, 0x01,
|
||||
0x03, 0xe8, 0xde, 0xfe,
|
||||
0x03, 0xe8, 0xe1, 0xff,
|
||||
},
|
||||
ext: &MPLSLabelStack{
|
||||
Class: classMPLSLabelStack,
|
||||
Type: typeIncomingMPLSLabelStack,
|
||||
Labels: []MPLSLabel{
|
||||
{
|
||||
Label: 16013,
|
||||
TC: 0x7,
|
||||
S: false,
|
||||
TTL: 254,
|
||||
},
|
||||
{
|
||||
Label: 16014,
|
||||
TC: 0,
|
||||
S: true,
|
||||
TTL: 255,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} {
|
||||
if err := fn(t, et.proto, et.typ, et.hdr, et.obj, et.ext); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
t.Run("InterfaceInfo", func(t *testing.T) {
|
||||
for _, et := range []struct {
|
||||
proto int
|
||||
typ Type
|
||||
hdr []byte
|
||||
obj []byte
|
||||
ext Extension
|
||||
}{
|
||||
// Interface information with no attribute
|
||||
{
|
||||
proto: iana.ProtocolICMP,
|
||||
typ: ipv4.ICMPTypeDestinationUnreachable,
|
||||
hdr: []byte{
|
||||
0x20, 0x00, 0x00, 0x00,
|
||||
},
|
||||
obj: []byte{
|
||||
0x00, 0x04, 0x02, 0x00,
|
||||
},
|
||||
ext: &InterfaceInfo{
|
||||
Class: classInterfaceInfo,
|
||||
},
|
||||
},
|
||||
// Interface information with ifIndex and name
|
||||
{
|
||||
proto: iana.ProtocolICMP,
|
||||
typ: ipv4.ICMPTypeDestinationUnreachable,
|
||||
hdr: []byte{
|
||||
0x20, 0x00, 0x00, 0x00,
|
||||
},
|
||||
obj: []byte{
|
||||
0x00, 0x10, 0x02, 0x0a,
|
||||
0x00, 0x00, 0x00, 0x10,
|
||||
0x08, byte('e'), byte('n'), byte('1'),
|
||||
byte('0'), byte('1'), 0x00, 0x00,
|
||||
},
|
||||
ext: &InterfaceInfo{
|
||||
Class: classInterfaceInfo,
|
||||
Type: 0x0a,
|
||||
Interface: &net.Interface{
|
||||
Index: 16,
|
||||
Name: "en101",
|
||||
},
|
||||
},
|
||||
},
|
||||
// Interface information with ifIndex, IPAddr, name and MTU
|
||||
{
|
||||
proto: iana.ProtocolIPv6ICMP,
|
||||
typ: ipv6.ICMPTypeDestinationUnreachable,
|
||||
hdr: []byte{
|
||||
0x20, 0x00, 0x00, 0x00,
|
||||
},
|
||||
obj: []byte{
|
||||
0x00, 0x28, 0x02, 0x0f,
|
||||
0x00, 0x00, 0x00, 0x0f,
|
||||
0x00, 0x02, 0x00, 0x00,
|
||||
0xfe, 0x80, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01,
|
||||
0x08, byte('e'), byte('n'), byte('1'),
|
||||
byte('0'), byte('1'), 0x00, 0x00,
|
||||
0x00, 0x00, 0x20, 0x00,
|
||||
},
|
||||
ext: &InterfaceInfo{
|
||||
Class: classInterfaceInfo,
|
||||
Type: 0x0f,
|
||||
Interface: &net.Interface{
|
||||
Index: 15,
|
||||
Name: "en101",
|
||||
MTU: 8192,
|
||||
},
|
||||
Addr: &net.IPAddr{
|
||||
IP: net.ParseIP("fe80::1"),
|
||||
Zone: "en101",
|
||||
},
|
||||
},
|
||||
},
|
||||
} {
|
||||
if err := fn(t, et.proto, et.typ, et.hdr, et.obj, et.ext); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
t.Run("InterfaceIdent", func(t *testing.T) {
|
||||
for _, et := range []struct {
|
||||
proto int
|
||||
typ Type
|
||||
hdr []byte
|
||||
obj []byte
|
||||
ext Extension
|
||||
}{
|
||||
// Interface identification by name
|
||||
{
|
||||
proto: iana.ProtocolICMP,
|
||||
typ: ipv4.ICMPTypeExtendedEchoRequest,
|
||||
hdr: []byte{
|
||||
0x20, 0x00, 0x00, 0x00,
|
||||
},
|
||||
obj: []byte{
|
||||
0x00, 0x0c, 0x03, 0x01,
|
||||
byte('e'), byte('n'), byte('1'), byte('0'),
|
||||
byte('1'), 0x00, 0x00, 0x00,
|
||||
},
|
||||
ext: &InterfaceIdent{
|
||||
Class: classInterfaceIdent,
|
||||
Type: typeInterfaceByName,
|
||||
Name: "en101",
|
||||
},
|
||||
},
|
||||
// Interface identification by index
|
||||
{
|
||||
proto: iana.ProtocolIPv6ICMP,
|
||||
typ: ipv6.ICMPTypeExtendedEchoRequest,
|
||||
hdr: []byte{
|
||||
0x20, 0x00, 0x00, 0x00,
|
||||
},
|
||||
obj: []byte{
|
||||
0x00, 0x0c, 0x03, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x03, 0x8f,
|
||||
},
|
||||
ext: &InterfaceIdent{
|
||||
Class: classInterfaceIdent,
|
||||
Type: typeInterfaceByIndex,
|
||||
Index: 911,
|
||||
},
|
||||
},
|
||||
// Interface identification by address
|
||||
{
|
||||
proto: iana.ProtocolICMP,
|
||||
typ: ipv4.ICMPTypeExtendedEchoRequest,
|
||||
hdr: []byte{
|
||||
0x20, 0x00, 0x00, 0x00,
|
||||
},
|
||||
obj: []byte{
|
||||
0x00, 0x10, 0x03, 0x03,
|
||||
byte(iana.AddrFamily48bitMAC >> 8), byte(iana.AddrFamily48bitMAC & 0x0f), 0x06, 0x00,
|
||||
0x01, 0x23, 0x45, 0x67,
|
||||
0x89, 0xab, 0x00, 0x00,
|
||||
},
|
||||
ext: &InterfaceIdent{
|
||||
Class: classInterfaceIdent,
|
||||
Type: typeInterfaceByAddress,
|
||||
AFI: iana.AddrFamily48bitMAC,
|
||||
Addr: []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab},
|
||||
},
|
||||
},
|
||||
} {
|
||||
if err := fn(t, et.proto, et.typ, et.hdr, et.obj, et.ext); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestParseInterfaceName(t *testing.T) {
|
||||
ifi := InterfaceInfo{Interface: &net.Interface{}}
|
||||
for i, tt := range []struct {
|
||||
b []byte
|
||||
error
|
||||
}{
|
||||
{[]byte{0, 'e', 'n', '0'}, errInvalidExtension},
|
||||
{[]byte{4, 'e', 'n', '0'}, nil},
|
||||
{[]byte{7, 'e', 'n', '0', 0xff, 0xff, 0xff, 0xff}, errInvalidExtension},
|
||||
{[]byte{8, 'e', 'n', '0', 0xff, 0xff, 0xff}, errMessageTooShort},
|
||||
} {
|
||||
if _, err := ifi.parseName(tt.b); err != tt.error {
|
||||
t.Errorf("#%d: got %v; want %v", i, err, tt.error)
|
||||
}
|
||||
}
|
||||
}
|
75
vendor/golang.org/x/net/icmp/helper_posix.go
generated
vendored
Normal file
75
vendor/golang.org/x/net/icmp/helper_posix.go
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
// 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 windows
|
||||
|
||||
package icmp
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strconv"
|
||||
"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, err := strconv.Atoi(zone)
|
||||
if err != nil {
|
||||
return 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
|
||||
}
|
322
vendor/golang.org/x/net/icmp/interface.go
generated
vendored
Normal file
322
vendor/golang.org/x/net/icmp/interface.go
generated
vendored
Normal file
@ -0,0 +1,322 @@
|
||||
// Copyright 2015 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 (
|
||||
"encoding/binary"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/net/internal/iana"
|
||||
)
|
||||
|
||||
const (
|
||||
classInterfaceInfo = 2
|
||||
)
|
||||
|
||||
const (
|
||||
attrMTU = 1 << iota
|
||||
attrName
|
||||
attrIPAddr
|
||||
attrIfIndex
|
||||
)
|
||||
|
||||
// An 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) nameLen() int {
|
||||
if len(ifi.Interface.Name) > 63 {
|
||||
return 64
|
||||
}
|
||||
l := 1 + len(ifi.Interface.Name)
|
||||
return (l + 3) &^ 3
|
||||
}
|
||||
|
||||
func (ifi *InterfaceInfo) attrsAndLen(proto int) (attrs, l int) {
|
||||
l = 4
|
||||
if ifi.Interface != nil && ifi.Interface.Index > 0 {
|
||||
attrs |= attrIfIndex
|
||||
l += 4
|
||||
if len(ifi.Interface.Name) > 0 {
|
||||
attrs |= attrName
|
||||
l += ifi.nameLen()
|
||||
}
|
||||
if ifi.Interface.MTU > 0 {
|
||||
attrs |= attrMTU
|
||||
l += 4
|
||||
}
|
||||
}
|
||||
if ifi.Addr != nil {
|
||||
switch proto {
|
||||
case iana.ProtocolICMP:
|
||||
if ifi.Addr.IP.To4() != nil {
|
||||
attrs |= attrIPAddr
|
||||
l += 4 + net.IPv4len
|
||||
}
|
||||
case iana.ProtocolIPv6ICMP:
|
||||
if ifi.Addr.IP.To16() != nil && ifi.Addr.IP.To4() == nil {
|
||||
attrs |= attrIPAddr
|
||||
l += 4 + net.IPv6len
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Len implements the Len method of Extension interface.
|
||||
func (ifi *InterfaceInfo) Len(proto int) int {
|
||||
_, l := ifi.attrsAndLen(proto)
|
||||
return l
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of Extension interface.
|
||||
func (ifi *InterfaceInfo) Marshal(proto int) ([]byte, error) {
|
||||
attrs, l := ifi.attrsAndLen(proto)
|
||||
b := make([]byte, l)
|
||||
if err := ifi.marshal(proto, b, attrs, l); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (ifi *InterfaceInfo) marshal(proto int, b []byte, attrs, l int) error {
|
||||
binary.BigEndian.PutUint16(b[:2], uint16(l))
|
||||
b[2], b[3] = classInterfaceInfo, byte(ifi.Type)
|
||||
for b = b[4:]; len(b) > 0 && attrs != 0; {
|
||||
switch {
|
||||
case attrs&attrIfIndex != 0:
|
||||
b = ifi.marshalIfIndex(proto, b)
|
||||
attrs &^= attrIfIndex
|
||||
case attrs&attrIPAddr != 0:
|
||||
b = ifi.marshalIPAddr(proto, b)
|
||||
attrs &^= attrIPAddr
|
||||
case attrs&attrName != 0:
|
||||
b = ifi.marshalName(proto, b)
|
||||
attrs &^= attrName
|
||||
case attrs&attrMTU != 0:
|
||||
b = ifi.marshalMTU(proto, b)
|
||||
attrs &^= attrMTU
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ifi *InterfaceInfo) marshalIfIndex(proto int, b []byte) []byte {
|
||||
binary.BigEndian.PutUint32(b[:4], uint32(ifi.Interface.Index))
|
||||
return b[4:]
|
||||
}
|
||||
|
||||
func (ifi *InterfaceInfo) parseIfIndex(b []byte) ([]byte, error) {
|
||||
if len(b) < 4 {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
ifi.Interface.Index = int(binary.BigEndian.Uint32(b[:4]))
|
||||
return b[4:], nil
|
||||
}
|
||||
|
||||
func (ifi *InterfaceInfo) marshalIPAddr(proto int, b []byte) []byte {
|
||||
switch proto {
|
||||
case iana.ProtocolICMP:
|
||||
binary.BigEndian.PutUint16(b[:2], uint16(iana.AddrFamilyIPv4))
|
||||
copy(b[4:4+net.IPv4len], ifi.Addr.IP.To4())
|
||||
b = b[4+net.IPv4len:]
|
||||
case iana.ProtocolIPv6ICMP:
|
||||
binary.BigEndian.PutUint16(b[:2], uint16(iana.AddrFamilyIPv6))
|
||||
copy(b[4:4+net.IPv6len], ifi.Addr.IP.To16())
|
||||
b = b[4+net.IPv6len:]
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (ifi *InterfaceInfo) parseIPAddr(b []byte) ([]byte, error) {
|
||||
if len(b) < 4 {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
afi := int(binary.BigEndian.Uint16(b[:2]))
|
||||
b = b[4:]
|
||||
switch afi {
|
||||
case iana.AddrFamilyIPv4:
|
||||
if len(b) < net.IPv4len {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
ifi.Addr.IP = make(net.IP, net.IPv4len)
|
||||
copy(ifi.Addr.IP, b[:net.IPv4len])
|
||||
b = b[net.IPv4len:]
|
||||
case iana.AddrFamilyIPv6:
|
||||
if len(b) < net.IPv6len {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
ifi.Addr.IP = make(net.IP, net.IPv6len)
|
||||
copy(ifi.Addr.IP, b[:net.IPv6len])
|
||||
b = b[net.IPv6len:]
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (ifi *InterfaceInfo) marshalName(proto int, b []byte) []byte {
|
||||
l := byte(ifi.nameLen())
|
||||
b[0] = l
|
||||
copy(b[1:], []byte(ifi.Interface.Name))
|
||||
return b[l:]
|
||||
}
|
||||
|
||||
func (ifi *InterfaceInfo) parseName(b []byte) ([]byte, error) {
|
||||
if 4 > len(b) || len(b) < int(b[0]) {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
l := int(b[0])
|
||||
if l%4 != 0 || 4 > l || l > 64 {
|
||||
return nil, errInvalidExtension
|
||||
}
|
||||
var name [63]byte
|
||||
copy(name[:], b[1:l])
|
||||
ifi.Interface.Name = strings.Trim(string(name[:]), "\000")
|
||||
return b[l:], nil
|
||||
}
|
||||
|
||||
func (ifi *InterfaceInfo) marshalMTU(proto int, b []byte) []byte {
|
||||
binary.BigEndian.PutUint32(b[:4], uint32(ifi.Interface.MTU))
|
||||
return b[4:]
|
||||
}
|
||||
|
||||
func (ifi *InterfaceInfo) parseMTU(b []byte) ([]byte, error) {
|
||||
if len(b) < 4 {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
ifi.Interface.MTU = int(binary.BigEndian.Uint32(b[:4]))
|
||||
return b[4:], nil
|
||||
}
|
||||
|
||||
func parseInterfaceInfo(b []byte) (Extension, error) {
|
||||
ifi := &InterfaceInfo{
|
||||
Class: int(b[2]),
|
||||
Type: int(b[3]),
|
||||
}
|
||||
if ifi.Type&(attrIfIndex|attrName|attrMTU) != 0 {
|
||||
ifi.Interface = &net.Interface{}
|
||||
}
|
||||
if ifi.Type&attrIPAddr != 0 {
|
||||
ifi.Addr = &net.IPAddr{}
|
||||
}
|
||||
attrs := ifi.Type & (attrIfIndex | attrIPAddr | attrName | attrMTU)
|
||||
for b = b[4:]; len(b) > 0 && attrs != 0; {
|
||||
var err error
|
||||
switch {
|
||||
case attrs&attrIfIndex != 0:
|
||||
b, err = ifi.parseIfIndex(b)
|
||||
attrs &^= attrIfIndex
|
||||
case attrs&attrIPAddr != 0:
|
||||
b, err = ifi.parseIPAddr(b)
|
||||
attrs &^= attrIPAddr
|
||||
case attrs&attrName != 0:
|
||||
b, err = ifi.parseName(b)
|
||||
attrs &^= attrName
|
||||
case attrs&attrMTU != 0:
|
||||
b, err = ifi.parseMTU(b)
|
||||
attrs &^= attrMTU
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if ifi.Interface != nil && ifi.Interface.Name != "" && ifi.Addr != nil && ifi.Addr.IP.To16() != nil && ifi.Addr.IP.To4() == nil {
|
||||
ifi.Addr.Zone = ifi.Interface.Name
|
||||
}
|
||||
return ifi, nil
|
||||
}
|
||||
|
||||
const (
|
||||
classInterfaceIdent = 3
|
||||
typeInterfaceByName = 1
|
||||
typeInterfaceByIndex = 2
|
||||
typeInterfaceByAddress = 3
|
||||
)
|
||||
|
||||
// An 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; see address family numbers in IANA registry
|
||||
Addr []byte // address
|
||||
}
|
||||
|
||||
// Len implements the Len method of Extension interface.
|
||||
func (ifi *InterfaceIdent) Len(_ int) int {
|
||||
switch ifi.Type {
|
||||
case typeInterfaceByName:
|
||||
l := len(ifi.Name)
|
||||
if l > 255 {
|
||||
l = 255
|
||||
}
|
||||
return 4 + (l+3)&^3
|
||||
case typeInterfaceByIndex:
|
||||
return 4 + 8
|
||||
case typeInterfaceByAddress:
|
||||
return 4 + 4 + (len(ifi.Addr)+3)&^3
|
||||
default:
|
||||
return 4
|
||||
}
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of Extension interface.
|
||||
func (ifi *InterfaceIdent) Marshal(proto int) ([]byte, error) {
|
||||
b := make([]byte, ifi.Len(proto))
|
||||
if err := ifi.marshal(proto, b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (ifi *InterfaceIdent) marshal(proto int, b []byte) error {
|
||||
l := ifi.Len(proto)
|
||||
binary.BigEndian.PutUint16(b[:2], uint16(l))
|
||||
b[2], b[3] = classInterfaceIdent, byte(ifi.Type)
|
||||
switch ifi.Type {
|
||||
case typeInterfaceByName:
|
||||
copy(b[4:], ifi.Name)
|
||||
case typeInterfaceByIndex:
|
||||
binary.BigEndian.PutUint64(b[4:4+8], uint64(ifi.Index))
|
||||
case typeInterfaceByAddress:
|
||||
binary.BigEndian.PutUint16(b[4:4+2], uint16(ifi.AFI))
|
||||
b[4+2] = byte(len(ifi.Addr))
|
||||
copy(b[4+4:], ifi.Addr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseInterfaceIdent(b []byte) (Extension, error) {
|
||||
ifi := &InterfaceIdent{
|
||||
Class: int(b[2]),
|
||||
Type: int(b[3]),
|
||||
}
|
||||
switch ifi.Type {
|
||||
case typeInterfaceByName:
|
||||
ifi.Name = strings.Trim(string(b[4:]), string(0))
|
||||
case typeInterfaceByIndex:
|
||||
if len(b[4:]) < 8 {
|
||||
return nil, errInvalidExtension
|
||||
}
|
||||
ifi.Index = int(binary.BigEndian.Uint64(b[4 : 4+8]))
|
||||
case typeInterfaceByAddress:
|
||||
if len(b[4:]) < 4 {
|
||||
return nil, errInvalidExtension
|
||||
}
|
||||
ifi.AFI = int(binary.BigEndian.Uint16(b[4 : 4+2]))
|
||||
l := int(b[4+2])
|
||||
if len(b[4+4:]) < l {
|
||||
return nil, errInvalidExtension
|
||||
}
|
||||
ifi.Addr = make([]byte, l)
|
||||
copy(ifi.Addr, b[4+4:])
|
||||
}
|
||||
return ifi, nil
|
||||
}
|
61
vendor/golang.org/x/net/icmp/ipv4.go
generated
vendored
Normal file
61
vendor/golang.org/x/net/icmp/ipv4.go
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
// 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 (
|
||||
"encoding/binary"
|
||||
"net"
|
||||
"runtime"
|
||||
|
||||
"golang.org/x/net/internal/socket"
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
// freebsdVersion is set in sys_freebsd.go.
|
||||
// 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(binary.BigEndian.Uint16(b[4:6])),
|
||||
FragOff: int(binary.BigEndian.Uint16(b[6:8])),
|
||||
TTL: int(b[8]),
|
||||
Protocol: int(b[9]),
|
||||
Checksum: int(binary.BigEndian.Uint16(b[10:12])),
|
||||
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":
|
||||
h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4]))
|
||||
case "freebsd":
|
||||
if freebsdVersion >= 1000000 {
|
||||
h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
|
||||
} else {
|
||||
h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4]))
|
||||
}
|
||||
default:
|
||||
h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
|
||||
}
|
||||
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
|
||||
}
|
75
vendor/golang.org/x/net/icmp/ipv4_test.go
generated
vendored
Normal file
75
vendor/golang.org/x/net/icmp/ipv4_test.go
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
// 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 (
|
||||
"encoding/binary"
|
||||
"net"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/internal/socket"
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
func TestParseIPv4Header(t *testing.T) {
|
||||
switch socket.NativeEndian {
|
||||
case binary.LittleEndian:
|
||||
t.Run("LittleEndian", func(t *testing.T) {
|
||||
// TODO(mikio): Add platform dependent wire
|
||||
// header formats when we support new
|
||||
// platforms.
|
||||
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,
|
||||
}
|
||||
th := &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),
|
||||
}
|
||||
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, th) {
|
||||
t.Fatalf("got %#v; want %#v", h, th)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
23
vendor/golang.org/x/net/icmp/ipv6.go
generated
vendored
Normal file
23
vendor/golang.org/x/net/icmp/ipv6.go
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
// 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 checksum
|
||||
// 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
|
||||
}
|
100
vendor/golang.org/x/net/icmp/listen_posix.go
generated
vendored
Normal file
100
vendor/golang.org/x/net/icmp/listen_posix.go
generated
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
// 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 windows
|
||||
|
||||
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 Darwin 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 cerr 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)
|
||||
}
|
||||
if runtime.GOOS == "darwin" && family == syscall.AF_INET {
|
||||
if err := syscall.SetsockoptInt(s, iana.ProtocolIP, sysIP_STRIPHDR, 1); err != nil {
|
||||
syscall.Close(s)
|
||||
return nil, os.NewSyscallError("setsockopt", err)
|
||||
}
|
||||
}
|
||||
sa, err := sockaddr(family, address)
|
||||
if err != nil {
|
||||
syscall.Close(s)
|
||||
return nil, err
|
||||
}
|
||||
if err := syscall.Bind(s, sa); err != nil {
|
||||
syscall.Close(s)
|
||||
return nil, os.NewSyscallError("bind", err)
|
||||
}
|
||||
f := os.NewFile(uintptr(s), "datagram-oriented icmp")
|
||||
c, cerr = net.FilePacketConn(f)
|
||||
f.Close()
|
||||
default:
|
||||
c, cerr = net.ListenPacket(network, address)
|
||||
}
|
||||
if cerr != nil {
|
||||
return nil, cerr
|
||||
}
|
||||
switch proto {
|
||||
case iana.ProtocolICMP:
|
||||
return &PacketConn{c: c, p4: ipv4.NewPacketConn(c)}, nil
|
||||
case iana.ProtocolIPv6ICMP:
|
||||
return &PacketConn{c: c, p6: ipv6.NewPacketConn(c)}, nil
|
||||
default:
|
||||
return &PacketConn{c: c}, nil
|
||||
}
|
||||
}
|
33
vendor/golang.org/x/net/icmp/listen_stub.go
generated
vendored
Normal file
33
vendor/golang.org/x/net/icmp/listen_stub.go
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
// 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,!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 Darwin 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
|
||||
}
|
157
vendor/golang.org/x/net/icmp/message.go
generated
vendored
Normal file
157
vendor/golang.org/x/net/icmp/message.go
generated
vendored
Normal file
@ -0,0 +1,157 @@
|
||||
// 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
|
||||
// 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.
|
||||
// PROBE: A utility for probing interfaces is defined in RFC 8335.
|
||||
package icmp // import "golang.org/x/net/icmp"
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"net"
|
||||
|
||||
"golang.org/x/net/internal/iana"
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
// BUG(mikio): This package is not implemented on JS, NaCl and Plan 9.
|
||||
|
||||
var (
|
||||
errInvalidConn = errors.New("invalid connection")
|
||||
errMessageTooShort = errors.New("message too short")
|
||||
errHeaderTooShort = errors.New("header too short")
|
||||
errBufferTooShort = errors.New("buffer too short")
|
||||
errOpNoSupport = errors.New("operation not supported")
|
||||
errNoExtension = errors.New("no extension")
|
||||
errInvalidExtension = errors.New("invalid extension")
|
||||
)
|
||||
|
||||
func checksum(b []byte) uint16 {
|
||||
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
|
||||
return ^uint16(s)
|
||||
}
|
||||
|
||||
// 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 encoding of the ICMP message m.
|
||||
//
|
||||
// For an ICMPv4 message, the returned message always contains the
|
||||
// calculated checksum field.
|
||||
//
|
||||
// For an ICMPv6 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, errInvalidConn
|
||||
}
|
||||
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(m.Type.Protocol()) != 0 {
|
||||
mb, err := m.Body.Marshal(m.Type.Protocol())
|
||||
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)
|
||||
binary.BigEndian.PutUint32(b[off:off+4], uint32(l))
|
||||
}
|
||||
s := checksum(b)
|
||||
// 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(int, Type, []byte) (MessageBody, error){
|
||||
ipv4.ICMPTypeDestinationUnreachable: parseDstUnreach,
|
||||
ipv4.ICMPTypeTimeExceeded: parseTimeExceeded,
|
||||
ipv4.ICMPTypeParameterProblem: parseParamProb,
|
||||
|
||||
ipv4.ICMPTypeEcho: parseEcho,
|
||||
ipv4.ICMPTypeEchoReply: parseEcho,
|
||||
ipv4.ICMPTypeExtendedEchoRequest: parseExtendedEchoRequest,
|
||||
ipv4.ICMPTypeExtendedEchoReply: parseExtendedEchoReply,
|
||||
|
||||
ipv6.ICMPTypeDestinationUnreachable: parseDstUnreach,
|
||||
ipv6.ICMPTypePacketTooBig: parsePacketTooBig,
|
||||
ipv6.ICMPTypeTimeExceeded: parseTimeExceeded,
|
||||
ipv6.ICMPTypeParameterProblem: parseParamProb,
|
||||
|
||||
ipv6.ICMPTypeEchoRequest: parseEcho,
|
||||
ipv6.ICMPTypeEchoReply: parseEcho,
|
||||
ipv6.ICMPTypeExtendedEchoRequest: parseExtendedEchoRequest,
|
||||
ipv6.ICMPTypeExtendedEchoReply: parseExtendedEchoReply,
|
||||
}
|
||||
|
||||
// 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(binary.BigEndian.Uint16(b[2:4]))}
|
||||
switch proto {
|
||||
case iana.ProtocolICMP:
|
||||
m.Type = ipv4.ICMPType(b[0])
|
||||
case iana.ProtocolIPv6ICMP:
|
||||
m.Type = ipv6.ICMPType(b[0])
|
||||
default:
|
||||
return nil, errInvalidConn
|
||||
}
|
||||
if fn, ok := parseFns[m.Type]; !ok {
|
||||
m.Body, err = parseDefaultMessageBody(proto, b[4:])
|
||||
} else {
|
||||
m.Body, err = fn(proto, m.Type, b[4:])
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
155
vendor/golang.org/x/net/icmp/message_test.go
generated
vendored
Normal file
155
vendor/golang.org/x/net/icmp/message_test.go
generated
vendored
Normal file
@ -0,0 +1,155 @@
|
||||
// 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/icmp"
|
||||
"golang.org/x/net/internal/iana"
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
func TestMarshalAndParseMessage(t *testing.T) {
|
||||
fn := func(t *testing.T, proto int, tms []icmp.Message) {
|
||||
var pshs [][]byte
|
||||
switch proto {
|
||||
case iana.ProtocolICMP:
|
||||
pshs = [][]byte{nil}
|
||||
case iana.ProtocolIPv6ICMP:
|
||||
pshs = [][]byte{
|
||||
icmp.IPv6PseudoHeader(net.ParseIP("fe80::1"), net.ParseIP("ff02::1")),
|
||||
nil,
|
||||
}
|
||||
}
|
||||
for i, tm := range tms {
|
||||
for _, psh := range pshs {
|
||||
b, err := tm.Marshal(psh)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m, err := icmp.ParseMessage(proto, b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if m.Type != tm.Type || m.Code != tm.Code {
|
||||
t.Errorf("#%d: got %#v; want %#v", i, m, &tm)
|
||||
}
|
||||
if !reflect.DeepEqual(m.Body, tm.Body) {
|
||||
t.Errorf("#%d: got %#v; want %#v", i, m.Body, tm.Body)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("IPv4", func(t *testing.T) {
|
||||
fn(t, iana.ProtocolICMP,
|
||||
[]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.ICMPTypeExtendedEchoRequest, Code: 0,
|
||||
Body: &icmp.ExtendedEchoRequest{
|
||||
ID: 1, Seq: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: ipv4.ICMPTypeExtendedEchoReply, Code: 0,
|
||||
Body: &icmp.ExtendedEchoReply{
|
||||
State: 4 /* Delay */, Active: true, IPv4: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: ipv4.ICMPTypePhoturis,
|
||||
Body: &icmp.DefaultMessageBody{
|
||||
Data: []byte{0x80, 0x40, 0x20, 0x10},
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
t.Run("IPv6", func(t *testing.T) {
|
||||
fn(t, iana.ProtocolIPv6ICMP,
|
||||
[]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.ICMPTypeExtendedEchoRequest, Code: 0,
|
||||
Body: &icmp.ExtendedEchoRequest{
|
||||
ID: 1, Seq: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: ipv6.ICMPTypeExtendedEchoReply, Code: 0,
|
||||
Body: &icmp.ExtendedEchoReply{
|
||||
State: 5 /* Probe */, Active: true, IPv6: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: ipv6.ICMPTypeDuplicateAddressConfirmation,
|
||||
Body: &icmp.DefaultMessageBody{
|
||||
Data: []byte{0x80, 0x40, 0x20, 0x10},
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
41
vendor/golang.org/x/net/icmp/messagebody.go
generated
vendored
Normal file
41
vendor/golang.org/x/net/icmp/messagebody.go
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
// 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.
|
||||
// Proto must be either the ICMPv4 or ICMPv6 protocol number.
|
||||
Len(proto int) int
|
||||
|
||||
// Marshal returns the binary encoding of ICMP message body.
|
||||
// Proto must be either the ICMPv4 or ICMPv6 protocol number.
|
||||
Marshal(proto int) ([]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(proto int) int {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
return len(p.Data)
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of MessageBody interface.
|
||||
func (p *DefaultMessageBody) Marshal(proto int) ([]byte, error) {
|
||||
return p.Data, nil
|
||||
}
|
||||
|
||||
// parseDefaultMessageBody parses b as an ICMP message body.
|
||||
func parseDefaultMessageBody(proto int, b []byte) (MessageBody, error) {
|
||||
p := &DefaultMessageBody{Data: make([]byte, len(b))}
|
||||
copy(p.Data, b)
|
||||
return p, nil
|
||||
}
|
77
vendor/golang.org/x/net/icmp/mpls.go
generated
vendored
Normal file
77
vendor/golang.org/x/net/icmp/mpls.go
generated
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
// Copyright 2015 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 "encoding/binary"
|
||||
|
||||
// MPLSLabel represents an MPLS label stack entry.
|
||||
type MPLSLabel struct {
|
||||
Label int // label value
|
||||
TC int // traffic class; formerly experimental use
|
||||
S bool // bottom of stack
|
||||
TTL int // time to live
|
||||
}
|
||||
|
||||
const (
|
||||
classMPLSLabelStack = 1
|
||||
typeIncomingMPLSLabelStack = 1
|
||||
)
|
||||
|
||||
// MPLSLabelStack represents an MPLS label stack.
|
||||
type MPLSLabelStack struct {
|
||||
Class int // extension object class number
|
||||
Type int // extension object sub-type
|
||||
Labels []MPLSLabel
|
||||
}
|
||||
|
||||
// Len implements the Len method of Extension interface.
|
||||
func (ls *MPLSLabelStack) Len(proto int) int {
|
||||
return 4 + (4 * len(ls.Labels))
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of Extension interface.
|
||||
func (ls *MPLSLabelStack) Marshal(proto int) ([]byte, error) {
|
||||
b := make([]byte, ls.Len(proto))
|
||||
if err := ls.marshal(proto, b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (ls *MPLSLabelStack) marshal(proto int, b []byte) error {
|
||||
l := ls.Len(proto)
|
||||
binary.BigEndian.PutUint16(b[:2], uint16(l))
|
||||
b[2], b[3] = classMPLSLabelStack, typeIncomingMPLSLabelStack
|
||||
off := 4
|
||||
for _, ll := range ls.Labels {
|
||||
b[off], b[off+1], b[off+2] = byte(ll.Label>>12), byte(ll.Label>>4&0xff), byte(ll.Label<<4&0xf0)
|
||||
b[off+2] |= byte(ll.TC << 1 & 0x0e)
|
||||
if ll.S {
|
||||
b[off+2] |= 0x1
|
||||
}
|
||||
b[off+3] = byte(ll.TTL)
|
||||
off += 4
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseMPLSLabelStack(b []byte) (Extension, error) {
|
||||
ls := &MPLSLabelStack{
|
||||
Class: int(b[2]),
|
||||
Type: int(b[3]),
|
||||
}
|
||||
for b = b[4:]; len(b) >= 4; b = b[4:] {
|
||||
ll := MPLSLabel{
|
||||
Label: int(b[0])<<12 | int(b[1])<<4 | int(b[2])>>4,
|
||||
TC: int(b[2]&0x0e) >> 1,
|
||||
TTL: int(b[3]),
|
||||
}
|
||||
if b[2]&0x1 != 0 {
|
||||
ll.S = true
|
||||
}
|
||||
ls.Labels = append(ls.Labels, ll)
|
||||
}
|
||||
return ls, nil
|
||||
}
|
121
vendor/golang.org/x/net/icmp/multipart.go
generated
vendored
Normal file
121
vendor/golang.org/x/net/icmp/multipart.go
generated
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
// Copyright 2015 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 "golang.org/x/net/internal/iana"
|
||||
|
||||
// multipartMessageBodyDataLen takes b as an original datagram and
|
||||
// exts as extensions, and returns a required length for message body
|
||||
// and a required length for a padded original datagram in wire
|
||||
// format.
|
||||
func multipartMessageBodyDataLen(proto int, withOrigDgram bool, b []byte, exts []Extension) (bodyLen, dataLen int) {
|
||||
for _, ext := range exts {
|
||||
bodyLen += ext.Len(proto)
|
||||
}
|
||||
if bodyLen > 0 {
|
||||
if withOrigDgram {
|
||||
dataLen = multipartMessageOrigDatagramLen(proto, b)
|
||||
}
|
||||
bodyLen += 4 // length of extension header
|
||||
} else {
|
||||
dataLen = len(b)
|
||||
}
|
||||
bodyLen += dataLen
|
||||
return bodyLen, dataLen
|
||||
}
|
||||
|
||||
// multipartMessageOrigDatagramLen takes b as an original datagram,
|
||||
// and returns a required length for a padded orignal datagram in wire
|
||||
// format.
|
||||
func multipartMessageOrigDatagramLen(proto int, b []byte) int {
|
||||
roundup := func(b []byte, align int) int {
|
||||
// According to RFC 4884, the padded original datagram
|
||||
// field must contain at least 128 octets.
|
||||
if len(b) < 128 {
|
||||
return 128
|
||||
}
|
||||
r := len(b)
|
||||
return (r + align - 1) & ^(align - 1)
|
||||
}
|
||||
switch proto {
|
||||
case iana.ProtocolICMP:
|
||||
return roundup(b, 4)
|
||||
case iana.ProtocolIPv6ICMP:
|
||||
return roundup(b, 8)
|
||||
default:
|
||||
return len(b)
|
||||
}
|
||||
}
|
||||
|
||||
// marshalMultipartMessageBody takes data as an original datagram and
|
||||
// exts as extesnsions, and returns a binary encoding of message body.
|
||||
// It can be used for non-multipart message bodies when exts is nil.
|
||||
func marshalMultipartMessageBody(proto int, withOrigDgram bool, data []byte, exts []Extension) ([]byte, error) {
|
||||
bodyLen, dataLen := multipartMessageBodyDataLen(proto, withOrigDgram, data, exts)
|
||||
b := make([]byte, 4+bodyLen)
|
||||
copy(b[4:], data)
|
||||
off := dataLen + 4
|
||||
if len(exts) > 0 {
|
||||
b[dataLen+4] = byte(extensionVersion << 4)
|
||||
off += 4 // length of object header
|
||||
for _, ext := range exts {
|
||||
switch ext := ext.(type) {
|
||||
case *MPLSLabelStack:
|
||||
if err := ext.marshal(proto, b[off:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
off += ext.Len(proto)
|
||||
case *InterfaceInfo:
|
||||
attrs, l := ext.attrsAndLen(proto)
|
||||
if err := ext.marshal(proto, b[off:], attrs, l); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
off += ext.Len(proto)
|
||||
case *InterfaceIdent:
|
||||
if err := ext.marshal(proto, b[off:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
off += ext.Len(proto)
|
||||
}
|
||||
}
|
||||
s := checksum(b[dataLen+4:])
|
||||
b[dataLen+4+2] ^= byte(s)
|
||||
b[dataLen+4+3] ^= byte(s >> 8)
|
||||
if withOrigDgram {
|
||||
switch proto {
|
||||
case iana.ProtocolICMP:
|
||||
b[1] = byte(dataLen / 4)
|
||||
case iana.ProtocolIPv6ICMP:
|
||||
b[0] = byte(dataLen / 8)
|
||||
}
|
||||
}
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// parseMultipartMessageBody parses b as either a non-multipart
|
||||
// message body or a multipart message body.
|
||||
func parseMultipartMessageBody(proto int, typ Type, b []byte) ([]byte, []Extension, error) {
|
||||
var l int
|
||||
switch proto {
|
||||
case iana.ProtocolICMP:
|
||||
l = 4 * int(b[1])
|
||||
case iana.ProtocolIPv6ICMP:
|
||||
l = 8 * int(b[0])
|
||||
}
|
||||
if len(b) == 4 {
|
||||
return nil, nil, nil
|
||||
}
|
||||
exts, l, err := parseExtensions(typ, b[4:], l)
|
||||
if err != nil {
|
||||
l = len(b) - 4
|
||||
}
|
||||
var data []byte
|
||||
if l > 0 {
|
||||
data = make([]byte, l)
|
||||
copy(data, b[4:])
|
||||
}
|
||||
return data, exts, nil
|
||||
}
|
575
vendor/golang.org/x/net/icmp/multipart_test.go
generated
vendored
Normal file
575
vendor/golang.org/x/net/icmp/multipart_test.go
generated
vendored
Normal file
@ -0,0 +1,575 @@
|
||||
// Copyright 2015 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"
|
||||
"fmt"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/icmp"
|
||||
"golang.org/x/net/internal/iana"
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
func TestMarshalAndParseMultipartMessage(t *testing.T) {
|
||||
fn := func(t *testing.T, proto int, tm icmp.Message) error {
|
||||
b, err := tm.Marshal(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch tm.Type {
|
||||
case ipv4.ICMPTypeExtendedEchoRequest, ipv6.ICMPTypeExtendedEchoRequest:
|
||||
default:
|
||||
switch proto {
|
||||
case iana.ProtocolICMP:
|
||||
if b[5] != 32 {
|
||||
return fmt.Errorf("got %d; want 32", b[5])
|
||||
}
|
||||
case iana.ProtocolIPv6ICMP:
|
||||
if b[4] != 16 {
|
||||
return fmt.Errorf("got %d; want 16", b[4])
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unknown protocol: %d", proto)
|
||||
}
|
||||
}
|
||||
m, err := icmp.ParseMessage(proto, b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if m.Type != tm.Type || m.Code != tm.Code {
|
||||
return fmt.Errorf("got %v; want %v", m, &tm)
|
||||
}
|
||||
switch m.Type {
|
||||
case ipv4.ICMPTypeExtendedEchoRequest, ipv6.ICMPTypeExtendedEchoRequest:
|
||||
got, want := m.Body.(*icmp.ExtendedEchoRequest), tm.Body.(*icmp.ExtendedEchoRequest)
|
||||
if !reflect.DeepEqual(got.Extensions, want.Extensions) {
|
||||
return errors.New(dumpExtensions(got.Extensions, want.Extensions))
|
||||
}
|
||||
case ipv4.ICMPTypeDestinationUnreachable:
|
||||
got, want := m.Body.(*icmp.DstUnreach), tm.Body.(*icmp.DstUnreach)
|
||||
if !reflect.DeepEqual(got.Extensions, want.Extensions) {
|
||||
return errors.New(dumpExtensions(got.Extensions, want.Extensions))
|
||||
}
|
||||
if len(got.Data) != 128 {
|
||||
return fmt.Errorf("got %d; want 128", len(got.Data))
|
||||
}
|
||||
case ipv4.ICMPTypeTimeExceeded:
|
||||
got, want := m.Body.(*icmp.TimeExceeded), tm.Body.(*icmp.TimeExceeded)
|
||||
if !reflect.DeepEqual(got.Extensions, want.Extensions) {
|
||||
return errors.New(dumpExtensions(got.Extensions, want.Extensions))
|
||||
}
|
||||
if len(got.Data) != 128 {
|
||||
return fmt.Errorf("got %d; want 128", len(got.Data))
|
||||
}
|
||||
case ipv4.ICMPTypeParameterProblem:
|
||||
got, want := m.Body.(*icmp.ParamProb), tm.Body.(*icmp.ParamProb)
|
||||
if !reflect.DeepEqual(got.Extensions, want.Extensions) {
|
||||
return errors.New(dumpExtensions(got.Extensions, want.Extensions))
|
||||
}
|
||||
if len(got.Data) != 128 {
|
||||
return fmt.Errorf("got %d; want 128", len(got.Data))
|
||||
}
|
||||
case ipv6.ICMPTypeDestinationUnreachable:
|
||||
got, want := m.Body.(*icmp.DstUnreach), tm.Body.(*icmp.DstUnreach)
|
||||
if !reflect.DeepEqual(got.Extensions, want.Extensions) {
|
||||
return errors.New(dumpExtensions(got.Extensions, want.Extensions))
|
||||
}
|
||||
if len(got.Data) != 128 {
|
||||
return fmt.Errorf("got %d; want 128", len(got.Data))
|
||||
}
|
||||
case ipv6.ICMPTypeTimeExceeded:
|
||||
got, want := m.Body.(*icmp.TimeExceeded), tm.Body.(*icmp.TimeExceeded)
|
||||
if !reflect.DeepEqual(got.Extensions, want.Extensions) {
|
||||
return errors.New(dumpExtensions(got.Extensions, want.Extensions))
|
||||
}
|
||||
if len(got.Data) != 128 {
|
||||
return fmt.Errorf("got %d; want 128", len(got.Data))
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unknown message type: %v", m.Type)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
t.Run("IPv4", func(t *testing.T) {
|
||||
for i, tm := range []icmp.Message{
|
||||
{
|
||||
Type: ipv4.ICMPTypeDestinationUnreachable, Code: 15,
|
||||
Body: &icmp.DstUnreach{
|
||||
Data: []byte("ERROR-INVOKING-PACKET"),
|
||||
Extensions: []icmp.Extension{
|
||||
&icmp.MPLSLabelStack{
|
||||
Class: 1,
|
||||
Type: 1,
|
||||
Labels: []icmp.MPLSLabel{
|
||||
{
|
||||
Label: 16014,
|
||||
TC: 0x4,
|
||||
S: true,
|
||||
TTL: 255,
|
||||
},
|
||||
},
|
||||
},
|
||||
&icmp.InterfaceInfo{
|
||||
Class: 2,
|
||||
Type: 0x0f,
|
||||
Interface: &net.Interface{
|
||||
Index: 15,
|
||||
Name: "en101",
|
||||
MTU: 8192,
|
||||
},
|
||||
Addr: &net.IPAddr{
|
||||
IP: net.IPv4(192, 168, 0, 1).To4(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: ipv4.ICMPTypeTimeExceeded, Code: 1,
|
||||
Body: &icmp.TimeExceeded{
|
||||
Data: []byte("ERROR-INVOKING-PACKET"),
|
||||
Extensions: []icmp.Extension{
|
||||
&icmp.InterfaceInfo{
|
||||
Class: 2,
|
||||
Type: 0x0f,
|
||||
Interface: &net.Interface{
|
||||
Index: 15,
|
||||
Name: "en101",
|
||||
MTU: 8192,
|
||||
},
|
||||
Addr: &net.IPAddr{
|
||||
IP: net.IPv4(192, 168, 0, 1).To4(),
|
||||
},
|
||||
},
|
||||
&icmp.MPLSLabelStack{
|
||||
Class: 1,
|
||||
Type: 1,
|
||||
Labels: []icmp.MPLSLabel{
|
||||
{
|
||||
Label: 16014,
|
||||
TC: 0x4,
|
||||
S: true,
|
||||
TTL: 255,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: ipv4.ICMPTypeParameterProblem, Code: 2,
|
||||
Body: &icmp.ParamProb{
|
||||
Pointer: 8,
|
||||
Data: []byte("ERROR-INVOKING-PACKET"),
|
||||
Extensions: []icmp.Extension{
|
||||
&icmp.MPLSLabelStack{
|
||||
Class: 1,
|
||||
Type: 1,
|
||||
Labels: []icmp.MPLSLabel{
|
||||
{
|
||||
Label: 16014,
|
||||
TC: 0x4,
|
||||
S: true,
|
||||
TTL: 255,
|
||||
},
|
||||
},
|
||||
},
|
||||
&icmp.InterfaceInfo{
|
||||
Class: 2,
|
||||
Type: 0x0f,
|
||||
Interface: &net.Interface{
|
||||
Index: 15,
|
||||
Name: "en101",
|
||||
MTU: 8192,
|
||||
},
|
||||
Addr: &net.IPAddr{
|
||||
IP: net.IPv4(192, 168, 0, 1).To4(),
|
||||
},
|
||||
},
|
||||
&icmp.InterfaceInfo{
|
||||
Class: 2,
|
||||
Type: 0x2f,
|
||||
Interface: &net.Interface{
|
||||
Index: 16,
|
||||
Name: "en102",
|
||||
MTU: 8192,
|
||||
},
|
||||
Addr: &net.IPAddr{
|
||||
IP: net.IPv4(192, 168, 0, 2).To4(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: ipv4.ICMPTypeExtendedEchoRequest, Code: 0,
|
||||
Body: &icmp.ExtendedEchoRequest{
|
||||
ID: 1, Seq: 2, Local: true,
|
||||
Extensions: []icmp.Extension{
|
||||
&icmp.InterfaceIdent{
|
||||
Class: 3,
|
||||
Type: 1,
|
||||
Name: "en101",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: ipv4.ICMPTypeExtendedEchoRequest, Code: 0,
|
||||
Body: &icmp.ExtendedEchoRequest{
|
||||
ID: 1, Seq: 2, Local: true,
|
||||
Extensions: []icmp.Extension{
|
||||
&icmp.InterfaceIdent{
|
||||
Class: 3,
|
||||
Type: 2,
|
||||
Index: 911,
|
||||
},
|
||||
&icmp.InterfaceIdent{
|
||||
Class: 3,
|
||||
Type: 1,
|
||||
Name: "en101",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: ipv4.ICMPTypeExtendedEchoRequest, Code: 0,
|
||||
Body: &icmp.ExtendedEchoRequest{
|
||||
ID: 1, Seq: 2,
|
||||
Extensions: []icmp.Extension{
|
||||
&icmp.InterfaceIdent{
|
||||
Class: 3,
|
||||
Type: 3,
|
||||
AFI: iana.AddrFamily48bitMAC,
|
||||
Addr: []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} {
|
||||
if err := fn(t, iana.ProtocolICMP, tm); err != nil {
|
||||
t.Errorf("#%d: %v", i, err)
|
||||
}
|
||||
}
|
||||
})
|
||||
t.Run("IPv6", func(t *testing.T) {
|
||||
for i, tm := range []icmp.Message{
|
||||
{
|
||||
Type: ipv6.ICMPTypeDestinationUnreachable, Code: 6,
|
||||
Body: &icmp.DstUnreach{
|
||||
Data: []byte("ERROR-INVOKING-PACKET"),
|
||||
Extensions: []icmp.Extension{
|
||||
&icmp.MPLSLabelStack{
|
||||
Class: 1,
|
||||
Type: 1,
|
||||
Labels: []icmp.MPLSLabel{
|
||||
{
|
||||
Label: 16014,
|
||||
TC: 0x4,
|
||||
S: true,
|
||||
TTL: 255,
|
||||
},
|
||||
},
|
||||
},
|
||||
&icmp.InterfaceInfo{
|
||||
Class: 2,
|
||||
Type: 0x0f,
|
||||
Interface: &net.Interface{
|
||||
Index: 15,
|
||||
Name: "en101",
|
||||
MTU: 8192,
|
||||
},
|
||||
Addr: &net.IPAddr{
|
||||
IP: net.ParseIP("fe80::1"),
|
||||
Zone: "en101",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: ipv6.ICMPTypeTimeExceeded, Code: 1,
|
||||
Body: &icmp.TimeExceeded{
|
||||
Data: []byte("ERROR-INVOKING-PACKET"),
|
||||
Extensions: []icmp.Extension{
|
||||
&icmp.InterfaceInfo{
|
||||
Class: 2,
|
||||
Type: 0x0f,
|
||||
Interface: &net.Interface{
|
||||
Index: 15,
|
||||
Name: "en101",
|
||||
MTU: 8192,
|
||||
},
|
||||
Addr: &net.IPAddr{
|
||||
IP: net.ParseIP("fe80::1"),
|
||||
Zone: "en101",
|
||||
},
|
||||
},
|
||||
&icmp.MPLSLabelStack{
|
||||
Class: 1,
|
||||
Type: 1,
|
||||
Labels: []icmp.MPLSLabel{
|
||||
{
|
||||
Label: 16014,
|
||||
TC: 0x4,
|
||||
S: true,
|
||||
TTL: 255,
|
||||
},
|
||||
},
|
||||
},
|
||||
&icmp.InterfaceInfo{
|
||||
Class: 2,
|
||||
Type: 0x2f,
|
||||
Interface: &net.Interface{
|
||||
Index: 16,
|
||||
Name: "en102",
|
||||
MTU: 8192,
|
||||
},
|
||||
Addr: &net.IPAddr{
|
||||
IP: net.ParseIP("fe80::1"),
|
||||
Zone: "en102",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: ipv6.ICMPTypeExtendedEchoRequest, Code: 0,
|
||||
Body: &icmp.ExtendedEchoRequest{
|
||||
ID: 1, Seq: 2, Local: true,
|
||||
Extensions: []icmp.Extension{
|
||||
&icmp.InterfaceIdent{
|
||||
Class: 3,
|
||||
Type: 1,
|
||||
Name: "en101",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: ipv6.ICMPTypeExtendedEchoRequest, Code: 0,
|
||||
Body: &icmp.ExtendedEchoRequest{
|
||||
ID: 1, Seq: 2, Local: true,
|
||||
Extensions: []icmp.Extension{
|
||||
&icmp.InterfaceIdent{
|
||||
Class: 3,
|
||||
Type: 1,
|
||||
Name: "en101",
|
||||
},
|
||||
&icmp.InterfaceIdent{
|
||||
Class: 3,
|
||||
Type: 2,
|
||||
Index: 911,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: ipv6.ICMPTypeExtendedEchoRequest, Code: 0,
|
||||
Body: &icmp.ExtendedEchoRequest{
|
||||
ID: 1, Seq: 2,
|
||||
Extensions: []icmp.Extension{
|
||||
&icmp.InterfaceIdent{
|
||||
Class: 3,
|
||||
Type: 3,
|
||||
AFI: iana.AddrFamilyIPv4,
|
||||
Addr: []byte{192, 0, 2, 1},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} {
|
||||
if err := fn(t, iana.ProtocolIPv6ICMP, tm); err != nil {
|
||||
t.Errorf("#%d: %v", i, err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func dumpExtensions(gotExts, wantExts []icmp.Extension) string {
|
||||
var s string
|
||||
for i, got := range gotExts {
|
||||
switch got := got.(type) {
|
||||
case *icmp.MPLSLabelStack:
|
||||
want := wantExts[i].(*icmp.MPLSLabelStack)
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
s += fmt.Sprintf("#%d: got %#v; want %#v\n", i, got, want)
|
||||
}
|
||||
case *icmp.InterfaceInfo:
|
||||
want := wantExts[i].(*icmp.InterfaceInfo)
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
s += fmt.Sprintf("#%d: got %#v, %#v, %#v; want %#v, %#v, %#v\n", i, got, got.Interface, got.Addr, want, want.Interface, want.Addr)
|
||||
}
|
||||
case *icmp.InterfaceIdent:
|
||||
want := wantExts[i].(*icmp.InterfaceIdent)
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
s += fmt.Sprintf("#%d: got %#v; want %#v\n", i, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(s) == 0 {
|
||||
return "<nil>"
|
||||
}
|
||||
return s[:len(s)-1]
|
||||
}
|
||||
|
||||
func TestMultipartMessageBodyLen(t *testing.T) {
|
||||
for i, tt := range []struct {
|
||||
proto int
|
||||
in icmp.MessageBody
|
||||
out int
|
||||
}{
|
||||
{
|
||||
iana.ProtocolICMP,
|
||||
&icmp.DstUnreach{
|
||||
Data: make([]byte, ipv4.HeaderLen),
|
||||
},
|
||||
4 + ipv4.HeaderLen, // unused and original datagram
|
||||
},
|
||||
{
|
||||
iana.ProtocolICMP,
|
||||
&icmp.TimeExceeded{
|
||||
Data: make([]byte, ipv4.HeaderLen),
|
||||
},
|
||||
4 + ipv4.HeaderLen, // unused and original datagram
|
||||
},
|
||||
{
|
||||
iana.ProtocolICMP,
|
||||
&icmp.ParamProb{
|
||||
Data: make([]byte, ipv4.HeaderLen),
|
||||
},
|
||||
4 + ipv4.HeaderLen, // [pointer, unused] and original datagram
|
||||
},
|
||||
|
||||
{
|
||||
iana.ProtocolICMP,
|
||||
&icmp.ParamProb{
|
||||
Data: make([]byte, ipv4.HeaderLen),
|
||||
Extensions: []icmp.Extension{
|
||||
&icmp.MPLSLabelStack{},
|
||||
},
|
||||
},
|
||||
4 + 4 + 4 + 0 + 128, // [pointer, length, unused], extension header, object header, object payload, original datagram
|
||||
},
|
||||
{
|
||||
iana.ProtocolICMP,
|
||||
&icmp.ParamProb{
|
||||
Data: make([]byte, 128),
|
||||
Extensions: []icmp.Extension{
|
||||
&icmp.MPLSLabelStack{},
|
||||
},
|
||||
},
|
||||
4 + 4 + 4 + 0 + 128, // [pointer, length, unused], extension header, object header, object payload and original datagram
|
||||
},
|
||||
{
|
||||
iana.ProtocolICMP,
|
||||
&icmp.ParamProb{
|
||||
Data: make([]byte, 129),
|
||||
Extensions: []icmp.Extension{
|
||||
&icmp.MPLSLabelStack{},
|
||||
},
|
||||
},
|
||||
4 + 4 + 4 + 0 + 132, // [pointer, length, unused], extension header, object header, object payload and original datagram
|
||||
},
|
||||
|
||||
{
|
||||
iana.ProtocolIPv6ICMP,
|
||||
&icmp.DstUnreach{
|
||||
Data: make([]byte, ipv6.HeaderLen),
|
||||
},
|
||||
4 + ipv6.HeaderLen, // unused and original datagram
|
||||
},
|
||||
{
|
||||
iana.ProtocolIPv6ICMP,
|
||||
&icmp.PacketTooBig{
|
||||
Data: make([]byte, ipv6.HeaderLen),
|
||||
},
|
||||
4 + ipv6.HeaderLen, // mtu and original datagram
|
||||
},
|
||||
{
|
||||
iana.ProtocolIPv6ICMP,
|
||||
&icmp.TimeExceeded{
|
||||
Data: make([]byte, ipv6.HeaderLen),
|
||||
},
|
||||
4 + ipv6.HeaderLen, // unused and original datagram
|
||||
},
|
||||
{
|
||||
iana.ProtocolIPv6ICMP,
|
||||
&icmp.ParamProb{
|
||||
Data: make([]byte, ipv6.HeaderLen),
|
||||
},
|
||||
4 + ipv6.HeaderLen, // pointer and original datagram
|
||||
},
|
||||
|
||||
{
|
||||
iana.ProtocolIPv6ICMP,
|
||||
&icmp.DstUnreach{
|
||||
Data: make([]byte, 127),
|
||||
Extensions: []icmp.Extension{
|
||||
&icmp.MPLSLabelStack{},
|
||||
},
|
||||
},
|
||||
4 + 4 + 4 + 0 + 128, // [length, unused], extension header, object header, object payload and original datagram
|
||||
},
|
||||
{
|
||||
iana.ProtocolIPv6ICMP,
|
||||
&icmp.DstUnreach{
|
||||
Data: make([]byte, 128),
|
||||
Extensions: []icmp.Extension{
|
||||
&icmp.MPLSLabelStack{},
|
||||
},
|
||||
},
|
||||
4 + 4 + 4 + 0 + 128, // [length, unused], extension header, object header, object payload and original datagram
|
||||
},
|
||||
{
|
||||
iana.ProtocolIPv6ICMP,
|
||||
&icmp.DstUnreach{
|
||||
Data: make([]byte, 129),
|
||||
Extensions: []icmp.Extension{
|
||||
&icmp.MPLSLabelStack{},
|
||||
},
|
||||
},
|
||||
4 + 4 + 4 + 0 + 136, // [length, unused], extension header, object header, object payload and original datagram
|
||||
},
|
||||
|
||||
{
|
||||
iana.ProtocolICMP,
|
||||
&icmp.ExtendedEchoRequest{},
|
||||
4, // [id, seq, l-bit]
|
||||
},
|
||||
{
|
||||
iana.ProtocolICMP,
|
||||
&icmp.ExtendedEchoRequest{
|
||||
Extensions: []icmp.Extension{
|
||||
&icmp.InterfaceIdent{},
|
||||
},
|
||||
},
|
||||
4 + 4 + 4, // [id, seq, l-bit], extension header, object header
|
||||
},
|
||||
{
|
||||
iana.ProtocolIPv6ICMP,
|
||||
&icmp.ExtendedEchoRequest{
|
||||
Extensions: []icmp.Extension{
|
||||
&icmp.InterfaceIdent{
|
||||
Type: 3,
|
||||
AFI: iana.AddrFamilyNSAP,
|
||||
Addr: []byte{0x49, 0x00, 0x01, 0xaa, 0xaa, 0xbb, 0xbb, 0xcc, 0xcc, 0x00},
|
||||
},
|
||||
},
|
||||
},
|
||||
4 + 4 + 4 + 16, // [id, seq, l-bit], extension header, object header, object payload
|
||||
},
|
||||
} {
|
||||
if out := tt.in.Len(tt.proto); out != tt.out {
|
||||
t.Errorf("#%d: got %d; want %d", i, out, tt.out)
|
||||
}
|
||||
}
|
||||
}
|
43
vendor/golang.org/x/net/icmp/packettoobig.go
generated
vendored
Normal file
43
vendor/golang.org/x/net/icmp/packettoobig.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
// 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 "encoding/binary"
|
||||
|
||||
// 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, known as original datagram field
|
||||
}
|
||||
|
||||
// Len implements the Len method of MessageBody interface.
|
||||
func (p *PacketTooBig) Len(proto int) int {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
return 4 + len(p.Data)
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of MessageBody interface.
|
||||
func (p *PacketTooBig) Marshal(proto int) ([]byte, error) {
|
||||
b := make([]byte, 4+len(p.Data))
|
||||
binary.BigEndian.PutUint32(b[:4], uint32(p.MTU))
|
||||
copy(b[4:], p.Data)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// parsePacketTooBig parses b as an ICMP packet too big message body.
|
||||
func parsePacketTooBig(proto int, _ Type, b []byte) (MessageBody, error) {
|
||||
bodyLen := len(b)
|
||||
if bodyLen < 4 {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
p := &PacketTooBig{MTU: int(binary.BigEndian.Uint32(b[:4]))}
|
||||
if bodyLen > 4 {
|
||||
p.Data = make([]byte, bodyLen-4)
|
||||
copy(p.Data, b[4:])
|
||||
}
|
||||
return p, nil
|
||||
}
|
63
vendor/golang.org/x/net/icmp/paramprob.go
generated
vendored
Normal file
63
vendor/golang.org/x/net/icmp/paramprob.go
generated
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
// 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 (
|
||||
"encoding/binary"
|
||||
"golang.org/x/net/internal/iana"
|
||||
)
|
||||
|
||||
// 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, known as original datagram field
|
||||
Extensions []Extension // extensions
|
||||
}
|
||||
|
||||
// Len implements the Len method of MessageBody interface.
|
||||
func (p *ParamProb) Len(proto int) int {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
l, _ := multipartMessageBodyDataLen(proto, true, p.Data, p.Extensions)
|
||||
return 4 + l
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of MessageBody interface.
|
||||
func (p *ParamProb) Marshal(proto int) ([]byte, error) {
|
||||
if proto == iana.ProtocolIPv6ICMP {
|
||||
b := make([]byte, p.Len(proto))
|
||||
binary.BigEndian.PutUint32(b[:4], uint32(p.Pointer))
|
||||
copy(b[4:], p.Data)
|
||||
return b, nil
|
||||
}
|
||||
b, err := marshalMultipartMessageBody(proto, true, p.Data, p.Extensions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b[0] = byte(p.Pointer)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// parseParamProb parses b as an ICMP parameter problem message body.
|
||||
func parseParamProb(proto int, typ Type, b []byte) (MessageBody, error) {
|
||||
if len(b) < 4 {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
p := &ParamProb{}
|
||||
if proto == iana.ProtocolIPv6ICMP {
|
||||
p.Pointer = uintptr(binary.BigEndian.Uint32(b[:4]))
|
||||
p.Data = make([]byte, len(b)-4)
|
||||
copy(p.Data, b[4:])
|
||||
return p, nil
|
||||
}
|
||||
p.Pointer = uintptr(b[0])
|
||||
var err error
|
||||
p.Data, p.Extensions, err = parseMultipartMessageBody(proto, typ, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p, nil
|
||||
}
|
11
vendor/golang.org/x/net/icmp/sys_freebsd.go
generated
vendored
Normal file
11
vendor/golang.org/x/net/icmp/sys_freebsd.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
// 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")
|
||||
}
|
39
vendor/golang.org/x/net/icmp/timeexceeded.go
generated
vendored
Normal file
39
vendor/golang.org/x/net/icmp/timeexceeded.go
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
// 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, known as original datagram field
|
||||
Extensions []Extension // extensions
|
||||
}
|
||||
|
||||
// Len implements the Len method of MessageBody interface.
|
||||
func (p *TimeExceeded) Len(proto int) int {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
l, _ := multipartMessageBodyDataLen(proto, true, p.Data, p.Extensions)
|
||||
return 4 + l
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of MessageBody interface.
|
||||
func (p *TimeExceeded) Marshal(proto int) ([]byte, error) {
|
||||
return marshalMultipartMessageBody(proto, true, p.Data, p.Extensions)
|
||||
}
|
||||
|
||||
// parseTimeExceeded parses b as an ICMP time exceeded message body.
|
||||
func parseTimeExceeded(proto int, typ Type, b []byte) (MessageBody, error) {
|
||||
if len(b) < 4 {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
p := &TimeExceeded{}
|
||||
var err error
|
||||
p.Data, p.Extensions, err = parseMultipartMessageBody(proto, typ, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p, nil
|
||||
}
|
Reference in New Issue
Block a user