summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/header
diff options
context:
space:
mode:
authorGhanan Gowripalan <ghanan@google.com>2021-03-16 11:07:02 -0700
committergVisor bot <gvisor-bot@google.com>2021-03-16 11:09:26 -0700
commit68065d1ceb589b7ea1d3e4b3b067fb8772e30760 (patch)
treef3017f52fba725114b913cf893fcdcb6678415de /pkg/tcpip/header
parentebd7c1b889e5d212f4a694d3addbada241936e8e (diff)
Detect looped-back NDP DAD messages
...as per RFC 7527. If a looped-back DAD message is received, do not fail DAD since our own DAD message does not indicate that a neighbor has the address assigned. Test: ndp_test.TestDADResolveLoopback PiperOrigin-RevId: 363224288
Diffstat (limited to 'pkg/tcpip/header')
-rw-r--r--pkg/tcpip/header/ndp_options.go40
-rw-r--r--pkg/tcpip/header/ndp_test.go679
-rw-r--r--pkg/tcpip/header/ndpoptionidentifier_string.go14
3 files changed, 355 insertions, 378 deletions
diff --git a/pkg/tcpip/header/ndp_options.go b/pkg/tcpip/header/ndp_options.go
index 554242f0c..5deae465c 100644
--- a/pkg/tcpip/header/ndp_options.go
+++ b/pkg/tcpip/header/ndp_options.go
@@ -42,13 +42,17 @@ const (
// option, as per RFC 4861 section 4.6.2.
NDPPrefixInformationType NDPOptionIdentifier = 3
+ // NDPNonceOptionType is the type of the Nonce option, as per
+ // RFC 3971 section 5.3.2.
+ NDPNonceOptionType NDPOptionIdentifier = 14
+
// NDPRecursiveDNSServerOptionType is the type of the Recursive DNS
// Server option, as per RFC 8106 section 5.1.
NDPRecursiveDNSServerOptionType NDPOptionIdentifier = 25
// NDPDNSSearchListOptionType is the type of the DNS Search List option,
// as per RFC 8106 section 5.2.
- NDPDNSSearchListOptionType = 31
+ NDPDNSSearchListOptionType NDPOptionIdentifier = 31
)
const (
@@ -231,6 +235,9 @@ func (i *NDPOptionIterator) Next() (NDPOption, bool, error) {
case NDPTargetLinkLayerAddressOptionType:
return NDPTargetLinkLayerAddressOption(body), false, nil
+ case NDPNonceOptionType:
+ return NDPNonceOption(body), false, nil
+
case NDPPrefixInformationType:
// Make sure the length of a Prefix Information option
// body is ndpPrefixInformationLength, as per RFC 4861
@@ -416,6 +423,37 @@ func (b NDPOptionsSerializer) Length() int {
return l
}
+// NDPNonceOption is the NDP Nonce Option as defined by RFC 3971 section 5.3.2.
+//
+// It is the first X bytes following the NDP option's Type and Length field
+// where X is the value in Length multiplied by lengthByteUnits - 2 bytes.
+type NDPNonceOption []byte
+
+// Type implements NDPOption.
+func (o NDPNonceOption) Type() NDPOptionIdentifier {
+ return NDPNonceOptionType
+}
+
+// Length implements NDPOption.
+func (o NDPNonceOption) Length() int {
+ return len(o)
+}
+
+// serializeInto implements NDPOption.
+func (o NDPNonceOption) serializeInto(b []byte) int {
+ return copy(b, o)
+}
+
+// String implements fmt.Stringer.
+func (o NDPNonceOption) String() string {
+ return fmt.Sprintf("%T(%x)", o, []byte(o))
+}
+
+// Nonce returns the nonce value this option holds.
+func (o NDPNonceOption) Nonce() []byte {
+ return []byte(o)
+}
+
// NDPSourceLinkLayerAddressOption is the NDP Source Link Layer Option
// as defined by RFC 4861 section 4.6.1.
//
diff --git a/pkg/tcpip/header/ndp_test.go b/pkg/tcpip/header/ndp_test.go
index dc4591253..bfc73e245 100644
--- a/pkg/tcpip/header/ndp_test.go
+++ b/pkg/tcpip/header/ndp_test.go
@@ -16,6 +16,7 @@ package header
import (
"bytes"
+ "encoding/binary"
"errors"
"fmt"
"io"
@@ -192,90 +193,6 @@ func TestNDPSourceLinkLayerAddressOptionEthernetAddress(t *testing.T) {
}
}
-// TestNDPSourceLinkLayerAddressOptionSerialize tests serializing a
-// NDPSourceLinkLayerAddressOption.
-func TestNDPSourceLinkLayerAddressOptionSerialize(t *testing.T) {
- tests := []struct {
- name string
- buf []byte
- expectedBuf []byte
- addr tcpip.LinkAddress
- }{
- {
- "Ethernet",
- make([]byte, 8),
- []byte{1, 1, 1, 2, 3, 4, 5, 6},
- "\x01\x02\x03\x04\x05\x06",
- },
- {
- "Padding",
- []byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
- []byte{1, 2, 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0},
- "\x01\x02\x03\x04\x05\x06\x07\x08",
- },
- {
- "Empty",
- nil,
- nil,
- "",
- },
- }
-
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- opts := NDPOptions(test.buf)
- serializer := NDPOptionsSerializer{
- NDPSourceLinkLayerAddressOption(test.addr),
- }
- if got, want := int(serializer.Length()), len(test.expectedBuf); got != want {
- t.Fatalf("got Length = %d, want = %d", got, want)
- }
- opts.Serialize(serializer)
- if !bytes.Equal(test.buf, test.expectedBuf) {
- t.Fatalf("got b = %d, want = %d", test.buf, test.expectedBuf)
- }
-
- it, err := opts.Iter(true)
- if err != nil {
- t.Fatalf("got Iter = (_, %s), want = (_, nil)", err)
- }
-
- if len(test.expectedBuf) > 0 {
- next, done, err := it.Next()
- if err != nil {
- t.Fatalf("got Next = (_, _, %s), want = (_, _, nil)", err)
- }
- if done {
- t.Fatal("got Next = (_, true, _), want = (_, false, _)")
- }
- if got := next.Type(); got != NDPSourceLinkLayerAddressOptionType {
- t.Fatalf("got Type = %d, want = %d", got, NDPSourceLinkLayerAddressOptionType)
- }
- sll := next.(NDPSourceLinkLayerAddressOption)
- if got, want := []byte(sll), test.expectedBuf[2:]; !bytes.Equal(got, want) {
- t.Fatalf("got Next = (%x, _, _), want = (%x, _, _)", got, want)
- }
-
- if got, want := sll.EthernetAddress(), tcpip.LinkAddress(test.expectedBuf[2:][:EthernetAddressSize]); got != want {
- t.Errorf("got sll.EthernetAddress = %s, want = %s", got, want)
- }
- }
-
- // Iterator should not return anything else.
- next, done, err := it.Next()
- if err != nil {
- t.Errorf("got Next = (_, _, %s), want = (_, _, nil)", err)
- }
- if !done {
- t.Error("got Next = (_, false, _), want = (_, true, _)")
- }
- if next != nil {
- t.Errorf("got Next = (%x, _, _), want = (nil, _, _)", next)
- }
- })
- }
-}
-
// TestNDPTargetLinkLayerAddressOptionEthernetAddress tests getting the
// Ethernet address from an NDPTargetLinkLayerAddressOption.
func TestNDPTargetLinkLayerAddressOptionEthernetAddress(t *testing.T) {
@@ -311,32 +228,309 @@ func TestNDPTargetLinkLayerAddressOptionEthernetAddress(t *testing.T) {
}
}
-// TestNDPTargetLinkLayerAddressOptionSerialize tests serializing a
-// NDPTargetLinkLayerAddressOption.
-func TestNDPTargetLinkLayerAddressOptionSerialize(t *testing.T) {
+func TestOpts(t *testing.T) {
+ const optionHeaderLen = 2
+
+ checkNonce := func(expectedNonce []byte) func(*testing.T, NDPOption) {
+ return func(t *testing.T, opt NDPOption) {
+ if got := opt.Type(); got != NDPNonceOptionType {
+ t.Errorf("got Type() = %d, want = %d", got, NDPNonceOptionType)
+ }
+ nonce, ok := opt.(NDPNonceOption)
+ if !ok {
+ t.Fatalf("got nonce = %T, want = NDPNonceOption", opt)
+ }
+ if diff := cmp.Diff(expectedNonce, nonce.Nonce()); diff != "" {
+ t.Errorf("nonce mismatch (-want +got):\n%s", diff)
+ }
+ }
+ }
+
+ checkTLL := func(expectedAddr tcpip.LinkAddress) func(*testing.T, NDPOption) {
+ return func(t *testing.T, opt NDPOption) {
+ if got := opt.Type(); got != NDPTargetLinkLayerAddressOptionType {
+ t.Errorf("got Type() = %d, want = %d", got, NDPTargetLinkLayerAddressOptionType)
+ }
+ tll, ok := opt.(NDPTargetLinkLayerAddressOption)
+ if !ok {
+ t.Fatalf("got tll = %T, want = NDPTargetLinkLayerAddressOption", opt)
+ }
+ if got, want := tll.EthernetAddress(), expectedAddr; got != want {
+ t.Errorf("got tll.EthernetAddress = %s, want = %s", got, want)
+ }
+ }
+ }
+
+ checkSLL := func(expectedAddr tcpip.LinkAddress) func(*testing.T, NDPOption) {
+ return func(t *testing.T, opt NDPOption) {
+ if got := opt.Type(); got != NDPSourceLinkLayerAddressOptionType {
+ t.Errorf("got Type() = %d, want = %d", got, NDPSourceLinkLayerAddressOptionType)
+ }
+ sll, ok := opt.(NDPSourceLinkLayerAddressOption)
+ if !ok {
+ t.Fatalf("got sll = %T, want = NDPSourceLinkLayerAddressOption", opt)
+ }
+ if got, want := sll.EthernetAddress(), expectedAddr; got != want {
+ t.Errorf("got sll.EthernetAddress = %s, want = %s", got, want)
+ }
+ }
+ }
+
+ const validLifetimeSeconds = 16909060
+ const address = tcpip.Address("\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18")
+
+ expectedRDNSSBytes := [...]byte{
+ // Type, Length
+ 25, 3,
+
+ // Reserved
+ 0, 0,
+
+ // Lifetime
+ 1, 2, 4, 8,
+
+ // Address
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ }
+ binary.BigEndian.PutUint32(expectedRDNSSBytes[4:], validLifetimeSeconds)
+ if n := copy(expectedRDNSSBytes[8:], address); n != IPv6AddressSize {
+ t.Fatalf("got copy(...) = %d, want = %d", n, IPv6AddressSize)
+ }
+ // Update reserved fields to non zero values to make sure serializing sets
+ // them to zero.
+ rdnssBytes := expectedRDNSSBytes
+ rdnssBytes[1] = 1
+ rdnssBytes[2] = 2
+
+ const searchListPaddingBytes = 3
+ const domainName = "abc.abcd.e"
+ expectedSearchListBytes := [...]byte{
+ // Type, Length
+ 31, 3,
+
+ // Reserved
+ 0, 0,
+
+ // Lifetime
+ 1, 0, 0, 0,
+
+ // Domain names
+ 3, 'a', 'b', 'c',
+ 4, 'a', 'b', 'c', 'd',
+ 1, 'e',
+ 0,
+ 0, 0, 0, 0,
+ }
+ binary.BigEndian.PutUint32(expectedSearchListBytes[4:], validLifetimeSeconds)
+ // Update reserved fields to non zero values to make sure serializing sets
+ // them to zero.
+ searchListBytes := expectedSearchListBytes
+ searchListBytes[2] = 1
+ searchListBytes[3] = 2
+
+ const prefixLength = 43
+ const onLinkFlag = false
+ const slaacFlag = true
+ const preferredLifetimeSeconds = 84281096
+ const onLinkFlagBit = 7
+ const slaacFlagBit = 6
+ boolToByte := func(v bool) byte {
+ if v {
+ return 1
+ }
+ return 0
+ }
+ flags := boolToByte(onLinkFlag)<<onLinkFlagBit | boolToByte(slaacFlag)<<slaacFlagBit
+ expectedPrefixInformationBytes := [...]byte{
+ // Type, Length
+ 3, 4,
+
+ prefixLength, flags,
+
+ // Valid Lifetime
+ 1, 2, 3, 4,
+
+ // Preferred Lifetime
+ 5, 6, 7, 8,
+
+ // Reserved2
+ 0, 0, 0, 0,
+
+ // Address
+ 9, 10, 11, 12,
+ 13, 14, 15, 16,
+ 17, 18, 19, 20,
+ 21, 22, 23, 24,
+ }
+ binary.BigEndian.PutUint32(expectedPrefixInformationBytes[4:], validLifetimeSeconds)
+ binary.BigEndian.PutUint32(expectedPrefixInformationBytes[8:], preferredLifetimeSeconds)
+ if n := copy(expectedPrefixInformationBytes[16:], address); n != IPv6AddressSize {
+ t.Fatalf("got copy(...) = %d, want = %d", n, IPv6AddressSize)
+ }
+ // Update reserved fields to non zero values to make sure serializing sets
+ // them to zero.
+ prefixInformationBytes := expectedPrefixInformationBytes
+ prefixInformationBytes[3] |= (1 << slaacFlagBit) - 1
+ binary.BigEndian.PutUint32(prefixInformationBytes[12:], validLifetimeSeconds+1)
tests := []struct {
name string
buf []byte
+ opt NDPOption
expectedBuf []byte
- addr tcpip.LinkAddress
+ check func(*testing.T, NDPOption)
}{
{
- "Ethernet",
- make([]byte, 8),
- []byte{2, 1, 1, 2, 3, 4, 5, 6},
- "\x01\x02\x03\x04\x05\x06",
+ name: "Nonce",
+ buf: make([]byte, 8),
+ opt: NDPNonceOption([]byte{1, 2, 3, 4, 5, 6}),
+ expectedBuf: []byte{14, 1, 1, 2, 3, 4, 5, 6},
+ check: checkNonce([]byte{1, 2, 3, 4, 5, 6}),
+ },
+ {
+ name: "Nonce with padding",
+ buf: []byte{1, 1, 1, 1, 1, 1, 1, 1},
+ opt: NDPNonceOption([]byte{1, 2, 3, 4, 5}),
+ expectedBuf: []byte{14, 1, 1, 2, 3, 4, 5, 0},
+ check: checkNonce([]byte{1, 2, 3, 4, 5, 0}),
+ },
+
+ {
+ name: "TLL Ethernet",
+ buf: make([]byte, 8),
+ opt: NDPTargetLinkLayerAddressOption("\x01\x02\x03\x04\x05\x06"),
+ expectedBuf: []byte{2, 1, 1, 2, 3, 4, 5, 6},
+ check: checkTLL("\x01\x02\x03\x04\x05\x06"),
+ },
+ {
+ name: "TLL Padding",
+ buf: []byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+ opt: NDPTargetLinkLayerAddressOption("\x01\x02\x03\x04\x05\x06\x07\x08"),
+ expectedBuf: []byte{2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0},
+ check: checkTLL("\x01\x02\x03\x04\x05\x06"),
+ },
+ {
+ name: "TLL Empty",
+ buf: nil,
+ opt: NDPTargetLinkLayerAddressOption(""),
+ expectedBuf: nil,
+ },
+
+ {
+ name: "SLL Ethernet",
+ buf: make([]byte, 8),
+ opt: NDPSourceLinkLayerAddressOption("\x01\x02\x03\x04\x05\x06"),
+ expectedBuf: []byte{1, 1, 1, 2, 3, 4, 5, 6},
+ check: checkSLL("\x01\x02\x03\x04\x05\x06"),
+ },
+ {
+ name: "SLL Padding",
+ buf: []byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+ opt: NDPSourceLinkLayerAddressOption("\x01\x02\x03\x04\x05\x06\x07\x08"),
+ expectedBuf: []byte{1, 2, 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0},
+ check: checkSLL("\x01\x02\x03\x04\x05\x06"),
+ },
+ {
+ name: "SLL Empty",
+ buf: nil,
+ opt: NDPSourceLinkLayerAddressOption(""),
+ expectedBuf: nil,
+ },
+
+ {
+ name: "RDNSS",
+ buf: []byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+ // NDPRecursiveDNSServer holds the option after the header bytes.
+ opt: NDPRecursiveDNSServer(rdnssBytes[optionHeaderLen:]),
+ expectedBuf: expectedRDNSSBytes[:],
+ check: func(t *testing.T, opt NDPOption) {
+ if got := opt.Type(); got != NDPRecursiveDNSServerOptionType {
+ t.Errorf("got Type() = %d, want = %d", got, NDPRecursiveDNSServerOptionType)
+ }
+ rdnss, ok := opt.(NDPRecursiveDNSServer)
+ if !ok {
+ t.Fatalf("got opt = %T, want = NDPRecursiveDNSServer", opt)
+ }
+ if got, want := rdnss.Length(), len(expectedRDNSSBytes[optionHeaderLen:]); got != want {
+ t.Errorf("got Length() = %d, want = %d", got, want)
+ }
+ if got, want := rdnss.Lifetime(), validLifetimeSeconds*time.Second; got != want {
+ t.Errorf("got Lifetime() = %s, want = %s", got, want)
+ }
+ if addrs, err := rdnss.Addresses(); err != nil {
+ t.Errorf("Addresses(): %s", err)
+ } else if diff := cmp.Diff([]tcpip.Address{address}, addrs); diff != "" {
+ t.Errorf("mismatched addresses (-want +got):\n%s", diff)
+ }
+ },
},
+
{
- "Padding",
- []byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
- []byte{2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0},
- "\x01\x02\x03\x04\x05\x06\x07\x08",
+ name: "Search list",
+ buf: []byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+ opt: NDPDNSSearchList(searchListBytes[optionHeaderLen:]),
+ expectedBuf: expectedSearchListBytes[:],
+ check: func(t *testing.T, opt NDPOption) {
+ if got := opt.Type(); got != NDPDNSSearchListOptionType {
+ t.Errorf("got Type() = %d, want = %d", got, NDPDNSSearchListOptionType)
+ }
+
+ dnssl, ok := opt.(NDPDNSSearchList)
+ if !ok {
+ t.Fatalf("got opt = %T, want = NDPDNSSearchList", opt)
+ }
+ if got, want := dnssl.Length(), len(expectedRDNSSBytes[optionHeaderLen:]); got != want {
+ t.Errorf("got Length() = %d, want = %d", got, want)
+ }
+ if got, want := dnssl.Lifetime(), validLifetimeSeconds*time.Second; got != want {
+ t.Errorf("got Lifetime() = %s, want = %s", got, want)
+ }
+
+ if domainNames, err := dnssl.DomainNames(); err != nil {
+ t.Errorf("DomainNames(): %s", err)
+ } else if diff := cmp.Diff([]string{domainName}, domainNames); diff != "" {
+ t.Errorf("domain names mismatch (-want +got):\n%s", diff)
+ }
+ },
},
+
{
- "Empty",
- nil,
- nil,
- "",
+ name: "Prefix Information",
+ buf: []byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+ // NDPPrefixInformation holds the option after the header bytes.
+ opt: NDPPrefixInformation(prefixInformationBytes[optionHeaderLen:]),
+ expectedBuf: expectedPrefixInformationBytes[:],
+ check: func(t *testing.T, opt NDPOption) {
+ if got := opt.Type(); got != NDPPrefixInformationType {
+ t.Errorf("got Type() = %d, want = %d", got, NDPPrefixInformationType)
+ }
+
+ pi, ok := opt.(NDPPrefixInformation)
+ if !ok {
+ t.Fatalf("got opt = %T, want = NDPPrefixInformation", opt)
+ }
+
+ if got, want := pi.Length(), len(expectedPrefixInformationBytes[optionHeaderLen:]); got != want {
+ t.Errorf("got Length() = %d, want = %d", got, want)
+ }
+ if got := pi.PrefixLength(); got != prefixLength {
+ t.Errorf("got PrefixLength() = %d, want = %d", got, prefixLength)
+ }
+ if got := pi.OnLinkFlag(); got != onLinkFlag {
+ t.Errorf("got OnLinkFlag() = %t, want = %t", got, onLinkFlag)
+ }
+ if got := pi.AutonomousAddressConfigurationFlag(); got != slaacFlag {
+ t.Errorf("got AutonomousAddressConfigurationFlag() = %t, want = %t", got, slaacFlag)
+ }
+ if got, want := pi.ValidLifetime(), validLifetimeSeconds*time.Second; got != want {
+ t.Errorf("got ValidLifetime() = %s, want = %s", got, want)
+ }
+ if got, want := pi.PreferredLifetime(), preferredLifetimeSeconds*time.Second; got != want {
+ t.Errorf("got PreferredLifetime() = %s, want = %s", got, want)
+ }
+ if got := pi.Prefix(); got != address {
+ t.Errorf("got Prefix() = %s, want = %s", got, address)
+ }
+ },
},
}
@@ -344,230 +538,47 @@ func TestNDPTargetLinkLayerAddressOptionSerialize(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
opts := NDPOptions(test.buf)
serializer := NDPOptionsSerializer{
- NDPTargetLinkLayerAddressOption(test.addr),
+ test.opt,
}
if got, want := int(serializer.Length()), len(test.expectedBuf); got != want {
- t.Fatalf("got Length = %d, want = %d", got, want)
+ t.Fatalf("got Length() = %d, want = %d", got, want)
}
opts.Serialize(serializer)
- if !bytes.Equal(test.buf, test.expectedBuf) {
- t.Fatalf("got b = %d, want = %d", test.buf, test.expectedBuf)
+ if diff := cmp.Diff(test.expectedBuf, test.buf); diff != "" {
+ t.Fatalf("serialized buffer mismatch (-want +got):\n%s", diff)
}
it, err := opts.Iter(true)
if err != nil {
- t.Fatalf("got Iter = (_, %s), want = (_, nil)", err)
+ t.Fatalf("got Iter(true) = (_, %s), want = (_, nil)", err)
}
if len(test.expectedBuf) > 0 {
next, done, err := it.Next()
if err != nil {
- t.Fatalf("got Next = (_, _, %s), want = (_, _, nil)", err)
+ t.Fatalf("got Next() = (_, _, %s), want = (_, _, nil)", err)
}
if done {
- t.Fatal("got Next = (_, true, _), want = (_, false, _)")
- }
- if got := next.Type(); got != NDPTargetLinkLayerAddressOptionType {
- t.Fatalf("got Type = %d, want = %d", got, NDPTargetLinkLayerAddressOptionType)
- }
- tll := next.(NDPTargetLinkLayerAddressOption)
- if got, want := []byte(tll), test.expectedBuf[2:]; !bytes.Equal(got, want) {
- t.Fatalf("got Next = (%x, _, _), want = (%x, _, _)", got, want)
- }
-
- if got, want := tll.EthernetAddress(), tcpip.LinkAddress(test.expectedBuf[2:][:EthernetAddressSize]); got != want {
- t.Errorf("got tll.EthernetAddress = %s, want = %s", got, want)
+ t.Fatal("got Next() = (_, true, _), want = (_, false, _)")
}
+ test.check(t, next)
}
// Iterator should not return anything else.
next, done, err := it.Next()
if err != nil {
- t.Errorf("got Next = (_, _, %s), want = (_, _, nil)", err)
+ t.Errorf("got Next() = (_, _, %s), want = (_, _, nil)", err)
}
if !done {
- t.Error("got Next = (_, false, _), want = (_, true, _)")
+ t.Error("got Next() = (_, false, _), want = (_, true, _)")
}
if next != nil {
- t.Errorf("got Next = (%x, _, _), want = (nil, _, _)", next)
+ t.Errorf("got Next() = (%x, _, _), want = (nil, _, _)", next)
}
})
}
}
-// TestNDPPrefixInformationOption tests the field getters and serialization of a
-// NDPPrefixInformation.
-func TestNDPPrefixInformationOption(t *testing.T) {
- b := []byte{
- 43, 127,
- 1, 2, 3, 4,
- 5, 6, 7, 8,
- 5, 5, 5, 5,
- 9, 10, 11, 12,
- 13, 14, 15, 16,
- 17, 18, 19, 20,
- 21, 22, 23, 24,
- }
-
- targetBuf := []byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
- opts := NDPOptions(targetBuf)
- serializer := NDPOptionsSerializer{
- NDPPrefixInformation(b),
- }
- opts.Serialize(serializer)
- expectedBuf := []byte{
- 3, 4, 43, 64,
- 1, 2, 3, 4,
- 5, 6, 7, 8,
- 0, 0, 0, 0,
- 9, 10, 11, 12,
- 13, 14, 15, 16,
- 17, 18, 19, 20,
- 21, 22, 23, 24,
- }
- if !bytes.Equal(targetBuf, expectedBuf) {
- t.Fatalf("got targetBuf = %x, want = %x", targetBuf, expectedBuf)
- }
-
- it, err := opts.Iter(true)
- if err != nil {
- t.Fatalf("got Iter = (_, %s), want = (_, nil)", err)
- }
-
- next, done, err := it.Next()
- if err != nil {
- t.Fatalf("got Next = (_, _, %s), want = (_, _, nil)", err)
- }
- if done {
- t.Fatal("got Next = (_, true, _), want = (_, false, _)")
- }
- if got := next.Type(); got != NDPPrefixInformationType {
- t.Errorf("got Type = %d, want = %d", got, NDPPrefixInformationType)
- }
-
- pi := next.(NDPPrefixInformation)
-
- if got := pi.Type(); got != 3 {
- t.Errorf("got Type = %d, want = 3", got)
- }
-
- if got := pi.Length(); got != 30 {
- t.Errorf("got Length = %d, want = 30", got)
- }
-
- if got := pi.PrefixLength(); got != 43 {
- t.Errorf("got PrefixLength = %d, want = 43", got)
- }
-
- if pi.OnLinkFlag() {
- t.Error("got OnLinkFlag = true, want = false")
- }
-
- if !pi.AutonomousAddressConfigurationFlag() {
- t.Error("got AutonomousAddressConfigurationFlag = false, want = true")
- }
-
- if got, want := pi.ValidLifetime(), 16909060*time.Second; got != want {
- t.Errorf("got ValidLifetime = %d, want = %d", got, want)
- }
-
- if got, want := pi.PreferredLifetime(), 84281096*time.Second; got != want {
- t.Errorf("got PreferredLifetime = %d, want = %d", got, want)
- }
-
- if got, want := pi.Prefix(), tcpip.Address("\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18"); got != want {
- t.Errorf("got Prefix = %s, want = %s", got, want)
- }
-
- // Iterator should not return anything else.
- next, done, err = it.Next()
- if err != nil {
- t.Errorf("got Next = (_, _, %s), want = (_, _, nil)", err)
- }
- if !done {
- t.Error("got Next = (_, false, _), want = (_, true, _)")
- }
- if next != nil {
- t.Errorf("got Next = (%x, _, _), want = (nil, _, _)", next)
- }
-}
-
-func TestNDPRecursiveDNSServerOptionSerialize(t *testing.T) {
- b := []byte{
- 9, 8,
- 1, 2, 4, 8,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- }
- targetBuf := []byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
- expected := []byte{
- 25, 3, 0, 0,
- 1, 2, 4, 8,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- }
- opts := NDPOptions(targetBuf)
- serializer := NDPOptionsSerializer{
- NDPRecursiveDNSServer(b),
- }
- if got, want := opts.Serialize(serializer), len(expected); got != want {
- t.Errorf("got Serialize = %d, want = %d", got, want)
- }
- if !bytes.Equal(targetBuf, expected) {
- t.Fatalf("got targetBuf = %x, want = %x", targetBuf, expected)
- }
-
- it, err := opts.Iter(true)
- if err != nil {
- t.Fatalf("got Iter = (_, %s), want = (_, nil)", err)
- }
-
- next, done, err := it.Next()
- if err != nil {
- t.Fatalf("got Next = (_, _, %s), want = (_, _, nil)", err)
- }
- if done {
- t.Fatal("got Next = (_, true, _), want = (_, false, _)")
- }
- if got := next.Type(); got != NDPRecursiveDNSServerOptionType {
- t.Errorf("got Type = %d, want = %d", got, NDPRecursiveDNSServerOptionType)
- }
-
- opt, ok := next.(NDPRecursiveDNSServer)
- if !ok {
- t.Fatalf("next (type = %T) cannot be casted to an NDPRecursiveDNSServer", next)
- }
- if got := opt.Type(); got != 25 {
- t.Errorf("got Type = %d, want = 31", got)
- }
- if got := opt.Length(); got != 22 {
- t.Errorf("got Length = %d, want = 22", got)
- }
- if got, want := opt.Lifetime(), 16909320*time.Second; got != want {
- t.Errorf("got Lifetime = %s, want = %s", got, want)
- }
- want := []tcpip.Address{
- "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
- }
- addrs, err := opt.Addresses()
- if err != nil {
- t.Errorf("opt.Addresses() = %s", err)
- }
- if diff := cmp.Diff(addrs, want); diff != "" {
- t.Errorf("mismatched addresses (-want +got):\n%s", diff)
- }
-
- // Iterator should not return anything else.
- next, done, err = it.Next()
- if err != nil {
- t.Errorf("got Next = (_, _, %s), want = (_, _, nil)", err)
- }
- if !done {
- t.Error("got Next = (_, false, _), want = (_, true, _)")
- }
- if next != nil {
- t.Errorf("got Next = (%x, _, _), want = (nil, _, _)", next)
- }
-}
-
func TestNDPRecursiveDNSServerOption(t *testing.T) {
tests := []struct {
name string
@@ -1060,86 +1071,6 @@ func TestNDPSearchListOptionDomainNameLabelInvalidSymbols(t *testing.T) {
}
}
-func TestNDPDNSSearchListOptionSerialize(t *testing.T) {
- b := []byte{
- 9, 8,
- 1, 0, 0, 0,
- 3, 'a', 'b', 'c',
- 4, 'a', 'b', 'c', 'd',
- 1, 'e',
- 0,
- }
- targetBuf := []byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
- expected := []byte{
- 31, 3, 0, 0,
- 1, 0, 0, 0,
- 3, 'a', 'b', 'c',
- 4, 'a', 'b', 'c', 'd',
- 1, 'e',
- 0,
- 0, 0, 0, 0,
- }
- opts := NDPOptions(targetBuf)
- serializer := NDPOptionsSerializer{
- NDPDNSSearchList(b),
- }
- if got, want := opts.Serialize(serializer), len(expected); got != want {
- t.Errorf("got Serialize = %d, want = %d", got, want)
- }
- if !bytes.Equal(targetBuf, expected) {
- t.Fatalf("got targetBuf = %x, want = %x", targetBuf, expected)
- }
-
- it, err := opts.Iter(true)
- if err != nil {
- t.Fatalf("got Iter = (_, %s), want = (_, nil)", err)
- }
-
- next, done, err := it.Next()
- if err != nil {
- t.Fatalf("got Next = (_, _, %s), want = (_, _, nil)", err)
- }
- if done {
- t.Fatal("got Next = (_, true, _), want = (_, false, _)")
- }
- if got := next.Type(); got != NDPDNSSearchListOptionType {
- t.Errorf("got Type = %d, want = %d", got, NDPDNSSearchListOptionType)
- }
-
- opt, ok := next.(NDPDNSSearchList)
- if !ok {
- t.Fatalf("next (type = %T) cannot be casted to an NDPDNSSearchList", next)
- }
- if got := opt.Type(); got != 31 {
- t.Errorf("got Type = %d, want = 31", got)
- }
- if got := opt.Length(); got != 22 {
- t.Errorf("got Length = %d, want = 22", got)
- }
- if got, want := opt.Lifetime(), 16777216*time.Second; got != want {
- t.Errorf("got Lifetime = %s, want = %s", got, want)
- }
- domainNames, err := opt.DomainNames()
- if err != nil {
- t.Errorf("opt.DomainNames() = %s", err)
- }
- if diff := cmp.Diff(domainNames, []string{"abc.abcd.e"}); diff != "" {
- t.Errorf("domain names mismatch (-want +got):\n%s", diff)
- }
-
- // Iterator should not return anything else.
- next, done, err = it.Next()
- if err != nil {
- t.Errorf("got Next = (_, _, %s), want = (_, _, nil)", err)
- }
- if !done {
- t.Error("got Next = (_, false, _), want = (_, true, _)")
- }
- if next != nil {
- t.Errorf("got Next = (%x, _, _), want = (nil, _, _)", next)
- }
-}
-
// TestNDPOptionsIterCheck tests that Iter will return false if the NDPOptions
// the iterator was returned for is malformed.
func TestNDPOptionsIterCheck(t *testing.T) {
diff --git a/pkg/tcpip/header/ndpoptionidentifier_string.go b/pkg/tcpip/header/ndpoptionidentifier_string.go
index 6fe9a336b..83f94a730 100644
--- a/pkg/tcpip/header/ndpoptionidentifier_string.go
+++ b/pkg/tcpip/header/ndpoptionidentifier_string.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// Code generated by "stringer -type NDPOptionIdentifier ."; DO NOT EDIT.
+// Code generated by "stringer -type NDPOptionIdentifier"; DO NOT EDIT.
package header
@@ -25,12 +25,16 @@ func _() {
_ = x[NDPSourceLinkLayerAddressOptionType-1]
_ = x[NDPTargetLinkLayerAddressOptionType-2]
_ = x[NDPPrefixInformationType-3]
+ _ = x[NDPNonceOptionType-14]
_ = x[NDPRecursiveDNSServerOptionType-25]
+ _ = x[NDPDNSSearchListOptionType-31]
}
const (
_NDPOptionIdentifier_name_0 = "NDPSourceLinkLayerAddressOptionTypeNDPTargetLinkLayerAddressOptionTypeNDPPrefixInformationType"
- _NDPOptionIdentifier_name_1 = "NDPRecursiveDNSServerOptionType"
+ _NDPOptionIdentifier_name_1 = "NDPNonceOptionType"
+ _NDPOptionIdentifier_name_2 = "NDPRecursiveDNSServerOptionType"
+ _NDPOptionIdentifier_name_3 = "NDPDNSSearchListOptionType"
)
var (
@@ -42,8 +46,12 @@ func (i NDPOptionIdentifier) String() string {
case 1 <= i && i <= 3:
i -= 1
return _NDPOptionIdentifier_name_0[_NDPOptionIdentifier_index_0[i]:_NDPOptionIdentifier_index_0[i+1]]
- case i == 25:
+ case i == 14:
return _NDPOptionIdentifier_name_1
+ case i == 25:
+ return _NDPOptionIdentifier_name_2
+ case i == 31:
+ return _NDPOptionIdentifier_name_3
default:
return "NDPOptionIdentifier(" + strconv.FormatInt(int64(i), 10) + ")"
}