github.com/sagernet/gvisor@v0.0.0-20240428053021-e691de28565f/pkg/tcpip/network/ipv6/ndp.go (about)

     1  // Copyright 2019 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package ipv6
    16  
    17  import (
    18  	"fmt"
    19  	"time"
    20  
    21  	"github.com/sagernet/gvisor/pkg/buffer"
    22  	"github.com/sagernet/gvisor/pkg/sync"
    23  	"github.com/sagernet/gvisor/pkg/tcpip"
    24  	"github.com/sagernet/gvisor/pkg/tcpip/header"
    25  	"github.com/sagernet/gvisor/pkg/tcpip/network/internal/ip"
    26  	"github.com/sagernet/gvisor/pkg/tcpip/stack"
    27  )
    28  
    29  const (
    30  	// defaultMaxRtrSolicitations is the default number of Router
    31  	// Solicitation messages to send when an IPv6 endpoint becomes enabled.
    32  	//
    33  	// Default = 3 (from RFC 4861 section 10).
    34  	defaultMaxRtrSolicitations = 3
    35  
    36  	// defaultRtrSolicitationInterval is the default amount of time between
    37  	// sending Router Solicitation messages.
    38  	//
    39  	// Default = 4s (from 4861 section 10).
    40  	defaultRtrSolicitationInterval = 4 * time.Second
    41  
    42  	// defaultMaxRtrSolicitationDelay is the default maximum amount of time
    43  	// to wait before sending the first Router Solicitation message.
    44  	//
    45  	// Default = 1s (from 4861 section 10).
    46  	defaultMaxRtrSolicitationDelay = time.Second
    47  
    48  	// defaultHandleRAs is the default configuration for whether or not to
    49  	// handle incoming Router Advertisements as a host.
    50  	defaultHandleRAs = HandlingRAsEnabledWhenForwardingDisabled
    51  
    52  	// defaultDiscoverDefaultRouters is the default configuration for
    53  	// whether or not to discover default routers from incoming Router
    54  	// Advertisements, as a host.
    55  	defaultDiscoverDefaultRouters = true
    56  
    57  	// defaultDiscoverMoreSpecificRoutes is the default configuration for
    58  	// whether or not to discover more-specific routes from incoming Router
    59  	// Advertisements, as a host.
    60  	defaultDiscoverMoreSpecificRoutes = true
    61  
    62  	// defaultDiscoverOnLinkPrefixes is the default configuration for
    63  	// whether or not to discover on-link prefixes from incoming Router
    64  	// Advertisements' Prefix Information option, as a host.
    65  	defaultDiscoverOnLinkPrefixes = true
    66  
    67  	// defaultAutoGenGlobalAddresses is the default configuration for
    68  	// whether or not to generate global IPv6 addresses in response to
    69  	// receiving a new Prefix Information option with its Autonomous
    70  	// Address AutoConfiguration flag set, as a host.
    71  	//
    72  	// Default = true.
    73  	defaultAutoGenGlobalAddresses = true
    74  
    75  	// minimumRtrSolicitationInterval is the minimum amount of time to wait
    76  	// between sending Router Solicitation messages. This limit is imposed
    77  	// to make sure that Router Solicitation messages are not sent all at
    78  	// once, defeating the purpose of sending the initial few messages.
    79  	minimumRtrSolicitationInterval = 500 * time.Millisecond
    80  
    81  	// minimumMaxRtrSolicitationDelay is the minimum amount of time to wait
    82  	// before sending the first Router Solicitation message. It is 0 because
    83  	// we cannot have a negative delay.
    84  	minimumMaxRtrSolicitationDelay = 0
    85  
    86  	// MaxDiscoveredOffLinkRoutes is the maximum number of discovered off-link
    87  	// routes. The stack should stop discovering new off-link routes after
    88  	// this limit is reached.
    89  	//
    90  	// This value MUST be at minimum 2 as per RFC 4861 section 6.3.4, and
    91  	// SHOULD be more.
    92  	MaxDiscoveredOffLinkRoutes = 10
    93  
    94  	// MaxDiscoveredOnLinkPrefixes is the maximum number of discovered
    95  	// on-link prefixes. The stack should stop discovering new on-link
    96  	// prefixes after discovering MaxDiscoveredOnLinkPrefixes on-link
    97  	// prefixes.
    98  	MaxDiscoveredOnLinkPrefixes = 10
    99  
   100  	// MaxDiscoveredSLAACPrefixes is the maximum number of discovered
   101  	// SLAAC prefixes. The stack will stop discovering new SLAAC
   102  	// prefixes after discovering MaxDiscoveredSLAACPrefixes SLAAC prefixes.
   103  	MaxDiscoveredSLAACPrefixes = 10
   104  
   105  	// validPrefixLenForAutoGen is the expected prefix length that an
   106  	// address can be generated for. Must be 64 bits as the interface
   107  	// identifier (IID) is 64 bits and an IPv6 address is 128 bits, so
   108  	// 128 - 64 = 64.
   109  	validPrefixLenForAutoGen = 64
   110  
   111  	// defaultAutoGenTempGlobalAddresses is the default configuration for whether
   112  	// or not to generate temporary SLAAC addresses.
   113  	defaultAutoGenTempGlobalAddresses = true
   114  
   115  	// defaultMaxTempAddrValidLifetime is the default maximum valid lifetime
   116  	// for temporary SLAAC addresses generated as part of RFC 4941.
   117  	//
   118  	// Default = 7 days (from RFC 4941 section 5).
   119  	defaultMaxTempAddrValidLifetime = 7 * 24 * time.Hour
   120  
   121  	// defaultMaxTempAddrPreferredLifetime is the default preferred lifetime
   122  	// for temporary SLAAC addresses generated as part of RFC 4941.
   123  	//
   124  	// Default = 1 day (from RFC 4941 section 5).
   125  	defaultMaxTempAddrPreferredLifetime = 24 * time.Hour
   126  
   127  	// defaultRegenAdvanceDuration is the default duration before the deprecation
   128  	// of a temporary address when a new address will be generated.
   129  	//
   130  	// Default = 5s (from RFC 4941 section 5).
   131  	defaultRegenAdvanceDuration = 5 * time.Second
   132  
   133  	// minRegenAdvanceDuration is the minimum duration before the deprecation
   134  	// of a temporary address when a new address will be generated.
   135  	minRegenAdvanceDuration = time.Duration(0)
   136  
   137  	// maxSLAACAddrLocalRegenAttempts is the maximum number of times to attempt
   138  	// SLAAC address regenerations in response to an IPv6 endpoint-local conflict.
   139  	maxSLAACAddrLocalRegenAttempts = 10
   140  
   141  	// MinPrefixInformationValidLifetimeForUpdate is the minimum Valid
   142  	// Lifetime to update the valid lifetime of a generated address by
   143  	// SLAAC.
   144  	//
   145  	// Min = 2hrs.
   146  	MinPrefixInformationValidLifetimeForUpdate = 2 * time.Hour
   147  
   148  	// MaxDesyncFactor is the upper bound for the preferred lifetime's desync
   149  	// factor for temporary SLAAC addresses.
   150  	//
   151  	// Must be greater than 0.
   152  	//
   153  	// Max = 10m (from RFC 4941 section 5).
   154  	MaxDesyncFactor = 10 * time.Minute
   155  
   156  	// MinMaxTempAddrPreferredLifetime is the minimum value allowed for the
   157  	// maximum preferred lifetime for temporary SLAAC addresses.
   158  	//
   159  	// This value guarantees that a temporary address is preferred for at
   160  	// least 1hr if the SLAAC prefix is valid for at least that time.
   161  	MinMaxTempAddrPreferredLifetime = defaultRegenAdvanceDuration + MaxDesyncFactor + time.Hour
   162  
   163  	// MinMaxTempAddrValidLifetime is the minimum value allowed for the
   164  	// maximum valid lifetime for temporary SLAAC addresses.
   165  	//
   166  	// This value guarantees that a temporary address is valid for at least
   167  	// 2hrs if the SLAAC prefix is valid for at least that time.
   168  	MinMaxTempAddrValidLifetime = 2 * time.Hour
   169  )
   170  
   171  // NDPEndpoint is an endpoint that supports NDP.
   172  type NDPEndpoint interface {
   173  	// SetNDPConfigurations sets the NDP configurations.
   174  	SetNDPConfigurations(NDPConfigurations)
   175  }
   176  
   177  // DHCPv6ConfigurationFromNDPRA is a configuration available via DHCPv6 that an
   178  // NDP Router Advertisement informed the Stack about.
   179  type DHCPv6ConfigurationFromNDPRA int
   180  
   181  const (
   182  	_ DHCPv6ConfigurationFromNDPRA = iota
   183  
   184  	// DHCPv6NoConfiguration indicates that no configurations are available via
   185  	// DHCPv6.
   186  	DHCPv6NoConfiguration
   187  
   188  	// DHCPv6ManagedAddress indicates that addresses are available via DHCPv6.
   189  	//
   190  	// DHCPv6ManagedAddress also implies DHCPv6OtherConfigurations because DHCPv6
   191  	// returns all available configuration information when serving addresses.
   192  	DHCPv6ManagedAddress
   193  
   194  	// DHCPv6OtherConfigurations indicates that other configuration information is
   195  	// available via DHCPv6.
   196  	//
   197  	// Other configurations are configurations other than addresses. Examples of
   198  	// other configurations are recursive DNS server list, DNS search lists and
   199  	// default gateway.
   200  	DHCPv6OtherConfigurations
   201  )
   202  
   203  // NDPDispatcher is the interface integrators of netstack must implement to
   204  // receive and handle NDP related events.
   205  type NDPDispatcher interface {
   206  	// OnDuplicateAddressDetectionResult is called when the DAD process for an
   207  	// address on a NIC completes.
   208  	//
   209  	// This function is not permitted to block indefinitely. This function
   210  	// is also not permitted to call into the stack.
   211  	OnDuplicateAddressDetectionResult(tcpip.NICID, tcpip.Address, stack.DADResult)
   212  
   213  	// OnOffLinkRouteUpdated is called when an off-link route is updated.
   214  	//
   215  	// This function is not permitted to block indefinitely. This function
   216  	// is also not permitted to call into the stack.
   217  	OnOffLinkRouteUpdated(tcpip.NICID, tcpip.Subnet, tcpip.Address, header.NDPRoutePreference)
   218  
   219  	// OnOffLinkRouteInvalidated is called when an off-link route is invalidated.
   220  	//
   221  	// This function is not permitted to block indefinitely. This function
   222  	// is also not permitted to call into the stack.
   223  	OnOffLinkRouteInvalidated(tcpip.NICID, tcpip.Subnet, tcpip.Address)
   224  
   225  	// OnOnLinkPrefixDiscovered is called when a new on-link prefix is discovered.
   226  	//
   227  	// This function is not permitted to block indefinitely. This function
   228  	// is also not permitted to call into the stack.
   229  	OnOnLinkPrefixDiscovered(tcpip.NICID, tcpip.Subnet)
   230  
   231  	// OnOnLinkPrefixInvalidated is called when a discovered on-link prefix that
   232  	// was remembered is invalidated.
   233  	//
   234  	// This function is not permitted to block indefinitely. This function
   235  	// is also not permitted to call into the stack.
   236  	OnOnLinkPrefixInvalidated(tcpip.NICID, tcpip.Subnet)
   237  
   238  	// OnAutoGenAddress is called when a new prefix with its autonomous address-
   239  	// configuration flag set is received and SLAAC was performed.
   240  	//
   241  	// This function is not permitted to block indefinitely. It must not
   242  	// call functions on the stack itself.
   243  	//
   244  	// If a non-nil AddressDispatcher is returned, events related to the address
   245  	// will be sent to the dispatcher.
   246  	OnAutoGenAddress(tcpip.NICID, tcpip.AddressWithPrefix) stack.AddressDispatcher
   247  
   248  	// OnAutoGenAddressDeprecated is called when an auto-generated address (SLAAC)
   249  	// is deprecated, but is still considered valid. Note, if an address is
   250  	// invalidated at the same time it is deprecated, the deprecation event may
   251  	// not be received.
   252  	//
   253  	// This function is not permitted to block indefinitely. It must not
   254  	// call functions on the stack itself.
   255  	OnAutoGenAddressDeprecated(tcpip.NICID, tcpip.AddressWithPrefix)
   256  
   257  	// OnAutoGenAddressInvalidated is called when an auto-generated address
   258  	// (SLAAC) is invalidated.
   259  	//
   260  	// This function is not permitted to block indefinitely. It must not
   261  	// call functions on the stack itself.
   262  	OnAutoGenAddressInvalidated(tcpip.NICID, tcpip.AddressWithPrefix)
   263  
   264  	// OnRecursiveDNSServerOption is called when the stack learns of DNS servers
   265  	// through NDP. Note, the addresses may contain link-local addresses.
   266  	//
   267  	// It is up to the caller to use the DNS Servers only for their valid
   268  	// lifetime. OnRecursiveDNSServerOption may be called for new or
   269  	// already known DNS servers. If called with known DNS servers, their
   270  	// valid lifetimes must be refreshed to the lifetime (it may be increased,
   271  	// decreased, or completely invalidated when the lifetime = 0).
   272  	//
   273  	// This function is not permitted to block indefinitely. It must not
   274  	// call functions on the stack itself.
   275  	OnRecursiveDNSServerOption(tcpip.NICID, []tcpip.Address, time.Duration)
   276  
   277  	// OnDNSSearchListOption is called when the stack learns of DNS search lists
   278  	// through NDP.
   279  	//
   280  	// It is up to the caller to use the domain names in the search list
   281  	// for only their valid lifetime. OnDNSSearchListOption may be called
   282  	// with new or already known domain names. If called with known domain
   283  	// names, their valid lifetimes must be refreshed to the lifetime (it may
   284  	// be increased, decreased or completely invalidated when the lifetime = 0.
   285  	OnDNSSearchListOption(tcpip.NICID, []string, time.Duration)
   286  
   287  	// OnDHCPv6Configuration is called with an updated configuration that is
   288  	// available via DHCPv6 for the passed NIC.
   289  	//
   290  	// This function is not permitted to block indefinitely. It must not
   291  	// call functions on the stack itself.
   292  	OnDHCPv6Configuration(tcpip.NICID, DHCPv6ConfigurationFromNDPRA)
   293  }
   294  
   295  var _ fmt.Stringer = HandleRAsConfiguration(0)
   296  
   297  // HandleRAsConfiguration enumerates when RAs may be handled.
   298  type HandleRAsConfiguration int
   299  
   300  const (
   301  	// HandlingRAsDisabled indicates that Router Advertisements will not be
   302  	// handled.
   303  	HandlingRAsDisabled HandleRAsConfiguration = iota
   304  
   305  	// HandlingRAsEnabledWhenForwardingDisabled indicates that router
   306  	// advertisements will only be handled when forwarding is disabled.
   307  	HandlingRAsEnabledWhenForwardingDisabled
   308  
   309  	// HandlingRAsAlwaysEnabled indicates that Router Advertisements will always
   310  	// be handled, even when forwarding is enabled.
   311  	HandlingRAsAlwaysEnabled
   312  )
   313  
   314  // String implements fmt.Stringer.
   315  func (c HandleRAsConfiguration) String() string {
   316  	switch c {
   317  	case HandlingRAsDisabled:
   318  		return "HandlingRAsDisabled"
   319  	case HandlingRAsEnabledWhenForwardingDisabled:
   320  		return "HandlingRAsEnabledWhenForwardingDisabled"
   321  	case HandlingRAsAlwaysEnabled:
   322  		return "HandlingRAsAlwaysEnabled"
   323  	default:
   324  		return fmt.Sprintf("HandleRAsConfiguration(%d)", c)
   325  	}
   326  }
   327  
   328  // enabled returns true iff Router Advertisements may be handled given the
   329  // specified forwarding status.
   330  func (c HandleRAsConfiguration) enabled(forwarding bool) bool {
   331  	switch c {
   332  	case HandlingRAsDisabled:
   333  		return false
   334  	case HandlingRAsEnabledWhenForwardingDisabled:
   335  		return !forwarding
   336  	case HandlingRAsAlwaysEnabled:
   337  		return true
   338  	default:
   339  		panic(fmt.Sprintf("unhandled HandleRAsConfiguration = %d", c))
   340  	}
   341  }
   342  
   343  // NDPConfigurations is the NDP configurations for the netstack.
   344  type NDPConfigurations struct {
   345  	// The number of Router Solicitation messages to send when the IPv6 endpoint
   346  	// becomes enabled.
   347  	//
   348  	// Ignored unless configured to handle Router Advertisements.
   349  	MaxRtrSolicitations uint8
   350  
   351  	// The amount of time between transmitting Router Solicitation messages.
   352  	//
   353  	// Must be greater than or equal to 0.5s.
   354  	RtrSolicitationInterval time.Duration
   355  
   356  	// The maximum amount of time before transmitting the first Router
   357  	// Solicitation message.
   358  	//
   359  	// Must be greater than or equal to 0s.
   360  	MaxRtrSolicitationDelay time.Duration
   361  
   362  	// HandleRAs is the configuration for when Router Advertisements should be
   363  	// handled.
   364  	HandleRAs HandleRAsConfiguration
   365  
   366  	// DiscoverDefaultRouters determines whether or not default routers are
   367  	// discovered from Router Advertisements, as per RFC 4861 section 6. This
   368  	// configuration is ignored if RAs will not be processed (see HandleRAs).
   369  	DiscoverDefaultRouters bool
   370  
   371  	// DiscoverMoreSpecificRoutes determines whether or not more specific routes
   372  	// are discovered from Router Advertisements, as per RFC 4191. This
   373  	// configuration is ignored if RAs will not be processed (see HandleRAs).
   374  	DiscoverMoreSpecificRoutes bool
   375  
   376  	// DiscoverOnLinkPrefixes determines whether or not on-link prefixes are
   377  	// discovered from Router Advertisements' Prefix Information option, as per
   378  	// RFC 4861 section 6. This configuration is ignored if RAs will not be
   379  	// processed (see HandleRAs).
   380  	DiscoverOnLinkPrefixes bool
   381  
   382  	// AutoGenGlobalAddresses determines whether or not an IPv6 endpoint performs
   383  	// SLAAC to auto-generate global SLAAC addresses in response to Prefix
   384  	// Information options, as per RFC 4862.
   385  	//
   386  	// Note, if an address was already generated for some unique prefix, as
   387  	// part of SLAAC, this option does not affect whether or not the
   388  	// lifetime(s) of the generated address changes; this option only
   389  	// affects the generation of new addresses as part of SLAAC.
   390  	AutoGenGlobalAddresses bool
   391  
   392  	// AutoGenAddressConflictRetries determines how many times to attempt to retry
   393  	// generation of a permanent auto-generated address in response to DAD
   394  	// conflicts.
   395  	//
   396  	// If the method used to generate the address does not support creating
   397  	// alternative addresses (e.g. IIDs based on the modified EUI64 of a NIC's
   398  	// MAC address), then no attempt is made to resolve the conflict.
   399  	AutoGenAddressConflictRetries uint8
   400  
   401  	// AutoGenTempGlobalAddresses determines whether or not temporary SLAAC
   402  	// addresses are generated for an IPv6 endpoint as part of SLAAC privacy
   403  	// extensions, as per RFC 4941.
   404  	//
   405  	// Ignored if AutoGenGlobalAddresses is false.
   406  	AutoGenTempGlobalAddresses bool
   407  
   408  	// MaxTempAddrValidLifetime is the maximum valid lifetime for temporary
   409  	// SLAAC addresses.
   410  	MaxTempAddrValidLifetime time.Duration
   411  
   412  	// MaxTempAddrPreferredLifetime is the maximum preferred lifetime for
   413  	// temporary SLAAC addresses.
   414  	MaxTempAddrPreferredLifetime time.Duration
   415  
   416  	// RegenAdvanceDuration is the duration before the deprecation of a temporary
   417  	// address when a new address will be generated.
   418  	RegenAdvanceDuration time.Duration
   419  }
   420  
   421  // DefaultNDPConfigurations returns an NDPConfigurations populated with
   422  // default values.
   423  func DefaultNDPConfigurations() NDPConfigurations {
   424  	return NDPConfigurations{
   425  		MaxRtrSolicitations:          defaultMaxRtrSolicitations,
   426  		RtrSolicitationInterval:      defaultRtrSolicitationInterval,
   427  		MaxRtrSolicitationDelay:      defaultMaxRtrSolicitationDelay,
   428  		HandleRAs:                    defaultHandleRAs,
   429  		DiscoverDefaultRouters:       defaultDiscoverDefaultRouters,
   430  		DiscoverMoreSpecificRoutes:   defaultDiscoverMoreSpecificRoutes,
   431  		DiscoverOnLinkPrefixes:       defaultDiscoverOnLinkPrefixes,
   432  		AutoGenGlobalAddresses:       defaultAutoGenGlobalAddresses,
   433  		AutoGenTempGlobalAddresses:   defaultAutoGenTempGlobalAddresses,
   434  		MaxTempAddrValidLifetime:     defaultMaxTempAddrValidLifetime,
   435  		MaxTempAddrPreferredLifetime: defaultMaxTempAddrPreferredLifetime,
   436  		RegenAdvanceDuration:         defaultRegenAdvanceDuration,
   437  	}
   438  }
   439  
   440  // validate modifies an NDPConfigurations with valid values. If invalid values
   441  // are present in c, the corresponding default values are used instead.
   442  func (c *NDPConfigurations) validate() {
   443  	if c.RtrSolicitationInterval < minimumRtrSolicitationInterval {
   444  		c.RtrSolicitationInterval = defaultRtrSolicitationInterval
   445  	}
   446  
   447  	if c.MaxRtrSolicitationDelay < minimumMaxRtrSolicitationDelay {
   448  		c.MaxRtrSolicitationDelay = defaultMaxRtrSolicitationDelay
   449  	}
   450  
   451  	if c.MaxTempAddrValidLifetime < MinMaxTempAddrValidLifetime {
   452  		c.MaxTempAddrValidLifetime = MinMaxTempAddrValidLifetime
   453  	}
   454  
   455  	if c.MaxTempAddrPreferredLifetime < MinMaxTempAddrPreferredLifetime || c.MaxTempAddrPreferredLifetime > c.MaxTempAddrValidLifetime {
   456  		c.MaxTempAddrPreferredLifetime = MinMaxTempAddrPreferredLifetime
   457  	}
   458  
   459  	if c.RegenAdvanceDuration < minRegenAdvanceDuration {
   460  		c.RegenAdvanceDuration = minRegenAdvanceDuration
   461  	}
   462  }
   463  
   464  type timer struct {
   465  	// done indicates to the timer that the timer was stopped.
   466  	done *bool
   467  
   468  	timer tcpip.Timer
   469  }
   470  
   471  type offLinkRoute struct {
   472  	dest   tcpip.Subnet
   473  	router tcpip.Address
   474  }
   475  
   476  // ndpState is the per-Interface NDP state.
   477  type ndpState struct {
   478  	// Do not allow overwriting this state.
   479  	_ sync.NoCopy
   480  
   481  	// The IPv6 endpoint this ndpState is for.
   482  	ep *endpoint
   483  
   484  	// configs is the per-interface NDP configurations.
   485  	configs NDPConfigurations
   486  
   487  	// The DAD timers to send the next NS message, or resolve the address.
   488  	dad ip.DAD
   489  
   490  	// The off-link routes discovered through Router Advertisements.
   491  	offLinkRoutes map[offLinkRoute]offLinkRouteState
   492  
   493  	// rtrSolicitTimer is the timer used to send the next router solicitation
   494  	// message.
   495  	//
   496  	// rtrSolicitTimer is the zero value when NDP is not soliciting routers.
   497  	rtrSolicitTimer timer
   498  
   499  	// The on-link prefixes discovered through Router Advertisements' Prefix
   500  	// Information option.
   501  	onLinkPrefixes map[tcpip.Subnet]onLinkPrefixState
   502  
   503  	// The SLAAC prefixes discovered through Router Advertisements' Prefix
   504  	// Information option.
   505  	slaacPrefixes map[tcpip.Subnet]slaacPrefixState
   506  
   507  	// The last learned DHCPv6 configuration from an NDP RA.
   508  	dhcpv6Configuration DHCPv6ConfigurationFromNDPRA
   509  
   510  	// temporaryIIDHistory is the history value used to generate a new temporary
   511  	// IID.
   512  	temporaryIIDHistory [header.IIDSize]byte
   513  
   514  	// temporaryAddressDesyncFactor is the preferred lifetime's desync factor for
   515  	// temporary SLAAC addresses.
   516  	temporaryAddressDesyncFactor time.Duration
   517  }
   518  
   519  // offLinkRouteState holds data associated with an off-link route discovered by
   520  // a Router Advertisement (RA).
   521  type offLinkRouteState struct {
   522  	prf header.NDPRoutePreference
   523  
   524  	// Job to invalidate the route.
   525  	//
   526  	// Must not be nil.
   527  	invalidationJob *tcpip.Job
   528  }
   529  
   530  // onLinkPrefixState holds data associated with an on-link prefix discovered by
   531  // a Router Advertisement's Prefix Information option (PI) when the NDP
   532  // configurations was configured to do so.
   533  type onLinkPrefixState struct {
   534  	// Job to invalidate the on-link prefix.
   535  	//
   536  	// Must not be nil.
   537  	invalidationJob *tcpip.Job
   538  }
   539  
   540  // tempSLAACAddrState holds state associated with a temporary SLAAC address.
   541  type tempSLAACAddrState struct {
   542  	// Job to deprecate the temporary SLAAC address.
   543  	//
   544  	// Must not be nil.
   545  	deprecationJob *tcpip.Job
   546  
   547  	// Job to invalidate the temporary SLAAC address.
   548  	//
   549  	// Must not be nil.
   550  	invalidationJob *tcpip.Job
   551  
   552  	// Job to regenerate the temporary SLAAC address.
   553  	//
   554  	// Must not be nil.
   555  	regenJob *tcpip.Job
   556  
   557  	createdAt tcpip.MonotonicTime
   558  
   559  	// The address's endpoint.
   560  	//
   561  	// Must not be nil.
   562  	addressEndpoint stack.AddressEndpoint
   563  
   564  	// Has a new temporary SLAAC address already been regenerated?
   565  	regenerated bool
   566  }
   567  
   568  // slaacPrefixState holds state associated with a SLAAC prefix.
   569  type slaacPrefixState struct {
   570  	// Job to deprecate the prefix.
   571  	//
   572  	// Must not be nil.
   573  	deprecationJob *tcpip.Job
   574  
   575  	// Job to invalidate the prefix.
   576  	//
   577  	// Must not be nil.
   578  	invalidationJob *tcpip.Job
   579  
   580  	// nil iff the address is valid forever.
   581  	validUntil *tcpip.MonotonicTime
   582  
   583  	// nil iff the address is preferred forever.
   584  	preferredUntil *tcpip.MonotonicTime
   585  
   586  	// State associated with the stable address generated for the prefix.
   587  	stableAddr struct {
   588  		// The address's endpoint.
   589  		//
   590  		// May only be nil when the address is being (re-)generated. Otherwise,
   591  		// must not be nil as all SLAAC prefixes must have a stable address.
   592  		addressEndpoint stack.AddressEndpoint
   593  
   594  		// The number of times an address has been generated locally where the IPv6
   595  		// endpoint already had the generated address.
   596  		localGenerationFailures uint8
   597  	}
   598  
   599  	// The temporary (short-lived) addresses generated for the SLAAC prefix.
   600  	tempAddrs map[tcpip.Address]tempSLAACAddrState
   601  
   602  	// The next two fields are used by both stable and temporary addresses
   603  	// generated for a SLAAC prefix. This is safe as only 1 address is in the
   604  	// generation and DAD process at any time. That is, no two addresses are
   605  	// generated at the same time for a given SLAAC prefix.
   606  
   607  	// The number of times an address has been generated and added to the IPv6
   608  	// endpoint.
   609  	//
   610  	// Addresses may be regenerated in reseponse to a DAD conflicts.
   611  	generationAttempts uint8
   612  
   613  	// The maximum number of times to attempt regeneration of a SLAAC address
   614  	// in response to DAD conflicts.
   615  	maxGenerationAttempts uint8
   616  }
   617  
   618  // startDuplicateAddressDetection performs Duplicate Address Detection.
   619  //
   620  // This function must only be called by IPv6 addresses that are currently
   621  // tentative.
   622  //
   623  // The IPv6 endpoint that ndp belongs to MUST be locked.
   624  func (ndp *ndpState) startDuplicateAddressDetection(addr tcpip.Address, addressEndpoint stack.AddressEndpoint) tcpip.Error {
   625  	// addr must be a valid unicast IPv6 address.
   626  	if !header.IsV6UnicastAddress(addr) {
   627  		return &tcpip.ErrAddressFamilyNotSupported{}
   628  	}
   629  
   630  	if addressEndpoint.GetKind() != stack.PermanentTentative {
   631  		// The endpoint should be marked as tentative since we are starting DAD.
   632  		panic(fmt.Sprintf("ndpdad: addr %s is not tentative on NIC(%d)", addr, ndp.ep.nic.ID()))
   633  	}
   634  
   635  	ret := ndp.dad.CheckDuplicateAddressLocked(addr, func(r stack.DADResult) {
   636  		if addressEndpoint.GetKind() != stack.PermanentTentative {
   637  			// The endpoint should still be marked as tentative since we are still
   638  			// performing DAD on it.
   639  			panic(fmt.Sprintf("ndpdad: addr %s is no longer tentative on NIC(%d)", addr, ndp.ep.nic.ID()))
   640  		}
   641  
   642  		var dadSucceeded bool
   643  		switch r.(type) {
   644  		case *stack.DADAborted, *stack.DADError, *stack.DADDupAddrDetected:
   645  			dadSucceeded = false
   646  		case *stack.DADSucceeded:
   647  			dadSucceeded = true
   648  		default:
   649  			panic(fmt.Sprintf("unrecognized DAD result = %T", r))
   650  		}
   651  
   652  		if dadSucceeded {
   653  			addressEndpoint.SetKind(stack.Permanent)
   654  		}
   655  
   656  		if ndpDisp := ndp.ep.protocol.options.NDPDisp; ndpDisp != nil {
   657  			ndpDisp.OnDuplicateAddressDetectionResult(ndp.ep.nic.ID(), addr, r)
   658  		}
   659  
   660  		if dadSucceeded {
   661  			if addressEndpoint.ConfigType() == stack.AddressConfigSlaac && !addressEndpoint.Temporary() {
   662  				// Reset the generation attempts counter as we are starting the
   663  				// generation of a new address for the SLAAC prefix.
   664  				ndp.regenerateTempSLAACAddr(addressEndpoint.AddressWithPrefix().Subnet(), true /* resetGenAttempts */)
   665  			}
   666  			ndp.ep.onAddressAssignedLocked(addr)
   667  		}
   668  	})
   669  
   670  	switch ret {
   671  	case stack.DADStarting:
   672  	case stack.DADAlreadyRunning:
   673  		panic(fmt.Sprintf("ndpdad: already performing DAD for addr %s on NIC(%d)", addr, ndp.ep.nic.ID()))
   674  	case stack.DADDisabled:
   675  		addressEndpoint.SetKind(stack.Permanent)
   676  
   677  		// Consider DAD to have resolved even if no DAD messages were actually
   678  		// transmitted.
   679  		if ndpDisp := ndp.ep.protocol.options.NDPDisp; ndpDisp != nil {
   680  			ndpDisp.OnDuplicateAddressDetectionResult(ndp.ep.nic.ID(), addr, &stack.DADSucceeded{})
   681  		}
   682  
   683  		ndp.ep.onAddressAssignedLocked(addr)
   684  	}
   685  
   686  	return nil
   687  }
   688  
   689  // stopDuplicateAddressDetection ends a running Duplicate Address Detection
   690  // process. Note, this may leave the DAD process for a tentative address in
   691  // such a state forever, unless some other external event resolves the DAD
   692  // process (receiving an NA from the true owner of addr, or an NS for addr
   693  // (implying another node is attempting to use addr)). It is up to the caller
   694  // of this function to handle such a scenario.
   695  //
   696  // The IPv6 endpoint that ndp belongs to MUST be locked.
   697  func (ndp *ndpState) stopDuplicateAddressDetection(addr tcpip.Address, reason stack.DADResult) {
   698  	ndp.dad.StopLocked(addr, reason)
   699  }
   700  
   701  // handleRA handles a Router Advertisement message that arrived on the NIC
   702  // this ndp is for. Does nothing if the NIC is configured to not handle RAs.
   703  //
   704  // The IPv6 endpoint that ndp belongs to MUST be locked.
   705  func (ndp *ndpState) handleRA(ip tcpip.Address, ra header.NDPRouterAdvert) {
   706  	// Is the IPv6 endpoint configured to handle RAs at all?
   707  	//
   708  	// Currently, the stack does not determine router interface status on a
   709  	// per-interface basis; it is a protocol-wide configuration, so we check the
   710  	// protocol's forwarding flag to determine if the IPv6 endpoint is forwarding
   711  	// packets.
   712  	if !ndp.configs.HandleRAs.enabled(ndp.ep.Forwarding()) {
   713  		ndp.ep.stats.localStats.UnhandledRouterAdvertisements.Increment()
   714  		return
   715  	}
   716  
   717  	// Only worry about the DHCPv6 configuration if we have an NDPDispatcher as we
   718  	// only inform the dispatcher on configuration changes. We do nothing else
   719  	// with the information.
   720  	if ndpDisp := ndp.ep.protocol.options.NDPDisp; ndpDisp != nil {
   721  		var configuration DHCPv6ConfigurationFromNDPRA
   722  		switch {
   723  		case ra.ManagedAddrConfFlag():
   724  			configuration = DHCPv6ManagedAddress
   725  
   726  		case ra.OtherConfFlag():
   727  			configuration = DHCPv6OtherConfigurations
   728  
   729  		default:
   730  			configuration = DHCPv6NoConfiguration
   731  		}
   732  
   733  		if ndp.dhcpv6Configuration != configuration {
   734  			ndp.dhcpv6Configuration = configuration
   735  			ndpDisp.OnDHCPv6Configuration(ndp.ep.nic.ID(), configuration)
   736  		}
   737  	}
   738  
   739  	// Is the IPv6 endpoint configured to discover default routers?
   740  	if ndp.configs.DiscoverDefaultRouters {
   741  		prf := ra.DefaultRouterPreference()
   742  		if prf == header.ReservedRoutePreference {
   743  			// As per RFC 4191 section 2.2,
   744  			//
   745  			//   Prf (Default Router Preference)
   746  			//
   747  			//     If the Reserved (10) value is received, the receiver MUST treat the
   748  			//     value as if it were (00).
   749  			//
   750  			// Note that the value 00 is the medium (default) router preference value.
   751  			prf = header.MediumRoutePreference
   752  		}
   753  
   754  		// We represent default routers with a default (off-link) route through the
   755  		// router.
   756  		ndp.handleOffLinkRouteDiscovery(offLinkRoute{dest: header.IPv6EmptySubnet, router: ip}, ra.RouterLifetime(), prf)
   757  	}
   758  
   759  	// TODO(b/141556115): Do (RetransTimer, ReachableTime)) Parameter
   760  	//                    Discovery.
   761  
   762  	// We know the options is valid as far as wire format is concerned since
   763  	// we got the Router Advertisement, as documented by this fn. Given this
   764  	// we do not check the iterator for errors on calls to Next.
   765  	it, _ := ra.Options().Iter(false)
   766  	for opt, done, _ := it.Next(); !done; opt, done, _ = it.Next() {
   767  		switch opt := opt.(type) {
   768  		case header.NDPRecursiveDNSServer:
   769  			if ndp.ep.protocol.options.NDPDisp == nil {
   770  				continue
   771  			}
   772  
   773  			addrs, _ := opt.Addresses()
   774  			ndp.ep.protocol.options.NDPDisp.OnRecursiveDNSServerOption(ndp.ep.nic.ID(), addrs, opt.Lifetime())
   775  
   776  		case header.NDPDNSSearchList:
   777  			if ndp.ep.protocol.options.NDPDisp == nil {
   778  				continue
   779  			}
   780  
   781  			domainNames, _ := opt.DomainNames()
   782  			ndp.ep.protocol.options.NDPDisp.OnDNSSearchListOption(ndp.ep.nic.ID(), domainNames, opt.Lifetime())
   783  
   784  		case header.NDPPrefixInformation:
   785  			prefix := opt.Subnet()
   786  
   787  			// Is the prefix a link-local?
   788  			if header.IsV6LinkLocalUnicastAddress(prefix.ID()) {
   789  				// ...Yes, skip as per RFC 4861 section 6.3.4,
   790  				// and RFC 4862 section 5.5.3.b (for SLAAC).
   791  				continue
   792  			}
   793  
   794  			// Is the Prefix Length 0?
   795  			if prefix.Prefix() == 0 {
   796  				// ...Yes, skip as this is an invalid prefix
   797  				// as all IPv6 addresses cannot be on-link.
   798  				continue
   799  			}
   800  
   801  			if opt.OnLinkFlag() {
   802  				ndp.handleOnLinkPrefixInformation(opt)
   803  			}
   804  
   805  			if opt.AutonomousAddressConfigurationFlag() {
   806  				ndp.handleAutonomousPrefixInformation(opt)
   807  			}
   808  
   809  		case header.NDPRouteInformation:
   810  			if !ndp.configs.DiscoverMoreSpecificRoutes {
   811  				continue
   812  			}
   813  
   814  			dest, err := opt.Prefix()
   815  			if err != nil {
   816  				panic(fmt.Sprintf("%T.Prefix(): %s", opt, err))
   817  			}
   818  
   819  			prf := opt.RoutePreference()
   820  			if prf == header.ReservedRoutePreference {
   821  				// As per RFC 4191 section 2.3,
   822  				//
   823  				//   Prf (Route Preference)
   824  				//       2-bit signed integer.  The Route Preference indicates
   825  				//       whether to prefer the router associated with this prefix
   826  				//       over others, when multiple identical prefixes (for
   827  				//       different routers) have been received.  If the Reserved
   828  				//       (10) value is received, the Route Information Option MUST
   829  				//       be ignored.
   830  				continue
   831  			}
   832  
   833  			ndp.handleOffLinkRouteDiscovery(offLinkRoute{dest: dest, router: ip}, opt.RouteLifetime(), prf)
   834  		}
   835  
   836  		// TODO(b/141556115): Do (MTU) Parameter Discovery.
   837  	}
   838  }
   839  
   840  // invalidateOffLinkRoute invalidates a discovered off-link route.
   841  //
   842  // The IPv6 endpoint that ndp belongs to MUST be locked.
   843  func (ndp *ndpState) invalidateOffLinkRoute(route offLinkRoute) {
   844  	state, ok := ndp.offLinkRoutes[route]
   845  	if !ok {
   846  		return
   847  	}
   848  
   849  	state.invalidationJob.Cancel()
   850  	delete(ndp.offLinkRoutes, route)
   851  
   852  	// Let the integrator know a discovered off-link route is invalidated.
   853  	if ndpDisp := ndp.ep.protocol.options.NDPDisp; ndpDisp != nil {
   854  		ndpDisp.OnOffLinkRouteInvalidated(ndp.ep.nic.ID(), route.dest, route.router)
   855  	}
   856  }
   857  
   858  // handleOffLinkRouteDiscovery handles the discovery of an off-link route.
   859  //
   860  // Precondition: ndp.ep.mu must be locked.
   861  func (ndp *ndpState) handleOffLinkRouteDiscovery(route offLinkRoute, lifetime time.Duration, prf header.NDPRoutePreference) {
   862  	ndpDisp := ndp.ep.protocol.options.NDPDisp
   863  	if ndpDisp == nil {
   864  		return
   865  	}
   866  
   867  	state, ok := ndp.offLinkRoutes[route]
   868  	switch {
   869  	case !ok && lifetime != 0:
   870  		// This is a new route we are discovering.
   871  		//
   872  		// Only remember it if we currently know about less than
   873  		// MaxDiscoveredOffLinkRoutes routers.
   874  		if len(ndp.offLinkRoutes) < MaxDiscoveredOffLinkRoutes {
   875  			// Inform the integrator when we discovered an off-link route.
   876  			ndpDisp.OnOffLinkRouteUpdated(ndp.ep.nic.ID(), route.dest, route.router, prf)
   877  
   878  			state := offLinkRouteState{
   879  				prf: prf,
   880  				invalidationJob: tcpip.NewJob(ndp.ep.protocol.stack.Clock(), &ndp.ep.mu, func() {
   881  					ndp.invalidateOffLinkRoute(route)
   882  				}),
   883  			}
   884  
   885  			state.invalidationJob.Schedule(lifetime)
   886  
   887  			ndp.offLinkRoutes[route] = state
   888  		}
   889  
   890  	case ok && lifetime != 0:
   891  		// This is an already discovered off-link route. Update the lifetime.
   892  		state.invalidationJob.Cancel()
   893  		state.invalidationJob.Schedule(lifetime)
   894  
   895  		if prf != state.prf {
   896  			state.prf = prf
   897  
   898  			// Inform the integrator about route preference updates.
   899  			ndpDisp.OnOffLinkRouteUpdated(ndp.ep.nic.ID(), route.dest, route.router, prf)
   900  		}
   901  
   902  		ndp.offLinkRoutes[route] = state
   903  
   904  	case ok && lifetime == 0:
   905  		// The already discovered off-link route is no longer considered valid so we
   906  		// invalidate it immediately.
   907  		ndp.invalidateOffLinkRoute(route)
   908  	}
   909  }
   910  
   911  // rememberOnLinkPrefix remembers a newly discovered on-link prefix with IPv6
   912  // address with prefix prefix with lifetime l.
   913  //
   914  // The prefix identified by prefix MUST NOT already be known.
   915  //
   916  // The IPv6 endpoint that ndp belongs to MUST be locked.
   917  func (ndp *ndpState) rememberOnLinkPrefix(prefix tcpip.Subnet, l time.Duration) {
   918  	ndpDisp := ndp.ep.protocol.options.NDPDisp
   919  	if ndpDisp == nil {
   920  		return
   921  	}
   922  
   923  	// Inform the integrator when we discovered an on-link prefix.
   924  	ndpDisp.OnOnLinkPrefixDiscovered(ndp.ep.nic.ID(), prefix)
   925  
   926  	state := onLinkPrefixState{
   927  		invalidationJob: tcpip.NewJob(ndp.ep.protocol.stack.Clock(), &ndp.ep.mu, func() {
   928  			ndp.invalidateOnLinkPrefix(prefix)
   929  		}),
   930  	}
   931  
   932  	if l < header.NDPInfiniteLifetime {
   933  		state.invalidationJob.Schedule(l)
   934  	}
   935  
   936  	ndp.onLinkPrefixes[prefix] = state
   937  }
   938  
   939  // invalidateOnLinkPrefix invalidates a discovered on-link prefix.
   940  //
   941  // The IPv6 endpoint that ndp belongs to MUST be locked.
   942  func (ndp *ndpState) invalidateOnLinkPrefix(prefix tcpip.Subnet) {
   943  	s, ok := ndp.onLinkPrefixes[prefix]
   944  
   945  	// Is the on-link prefix still discovered?
   946  	if !ok {
   947  		// ...Nope, do nothing further.
   948  		return
   949  	}
   950  
   951  	s.invalidationJob.Cancel()
   952  	delete(ndp.onLinkPrefixes, prefix)
   953  
   954  	// Let the integrator know a discovered on-link prefix is invalidated.
   955  	if ndpDisp := ndp.ep.protocol.options.NDPDisp; ndpDisp != nil {
   956  		ndpDisp.OnOnLinkPrefixInvalidated(ndp.ep.nic.ID(), prefix)
   957  	}
   958  }
   959  
   960  // handleOnLinkPrefixInformation handles a Prefix Information option with
   961  // its on-link flag set, as per RFC 4861 section 6.3.4.
   962  //
   963  // handleOnLinkPrefixInformation assumes that the prefix this pi is for is
   964  // not the link-local prefix and the on-link flag is set.
   965  //
   966  // The IPv6 endpoint that ndp belongs to MUST be locked.
   967  func (ndp *ndpState) handleOnLinkPrefixInformation(pi header.NDPPrefixInformation) {
   968  	prefix := pi.Subnet()
   969  	prefixState, ok := ndp.onLinkPrefixes[prefix]
   970  	vl := pi.ValidLifetime()
   971  
   972  	if !ok && vl == 0 {
   973  		// Don't know about this prefix but it has a zero valid
   974  		// lifetime, so just ignore.
   975  		return
   976  	}
   977  
   978  	if !ok && vl != 0 {
   979  		// This is a new on-link prefix we are discovering
   980  		//
   981  		// Only remember it if we currently know about less than
   982  		// MaxDiscoveredOnLinkPrefixes on-link prefixes.
   983  		if ndp.configs.DiscoverOnLinkPrefixes && len(ndp.onLinkPrefixes) < MaxDiscoveredOnLinkPrefixes {
   984  			ndp.rememberOnLinkPrefix(prefix, vl)
   985  		}
   986  		return
   987  	}
   988  
   989  	if ok && vl == 0 {
   990  		// We know about the on-link prefix, but it is
   991  		// no longer to be considered on-link, so
   992  		// invalidate it.
   993  		ndp.invalidateOnLinkPrefix(prefix)
   994  		return
   995  	}
   996  
   997  	// This is an already discovered on-link prefix with a
   998  	// new non-zero valid lifetime.
   999  	//
  1000  	// Update the invalidation job.
  1001  
  1002  	prefixState.invalidationJob.Cancel()
  1003  
  1004  	if vl < header.NDPInfiniteLifetime {
  1005  		// Prefix is valid for a finite lifetime, schedule the job to execute after
  1006  		// the new valid lifetime.
  1007  		prefixState.invalidationJob.Schedule(vl)
  1008  	}
  1009  
  1010  	ndp.onLinkPrefixes[prefix] = prefixState
  1011  }
  1012  
  1013  // handleAutonomousPrefixInformation handles a Prefix Information option with
  1014  // its autonomous flag set, as per RFC 4862 section 5.5.3.
  1015  //
  1016  // handleAutonomousPrefixInformation assumes that the prefix this pi is for is
  1017  // not the link-local prefix and the autonomous flag is set.
  1018  //
  1019  // The IPv6 endpoint that ndp belongs to MUST be locked.
  1020  func (ndp *ndpState) handleAutonomousPrefixInformation(pi header.NDPPrefixInformation) {
  1021  	vl := pi.ValidLifetime()
  1022  	pl := pi.PreferredLifetime()
  1023  
  1024  	// If the preferred lifetime is greater than the valid lifetime,
  1025  	// silently ignore the Prefix Information option, as per RFC 4862
  1026  	// section 5.5.3.c.
  1027  	if pl > vl {
  1028  		return
  1029  	}
  1030  
  1031  	prefix := pi.Subnet()
  1032  
  1033  	// Check if we already maintain SLAAC state for prefix.
  1034  	if state, ok := ndp.slaacPrefixes[prefix]; ok {
  1035  		// As per RFC 4862 section 5.5.3.e, refresh prefix's SLAAC lifetimes.
  1036  		ndp.refreshSLAACPrefixLifetimes(prefix, &state, pl, vl)
  1037  		ndp.slaacPrefixes[prefix] = state
  1038  		return
  1039  	}
  1040  
  1041  	// prefix is a new SLAAC prefix. Do the work as outlined by RFC 4862 section
  1042  	// 5.5.3.d if ndp is configured to auto-generate new addresses via SLAAC.
  1043  	if !ndp.configs.AutoGenGlobalAddresses {
  1044  		return
  1045  	}
  1046  
  1047  	// Limit the number of discovered SLAAC prefixes.
  1048  	if len(ndp.slaacPrefixes) == MaxDiscoveredSLAACPrefixes {
  1049  		return
  1050  	}
  1051  
  1052  	ndp.doSLAAC(prefix, pl, vl)
  1053  }
  1054  
  1055  // doSLAAC generates a new SLAAC address with the provided lifetimes
  1056  // for prefix.
  1057  //
  1058  // pl is the new preferred lifetime. vl is the new valid lifetime.
  1059  //
  1060  // The IPv6 endpoint that ndp belongs to MUST be locked.
  1061  func (ndp *ndpState) doSLAAC(prefix tcpip.Subnet, pl, vl time.Duration) {
  1062  	// If we do not already have an address for this prefix and the valid
  1063  	// lifetime is 0, no need to do anything further, as per RFC 4862
  1064  	// section 5.5.3.d.
  1065  	if vl == 0 {
  1066  		return
  1067  	}
  1068  
  1069  	// Make sure the prefix is valid (as far as its length is concerned) to
  1070  	// generate a valid IPv6 address from an interface identifier (IID), as
  1071  	// per RFC 4862 sectiion 5.5.3.d.
  1072  	if prefix.Prefix() != validPrefixLenForAutoGen {
  1073  		return
  1074  	}
  1075  
  1076  	state := slaacPrefixState{
  1077  		deprecationJob: tcpip.NewJob(ndp.ep.protocol.stack.Clock(), &ndp.ep.mu, func() {
  1078  			state, ok := ndp.slaacPrefixes[prefix]
  1079  			if !ok {
  1080  				panic(fmt.Sprintf("ndp: must have a slaacPrefixes entry for the deprecated SLAAC prefix %s", prefix))
  1081  			}
  1082  
  1083  			ndp.deprecateSLAACAddress(state.stableAddr.addressEndpoint)
  1084  		}),
  1085  		invalidationJob: tcpip.NewJob(ndp.ep.protocol.stack.Clock(), &ndp.ep.mu, func() {
  1086  			state, ok := ndp.slaacPrefixes[prefix]
  1087  			if !ok {
  1088  				panic(fmt.Sprintf("ndp: must have a slaacPrefixes entry for the invalidated SLAAC prefix %s", prefix))
  1089  			}
  1090  
  1091  			ndp.invalidateSLAACPrefix(prefix, state)
  1092  		}),
  1093  		tempAddrs:             make(map[tcpip.Address]tempSLAACAddrState),
  1094  		maxGenerationAttempts: ndp.configs.AutoGenAddressConflictRetries + 1,
  1095  	}
  1096  
  1097  	now := ndp.ep.protocol.stack.Clock().NowMonotonic()
  1098  
  1099  	// The time an address is preferred until is needed to properly generate the
  1100  	// address.
  1101  	if pl < header.NDPInfiniteLifetime {
  1102  		t := now.Add(pl)
  1103  		state.preferredUntil = &t
  1104  	}
  1105  	// The time at which an address is invalidated is exposed as a property of the
  1106  	// address.
  1107  	if vl < header.NDPInfiniteLifetime {
  1108  		t := now.Add(vl)
  1109  		state.validUntil = &t
  1110  	}
  1111  
  1112  	if !ndp.generateSLAACAddr(prefix, &state) {
  1113  		// We were unable to generate an address for the prefix, we do not nothing
  1114  		// further as there is no reason to maintain state or jobs for a prefix we
  1115  		// do not have an address for.
  1116  		return
  1117  	}
  1118  
  1119  	// Setup the initial jobs to deprecate and invalidate prefix.
  1120  
  1121  	if pl < header.NDPInfiniteLifetime && pl != 0 {
  1122  		state.deprecationJob.Schedule(pl)
  1123  	}
  1124  
  1125  	if vl < header.NDPInfiniteLifetime {
  1126  		state.invalidationJob.Schedule(vl)
  1127  	}
  1128  
  1129  	// If the address is assigned (DAD resolved), generate a temporary address.
  1130  	if state.stableAddr.addressEndpoint.GetKind() == stack.Permanent {
  1131  		// Reset the generation attempts counter as we are starting the generation
  1132  		// of a new address for the SLAAC prefix.
  1133  		ndp.generateTempSLAACAddr(prefix, &state, true /* resetGenAttempts */)
  1134  	}
  1135  
  1136  	ndp.slaacPrefixes[prefix] = state
  1137  }
  1138  
  1139  // addAndAcquireSLAACAddr adds a SLAAC address to the IPv6 endpoint.
  1140  //
  1141  // The IPv6 endpoint that ndp belongs to MUST be locked.
  1142  func (ndp *ndpState) addAndAcquireSLAACAddr(addr tcpip.AddressWithPrefix, temporary bool, lifetimes stack.AddressLifetimes) stack.AddressEndpoint {
  1143  	addressEndpoint, err := ndp.ep.addAndAcquirePermanentAddressLocked(addr, stack.AddressProperties{
  1144  		PEB:        stack.FirstPrimaryEndpoint,
  1145  		ConfigType: stack.AddressConfigSlaac,
  1146  		Lifetimes:  lifetimes,
  1147  		Temporary:  temporary,
  1148  	})
  1149  	if err != nil {
  1150  		panic(fmt.Sprintf("ndp: error when adding SLAAC address %+v: %s", addr, err))
  1151  	}
  1152  
  1153  	// Inform the integrator that we have a new SLAAC address.
  1154  	if ndpDisp := ndp.ep.protocol.options.NDPDisp; ndpDisp != nil {
  1155  		if disp := ndpDisp.OnAutoGenAddress(ndp.ep.nic.ID(), addr); disp != nil {
  1156  			addressEndpoint.RegisterDispatcher(disp)
  1157  		}
  1158  	}
  1159  
  1160  	return addressEndpoint
  1161  }
  1162  
  1163  // generateSLAACAddr generates a SLAAC address for prefix.
  1164  //
  1165  // Returns true if an address was successfully generated.
  1166  //
  1167  // Panics if the prefix is not a SLAAC prefix or it already has an address.
  1168  //
  1169  // The IPv6 endpoint that ndp belongs to MUST be locked.
  1170  func (ndp *ndpState) generateSLAACAddr(prefix tcpip.Subnet, state *slaacPrefixState) bool {
  1171  	if addressEndpoint := state.stableAddr.addressEndpoint; addressEndpoint != nil {
  1172  		panic(fmt.Sprintf("ndp: SLAAC prefix %s already has a permanent address %s", prefix, addressEndpoint.AddressWithPrefix()))
  1173  	}
  1174  
  1175  	// If we have already reached the maximum address generation attempts for the
  1176  	// prefix, do not generate another address.
  1177  	if state.generationAttempts == state.maxGenerationAttempts {
  1178  		return false
  1179  	}
  1180  
  1181  	var generatedAddr tcpip.AddressWithPrefix
  1182  	prefixID := prefix.ID()
  1183  	addrBytes := prefixID.AsSlice()
  1184  
  1185  	for i := 0; ; i++ {
  1186  		// If we were unable to generate an address after the maximum SLAAC address
  1187  		// local regeneration attempts, do nothing further.
  1188  		if i == maxSLAACAddrLocalRegenAttempts {
  1189  			return false
  1190  		}
  1191  
  1192  		dadCounter := state.generationAttempts + state.stableAddr.localGenerationFailures
  1193  		if oIID := ndp.ep.protocol.options.OpaqueIIDOpts; oIID.NICNameFromID != nil {
  1194  			addrBytes = header.AppendOpaqueInterfaceIdentifier(
  1195  				addrBytes[:header.IIDOffsetInIPv6Address],
  1196  				prefix,
  1197  				oIID.NICNameFromID(ndp.ep.nic.ID(), ndp.ep.nic.Name()),
  1198  				dadCounter,
  1199  				oIID.SecretKey,
  1200  			)
  1201  		} else if dadCounter == 0 {
  1202  			// Modified-EUI64 based IIDs have no way to resolve DAD conflicts, so if
  1203  			// the DAD counter is non-zero, we cannot use this method.
  1204  			//
  1205  			// Only attempt to generate an interface-specific IID if we have a valid
  1206  			// link address.
  1207  			//
  1208  			// TODO(b/141011931): Validate a LinkEndpoint's link address (provided by
  1209  			// LinkEndpoint.LinkAddress) before reaching this point.
  1210  			linkAddr := ndp.ep.nic.LinkAddress()
  1211  			if !header.IsValidUnicastEthernetAddress(linkAddr) {
  1212  				return false
  1213  			}
  1214  
  1215  			// Generate an address within prefix from the modified EUI-64 of ndp's
  1216  			// NIC's Ethernet MAC address.
  1217  			header.EthernetAdddressToModifiedEUI64IntoBuf(linkAddr, addrBytes[header.IIDOffsetInIPv6Address:])
  1218  		} else {
  1219  			// We have no way to regenerate an address in response to an address
  1220  			// conflict when addresses are not generated with opaque IIDs.
  1221  			return false
  1222  		}
  1223  
  1224  		generatedAddr = tcpip.AddressWithPrefix{
  1225  			Address:   tcpip.AddrFrom16Slice(addrBytes),
  1226  			PrefixLen: validPrefixLenForAutoGen,
  1227  		}
  1228  
  1229  		if !ndp.ep.hasPermanentAddressRLocked(generatedAddr.Address) {
  1230  			break
  1231  		}
  1232  
  1233  		state.stableAddr.localGenerationFailures++
  1234  	}
  1235  
  1236  	deprecated := state.preferredUntil != nil && !state.preferredUntil.After(ndp.ep.protocol.stack.Clock().NowMonotonic())
  1237  	var preferredUntil tcpip.MonotonicTime
  1238  	if !deprecated {
  1239  		if state.preferredUntil != nil {
  1240  			preferredUntil = *state.preferredUntil
  1241  		} else {
  1242  			preferredUntil = tcpip.MonotonicTimeInfinite()
  1243  		}
  1244  	}
  1245  	validUntil := tcpip.MonotonicTimeInfinite()
  1246  	if state.validUntil != nil {
  1247  		validUntil = *state.validUntil
  1248  	}
  1249  	if addressEndpoint := ndp.addAndAcquireSLAACAddr(generatedAddr, false /* temporary */, stack.AddressLifetimes{
  1250  		Deprecated:     deprecated,
  1251  		PreferredUntil: preferredUntil,
  1252  		ValidUntil:     validUntil,
  1253  	}); addressEndpoint != nil {
  1254  		state.stableAddr.addressEndpoint = addressEndpoint
  1255  		state.generationAttempts++
  1256  		return true
  1257  	}
  1258  
  1259  	return false
  1260  }
  1261  
  1262  // regenerateSLAACAddr regenerates an address for a SLAAC prefix.
  1263  //
  1264  // If generating a new address for the prefix fails, the prefix is invalidated.
  1265  //
  1266  // The IPv6 endpoint that ndp belongs to MUST be locked.
  1267  func (ndp *ndpState) regenerateSLAACAddr(prefix tcpip.Subnet) {
  1268  	state, ok := ndp.slaacPrefixes[prefix]
  1269  	if !ok {
  1270  		panic(fmt.Sprintf("ndp: SLAAC prefix state not found to regenerate address for %s", prefix))
  1271  	}
  1272  
  1273  	if ndp.generateSLAACAddr(prefix, &state) {
  1274  		ndp.slaacPrefixes[prefix] = state
  1275  		return
  1276  	}
  1277  
  1278  	// We were unable to generate a permanent address for the SLAAC prefix so
  1279  	// invalidate the prefix as there is no reason to maintain state for a
  1280  	// SLAAC prefix we do not have an address for.
  1281  	ndp.invalidateSLAACPrefix(prefix, state)
  1282  }
  1283  
  1284  // generateTempSLAACAddr generates a new temporary SLAAC address.
  1285  //
  1286  // If resetGenAttempts is true, the prefix's generation counter is reset.
  1287  //
  1288  // Returns true if a new address was generated.
  1289  func (ndp *ndpState) generateTempSLAACAddr(prefix tcpip.Subnet, prefixState *slaacPrefixState, resetGenAttempts bool) bool {
  1290  	// Are we configured to auto-generate new temporary global addresses for the
  1291  	// prefix?
  1292  	if !ndp.configs.AutoGenTempGlobalAddresses || prefix == header.IPv6LinkLocalPrefix.Subnet() {
  1293  		return false
  1294  	}
  1295  
  1296  	if resetGenAttempts {
  1297  		prefixState.generationAttempts = 0
  1298  		prefixState.maxGenerationAttempts = ndp.configs.AutoGenAddressConflictRetries + 1
  1299  	}
  1300  
  1301  	// If we have already reached the maximum address generation attempts for the
  1302  	// prefix, do not generate another address.
  1303  	if prefixState.generationAttempts == prefixState.maxGenerationAttempts {
  1304  		return false
  1305  	}
  1306  
  1307  	stableAddr := prefixState.stableAddr.addressEndpoint.AddressWithPrefix().Address
  1308  	now := ndp.ep.protocol.stack.Clock().NowMonotonic()
  1309  
  1310  	// As per RFC 4941 section 3.3 step 4, the valid lifetime of a temporary
  1311  	// address is the lower of the valid lifetime of the stable address or the
  1312  	// maximum temporary address valid lifetime.
  1313  	vl := ndp.configs.MaxTempAddrValidLifetime
  1314  	if prefixState.validUntil != nil {
  1315  		if prefixVL := prefixState.validUntil.Sub(now); vl > prefixVL {
  1316  			vl = prefixVL
  1317  		}
  1318  	}
  1319  
  1320  	if vl <= 0 {
  1321  		// Cannot create an address without a valid lifetime.
  1322  		return false
  1323  	}
  1324  
  1325  	// As per RFC 4941 section 3.3 step 4, the preferred lifetime of a temporary
  1326  	// address is the lower of the preferred lifetime of the stable address or the
  1327  	// maximum temporary address preferred lifetime - the temporary address desync
  1328  	// factor.
  1329  	pl := ndp.configs.MaxTempAddrPreferredLifetime - ndp.temporaryAddressDesyncFactor
  1330  	if prefixState.preferredUntil != nil {
  1331  		if prefixPL := prefixState.preferredUntil.Sub(now); pl > prefixPL {
  1332  			// Respect the preferred lifetime of the prefix, as per RFC 4941 section
  1333  			// 3.3 step 4.
  1334  			pl = prefixPL
  1335  		}
  1336  	}
  1337  
  1338  	// As per RFC 4941 section 3.3 step 5, a temporary address is created only if
  1339  	// the calculated preferred lifetime is greater than the advance regeneration
  1340  	// duration. In particular, we MUST NOT create a temporary address with a zero
  1341  	// Preferred Lifetime.
  1342  	if pl <= ndp.configs.RegenAdvanceDuration {
  1343  		return false
  1344  	}
  1345  
  1346  	// Attempt to generate a new address that is not already assigned to the IPv6
  1347  	// endpoint.
  1348  	var generatedAddr tcpip.AddressWithPrefix
  1349  	for i := 0; ; i++ {
  1350  		// If we were unable to generate an address after the maximum SLAAC address
  1351  		// local regeneration attempts, do nothing further.
  1352  		if i == maxSLAACAddrLocalRegenAttempts {
  1353  			return false
  1354  		}
  1355  
  1356  		generatedAddr = header.GenerateTempIPv6SLAACAddr(ndp.temporaryIIDHistory[:], stableAddr)
  1357  		if !ndp.ep.hasPermanentAddressRLocked(generatedAddr.Address) {
  1358  			break
  1359  		}
  1360  	}
  1361  
  1362  	// As per RFC RFC 4941 section 3.3 step 5, we MUST NOT create a temporary
  1363  	// address with a zero preferred lifetime. The checks above ensure this
  1364  	// so we know the address is not deprecated.
  1365  	addressEndpoint := ndp.addAndAcquireSLAACAddr(generatedAddr, true /* temporary */, stack.AddressLifetimes{
  1366  		Deprecated:     false,
  1367  		PreferredUntil: now.Add(pl),
  1368  		ValidUntil:     now.Add(vl),
  1369  	})
  1370  	if addressEndpoint == nil {
  1371  		return false
  1372  	}
  1373  
  1374  	state := tempSLAACAddrState{
  1375  		deprecationJob: tcpip.NewJob(ndp.ep.protocol.stack.Clock(), &ndp.ep.mu, func() {
  1376  			prefixState, ok := ndp.slaacPrefixes[prefix]
  1377  			if !ok {
  1378  				panic(fmt.Sprintf("ndp: must have a slaacPrefixes entry for %s to deprecate temporary address %s", prefix, generatedAddr))
  1379  			}
  1380  
  1381  			tempAddrState, ok := prefixState.tempAddrs[generatedAddr.Address]
  1382  			if !ok {
  1383  				panic(fmt.Sprintf("ndp: must have a tempAddr entry to deprecate temporary address %s", generatedAddr))
  1384  			}
  1385  
  1386  			ndp.deprecateSLAACAddress(tempAddrState.addressEndpoint)
  1387  		}),
  1388  		invalidationJob: tcpip.NewJob(ndp.ep.protocol.stack.Clock(), &ndp.ep.mu, func() {
  1389  			prefixState, ok := ndp.slaacPrefixes[prefix]
  1390  			if !ok {
  1391  				panic(fmt.Sprintf("ndp: must have a slaacPrefixes entry for %s to invalidate temporary address %s", prefix, generatedAddr))
  1392  			}
  1393  
  1394  			tempAddrState, ok := prefixState.tempAddrs[generatedAddr.Address]
  1395  			if !ok {
  1396  				panic(fmt.Sprintf("ndp: must have a tempAddr entry to invalidate temporary address %s", generatedAddr))
  1397  			}
  1398  
  1399  			ndp.invalidateTempSLAACAddr(prefixState.tempAddrs, generatedAddr.Address, tempAddrState)
  1400  		}),
  1401  		regenJob: tcpip.NewJob(ndp.ep.protocol.stack.Clock(), &ndp.ep.mu, func() {
  1402  			prefixState, ok := ndp.slaacPrefixes[prefix]
  1403  			if !ok {
  1404  				panic(fmt.Sprintf("ndp: must have a slaacPrefixes entry for %s to regenerate temporary address after %s", prefix, generatedAddr))
  1405  			}
  1406  
  1407  			tempAddrState, ok := prefixState.tempAddrs[generatedAddr.Address]
  1408  			if !ok {
  1409  				panic(fmt.Sprintf("ndp: must have a tempAddr entry to regenerate temporary address after %s", generatedAddr))
  1410  			}
  1411  
  1412  			// If an address has already been regenerated for this address, don't
  1413  			// regenerate another address.
  1414  			if tempAddrState.regenerated {
  1415  				return
  1416  			}
  1417  
  1418  			// Reset the generation attempts counter as we are starting the generation
  1419  			// of a new address for the SLAAC prefix.
  1420  			tempAddrState.regenerated = ndp.generateTempSLAACAddr(prefix, &prefixState, true /* resetGenAttempts */)
  1421  			prefixState.tempAddrs[generatedAddr.Address] = tempAddrState
  1422  			ndp.slaacPrefixes[prefix] = prefixState
  1423  		}),
  1424  		createdAt:       now,
  1425  		addressEndpoint: addressEndpoint,
  1426  	}
  1427  
  1428  	state.deprecationJob.Schedule(pl)
  1429  	state.invalidationJob.Schedule(vl)
  1430  	state.regenJob.Schedule(pl - ndp.configs.RegenAdvanceDuration)
  1431  
  1432  	prefixState.generationAttempts++
  1433  	prefixState.tempAddrs[generatedAddr.Address] = state
  1434  
  1435  	return true
  1436  }
  1437  
  1438  // regenerateTempSLAACAddr regenerates a temporary address for a SLAAC prefix.
  1439  //
  1440  // The IPv6 endpoint that ndp belongs to MUST be locked.
  1441  func (ndp *ndpState) regenerateTempSLAACAddr(prefix tcpip.Subnet, resetGenAttempts bool) {
  1442  	state, ok := ndp.slaacPrefixes[prefix]
  1443  	if !ok {
  1444  		panic(fmt.Sprintf("ndp: SLAAC prefix state not found to regenerate temporary address for %s", prefix))
  1445  	}
  1446  
  1447  	ndp.generateTempSLAACAddr(prefix, &state, resetGenAttempts)
  1448  	ndp.slaacPrefixes[prefix] = state
  1449  }
  1450  
  1451  // refreshSLAACPrefixLifetimes refreshes the lifetimes of a SLAAC prefix.
  1452  //
  1453  // pl is the new preferred lifetime. vl is the new valid lifetime.
  1454  //
  1455  // The IPv6 endpoint that ndp belongs to MUST be locked.
  1456  func (ndp *ndpState) refreshSLAACPrefixLifetimes(prefix tcpip.Subnet, prefixState *slaacPrefixState, pl, vl time.Duration) {
  1457  	// If prefix was preferred for some finite lifetime before, cancel the
  1458  	// deprecation job so it can be reset.
  1459  	prefixState.deprecationJob.Cancel()
  1460  
  1461  	now := ndp.ep.protocol.stack.Clock().NowMonotonic()
  1462  
  1463  	// Schedule the deprecation job if prefix has a finite preferred lifetime.
  1464  	deprecated := pl == 0
  1465  	if pl < header.NDPInfiniteLifetime {
  1466  		if !deprecated {
  1467  			prefixState.deprecationJob.Schedule(pl)
  1468  		}
  1469  		t := now.Add(pl)
  1470  		prefixState.preferredUntil = &t
  1471  	} else {
  1472  		prefixState.preferredUntil = nil
  1473  	}
  1474  
  1475  	// As per RFC 4862 section 5.5.3.e, update the valid lifetime for prefix:
  1476  	//
  1477  	// 1) If the received Valid Lifetime is greater than 2 hours or greater than
  1478  	//    RemainingLifetime, set the valid lifetime of the prefix to the
  1479  	//    advertised Valid Lifetime.
  1480  	//
  1481  	// 2) If RemainingLifetime is less than or equal to 2 hours, ignore the
  1482  	//    advertised Valid Lifetime.
  1483  	//
  1484  	// 3) Otherwise, reset the valid lifetime of the prefix to 2 hours.
  1485  
  1486  	if vl >= header.NDPInfiniteLifetime {
  1487  		// Handle the infinite valid lifetime separately as we do not schedule a
  1488  		// job in this case.
  1489  		prefixState.invalidationJob.Cancel()
  1490  		prefixState.validUntil = nil
  1491  	} else {
  1492  		var effectiveVl time.Duration
  1493  		var rl time.Duration
  1494  
  1495  		// If the prefix was originally set to be valid forever, assume the
  1496  		// remaining time to be the maximum possible value.
  1497  		if prefixState.validUntil == nil {
  1498  			rl = header.NDPInfiniteLifetime
  1499  		} else {
  1500  			rl = prefixState.validUntil.Sub(now)
  1501  		}
  1502  
  1503  		if vl > MinPrefixInformationValidLifetimeForUpdate || vl > rl {
  1504  			effectiveVl = vl
  1505  		} else if rl > MinPrefixInformationValidLifetimeForUpdate {
  1506  			effectiveVl = MinPrefixInformationValidLifetimeForUpdate
  1507  		}
  1508  
  1509  		if effectiveVl != 0 {
  1510  			prefixState.invalidationJob.Cancel()
  1511  			prefixState.invalidationJob.Schedule(effectiveVl)
  1512  			t := now.Add(effectiveVl)
  1513  			prefixState.validUntil = &t
  1514  		}
  1515  	}
  1516  
  1517  	// If the preferred lifetime is zero, then the prefix should be deprecated.
  1518  	{
  1519  		var preferredUntil tcpip.MonotonicTime
  1520  		if !deprecated {
  1521  			if prefixState.preferredUntil == nil {
  1522  				preferredUntil = tcpip.MonotonicTimeInfinite()
  1523  			} else {
  1524  				preferredUntil = *prefixState.preferredUntil
  1525  			}
  1526  		}
  1527  		validUntil := tcpip.MonotonicTimeInfinite()
  1528  		if prefixState.validUntil != nil {
  1529  			validUntil = *prefixState.validUntil
  1530  		}
  1531  		if addressEndpoint := prefixState.stableAddr.addressEndpoint; !addressEndpoint.Deprecated() && deprecated {
  1532  			if ndpDisp := ndp.ep.protocol.options.NDPDisp; ndpDisp != nil {
  1533  				ndpDisp.OnAutoGenAddressDeprecated(ndp.ep.nic.ID(), addressEndpoint.AddressWithPrefix())
  1534  			}
  1535  		}
  1536  		prefixState.stableAddr.addressEndpoint.SetLifetimes(stack.AddressLifetimes{
  1537  			Deprecated:     deprecated,
  1538  			PreferredUntil: preferredUntil,
  1539  			ValidUntil:     validUntil,
  1540  		})
  1541  	}
  1542  
  1543  	// If DAD is not yet complete on the stable address, there is no need to do
  1544  	// work with temporary addresses.
  1545  	if prefixState.stableAddr.addressEndpoint.GetKind() != stack.Permanent {
  1546  		return
  1547  	}
  1548  
  1549  	// Note, we do not need to update the entries in the temporary address map
  1550  	// after updating the jobs because the jobs are held as pointers.
  1551  	var regenForAddr tcpip.Address
  1552  	allAddressesRegenerated := true
  1553  	for tempAddr, tempAddrState := range prefixState.tempAddrs {
  1554  		// As per RFC 4941 section 3.3 step 4, the valid lifetime of a temporary
  1555  		// address is the lower of the valid lifetime of the stable address or the
  1556  		// maximum temporary address valid lifetime. Note, the valid lifetime of a
  1557  		// temporary address is relative to the address's creation time.
  1558  		validUntil := tempAddrState.createdAt.Add(ndp.configs.MaxTempAddrValidLifetime)
  1559  		if prefixState.validUntil != nil && prefixState.validUntil.Before(validUntil) {
  1560  			validUntil = *prefixState.validUntil
  1561  		}
  1562  
  1563  		// If the address is no longer valid, invalidate it immediately. Otherwise,
  1564  		// reset the invalidation job.
  1565  		newValidLifetime := validUntil.Sub(now)
  1566  		if newValidLifetime <= 0 {
  1567  			ndp.invalidateTempSLAACAddr(prefixState.tempAddrs, tempAddr, tempAddrState)
  1568  			continue
  1569  		}
  1570  		tempAddrState.invalidationJob.Cancel()
  1571  		tempAddrState.invalidationJob.Schedule(newValidLifetime)
  1572  
  1573  		// As per RFC 4941 section 3.3 step 4, the preferred lifetime of a temporary
  1574  		// address is the lower of the preferred lifetime of the stable address or
  1575  		// the maximum temporary address preferred lifetime - the temporary address
  1576  		// desync factor. Note, the preferred lifetime of a temporary address is
  1577  		// relative to the address's creation time.
  1578  		preferredUntil := tempAddrState.createdAt.Add(ndp.configs.MaxTempAddrPreferredLifetime - ndp.temporaryAddressDesyncFactor)
  1579  		if prefixState.preferredUntil != nil && prefixState.preferredUntil.Before(preferredUntil) {
  1580  			preferredUntil = *prefixState.preferredUntil
  1581  		}
  1582  
  1583  		// If the address is no longer preferred, deprecate it immediately.
  1584  		// Otherwise, schedule the deprecation job again.
  1585  		newPreferredLifetime := preferredUntil.Sub(now)
  1586  		tempAddrState.deprecationJob.Cancel()
  1587  		deprecated := newPreferredLifetime <= 0
  1588  		if !deprecated {
  1589  			tempAddrState.deprecationJob.Schedule(newPreferredLifetime)
  1590  		}
  1591  
  1592  		if addressEndpoint := tempAddrState.addressEndpoint; !addressEndpoint.Deprecated() && deprecated {
  1593  			if ndpDisp := ndp.ep.protocol.options.NDPDisp; ndpDisp != nil {
  1594  				ndpDisp.OnAutoGenAddressDeprecated(ndp.ep.nic.ID(), addressEndpoint.AddressWithPrefix())
  1595  			}
  1596  		}
  1597  		tempAddrState.addressEndpoint.SetLifetimes(stack.AddressLifetimes{
  1598  			Deprecated:     deprecated,
  1599  			ValidUntil:     validUntil,
  1600  			PreferredUntil: preferredUntil,
  1601  		})
  1602  
  1603  		tempAddrState.regenJob.Cancel()
  1604  		if tempAddrState.regenerated {
  1605  		} else {
  1606  			allAddressesRegenerated = false
  1607  
  1608  			if newPreferredLifetime <= ndp.configs.RegenAdvanceDuration {
  1609  				// The new preferred lifetime is less than the advance regeneration
  1610  				// duration so regenerate an address for this temporary address
  1611  				// immediately after we finish iterating over the temporary addresses.
  1612  				regenForAddr = tempAddr
  1613  			} else {
  1614  				tempAddrState.regenJob.Schedule(newPreferredLifetime - ndp.configs.RegenAdvanceDuration)
  1615  			}
  1616  		}
  1617  	}
  1618  
  1619  	// Generate a new temporary address if all of the existing temporary addresses
  1620  	// have been regenerated, or we need to immediately regenerate an address
  1621  	// due to an update in preferred lifetime.
  1622  	//
  1623  	// If each temporary address has already been regenerated, no new temporary
  1624  	// address is generated. To ensure continuation of temporary SLAAC addresses,
  1625  	// we manually try to regenerate an address here.
  1626  	if regenForAddr.BitLen() != 0 || allAddressesRegenerated {
  1627  		// Reset the generation attempts counter as we are starting the generation
  1628  		// of a new address for the SLAAC prefix.
  1629  		if state, ok := prefixState.tempAddrs[regenForAddr]; ndp.generateTempSLAACAddr(prefix, prefixState, true /* resetGenAttempts */) && ok {
  1630  			state.regenerated = true
  1631  			prefixState.tempAddrs[regenForAddr] = state
  1632  		}
  1633  	}
  1634  }
  1635  
  1636  // deprecateSLAACAddress marks the address as deprecated and notifies the NDP
  1637  // dispatcher that address has been deprecated.
  1638  //
  1639  // deprecateSLAACAddress does nothing if the address is already deprecated.
  1640  //
  1641  // The IPv6 endpoint that ndp belongs to MUST be locked.
  1642  func (ndp *ndpState) deprecateSLAACAddress(addressEndpoint stack.AddressEndpoint) {
  1643  	if addressEndpoint.Deprecated() {
  1644  		return
  1645  	}
  1646  
  1647  	addressEndpoint.SetDeprecated(true)
  1648  	if ndpDisp := ndp.ep.protocol.options.NDPDisp; ndpDisp != nil {
  1649  		ndpDisp.OnAutoGenAddressDeprecated(ndp.ep.nic.ID(), addressEndpoint.AddressWithPrefix())
  1650  	}
  1651  }
  1652  
  1653  // invalidateSLAACPrefix invalidates a SLAAC prefix.
  1654  //
  1655  // The IPv6 endpoint that ndp belongs to MUST be locked.
  1656  func (ndp *ndpState) invalidateSLAACPrefix(prefix tcpip.Subnet, state slaacPrefixState) {
  1657  	ndp.cleanupSLAACPrefixResources(prefix, state)
  1658  
  1659  	if addressEndpoint := state.stableAddr.addressEndpoint; addressEndpoint != nil {
  1660  		if ndpDisp := ndp.ep.protocol.options.NDPDisp; ndpDisp != nil {
  1661  			ndpDisp.OnAutoGenAddressInvalidated(ndp.ep.nic.ID(), addressEndpoint.AddressWithPrefix())
  1662  		}
  1663  
  1664  		if err := ndp.ep.removePermanentEndpointInnerLocked(addressEndpoint, stack.AddressRemovalInvalidated, &stack.DADAborted{}); err != nil {
  1665  			panic(fmt.Sprintf("ndp: error removing stable SLAAC address %s: %s", addressEndpoint.AddressWithPrefix(), err))
  1666  		}
  1667  	}
  1668  }
  1669  
  1670  // cleanupSLAACAddrResourcesAndNotify cleans up an invalidated SLAAC address's
  1671  // resources.
  1672  //
  1673  // The IPv6 endpoint that ndp belongs to MUST be locked.
  1674  func (ndp *ndpState) cleanupSLAACAddrResourcesAndNotify(addr tcpip.AddressWithPrefix, invalidatePrefix bool) {
  1675  	if ndpDisp := ndp.ep.protocol.options.NDPDisp; ndpDisp != nil {
  1676  		ndpDisp.OnAutoGenAddressInvalidated(ndp.ep.nic.ID(), addr)
  1677  	}
  1678  
  1679  	prefix := addr.Subnet()
  1680  	state, ok := ndp.slaacPrefixes[prefix]
  1681  	if !ok || state.stableAddr.addressEndpoint == nil || addr.Address != state.stableAddr.addressEndpoint.AddressWithPrefix().Address {
  1682  		return
  1683  	}
  1684  
  1685  	if !invalidatePrefix {
  1686  		// If the prefix is not being invalidated, disassociate the address from the
  1687  		// prefix and do nothing further.
  1688  		state.stableAddr.addressEndpoint.DecRef()
  1689  		state.stableAddr.addressEndpoint = nil
  1690  		ndp.slaacPrefixes[prefix] = state
  1691  		return
  1692  	}
  1693  
  1694  	ndp.cleanupSLAACPrefixResources(prefix, state)
  1695  }
  1696  
  1697  // cleanupSLAACPrefixResources cleans up a SLAAC prefix's jobs and entry.
  1698  //
  1699  // Panics if the SLAAC prefix is not known.
  1700  //
  1701  // The IPv6 endpoint that ndp belongs to MUST be locked.
  1702  func (ndp *ndpState) cleanupSLAACPrefixResources(prefix tcpip.Subnet, state slaacPrefixState) {
  1703  	// Invalidate all temporary addresses.
  1704  	for tempAddr, tempAddrState := range state.tempAddrs {
  1705  		ndp.invalidateTempSLAACAddr(state.tempAddrs, tempAddr, tempAddrState)
  1706  	}
  1707  
  1708  	if state.stableAddr.addressEndpoint != nil {
  1709  		state.stableAddr.addressEndpoint.DecRef()
  1710  		state.stableAddr.addressEndpoint = nil
  1711  	}
  1712  	state.deprecationJob.Cancel()
  1713  	state.invalidationJob.Cancel()
  1714  	delete(ndp.slaacPrefixes, prefix)
  1715  }
  1716  
  1717  // invalidateTempSLAACAddr invalidates a temporary SLAAC address.
  1718  //
  1719  // The IPv6 endpoint that ndp belongs to MUST be locked.
  1720  func (ndp *ndpState) invalidateTempSLAACAddr(tempAddrs map[tcpip.Address]tempSLAACAddrState, tempAddr tcpip.Address, tempAddrState tempSLAACAddrState) {
  1721  	ndp.cleanupTempSLAACAddrResourcesAndNotifyInner(tempAddrs, tempAddr, tempAddrState)
  1722  
  1723  	if err := ndp.ep.removePermanentEndpointInnerLocked(tempAddrState.addressEndpoint, stack.AddressRemovalInvalidated, &stack.DADAborted{}); err != nil {
  1724  		panic(fmt.Sprintf("error removing temporary SLAAC address %s: %s", tempAddrState.addressEndpoint.AddressWithPrefix(), err))
  1725  	}
  1726  }
  1727  
  1728  // cleanupTempSLAACAddrResourcesAndNotify cleans up an invalidated temporary
  1729  // SLAAC address's resources from ndp and notifies the NDP dispatcher that the
  1730  // address was invalidated.
  1731  //
  1732  // The IPv6 endpoint that ndp belongs to MUST be locked.
  1733  func (ndp *ndpState) cleanupTempSLAACAddrResourcesAndNotify(addr tcpip.AddressWithPrefix) {
  1734  	prefix := addr.Subnet()
  1735  	state, ok := ndp.slaacPrefixes[prefix]
  1736  	if !ok {
  1737  		panic(fmt.Sprintf("ndp: must have a slaacPrefixes entry to clean up temp addr %s resources", addr))
  1738  	}
  1739  
  1740  	tempAddrState, ok := state.tempAddrs[addr.Address]
  1741  	if !ok {
  1742  		panic(fmt.Sprintf("ndp: must have a tempAddr entry to clean up temp addr %s resources", addr))
  1743  	}
  1744  
  1745  	ndp.cleanupTempSLAACAddrResourcesAndNotifyInner(state.tempAddrs, addr.Address, tempAddrState)
  1746  }
  1747  
  1748  // cleanupTempSLAACAddrResourcesAndNotifyInner is like
  1749  // cleanupTempSLAACAddrResourcesAndNotify except it does not lookup the
  1750  // temporary address's state in ndp - it assumes the passed state is valid.
  1751  //
  1752  // The IPv6 endpoint that ndp belongs to MUST be locked.
  1753  func (ndp *ndpState) cleanupTempSLAACAddrResourcesAndNotifyInner(tempAddrs map[tcpip.Address]tempSLAACAddrState, tempAddr tcpip.Address, tempAddrState tempSLAACAddrState) {
  1754  	if ndpDisp := ndp.ep.protocol.options.NDPDisp; ndpDisp != nil {
  1755  		ndpDisp.OnAutoGenAddressInvalidated(ndp.ep.nic.ID(), tempAddrState.addressEndpoint.AddressWithPrefix())
  1756  	}
  1757  
  1758  	tempAddrState.addressEndpoint.DecRef()
  1759  	tempAddrState.addressEndpoint = nil
  1760  	tempAddrState.deprecationJob.Cancel()
  1761  	tempAddrState.invalidationJob.Cancel()
  1762  	tempAddrState.regenJob.Cancel()
  1763  	delete(tempAddrs, tempAddr)
  1764  }
  1765  
  1766  // cleanupState cleans up ndp's state.
  1767  //
  1768  // This function invalidates all discovered on-link prefixes, discovered
  1769  // routers, and auto-generated addresses.
  1770  //
  1771  // The IPv6 endpoint that ndp belongs to MUST be locked.
  1772  func (ndp *ndpState) cleanupState() {
  1773  	for prefix, state := range ndp.slaacPrefixes {
  1774  		ndp.invalidateSLAACPrefix(prefix, state)
  1775  	}
  1776  
  1777  	for prefix := range ndp.onLinkPrefixes {
  1778  		ndp.invalidateOnLinkPrefix(prefix)
  1779  	}
  1780  
  1781  	if got := len(ndp.onLinkPrefixes); got != 0 {
  1782  		panic(fmt.Sprintf("ndp: still have discovered on-link prefixes after cleaning up; found = %d", got))
  1783  	}
  1784  
  1785  	for route := range ndp.offLinkRoutes {
  1786  		ndp.invalidateOffLinkRoute(route)
  1787  	}
  1788  
  1789  	if got := len(ndp.offLinkRoutes); got != 0 {
  1790  		panic(fmt.Sprintf("ndp: still have discovered off-link routes after cleaning up; found = %d", got))
  1791  	}
  1792  
  1793  	ndp.dhcpv6Configuration = 0
  1794  }
  1795  
  1796  // startSolicitingRouters starts soliciting routers, as per RFC 4861 section
  1797  // 6.3.7. If routers are already being solicited, this function does nothing.
  1798  //
  1799  // If ndp is not configured to handle Router Advertisements, routers will not
  1800  // be solicited as there is no point soliciting routers if we don't handle their
  1801  // advertisements.
  1802  //
  1803  // The IPv6 endpoint that ndp belongs to MUST be locked.
  1804  func (ndp *ndpState) startSolicitingRouters() {
  1805  	if ndp.rtrSolicitTimer.timer != nil {
  1806  		// We are already soliciting routers.
  1807  		return
  1808  	}
  1809  
  1810  	remaining := ndp.configs.MaxRtrSolicitations
  1811  	if remaining == 0 {
  1812  		return
  1813  	}
  1814  
  1815  	if !ndp.configs.HandleRAs.enabled(ndp.ep.Forwarding()) {
  1816  		return
  1817  	}
  1818  
  1819  	// Calculate the random delay before sending our first RS, as per RFC
  1820  	// 4861 section 6.3.7.
  1821  	var delay time.Duration
  1822  	if ndp.configs.MaxRtrSolicitationDelay > 0 {
  1823  		delay = time.Duration(ndp.ep.protocol.stack.InsecureRNG().Int63n(int64(ndp.configs.MaxRtrSolicitationDelay)))
  1824  	}
  1825  
  1826  	// Protected by ndp.ep.mu.
  1827  	done := false
  1828  
  1829  	ndp.rtrSolicitTimer = timer{
  1830  		done: &done,
  1831  		timer: ndp.ep.protocol.stack.Clock().AfterFunc(delay, func() {
  1832  			// As per RFC 4861 section 4.1:
  1833  			//
  1834  			//   IP Fields:
  1835  			//     Source Address
  1836  			//       An IP address assigned to the sending interface, or
  1837  			//       the unspecified address if no address is assigned
  1838  			//       to the sending interface.
  1839  			localAddr := header.IPv6Any
  1840  			if addressEndpoint := ndp.ep.AcquireOutgoingPrimaryAddress(header.IPv6AllRoutersLinkLocalMulticastAddress, tcpip.Address{} /* srcHint */, false); addressEndpoint != nil {
  1841  				localAddr = addressEndpoint.AddressWithPrefix().Address
  1842  				addressEndpoint.DecRef()
  1843  			}
  1844  
  1845  			// As per RFC 4861 section 4.1, an NDP RS SHOULD include the source
  1846  			// link-layer address option if the source address of the NDP RS is
  1847  			// specified. This option MUST NOT be included if the source address is
  1848  			// unspecified.
  1849  			//
  1850  			// TODO(b/141011931): Validate a LinkEndpoint's link address (provided by
  1851  			// LinkEndpoint.LinkAddress) before reaching this point.
  1852  			var optsSerializer header.NDPOptionsSerializer
  1853  			linkAddress := ndp.ep.nic.LinkAddress()
  1854  			if localAddr != header.IPv6Any && header.IsValidUnicastEthernetAddress(linkAddress) {
  1855  				optsSerializer = header.NDPOptionsSerializer{
  1856  					header.NDPSourceLinkLayerAddressOption(linkAddress),
  1857  				}
  1858  			}
  1859  			payloadSize := header.ICMPv6HeaderSize + header.NDPRSMinimumSize + optsSerializer.Length()
  1860  			icmpView := buffer.NewView(payloadSize)
  1861  			icmpView.Grow(payloadSize)
  1862  			icmpData := header.ICMPv6(icmpView.AsSlice())
  1863  			icmpData.SetType(header.ICMPv6RouterSolicit)
  1864  			rs := header.NDPRouterSolicit(icmpData.MessageBody())
  1865  			rs.Options().Serialize(optsSerializer)
  1866  			icmpData.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{
  1867  				Header: icmpData,
  1868  				Src:    localAddr,
  1869  				Dst:    header.IPv6AllRoutersLinkLocalMulticastAddress,
  1870  			}))
  1871  
  1872  			pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
  1873  				ReserveHeaderBytes: int(ndp.ep.MaxHeaderLength()),
  1874  				Payload:            buffer.MakeWithView(icmpView),
  1875  			})
  1876  			defer pkt.DecRef()
  1877  
  1878  			sent := ndp.ep.stats.icmp.packetsSent
  1879  			if err := addIPHeader(localAddr, header.IPv6AllRoutersLinkLocalMulticastAddress, pkt, stack.NetworkHeaderParams{
  1880  				Protocol: header.ICMPv6ProtocolNumber,
  1881  				TTL:      header.NDPHopLimit,
  1882  			}, nil /* extensionHeaders */); err != nil {
  1883  				panic(fmt.Sprintf("failed to add IP header: %s", err))
  1884  			}
  1885  
  1886  			if err := ndp.ep.nic.WritePacketToRemote(header.EthernetAddressFromMulticastIPv6Address(header.IPv6AllRoutersLinkLocalMulticastAddress), pkt); err != nil {
  1887  				sent.dropped.Increment()
  1888  				// Don't send any more messages if we had an error.
  1889  				remaining = 0
  1890  			} else {
  1891  				sent.routerSolicit.Increment()
  1892  				remaining--
  1893  			}
  1894  
  1895  			ndp.ep.mu.Lock()
  1896  			defer ndp.ep.mu.Unlock()
  1897  
  1898  			if done {
  1899  				// Router solicitation was stopped.
  1900  				return
  1901  			}
  1902  
  1903  			if remaining == 0 {
  1904  				// We are done soliciting routers.
  1905  				ndp.stopSolicitingRouters()
  1906  				return
  1907  			}
  1908  
  1909  			ndp.rtrSolicitTimer.timer.Reset(ndp.configs.RtrSolicitationInterval)
  1910  		}),
  1911  	}
  1912  }
  1913  
  1914  // forwardingChanged handles a change in forwarding configuration.
  1915  //
  1916  // If transitioning to a host, router solicitation will be started. Otherwise,
  1917  // router solicitation will be stopped if NDP is not configured to handle RAs
  1918  // as a router.
  1919  //
  1920  // Precondition: ndp.ep.mu must be locked.
  1921  func (ndp *ndpState) forwardingChanged(forwarding bool) {
  1922  	if forwarding {
  1923  		if ndp.configs.HandleRAs.enabled(forwarding) {
  1924  			return
  1925  		}
  1926  
  1927  		ndp.stopSolicitingRouters()
  1928  		return
  1929  	}
  1930  
  1931  	// Solicit routers when transitioning to a host.
  1932  	//
  1933  	// If the endpoint is not currently enabled, routers will be solicited when
  1934  	// the endpoint becomes enabled (if it is still a host).
  1935  	if ndp.ep.Enabled() {
  1936  		ndp.startSolicitingRouters()
  1937  	}
  1938  }
  1939  
  1940  // stopSolicitingRouters stops soliciting routers. If routers are not currently
  1941  // being solicited, this function does nothing.
  1942  //
  1943  // The IPv6 endpoint that ndp belongs to MUST be locked.
  1944  func (ndp *ndpState) stopSolicitingRouters() {
  1945  	if ndp.rtrSolicitTimer.timer == nil {
  1946  		// Nothing to do.
  1947  		return
  1948  	}
  1949  
  1950  	ndp.rtrSolicitTimer.timer.Stop()
  1951  	*ndp.rtrSolicitTimer.done = true
  1952  	ndp.rtrSolicitTimer = timer{}
  1953  }
  1954  
  1955  func (ndp *ndpState) init(ep *endpoint, dadOptions ip.DADOptions) {
  1956  	if ndp.offLinkRoutes != nil {
  1957  		panic("attempted to initialize NDP state twice")
  1958  	}
  1959  
  1960  	ndp.ep = ep
  1961  	ndp.configs = ep.protocol.options.NDPConfigs
  1962  	ndp.dad.Init(&ndp.ep.mu, ep.protocol.options.DADConfigs, dadOptions)
  1963  	ndp.offLinkRoutes = make(map[offLinkRoute]offLinkRouteState)
  1964  	ndp.onLinkPrefixes = make(map[tcpip.Subnet]onLinkPrefixState)
  1965  	ndp.slaacPrefixes = make(map[tcpip.Subnet]slaacPrefixState)
  1966  
  1967  	header.InitialTempIID(ndp.temporaryIIDHistory[:], ndp.ep.protocol.options.TempIIDSeed, ndp.ep.nic.ID())
  1968  	ndp.temporaryAddressDesyncFactor = time.Duration(ep.protocol.stack.InsecureRNG().Int63n(int64(MaxDesyncFactor)))
  1969  }
  1970  
  1971  func (ndp *ndpState) SendDADMessage(addr tcpip.Address, nonce []byte) tcpip.Error {
  1972  	snmc := header.SolicitedNodeAddr(addr)
  1973  	return ndp.ep.sendNDPNS(header.IPv6Any, snmc, addr, header.EthernetAddressFromMulticastIPv6Address(snmc), header.NDPOptionsSerializer{
  1974  		header.NDPNonceOption(nonce),
  1975  	})
  1976  }
  1977  
  1978  func (e *endpoint) sendNDPNS(srcAddr, dstAddr, targetAddr tcpip.Address, remoteLinkAddr tcpip.LinkAddress, opts header.NDPOptionsSerializer) tcpip.Error {
  1979  	icmpView := buffer.NewView(header.ICMPv6NeighborSolicitMinimumSize + opts.Length())
  1980  	icmpView.Grow(header.ICMPv6NeighborSolicitMinimumSize + opts.Length())
  1981  	icmp := header.ICMPv6(icmpView.AsSlice())
  1982  	icmp.SetType(header.ICMPv6NeighborSolicit)
  1983  	ns := header.NDPNeighborSolicit(icmp.MessageBody())
  1984  	ns.SetTargetAddress(targetAddr)
  1985  	ns.Options().Serialize(opts)
  1986  	icmp.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{
  1987  		Header: icmp,
  1988  		Src:    srcAddr,
  1989  		Dst:    dstAddr,
  1990  	}))
  1991  
  1992  	pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
  1993  		ReserveHeaderBytes: int(e.MaxHeaderLength()),
  1994  		Payload:            buffer.MakeWithView(icmpView),
  1995  	})
  1996  	defer pkt.DecRef()
  1997  
  1998  	if err := addIPHeader(srcAddr, dstAddr, pkt, stack.NetworkHeaderParams{
  1999  		Protocol: header.ICMPv6ProtocolNumber,
  2000  		TTL:      header.NDPHopLimit,
  2001  	}, nil /* extensionHeaders */); err != nil {
  2002  		panic(fmt.Sprintf("failed to add IP header: %s", err))
  2003  	}
  2004  
  2005  	sent := e.stats.icmp.packetsSent
  2006  	err := e.nic.WritePacketToRemote(remoteLinkAddr, pkt)
  2007  	if err != nil {
  2008  		sent.dropped.Increment()
  2009  	} else {
  2010  		sent.neighborSolicit.Increment()
  2011  	}
  2012  	return err
  2013  }