Limit the number of discovered SLAAC prefixes

...to prevent address explosion.

Fuchsia bug: https://fxbug.dev/110896

PiperOrigin-RevId: 479613489
This commit is contained in:
Ghanan Gowripalan
2022-10-07 10:25:35 -07:00
committed by gVisor bot
parent 1f101ba738
commit 76d800d410
2 changed files with 91 additions and 0 deletions
+10
View File
@@ -97,6 +97,11 @@ const (
// prefixes.
MaxDiscoveredOnLinkPrefixes = 10
// MaxDiscoveredSLAACPrefixes is the maximum number of discovered
// SLAAC prefixes. The stack will stop discovering new SLAAC
// prefixes after discovering MaxDiscoveredSLAACPrefixes SLAAC prefixes.
MaxDiscoveredSLAACPrefixes = 10
// validPrefixLenForAutoGen is the expected prefix length that an
// address can be generated for. Must be 64 bits as the interface
// identifier (IID) is 64 bits and an IPv6 address is 128 bits, so
@@ -1039,6 +1044,11 @@ func (ndp *ndpState) handleAutonomousPrefixInformation(pi header.NDPPrefixInform
return
}
// Limit the number of discovered SLAAC prefixes.
if len(ndp.slaacPrefixes) == MaxDiscoveredSLAACPrefixes {
return
}
ndp.doSLAAC(prefix, pl, vl)
}
+81
View File
@@ -2098,6 +2098,87 @@ func expectAutoGenAddrNewEvent(ndpDisp *ndpDispatcher, addr tcpip.AddressWithPre
}
}
func TestMaxSlaacPrefixes(t *testing.T) {
const (
nicID = 1
// Each SLAAC prefix gets a stable and temporary address.
slaacAddrsPerPrefix = 2
// Send an extra prefix than what we will discover to make sure we do not
// discover the extra prefix.
slaacPrefixesInRA = ipv6.MaxDiscoveredSLAACPrefixes + 1
)
ndpDisp := ndpDispatcher{
autoGenAddrNewC: make(chan ndpAutoGenAddrNewEvent, slaacPrefixesInRA*slaacAddrsPerPrefix),
}
e := channel.New(0, 1280, linkAddr1)
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{ipv6.NewProtocolWithOptions(ipv6.Options{
NDPConfigs: ipv6.NDPConfigurations{
HandleRAs: ipv6.HandlingRAsEnabledWhenForwardingDisabled,
AutoGenGlobalAddresses: true,
AutoGenTempGlobalAddresses: true,
},
NDPDisp: &ndpDisp,
})},
})
if err := s.CreateNIC(nicID, e); err != nil {
t.Fatalf("CreateNIC(%d) = %s", nicID, err)
}
optSer := make(header.NDPOptionsSerializer, 0, slaacPrefixesInRA)
prefixes := [slaacPrefixesInRA]tcpip.Subnet{}
for i := 0; i < slaacPrefixesInRA; i++ {
prefixAddr := [16]byte{1, 2, 3, 4, 5, 6, 7, byte(i), 0, 0, 0, 0, 0, 0, 0, 0}
prefix := tcpip.AddressWithPrefix{
Address: tcpip.Address(prefixAddr[:]),
PrefixLen: 64,
}
prefixes[i] = prefix.Subnet()
// Serialize a perfix information option.
buf := [30]byte{}
buf[0] = uint8(prefix.PrefixLen)
// Set the autonomous configuration flag.
buf[1] = 64
// Set the preferred and valid lifetimes to the maxiumum possible value.
binary.BigEndian.PutUint32(buf[2:], math.MaxUint32)
binary.BigEndian.PutUint32(buf[6:], math.MaxUint32)
if n := copy(buf[14:], prefix.Address); n != len(prefix.Address) {
t.Fatalf("got copy(...) = %d, want = %d", n, len(prefix.Address))
}
optSer = append(optSer, header.NDPPrefixInformation(buf[:]))
}
e.InjectInbound(header.IPv6ProtocolNumber, raBufWithOpts(llAddr1, 0, optSer))
for i := 0; i < slaacPrefixesInRA; i++ {
for j := 0; j < slaacAddrsPerPrefix; j++ {
if i < ipv6.MaxDiscoveredSLAACPrefixes {
select {
case e := <-ndpDisp.autoGenAddrNewC:
if e.nicID != nicID {
t.Errorf("got e.nicID = %d, want = %d", e.nicID, nicID)
}
if !prefixes[i].Contains(e.addr.Address) {
t.Errorf("got prefixes[%d].Contains(%s) = false, want = true", i, e.addr)
}
if e.addrDisp != nil {
t.Error("auto-gen new addr event unexpectedly contains address dispatcher")
}
default:
t.Fatalf("expected auto-gen new addr event; i=%d, j=%d", i, j)
}
} else {
select {
case <-ndpDisp.autoGenAddrNewC:
t.Fatal("should not have discovered a new auto-gen addr after we already discovered the max number of prefixes")
default:
}
}
}
}
}
// TestAutoGenAddr tests that an address is properly generated and invalidated
// when configured to do so.
func TestAutoGenAddr(t *testing.T) {