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