github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/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/MerlinKodo/gvisor/pkg/buffer" 22 "github.com/MerlinKodo/gvisor/pkg/sync" 23 "github.com/MerlinKodo/gvisor/pkg/tcpip" 24 "github.com/MerlinKodo/gvisor/pkg/tcpip/header" 25 "github.com/MerlinKodo/gvisor/pkg/tcpip/network/internal/ip" 26 "github.com/MerlinKodo/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 permenant 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 temporay 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.Rand().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, 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.Rand().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 }