diff options
author | Ghanan Gowripalan <ghanan@google.com> | 2021-03-16 11:07:02 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-03-16 11:09:26 -0700 |
commit | 68065d1ceb589b7ea1d3e4b3b067fb8772e30760 (patch) | |
tree | f3017f52fba725114b913cf893fcdcb6678415de /pkg/tcpip/header | |
parent | ebd7c1b889e5d212f4a694d3addbada241936e8e (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.go | 40 | ||||
-rw-r--r-- | pkg/tcpip/header/ndp_test.go | 679 | ||||
-rw-r--r-- | pkg/tcpip/header/ndpoptionidentifier_string.go | 14 |
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) + ")" } |