123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567 |
- // 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,
- },
- },
- },
- },
- {
- 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: 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)
- }
- case *icmp.RawExtension:
- s += fmt.Sprintf("#%d: raw extension\n", i)
- }
- }
- if len(s) == 0 {
- s += "empty extension"
- }
- 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)
- }
- }
- }
|