mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Support generating opaque interface identifiers as defined by RFC 7217
Support generating opaque interface identifiers as defined by RFC 7217 for auto-generated IPv6 link-local addresses. Opaque interface identifiers will also be used for IPv6 addresses auto-generated via SLAAC in a later change. Note, this change does not handle retries in response to DAD conflicts yet. That will also come in a later change. Tests: Test that when configured to generated opaque IIDs, they are properly generated as outlined by RFC 7217. PiperOrigin-RevId: 288035349
This commit is contained in:
committed by
gVisor bot
parent
1f384ac42b
commit
d1d878a801
@@ -44,6 +44,7 @@ go_test(
|
||||
],
|
||||
deps = [
|
||||
":header",
|
||||
"//pkg/rand",
|
||||
"//pkg/tcpip",
|
||||
"//pkg/tcpip/buffer",
|
||||
"@com_github_google_go-cmp//cmp:go_default_library",
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package header
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"strings"
|
||||
|
||||
@@ -102,6 +103,11 @@ const (
|
||||
// bytes including and after the IIDOffsetInIPv6Address-th byte are
|
||||
// for the IID.
|
||||
IIDOffsetInIPv6Address = 8
|
||||
|
||||
// OpaqueIIDSecretKeyMinBytes is the recommended minimum number of bytes
|
||||
// for the secret key used to generate an opaque interface identifier as
|
||||
// outlined by RFC 7217.
|
||||
OpaqueIIDSecretKeyMinBytes = 16
|
||||
)
|
||||
|
||||
// IPv6EmptySubnet is the empty IPv6 subnet. It may also be known as the
|
||||
@@ -326,3 +332,42 @@ func IsV6LinkLocalAddress(addr tcpip.Address) bool {
|
||||
}
|
||||
return addr[0] == 0xfe && (addr[1]&0xc0) == 0x80
|
||||
}
|
||||
|
||||
// AppendOpaqueInterfaceIdentifier appends a 64 bit opaque interface identifier
|
||||
// (IID) to buf as outlined by RFC 7217 and returns the extended buffer.
|
||||
//
|
||||
// The opaque IID is generated from the cryptographic hash of the concatenation
|
||||
// of the prefix, NIC's name, DAD counter (DAD retry counter) and the secret
|
||||
// key. The secret key SHOULD be at least OpaqueIIDSecretKeyMinBytes bytes and
|
||||
// MUST be generated to a pseudo-random number. See RFC 4086 for randomness
|
||||
// requirements for security.
|
||||
//
|
||||
// If buf has enough capacity for the IID (IIDSize bytes), a new underlying
|
||||
// array for the buffer will not be allocated.
|
||||
func AppendOpaqueInterfaceIdentifier(buf []byte, prefix tcpip.Subnet, nicName string, dadCounter uint8, secretKey []byte) []byte {
|
||||
// As per RFC 7217 section 5, the opaque identifier can be generated as a
|
||||
// cryptographic hash of the concatenation of each of the function parameters.
|
||||
// Note, we omit the optional Network_ID field.
|
||||
h := sha256.New()
|
||||
// h.Write never returns an error.
|
||||
h.Write([]byte(prefix.ID()[:IIDOffsetInIPv6Address]))
|
||||
h.Write([]byte(nicName))
|
||||
h.Write([]byte{dadCounter})
|
||||
h.Write(secretKey)
|
||||
|
||||
var sumBuf [sha256.Size]byte
|
||||
sum := h.Sum(sumBuf[:0])
|
||||
|
||||
return append(buf, sum[:IIDSize]...)
|
||||
}
|
||||
|
||||
// LinkLocalAddrWithOpaqueIID computes the default IPv6 link-local address with
|
||||
// an opaque IID.
|
||||
func LinkLocalAddrWithOpaqueIID(nicName string, dadCounter uint8, secretKey []byte) tcpip.Address {
|
||||
lladdrb := [IPv6AddressSize]byte{
|
||||
0: 0xFE,
|
||||
1: 0x80,
|
||||
}
|
||||
|
||||
return tcpip.Address(AppendOpaqueInterfaceIdentifier(lladdrb[:IIDOffsetInIPv6Address], IPv6LinkLocalPrefix.Subnet(), nicName, dadCounter, secretKey))
|
||||
}
|
||||
|
||||
@@ -15,9 +15,12 @@
|
||||
package header_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"gvisor.dev/gvisor/pkg/rand"
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/header"
|
||||
)
|
||||
@@ -43,3 +46,163 @@ func TestLinkLocalAddr(t *testing.T) {
|
||||
t.Errorf("got LinkLocalAddr(%s) = %s, want = %s", linkAddr, got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendOpaqueInterfaceIdentifier(t *testing.T) {
|
||||
var secretKeyBuf [header.OpaqueIIDSecretKeyMinBytes * 2]byte
|
||||
if n, err := rand.Read(secretKeyBuf[:]); err != nil {
|
||||
t.Fatalf("rand.Read(_): %s", err)
|
||||
} else if want := header.OpaqueIIDSecretKeyMinBytes * 2; n != want {
|
||||
t.Fatalf("expected rand.Read to read %d bytes, read %d bytes", want, n)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
prefix tcpip.Subnet
|
||||
nicName string
|
||||
dadCounter uint8
|
||||
secretKey []byte
|
||||
}{
|
||||
{
|
||||
name: "SecretKey of minimum size",
|
||||
prefix: header.IPv6LinkLocalPrefix.Subnet(),
|
||||
nicName: "eth0",
|
||||
dadCounter: 0,
|
||||
secretKey: secretKeyBuf[:header.OpaqueIIDSecretKeyMinBytes],
|
||||
},
|
||||
{
|
||||
name: "SecretKey of less than minimum size",
|
||||
prefix: func() tcpip.Subnet {
|
||||
addrWithPrefix := tcpip.AddressWithPrefix{
|
||||
Address: "\x01\x02\x03\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
|
||||
PrefixLen: header.IIDOffsetInIPv6Address * 8,
|
||||
}
|
||||
return addrWithPrefix.Subnet()
|
||||
}(),
|
||||
nicName: "eth10",
|
||||
dadCounter: 1,
|
||||
secretKey: secretKeyBuf[:header.OpaqueIIDSecretKeyMinBytes/2],
|
||||
},
|
||||
{
|
||||
name: "SecretKey of more than minimum size",
|
||||
prefix: func() tcpip.Subnet {
|
||||
addrWithPrefix := tcpip.AddressWithPrefix{
|
||||
Address: "\x01\x02\x03\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
|
||||
PrefixLen: header.IIDOffsetInIPv6Address * 8,
|
||||
}
|
||||
return addrWithPrefix.Subnet()
|
||||
}(),
|
||||
nicName: "eth11",
|
||||
dadCounter: 2,
|
||||
secretKey: secretKeyBuf[:header.OpaqueIIDSecretKeyMinBytes*2],
|
||||
},
|
||||
{
|
||||
name: "Nil SecretKey",
|
||||
prefix: func() tcpip.Subnet {
|
||||
addrWithPrefix := tcpip.AddressWithPrefix{
|
||||
Address: "\x01\x02\x03\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
|
||||
PrefixLen: header.IIDOffsetInIPv6Address * 8,
|
||||
}
|
||||
return addrWithPrefix.Subnet()
|
||||
}(),
|
||||
nicName: "eth12",
|
||||
dadCounter: 3,
|
||||
secretKey: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
h := sha256.New()
|
||||
h.Write([]byte(test.prefix.ID()[:header.IIDOffsetInIPv6Address]))
|
||||
h.Write([]byte(test.nicName))
|
||||
h.Write([]byte{test.dadCounter})
|
||||
if k := test.secretKey; k != nil {
|
||||
h.Write(k)
|
||||
}
|
||||
var hashSum [sha256.Size]byte
|
||||
h.Sum(hashSum[:0])
|
||||
want := hashSum[:header.IIDSize]
|
||||
|
||||
// Passing a nil buffer should result in a new buffer returned with the
|
||||
// IID.
|
||||
if got := header.AppendOpaqueInterfaceIdentifier(nil, test.prefix, test.nicName, test.dadCounter, test.secretKey); !bytes.Equal(got, want) {
|
||||
t.Errorf("got AppendOpaqueInterfaceIdentifier(nil, %s, %s, %d, %x) = %x, want = %x", test.prefix, test.nicName, test.dadCounter, test.secretKey, got, want)
|
||||
}
|
||||
|
||||
// Passing a buffer with sufficient capacity for the IID should populate
|
||||
// the buffer provided.
|
||||
var iidBuf [header.IIDSize]byte
|
||||
if got := header.AppendOpaqueInterfaceIdentifier(iidBuf[:0], test.prefix, test.nicName, test.dadCounter, test.secretKey); !bytes.Equal(got, want) {
|
||||
t.Errorf("got AppendOpaqueInterfaceIdentifier(iidBuf[:0], %s, %s, %d, %x) = %x, want = %x", test.prefix, test.nicName, test.dadCounter, test.secretKey, got, want)
|
||||
}
|
||||
if got := iidBuf[:]; !bytes.Equal(got, want) {
|
||||
t.Errorf("got iidBuf = %x, want = %x", got, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLinkLocalAddrWithOpaqueIID(t *testing.T) {
|
||||
var secretKeyBuf [header.OpaqueIIDSecretKeyMinBytes * 2]byte
|
||||
if n, err := rand.Read(secretKeyBuf[:]); err != nil {
|
||||
t.Fatalf("rand.Read(_): %s", err)
|
||||
} else if want := header.OpaqueIIDSecretKeyMinBytes * 2; n != want {
|
||||
t.Fatalf("expected rand.Read to read %d bytes, read %d bytes", want, n)
|
||||
}
|
||||
|
||||
prefix := header.IPv6LinkLocalPrefix.Subnet()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
prefix tcpip.Subnet
|
||||
nicName string
|
||||
dadCounter uint8
|
||||
secretKey []byte
|
||||
}{
|
||||
{
|
||||
name: "SecretKey of minimum size",
|
||||
nicName: "eth0",
|
||||
dadCounter: 0,
|
||||
secretKey: secretKeyBuf[:header.OpaqueIIDSecretKeyMinBytes],
|
||||
},
|
||||
{
|
||||
name: "SecretKey of less than minimum size",
|
||||
nicName: "eth10",
|
||||
dadCounter: 1,
|
||||
secretKey: secretKeyBuf[:header.OpaqueIIDSecretKeyMinBytes/2],
|
||||
},
|
||||
{
|
||||
name: "SecretKey of more than minimum size",
|
||||
nicName: "eth11",
|
||||
dadCounter: 2,
|
||||
secretKey: secretKeyBuf[:header.OpaqueIIDSecretKeyMinBytes*2],
|
||||
},
|
||||
{
|
||||
name: "Nil SecretKey",
|
||||
nicName: "eth12",
|
||||
dadCounter: 3,
|
||||
secretKey: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
addrBytes := [header.IPv6AddressSize]byte{
|
||||
0: 0xFE,
|
||||
1: 0x80,
|
||||
}
|
||||
|
||||
want := tcpip.Address(header.AppendOpaqueInterfaceIdentifier(
|
||||
addrBytes[:header.IIDOffsetInIPv6Address],
|
||||
prefix,
|
||||
test.nicName,
|
||||
test.dadCounter,
|
||||
test.secretKey,
|
||||
))
|
||||
|
||||
if got := header.LinkLocalAddrWithOpaqueIID(test.nicName, test.dadCounter, test.secretKey); got != want {
|
||||
t.Errorf("got LinkLocalAddrWithOpaqueIID(%s, %d, %x) = %s, want = %s", test.nicName, test.dadCounter, test.secretKey, got, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ go_test(
|
||||
],
|
||||
deps = [
|
||||
":stack",
|
||||
"//pkg/rand",
|
||||
"//pkg/tcpip",
|
||||
"//pkg/tcpip/buffer",
|
||||
"//pkg/tcpip/checker",
|
||||
|
||||
+15
-11
@@ -178,20 +178,24 @@ func (n *NIC) enable() *tcpip.Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
l2addr := n.linkEP.LinkAddress()
|
||||
var addr tcpip.Address
|
||||
if oIID := n.stack.opaqueIIDOpts; oIID.NICNameFromID != nil {
|
||||
addr = header.LinkLocalAddrWithOpaqueIID(oIID.NICNameFromID(n.ID()), 0, oIID.SecretKey)
|
||||
} else {
|
||||
l2addr := n.linkEP.LinkAddress()
|
||||
|
||||
// Only attempt to generate the link-local address if we have a
|
||||
// valid MAC address.
|
||||
//
|
||||
// TODO(b/141011931): Validate a LinkEndpoint's link address
|
||||
// (provided by LinkEndpoint.LinkAddress) before reaching this
|
||||
// point.
|
||||
if !header.IsValidUnicastEthernetAddress(l2addr) {
|
||||
return nil
|
||||
// Only attempt to generate the link-local address if we have a valid MAC
|
||||
// address.
|
||||
//
|
||||
// TODO(b/141011931): Validate a LinkEndpoint's link address (provided by
|
||||
// LinkEndpoint.LinkAddress) before reaching this point.
|
||||
if !header.IsValidUnicastEthernetAddress(l2addr) {
|
||||
return nil
|
||||
}
|
||||
|
||||
addr = header.LinkLocalAddr(l2addr)
|
||||
}
|
||||
|
||||
addr := header.LinkLocalAddr(l2addr)
|
||||
|
||||
_, err := n.addPermanentAddressLocked(tcpip.ProtocolAddress{
|
||||
Protocol: header.IPv6ProtocolNumber,
|
||||
AddressWithPrefix: tcpip.AddressWithPrefix{
|
||||
|
||||
@@ -352,6 +352,33 @@ func (u *uniqueIDGenerator) UniqueID() uint64 {
|
||||
return atomic.AddUint64((*uint64)(u), 1)
|
||||
}
|
||||
|
||||
// NICNameFromID is a function that returns a stable name for the specified NIC,
|
||||
// even if the NIC ID changes over time.
|
||||
type NICNameFromID func(tcpip.NICID) string
|
||||
|
||||
// OpaqueInterfaceIdentifierOptions holds the options related to the generation
|
||||
// of opaque interface indentifiers (IIDs) as defined by RFC 7217.
|
||||
type OpaqueInterfaceIdentifierOptions struct {
|
||||
// NICNameFromID is a function that returns a stable name for a specified NIC,
|
||||
// even if the NIC ID changes over time.
|
||||
//
|
||||
// Must be specified to generate the opaque IID.
|
||||
NICNameFromID NICNameFromID
|
||||
|
||||
// SecretKey is a pseudo-random number used as the secret key when generating
|
||||
// opaque IIDs as defined by RFC 7217. The key SHOULD be at least
|
||||
// header.OpaqueIIDSecretKeyMinBytes bytes and MUST follow minimum randomness
|
||||
// requirements for security as outlined by RFC 4086. SecretKey MUST NOT
|
||||
// change between program runs, unless explicitly changed.
|
||||
//
|
||||
// OpaqueInterfaceIdentifierOptions takes ownership of SecretKey. SecretKey
|
||||
// MUST NOT be modified after Stack is created.
|
||||
//
|
||||
// May be nil, but a nil value is highly discouraged to maintain
|
||||
// some level of randomness between nodes.
|
||||
SecretKey []byte
|
||||
}
|
||||
|
||||
// Stack is a networking stack, with all supported protocols, NICs, and route
|
||||
// table.
|
||||
type Stack struct {
|
||||
@@ -422,6 +449,10 @@ type Stack struct {
|
||||
|
||||
// uniqueIDGenerator is a generator of unique identifiers.
|
||||
uniqueIDGenerator UniqueID
|
||||
|
||||
// opaqueIIDOpts hold the options for generating opaque interface identifiers
|
||||
// (IIDs) as outlined by RFC 7217.
|
||||
opaqueIIDOpts OpaqueInterfaceIdentifierOptions
|
||||
}
|
||||
|
||||
// UniqueID is an abstract generator of unique identifiers.
|
||||
@@ -479,6 +510,10 @@ type Options struct {
|
||||
// RawFactory produces raw endpoints. Raw endpoints are enabled only if
|
||||
// this is non-nil.
|
||||
RawFactory RawFactory
|
||||
|
||||
// OpaqueIIDOpts hold the options for generating opaque interface identifiers
|
||||
// (IIDs) as outlined by RFC 7217.
|
||||
OpaqueIIDOpts OpaqueInterfaceIdentifierOptions
|
||||
}
|
||||
|
||||
// TransportEndpointInfo holds useful information about a transport endpoint
|
||||
@@ -549,6 +584,7 @@ func New(opts Options) *Stack {
|
||||
autoGenIPv6LinkLocal: opts.AutoGenIPv6LinkLocal,
|
||||
uniqueIDGenerator: opts.UniqueID,
|
||||
ndpDisp: opts.NDPDisp,
|
||||
opaqueIIDOpts: opts.OpaqueIIDOpts,
|
||||
}
|
||||
|
||||
// Add specified network protocols.
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"gvisor.dev/gvisor/pkg/rand"
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/buffer"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/header"
|
||||
@@ -1894,55 +1895,67 @@ func TestNICForwarding(t *testing.T) {
|
||||
}
|
||||
|
||||
// TestNICAutoGenAddr tests the auto-generation of IPv6 link-local addresses
|
||||
// (or lack there-of if disabled (default)). Note, DAD will be disabled in
|
||||
// these tests.
|
||||
// using the modified EUI-64 of the NIC's MAC address (or lack there-of if
|
||||
// disabled (default)). Note, DAD will be disabled in these tests.
|
||||
func TestNICAutoGenAddr(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
autoGen bool
|
||||
linkAddr tcpip.LinkAddress
|
||||
iidOpts stack.OpaqueInterfaceIdentifierOptions
|
||||
shouldGen bool
|
||||
}{
|
||||
{
|
||||
"Disabled",
|
||||
false,
|
||||
linkAddr1,
|
||||
stack.OpaqueInterfaceIdentifierOptions{
|
||||
NICNameFromID: func(nicID tcpip.NICID) string {
|
||||
return fmt.Sprintf("nic%d", nicID)
|
||||
},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"Enabled",
|
||||
true,
|
||||
linkAddr1,
|
||||
stack.OpaqueInterfaceIdentifierOptions{},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"Nil MAC",
|
||||
true,
|
||||
tcpip.LinkAddress([]byte(nil)),
|
||||
stack.OpaqueInterfaceIdentifierOptions{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"Empty MAC",
|
||||
true,
|
||||
tcpip.LinkAddress(""),
|
||||
stack.OpaqueInterfaceIdentifierOptions{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"Invalid MAC",
|
||||
true,
|
||||
tcpip.LinkAddress("\x01\x02\x03"),
|
||||
stack.OpaqueInterfaceIdentifierOptions{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"Multicast MAC",
|
||||
true,
|
||||
tcpip.LinkAddress("\x01\x02\x03\x04\x05\x06"),
|
||||
stack.OpaqueInterfaceIdentifierOptions{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"Unspecified MAC",
|
||||
true,
|
||||
tcpip.LinkAddress("\x00\x00\x00\x00\x00\x00"),
|
||||
stack.OpaqueInterfaceIdentifierOptions{},
|
||||
false,
|
||||
},
|
||||
}
|
||||
@@ -1951,6 +1964,112 @@ func TestNICAutoGenAddr(t *testing.T) {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
opts := stack.Options{
|
||||
NetworkProtocols: []stack.NetworkProtocol{ipv6.NewProtocol()},
|
||||
OpaqueIIDOpts: test.iidOpts,
|
||||
}
|
||||
|
||||
if test.autoGen {
|
||||
// Only set opts.AutoGenIPv6LinkLocal when test.autoGen is true because
|
||||
// opts.AutoGenIPv6LinkLocal should be false by default.
|
||||
opts.AutoGenIPv6LinkLocal = true
|
||||
}
|
||||
|
||||
e := channel.New(10, 1280, test.linkAddr)
|
||||
s := stack.New(opts)
|
||||
if err := s.CreateNIC(1, e); err != nil {
|
||||
t.Fatalf("CreateNIC(_) = %s", err)
|
||||
}
|
||||
|
||||
addr, err := s.GetMainNICAddress(1, header.IPv6ProtocolNumber)
|
||||
if err != nil {
|
||||
t.Fatalf("stack.GetMainNICAddress(_, _) err = %s", err)
|
||||
}
|
||||
|
||||
if test.shouldGen {
|
||||
// Should have auto-generated an address and resolved immediately (DAD
|
||||
// is disabled).
|
||||
if want := (tcpip.AddressWithPrefix{Address: header.LinkLocalAddr(test.linkAddr), PrefixLen: header.IPv6LinkLocalPrefix.PrefixLen}); addr != want {
|
||||
t.Fatalf("got stack.GetMainNICAddress(_, _) = %s, want = %s", addr, want)
|
||||
}
|
||||
} else {
|
||||
// Should not have auto-generated an address.
|
||||
if want := (tcpip.AddressWithPrefix{}); addr != want {
|
||||
t.Fatalf("got stack.GetMainNICAddress(_, _) = (%s, nil), want = (%s, nil)", addr, want)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestNICAutoGenAddrWithOpaque tests the auto-generation of IPv6 link-local
|
||||
// addresses with opaque interface identifiers. Link Local addresses should
|
||||
// always be generated with opaque IIDs if configured to use them, even if the
|
||||
// NIC has an invalid MAC address.
|
||||
func TestNICAutoGenAddrWithOpaque(t *testing.T) {
|
||||
var secretKey [header.OpaqueIIDSecretKeyMinBytes]byte
|
||||
n, err := rand.Read(secretKey[:])
|
||||
if err != nil {
|
||||
t.Fatalf("rand.Read(_): %s", err)
|
||||
}
|
||||
if n != header.OpaqueIIDSecretKeyMinBytes {
|
||||
t.Fatalf("expected rand.Read to read %d bytes, read %d bytes", header.OpaqueIIDSecretKeyMinBytes, n)
|
||||
}
|
||||
|
||||
iidOpts := stack.OpaqueInterfaceIdentifierOptions{
|
||||
NICNameFromID: func(nicID tcpip.NICID) string {
|
||||
return fmt.Sprintf("nic%d", nicID)
|
||||
},
|
||||
SecretKey: secretKey[:],
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
autoGen bool
|
||||
linkAddr tcpip.LinkAddress
|
||||
}{
|
||||
{
|
||||
"Disabled",
|
||||
false,
|
||||
linkAddr1,
|
||||
},
|
||||
{
|
||||
"Enabled",
|
||||
true,
|
||||
linkAddr1,
|
||||
},
|
||||
// These are all cases where we would not have generated a
|
||||
// link-local address if opaque IIDs were disabled.
|
||||
{
|
||||
"Nil MAC",
|
||||
true,
|
||||
tcpip.LinkAddress([]byte(nil)),
|
||||
},
|
||||
{
|
||||
"Empty MAC",
|
||||
true,
|
||||
tcpip.LinkAddress(""),
|
||||
},
|
||||
{
|
||||
"Invalid MAC",
|
||||
true,
|
||||
tcpip.LinkAddress("\x01\x02\x03"),
|
||||
},
|
||||
{
|
||||
"Multicast MAC",
|
||||
true,
|
||||
tcpip.LinkAddress("\x01\x02\x03\x04\x05\x06"),
|
||||
},
|
||||
{
|
||||
"Unspecified MAC",
|
||||
true,
|
||||
tcpip.LinkAddress("\x00\x00\x00\x00\x00\x00"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
opts := stack.Options{
|
||||
NetworkProtocols: []stack.NetworkProtocol{ipv6.NewProtocol()},
|
||||
OpaqueIIDOpts: iidOpts,
|
||||
}
|
||||
|
||||
if test.autoGen {
|
||||
@@ -1972,10 +2091,10 @@ func TestNICAutoGenAddr(t *testing.T) {
|
||||
t.Fatalf("stack.GetMainNICAddress(_, _) err = %s", err)
|
||||
}
|
||||
|
||||
if test.shouldGen {
|
||||
if test.autoGen {
|
||||
// Should have auto-generated an address and
|
||||
// resolved immediately (DAD is disabled).
|
||||
if want := (tcpip.AddressWithPrefix{Address: header.LinkLocalAddr(test.linkAddr), PrefixLen: header.IPv6LinkLocalPrefix.PrefixLen}); addr != want {
|
||||
if want := (tcpip.AddressWithPrefix{Address: header.LinkLocalAddrWithOpaqueIID("nic1", 0, secretKey[:]), PrefixLen: header.IPv6LinkLocalPrefix.PrefixLen}); addr != want {
|
||||
t.Fatalf("got stack.GetMainNICAddress(_, _) = %s, want = %s", addr, want)
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user