Update link address for targets of Neighbor Adverts

Get the link address for the target of an NDP Neighbor Advertisement
from the NDP Target Link Layer Address option.

Tests:
- ipv6.TestNeighorAdvertisementWithTargetLinkLayerOption
- ipv6.TestNeighorAdvertisementWithInvalidTargetLinkLayerOption
PiperOrigin-RevId: 293632609
This commit is contained in:
Ghanan Gowripalan
2020-02-06 11:13:29 -08:00
committed by gVisor bot
parent 0e96fcafd4
commit 6bd59b4e08
4 changed files with 352 additions and 164 deletions
+35 -9
View File
@@ -15,6 +15,8 @@
package ipv6
import (
"log"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/buffer"
"gvisor.dev/gvisor/pkg/tcpip/header"
@@ -194,7 +196,11 @@ func (e *endpoint) handleICMP(r *stack.Route, netHeader buffer.View, pkt tcpip.P
// TODO(b/148429853): Properly process the NS message and do Neighbor
// Unreachability Detection.
for {
opt, done, _ := it.Next()
opt, done, err := it.Next()
if err != nil {
// This should never happen as Iter(true) above did not return an error.
log.Fatalf("unexpected error when iterating over NDP options: %s", err)
}
if done {
break
}
@@ -253,21 +259,25 @@ func (e *endpoint) handleICMP(r *stack.Route, netHeader buffer.View, pkt tcpip.P
}
na := header.NDPNeighborAdvert(h.NDPPayload())
it, err := na.Options().Iter(true)
if err != nil {
// If we have a malformed NDP NA option, drop the packet.
received.Invalid.Increment()
return
}
targetAddr := na.TargetAddress()
stack := r.Stack()
rxNICID := r.NICID()
isTentative, err := stack.IsAddrTentative(rxNICID, targetAddr)
if err != nil {
if isTentative, err := stack.IsAddrTentative(rxNICID, targetAddr); err != nil {
// We will only get an error if rxNICID is unrecognized,
// which should not happen. For now short-circuit this
// packet.
//
// TODO(b/141002840): Handle this better?
return
}
if isTentative {
} else if isTentative {
// We just got an NA from a node that owns an address we
// are performing DAD on, implying the address is not
// unique. In this case we let the stack know so it can
@@ -283,13 +293,29 @@ func (e *endpoint) handleICMP(r *stack.Route, netHeader buffer.View, pkt tcpip.P
// scenario is beyond the scope of RFC 4862. As such, we simply
// ignore such a scenario for now and proceed as normal.
//
// If the NA message has the target link layer option, update the link
// address cache with the link address for the target of the message.
//
// TODO(b/143147598): Handle the scenario described above. Also
// inform the netstack integration that a duplicate address was
// detected outside of DAD.
//
// TODO(b/148429853): Properly process the NA message and do Neighbor
// Unreachability Detection.
for {
opt, done, err := it.Next()
if err != nil {
// This should never happen as Iter(true) above did not return an error.
log.Fatalf("unexpected error when iterating over NDP options: %s", err)
}
if done {
break
}
e.linkAddrCache.AddLinkAddress(e.nicID, targetAddr, r.RemoteLinkAddress)
if targetAddr != r.RemoteAddress {
e.linkAddrCache.AddLinkAddress(e.nicID, r.RemoteAddress, r.RemoteLinkAddress)
switch opt := opt.(type) {
case header.NDPTargetLinkLayerAddressOption:
e.linkAddrCache.AddLinkAddress(e.nicID, targetAddr, opt.EthernetAddress())
}
}
case header.ICMPv6EchoRequest:
+119 -67
View File
@@ -121,21 +121,60 @@ func TestICMPCounts(t *testing.T) {
}
defer r.Release()
var tllData [header.NDPLinkLayerAddressSize]byte
header.NDPOptions(tllData[:]).Serialize(header.NDPOptionsSerializer{
header.NDPTargetLinkLayerAddressOption(linkAddr1),
})
types := []struct {
typ header.ICMPv6Type
size int
typ header.ICMPv6Type
size int
extraData []byte
}{
{header.ICMPv6DstUnreachable, header.ICMPv6DstUnreachableMinimumSize},
{header.ICMPv6PacketTooBig, header.ICMPv6PacketTooBigMinimumSize},
{header.ICMPv6TimeExceeded, header.ICMPv6MinimumSize},
{header.ICMPv6ParamProblem, header.ICMPv6MinimumSize},
{header.ICMPv6EchoRequest, header.ICMPv6EchoMinimumSize},
{header.ICMPv6EchoReply, header.ICMPv6EchoMinimumSize},
{header.ICMPv6RouterSolicit, header.ICMPv6MinimumSize},
{header.ICMPv6RouterAdvert, header.ICMPv6HeaderSize + header.NDPRAMinimumSize},
{header.ICMPv6NeighborSolicit, header.ICMPv6NeighborSolicitMinimumSize},
{header.ICMPv6NeighborAdvert, header.ICMPv6NeighborAdvertSize},
{header.ICMPv6RedirectMsg, header.ICMPv6MinimumSize},
{
typ: header.ICMPv6DstUnreachable,
size: header.ICMPv6DstUnreachableMinimumSize,
},
{
typ: header.ICMPv6PacketTooBig,
size: header.ICMPv6PacketTooBigMinimumSize,
},
{
typ: header.ICMPv6TimeExceeded,
size: header.ICMPv6MinimumSize,
},
{
typ: header.ICMPv6ParamProblem,
size: header.ICMPv6MinimumSize,
},
{
typ: header.ICMPv6EchoRequest,
size: header.ICMPv6EchoMinimumSize,
},
{
typ: header.ICMPv6EchoReply,
size: header.ICMPv6EchoMinimumSize,
},
{
typ: header.ICMPv6RouterSolicit,
size: header.ICMPv6MinimumSize,
},
{
typ: header.ICMPv6RouterAdvert,
size: header.ICMPv6HeaderSize + header.NDPRAMinimumSize,
},
{
typ: header.ICMPv6NeighborSolicit,
size: header.ICMPv6NeighborSolicitMinimumSize},
{
typ: header.ICMPv6NeighborAdvert,
size: header.ICMPv6NeighborAdvertMinimumSize,
extraData: tllData[:],
},
{
typ: header.ICMPv6RedirectMsg,
size: header.ICMPv6MinimumSize,
},
}
handleIPv6Payload := func(hdr buffer.Prependable) {
@@ -154,10 +193,13 @@ func TestICMPCounts(t *testing.T) {
}
for _, typ := range types {
hdr := buffer.NewPrependable(header.IPv6MinimumSize + typ.size)
extraDataLen := len(typ.extraData)
hdr := buffer.NewPrependable(header.IPv6MinimumSize + typ.size + extraDataLen)
extraData := buffer.View(hdr.Prepend(extraDataLen))
copy(extraData, typ.extraData)
pkt := header.ICMPv6(hdr.Prepend(typ.size))
pkt.SetType(typ.typ)
pkt.SetChecksum(header.ICMPv6Checksum(pkt, r.LocalAddress, r.RemoteAddress, buffer.VectorisedView{}))
pkt.SetChecksum(header.ICMPv6Checksum(pkt, r.LocalAddress, r.RemoteAddress, extraData.ToVectorisedView()))
handleIPv6Payload(hdr)
}
@@ -372,97 +414,104 @@ func TestLinkResolution(t *testing.T) {
}
func TestICMPChecksumValidationSimple(t *testing.T) {
var tllData [header.NDPLinkLayerAddressSize]byte
header.NDPOptions(tllData[:]).Serialize(header.NDPOptionsSerializer{
header.NDPTargetLinkLayerAddressOption(linkAddr1),
})
types := []struct {
name string
typ header.ICMPv6Type
size int
extraData []byte
statCounter func(tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter
}{
{
"DstUnreachable",
header.ICMPv6DstUnreachable,
header.ICMPv6DstUnreachableMinimumSize,
func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
name: "DstUnreachable",
typ: header.ICMPv6DstUnreachable,
size: header.ICMPv6DstUnreachableMinimumSize,
statCounter: func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
return stats.DstUnreachable
},
},
{
"PacketTooBig",
header.ICMPv6PacketTooBig,
header.ICMPv6PacketTooBigMinimumSize,
func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
name: "PacketTooBig",
typ: header.ICMPv6PacketTooBig,
size: header.ICMPv6PacketTooBigMinimumSize,
statCounter: func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
return stats.PacketTooBig
},
},
{
"TimeExceeded",
header.ICMPv6TimeExceeded,
header.ICMPv6MinimumSize,
func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
name: "TimeExceeded",
typ: header.ICMPv6TimeExceeded,
size: header.ICMPv6MinimumSize,
statCounter: func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
return stats.TimeExceeded
},
},
{
"ParamProblem",
header.ICMPv6ParamProblem,
header.ICMPv6MinimumSize,
func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
name: "ParamProblem",
typ: header.ICMPv6ParamProblem,
size: header.ICMPv6MinimumSize,
statCounter: func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
return stats.ParamProblem
},
},
{
"EchoRequest",
header.ICMPv6EchoRequest,
header.ICMPv6EchoMinimumSize,
func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
name: "EchoRequest",
typ: header.ICMPv6EchoRequest,
size: header.ICMPv6EchoMinimumSize,
statCounter: func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
return stats.EchoRequest
},
},
{
"EchoReply",
header.ICMPv6EchoReply,
header.ICMPv6EchoMinimumSize,
func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
name: "EchoReply",
typ: header.ICMPv6EchoReply,
size: header.ICMPv6EchoMinimumSize,
statCounter: func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
return stats.EchoReply
},
},
{
"RouterSolicit",
header.ICMPv6RouterSolicit,
header.ICMPv6MinimumSize,
func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
name: "RouterSolicit",
typ: header.ICMPv6RouterSolicit,
size: header.ICMPv6MinimumSize,
statCounter: func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
return stats.RouterSolicit
},
},
{
"RouterAdvert",
header.ICMPv6RouterAdvert,
header.ICMPv6HeaderSize + header.NDPRAMinimumSize,
func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
name: "RouterAdvert",
typ: header.ICMPv6RouterAdvert,
size: header.ICMPv6HeaderSize + header.NDPRAMinimumSize,
statCounter: func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
return stats.RouterAdvert
},
},
{
"NeighborSolicit",
header.ICMPv6NeighborSolicit,
header.ICMPv6NeighborSolicitMinimumSize,
func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
name: "NeighborSolicit",
typ: header.ICMPv6NeighborSolicit,
size: header.ICMPv6NeighborSolicitMinimumSize,
statCounter: func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
return stats.NeighborSolicit
},
},
{
"NeighborAdvert",
header.ICMPv6NeighborAdvert,
header.ICMPv6NeighborAdvertSize,
func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
name: "NeighborAdvert",
typ: header.ICMPv6NeighborAdvert,
size: header.ICMPv6NeighborAdvertMinimumSize,
extraData: tllData[:],
statCounter: func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
return stats.NeighborAdvert
},
},
{
"RedirectMsg",
header.ICMPv6RedirectMsg,
header.ICMPv6MinimumSize,
func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
name: "RedirectMsg",
typ: header.ICMPv6RedirectMsg,
size: header.ICMPv6MinimumSize,
statCounter: func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
return stats.RedirectMsg
},
},
@@ -494,16 +543,19 @@ func TestICMPChecksumValidationSimple(t *testing.T) {
)
}
handleIPv6Payload := func(typ header.ICMPv6Type, size int, checksum bool) {
hdr := buffer.NewPrependable(header.IPv6MinimumSize + size)
pkt := header.ICMPv6(hdr.Prepend(size))
pkt.SetType(typ)
handleIPv6Payload := func(checksum bool) {
extraDataLen := len(typ.extraData)
hdr := buffer.NewPrependable(header.IPv6MinimumSize + typ.size + extraDataLen)
extraData := buffer.View(hdr.Prepend(extraDataLen))
copy(extraData, typ.extraData)
pkt := header.ICMPv6(hdr.Prepend(typ.size))
pkt.SetType(typ.typ)
if checksum {
pkt.SetChecksum(header.ICMPv6Checksum(pkt, lladdr1, lladdr0, buffer.VectorisedView{}))
pkt.SetChecksum(header.ICMPv6Checksum(pkt, lladdr1, lladdr0, extraData.ToVectorisedView()))
}
ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize))
ip.Encode(&header.IPv6Fields{
PayloadLength: uint16(size),
PayloadLength: uint16(typ.size + extraDataLen),
NextHeader: uint8(header.ICMPv6ProtocolNumber),
HopLimit: header.NDPHopLimit,
SrcAddr: lladdr1,
@@ -528,7 +580,7 @@ func TestICMPChecksumValidationSimple(t *testing.T) {
// Without setting checksum, the incoming packet should
// be invalid.
handleIPv6Payload(typ.typ, typ.size, false)
handleIPv6Payload(false)
if got := invalid.Value(); got != 1 {
t.Fatalf("got invalid = %d, want = 1", got)
}
@@ -538,7 +590,7 @@ func TestICMPChecksumValidationSimple(t *testing.T) {
}
// When checksum is set, it should be received.
handleIPv6Payload(typ.typ, typ.size, true)
handleIPv6Payload(true)
if got := typStat.Value(); got != 1 {
t.Fatalf("got %s = %d, want = 1", typ.name, got)
}
+192 -86
View File
@@ -70,76 +70,29 @@ func setupStackAndEndpoint(t *testing.T, llladdr, rlladdr tcpip.Address) (*stack
return s, ep
}
// TestNeighorSolicitationWithSourceLinkLayerOption tests that receiving an
// NDP NS message with the Source Link Layer Address option results in a
// TestNeighorSolicitationWithSourceLinkLayerOption tests that receiving a
// valid NDP NS message with the Source Link Layer Address option results in a
// new entry in the link address cache for the sender of the message.
func TestNeighorSolicitationWithSourceLinkLayerOption(t *testing.T) {
const nicID = 1
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocol{NewProtocol()},
})
e := channel.New(0, 1280, linkAddr0)
if err := s.CreateNIC(nicID, e); err != nil {
t.Fatalf("CreateNIC(%d, _) = %s", nicID, err)
}
if err := s.AddAddress(nicID, ProtocolNumber, lladdr0); err != nil {
t.Fatalf("AddAddress(%d, %d, %s) = %s", nicID, ProtocolNumber, lladdr0, err)
}
ndpNSSize := header.ICMPv6NeighborSolicitMinimumSize + header.NDPLinkLayerAddressSize
hdr := buffer.NewPrependable(header.IPv6MinimumSize + ndpNSSize)
pkt := header.ICMPv6(hdr.Prepend(ndpNSSize))
pkt.SetType(header.ICMPv6NeighborSolicit)
ns := header.NDPNeighborSolicit(pkt.NDPPayload())
ns.SetTargetAddress(lladdr0)
ns.Options().Serialize(header.NDPOptionsSerializer{
header.NDPSourceLinkLayerAddressOption(linkAddr1),
})
pkt.SetChecksum(header.ICMPv6Checksum(pkt, lladdr1, lladdr0, buffer.VectorisedView{}))
payloadLength := hdr.UsedLength()
ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize))
ip.Encode(&header.IPv6Fields{
PayloadLength: uint16(payloadLength),
NextHeader: uint8(header.ICMPv6ProtocolNumber),
HopLimit: 255,
SrcAddr: lladdr1,
DstAddr: lladdr0,
})
e.InjectInbound(ProtocolNumber, tcpip.PacketBuffer{
Data: hdr.View().ToVectorisedView(),
})
linkAddr, c, err := s.GetLinkAddress(nicID, lladdr1, lladdr0, ProtocolNumber, nil)
if err != nil {
t.Errorf("s.GetLinkAddress(%d, %s, %s, %d, nil): %s", nicID, lladdr1, lladdr0, ProtocolNumber, err)
}
if c != nil {
t.Errorf("got unexpected channel")
}
if linkAddr != linkAddr1 {
t.Errorf("got link address = %s, want = %s", linkAddr, linkAddr1)
}
}
// TestNeighorSolicitationWithInvalidSourceLinkLayerOption tests that receiving
// an NDP NS message with an invalid Source Link Layer Address option does not
// result in a new entry in the link address cache for the sender of the
// message.
func TestNeighorSolicitationWithInvalidSourceLinkLayerOption(t *testing.T) {
const nicID = 1
tests := []struct {
name string
optsBuf []byte
name string
optsBuf []byte
expectedLinkAddr tcpip.LinkAddress
}{
{
name: "Valid",
optsBuf: []byte{1, 1, 2, 3, 4, 5, 6, 7},
expectedLinkAddr: "\x02\x03\x04\x05\x06\x07",
},
{
name: "Too Small",
optsBuf: []byte{1, 1, 1, 2, 3, 4, 5},
optsBuf: []byte{1, 1, 2, 3, 4, 5, 6},
},
{
name: "Invalid Length",
optsBuf: []byte{1, 2, 1, 2, 3, 4, 5, 6},
optsBuf: []byte{1, 2, 2, 3, 4, 5, 6, 7},
},
}
@@ -186,20 +139,138 @@ func TestNeighorSolicitationWithInvalidSourceLinkLayerOption(t *testing.T) {
Data: hdr.View().ToVectorisedView(),
})
// Invalid count should have increased.
if got := invalid.Value(); got != 1 {
t.Fatalf("got invalid = %d, want = 1", got)
linkAddr, c, err := s.GetLinkAddress(nicID, lladdr1, lladdr0, ProtocolNumber, nil)
if linkAddr != test.expectedLinkAddr {
t.Errorf("got link address = %s, want = %s", linkAddr, test.expectedLinkAddr)
}
if test.expectedLinkAddr != "" {
if err != nil {
t.Errorf("s.GetLinkAddress(%d, %s, %s, %d, nil): %s", nicID, lladdr1, lladdr0, ProtocolNumber, err)
}
if c != nil {
t.Errorf("got unexpected channel")
}
// Invalid count should not have increased.
if got := invalid.Value(); got != 0 {
t.Errorf("got invalid = %d, want = 0", got)
}
} else {
if err != tcpip.ErrWouldBlock {
t.Errorf("got s.GetLinkAddress(%d, %s, %s, %d, nil) = (_, _, %v), want = (_, _, %s)", nicID, lladdr1, lladdr0, ProtocolNumber, err, tcpip.ErrWouldBlock)
}
if c == nil {
t.Errorf("expected channel from call to s.GetLinkAddress(%d, %s, %s, %d, nil)", nicID, lladdr1, lladdr0, ProtocolNumber)
}
// Invalid count should have increased.
if got := invalid.Value(); got != 1 {
t.Errorf("got invalid = %d, want = 1", got)
}
}
})
}
}
// TestNeighorAdvertisementWithTargetLinkLayerOption tests that receiving a
// valid NDP NA message with the Target Link Layer Address option results in a
// new entry in the link address cache for the target of the message.
func TestNeighorAdvertisementWithTargetLinkLayerOption(t *testing.T) {
const nicID = 1
tests := []struct {
name string
optsBuf []byte
expectedLinkAddr tcpip.LinkAddress
}{
{
name: "Valid",
optsBuf: []byte{2, 1, 2, 3, 4, 5, 6, 7},
expectedLinkAddr: "\x02\x03\x04\x05\x06\x07",
},
{
name: "Too Small",
optsBuf: []byte{2, 1, 2, 3, 4, 5, 6},
},
{
name: "Invalid Length",
optsBuf: []byte{2, 2, 2, 3, 4, 5, 6, 7},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocol{NewProtocol()},
})
e := channel.New(0, 1280, linkAddr0)
if err := s.CreateNIC(nicID, e); err != nil {
t.Fatalf("CreateNIC(%d, _) = %s", nicID, err)
}
if err := s.AddAddress(nicID, ProtocolNumber, lladdr0); err != nil {
t.Fatalf("AddAddress(%d, %d, %s) = %s", nicID, ProtocolNumber, lladdr0, err)
}
ndpNASize := header.ICMPv6NeighborAdvertMinimumSize + len(test.optsBuf)
hdr := buffer.NewPrependable(header.IPv6MinimumSize + ndpNASize)
pkt := header.ICMPv6(hdr.Prepend(ndpNASize))
pkt.SetType(header.ICMPv6NeighborAdvert)
ns := header.NDPNeighborAdvert(pkt.NDPPayload())
ns.SetTargetAddress(lladdr1)
opts := ns.Options()
copy(opts, test.optsBuf)
pkt.SetChecksum(header.ICMPv6Checksum(pkt, lladdr1, lladdr0, buffer.VectorisedView{}))
payloadLength := hdr.UsedLength()
ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize))
ip.Encode(&header.IPv6Fields{
PayloadLength: uint16(payloadLength),
NextHeader: uint8(header.ICMPv6ProtocolNumber),
HopLimit: 255,
SrcAddr: lladdr1,
DstAddr: lladdr0,
})
invalid := s.Stats().ICMP.V6PacketsReceived.Invalid
// Invalid count should initially be 0.
if got := invalid.Value(); got != 0 {
t.Fatalf("got invalid = %d, want = 0", got)
}
e.InjectInbound(ProtocolNumber, tcpip.PacketBuffer{
Data: hdr.View().ToVectorisedView(),
})
linkAddr, c, err := s.GetLinkAddress(nicID, lladdr1, lladdr0, ProtocolNumber, nil)
if err != tcpip.ErrWouldBlock {
t.Errorf("got s.GetLinkAddress(%d, %s, %s, %d, nil) = (_, _, %v), want = (_, _, %s)", nicID, lladdr1, lladdr0, ProtocolNumber, err, tcpip.ErrWouldBlock)
if linkAddr != test.expectedLinkAddr {
t.Errorf("got link address = %s, want = %s", linkAddr, test.expectedLinkAddr)
}
if c == nil {
t.Errorf("expected channel from call to s.GetLinkAddress(%d, %s, %s, %d, nil)", nicID, lladdr1, lladdr0, ProtocolNumber)
}
if linkAddr != "" {
t.Errorf("got s.GetLinkAddress(%d, %s, %s, %d, nil) = (%s, _, ), want = ('', _, _)", nicID, lladdr1, lladdr0, ProtocolNumber, linkAddr)
if test.expectedLinkAddr != "" {
if err != nil {
t.Errorf("s.GetLinkAddress(%d, %s, %s, %d, nil): %s", nicID, lladdr1, lladdr0, ProtocolNumber, err)
}
if c != nil {
t.Errorf("got unexpected channel")
}
// Invalid count should not have increased.
if got := invalid.Value(); got != 0 {
t.Errorf("got invalid = %d, want = 0", got)
}
} else {
if err != tcpip.ErrWouldBlock {
t.Errorf("got s.GetLinkAddress(%d, %s, %s, %d, nil) = (_, _, %v), want = (_, _, %s)", nicID, lladdr1, lladdr0, ProtocolNumber, err, tcpip.ErrWouldBlock)
}
if c == nil {
t.Errorf("expected channel from call to s.GetLinkAddress(%d, %s, %s, %d, nil)", nicID, lladdr1, lladdr0, ProtocolNumber)
}
// Invalid count should have increased.
if got := invalid.Value(); got != 1 {
t.Errorf("got invalid = %d, want = 1", got)
}
}
})
}
@@ -238,27 +309,59 @@ func TestHopLimitValidation(t *testing.T) {
})
}
var tllData [header.NDPLinkLayerAddressSize]byte
header.NDPOptions(tllData[:]).Serialize(header.NDPOptionsSerializer{
header.NDPTargetLinkLayerAddressOption(linkAddr1),
})
types := []struct {
name string
typ header.ICMPv6Type
size int
extraData []byte
statCounter func(tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter
}{
{"RouterSolicit", header.ICMPv6RouterSolicit, header.ICMPv6MinimumSize, func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
return stats.RouterSolicit
}},
{"RouterAdvert", header.ICMPv6RouterAdvert, header.ICMPv6HeaderSize + header.NDPRAMinimumSize, func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
return stats.RouterAdvert
}},
{"NeighborSolicit", header.ICMPv6NeighborSolicit, header.ICMPv6NeighborSolicitMinimumSize, func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
return stats.NeighborSolicit
}},
{"NeighborAdvert", header.ICMPv6NeighborAdvert, header.ICMPv6NeighborAdvertSize, func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
return stats.NeighborAdvert
}},
{"RedirectMsg", header.ICMPv6RedirectMsg, header.ICMPv6MinimumSize, func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
return stats.RedirectMsg
}},
{
name: "RouterSolicit",
typ: header.ICMPv6RouterSolicit,
size: header.ICMPv6MinimumSize,
statCounter: func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
return stats.RouterSolicit
},
},
{
name: "RouterAdvert",
typ: header.ICMPv6RouterAdvert,
size: header.ICMPv6HeaderSize + header.NDPRAMinimumSize,
statCounter: func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
return stats.RouterAdvert
},
},
{
name: "NeighborSolicit",
typ: header.ICMPv6NeighborSolicit,
size: header.ICMPv6NeighborSolicitMinimumSize,
statCounter: func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
return stats.NeighborSolicit
},
},
{
name: "NeighborAdvert",
typ: header.ICMPv6NeighborAdvert,
size: header.ICMPv6NeighborAdvertMinimumSize,
extraData: tllData[:],
statCounter: func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
return stats.NeighborAdvert
},
},
{
name: "RedirectMsg",
typ: header.ICMPv6RedirectMsg,
size: header.ICMPv6MinimumSize,
statCounter: func(stats tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter {
return stats.RedirectMsg
},
},
}
for _, typ := range types {
@@ -270,10 +373,13 @@ func TestHopLimitValidation(t *testing.T) {
invalid := stats.Invalid
typStat := typ.statCounter(stats)
hdr := buffer.NewPrependable(header.IPv6MinimumSize + typ.size)
extraDataLen := len(typ.extraData)
hdr := buffer.NewPrependable(header.IPv6MinimumSize + typ.size + extraDataLen)
extraData := buffer.View(hdr.Prepend(extraDataLen))
copy(extraData, typ.extraData)
pkt := header.ICMPv6(hdr.Prepend(typ.size))
pkt.SetType(typ.typ)
pkt.SetChecksum(header.ICMPv6Checksum(pkt, r.LocalAddress, r.RemoteAddress, buffer.VectorisedView{}))
pkt.SetChecksum(header.ICMPv6Checksum(pkt, r.LocalAddress, r.RemoteAddress, extraData.ToVectorisedView()))
// Invalid count should initially be 0.
if got := invalid.Value(); got != 0 {
+6 -2
View File
@@ -478,13 +478,17 @@ func TestDADFail(t *testing.T) {
{
"RxAdvert",
func(tgt tcpip.Address) buffer.Prependable {
hdr := buffer.NewPrependable(header.IPv6MinimumSize + header.ICMPv6NeighborAdvertSize)
pkt := header.ICMPv6(hdr.Prepend(header.ICMPv6NeighborAdvertSize))
naSize := header.ICMPv6NeighborAdvertMinimumSize + header.NDPLinkLayerAddressSize
hdr := buffer.NewPrependable(header.IPv6MinimumSize + naSize)
pkt := header.ICMPv6(hdr.Prepend(naSize))
pkt.SetType(header.ICMPv6NeighborAdvert)
na := header.NDPNeighborAdvert(pkt.NDPPayload())
na.SetSolicitedFlag(true)
na.SetOverrideFlag(true)
na.SetTargetAddress(tgt)
na.Options().Serialize(header.NDPOptionsSerializer{
header.NDPTargetLinkLayerAddressOption(linkAddr1),
})
pkt.SetChecksum(header.ICMPv6Checksum(pkt, tgt, header.IPv6AllNodesMulticastAddress, buffer.VectorisedView{}))
payloadLength := hdr.UsedLength()
ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize))