|
|
@@ -11,10 +11,12 @@ import (
|
|
|
"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, hdr, obj []byte, te Extension) error {
|
|
|
+ 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
|
|
|
@@ -22,39 +24,53 @@ func TestMarshalAndParseExtension(t *testing.T) {
|
|
|
if !reflect.DeepEqual(b, obj) {
|
|
|
return fmt.Errorf("got %#v; want %#v", b, obj)
|
|
|
}
|
|
|
- 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(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
|
|
|
+ switch typ {
|
|
|
+ case ipv4.ICMPTypeExtendedEchoRequest, ipv6.ICMPTypeExtendedEchoRequest:
|
|
|
+ exts, l, err := parseExtensions(typ, append(hdr, obj...), 0)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
}
|
|
|
- if l != wire.outlattr {
|
|
|
- return fmt.Errorf("#%d: got %d; want %d", i, l, wire.outlattr)
|
|
|
+ if l != 0 {
|
|
|
+ return fmt.Errorf("got %d; want 0", l)
|
|
|
}
|
|
|
if !reflect.DeepEqual(exts, []Extension{te}) {
|
|
|
- return fmt.Errorf("#%d: got %#v; want %#v", i, exts[0], 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
|
|
|
@@ -63,6 +79,7 @@ func TestMarshalAndParseExtension(t *testing.T) {
|
|
|
t.Run("MPLSLabelStack", func(t *testing.T) {
|
|
|
for _, et := range []struct {
|
|
|
proto int
|
|
|
+ typ Type
|
|
|
hdr []byte
|
|
|
obj []byte
|
|
|
ext Extension
|
|
|
@@ -70,6 +87,7 @@ func TestMarshalAndParseExtension(t *testing.T) {
|
|
|
// MPLS label stack with no label
|
|
|
{
|
|
|
proto: iana.ProtocolICMP,
|
|
|
+ typ: ipv4.ICMPTypeDestinationUnreachable,
|
|
|
hdr: []byte{
|
|
|
0x20, 0x00, 0x00, 0x00,
|
|
|
},
|
|
|
@@ -84,6 +102,7 @@ func TestMarshalAndParseExtension(t *testing.T) {
|
|
|
// MPLS label stack with a single label
|
|
|
{
|
|
|
proto: iana.ProtocolIPv6ICMP,
|
|
|
+ typ: ipv6.ICMPTypeDestinationUnreachable,
|
|
|
hdr: []byte{
|
|
|
0x20, 0x00, 0x00, 0x00,
|
|
|
},
|
|
|
@@ -107,6 +126,7 @@ func TestMarshalAndParseExtension(t *testing.T) {
|
|
|
// MPLS label stack with multiple labels
|
|
|
{
|
|
|
proto: iana.ProtocolICMP,
|
|
|
+ typ: ipv4.ICMPTypeDestinationUnreachable,
|
|
|
hdr: []byte{
|
|
|
0x20, 0x00, 0x00, 0x00,
|
|
|
},
|
|
|
@@ -135,7 +155,7 @@ func TestMarshalAndParseExtension(t *testing.T) {
|
|
|
},
|
|
|
},
|
|
|
} {
|
|
|
- if err := fn(t, et.proto, et.hdr, et.obj, et.ext); err != nil {
|
|
|
+ if err := fn(t, et.proto, et.typ, et.hdr, et.obj, et.ext); err != nil {
|
|
|
t.Error(err)
|
|
|
}
|
|
|
}
|
|
|
@@ -143,6 +163,7 @@ func TestMarshalAndParseExtension(t *testing.T) {
|
|
|
t.Run("InterfaceInfo", func(t *testing.T) {
|
|
|
for _, et := range []struct {
|
|
|
proto int
|
|
|
+ typ Type
|
|
|
hdr []byte
|
|
|
obj []byte
|
|
|
ext Extension
|
|
|
@@ -150,6 +171,7 @@ func TestMarshalAndParseExtension(t *testing.T) {
|
|
|
// Interface information with no attribute
|
|
|
{
|
|
|
proto: iana.ProtocolICMP,
|
|
|
+ typ: ipv4.ICMPTypeDestinationUnreachable,
|
|
|
hdr: []byte{
|
|
|
0x20, 0x00, 0x00, 0x00,
|
|
|
},
|
|
|
@@ -163,6 +185,7 @@ func TestMarshalAndParseExtension(t *testing.T) {
|
|
|
// Interface information with ifIndex and name
|
|
|
{
|
|
|
proto: iana.ProtocolICMP,
|
|
|
+ typ: ipv4.ICMPTypeDestinationUnreachable,
|
|
|
hdr: []byte{
|
|
|
0x20, 0x00, 0x00, 0x00,
|
|
|
},
|
|
|
@@ -184,6 +207,7 @@ func TestMarshalAndParseExtension(t *testing.T) {
|
|
|
// Interface information with ifIndex, IPAddr, name and MTU
|
|
|
{
|
|
|
proto: iana.ProtocolIPv6ICMP,
|
|
|
+ typ: ipv6.ICMPTypeDestinationUnreachable,
|
|
|
hdr: []byte{
|
|
|
0x20, 0x00, 0x00, 0x00,
|
|
|
},
|
|
|
@@ -214,7 +238,77 @@ func TestMarshalAndParseExtension(t *testing.T) {
|
|
|
},
|
|
|
},
|
|
|
} {
|
|
|
- if err := fn(t, et.proto, et.hdr, et.obj, et.ext); err != nil {
|
|
|
+ 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)
|
|
|
}
|
|
|
}
|