123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332 |
- // 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, 0x08, 0x03, 0x02,
- 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)
- }
- }
- }
|