github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/tcpip/network/ipv6/ndp.go (about) 1 // Copyright 2019 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package ipv6 16 17 import ( 18 "fmt" 19 "time" 20 21 "github.com/SagerNet/gvisor/pkg/sync" 22 "github.com/SagerNet/gvisor/pkg/tcpip" 23 "github.com/SagerNet/gvisor/pkg/tcpip/buffer" 24 "github.com/SagerNet/gvisor/pkg/tcpip/header" 25 "github.com/SagerNet/gvisor/pkg/tcpip/network/internal/ip" 26 "github.com/SagerNet/gvisor/pkg/tcpip/stack" 27 ) 28 29 const ( 30 // defaultMaxRtrSolicitations is the default number of Router 31 // Solicitation messages to send when an IPv6 endpoint becomes enabled. 32 // 33 // Default = 3 (from RFC 4861 section 10). 34 defaultMaxRtrSolicitations = 3 35 36 // defaultRtrSolicitationInterval is the default amount of time between 37 // sending Router Solicitation messages. 38 // 39 // Default = 4s (from 4861 section 10). 40 defaultRtrSolicitationInterval = 4 * time.Second 41 42 // defaultMaxRtrSolicitationDelay is the default maximum amount of time 43 // to wait before sending the first Router Solicitation message. 44 // 45 // Default = 1s (from 4861 section 10). 46 defaultMaxRtrSolicitationDelay = time.Second 47 48 // defaultHandleRAs is the default configuration for whether or not to 49 // handle incoming Router Advertisements as a host. 50 defaultHandleRAs = HandlingRAsEnabledWhenForwardingDisabled 51 52 // defaultDiscoverDefaultRouters is the default configuration for 53 // whether or not to discover default routers from incoming Router 54 // Advertisements, as a host. 55 defaultDiscoverDefaultRouters = true 56 57 // defaultDiscoverMoreSpecificRoutes is the default configuration for 58 // whether or not to discover more-specific routes from incoming Router 59 // Advertisements, as a host. 60 defaultDiscoverMoreSpecificRoutes = true 61 62 // defaultDiscoverOnLinkPrefixes is the default configuration for 63 // whether or not to discover on-link prefixes from incoming Router 64 // Advertisements' Prefix Information option, as a host. 65 defaultDiscoverOnLinkPrefixes = true 66 67 // defaultAutoGenGlobalAddresses is the default configuration for 68 // whether or not to generate global IPv6 addresses in response to 69 // receiving a new Prefix Information option with its Autonomous 70 // Address AutoConfiguration flag set, as a host. 71 // 72 // Default = true. 73 defaultAutoGenGlobalAddresses = true 74 75 // minimumRtrSolicitationInterval is the minimum amount of time to wait 76 // between sending Router Solicitation messages. This limit is imposed 77 // to make sure that Router Solicitation messages are not sent all at 78 // once, defeating the purpose of sending the initial few messages. 79 minimumRtrSolicitationInterval = 500 * time.Millisecond 80 81 // minimumMaxRtrSolicitationDelay is the minimum amount of time to wait 82 // before sending the first Router Solicitation message. It is 0 because 83 // we cannot have a negative delay. 84 minimumMaxRtrSolicitationDelay = 0 85 86 // MaxDiscoveredOffLinkRoutes is the maximum number of discovered off-link 87 // routes. The stack should stop discovering new off-link routes after 88 // this limit is reached. 89 // 90 // This value MUST be at minimum 2 as per RFC 4861 section 6.3.4, and 91 // SHOULD be more. 92 MaxDiscoveredOffLinkRoutes = 10 93 94 // MaxDiscoveredOnLinkPrefixes is the maximum number of discovered 95 // on-link prefixes. The stack should stop discovering new on-link 96 // prefixes after discovering MaxDiscoveredOnLinkPrefixes on-link 97 // prefixes. 98 MaxDiscoveredOnLinkPrefixes = 10 99 100 // 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: ndp.ep.protocol.stack.NewJob(&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: ndp.ep.protocol.stack.NewJob(&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: ndp.ep.protocol.stack.NewJob(&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: ndp.ep.protocol.stack.NewJob(&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.FirstPrimaryEndpoint, configType, deprecated) 1134 if err != nil { 1135 panic(fmt.Sprintf("ndp: error when adding SLAAC address %+v: %s", addr, err)) 1136 } 1137 1138 ndpDisp.OnAutoGenAddress(ndp.ep.nic.ID(), addr) 1139 1140 return addressEndpoint 1141 } 1142 1143 // generateSLAACAddr generates a SLAAC address for prefix. 1144 // 1145 // Returns true if an address was successfully generated. 1146 // 1147 // Panics if the prefix is not a SLAAC prefix or it already has an address. 1148 // 1149 // The IPv6 endpoint that ndp belongs to MUST be locked. 1150 func (ndp *ndpState) generateSLAACAddr(prefix tcpip.Subnet, state *slaacPrefixState) bool { 1151 if addressEndpoint := state.stableAddr.addressEndpoint; addressEndpoint != nil { 1152 panic(fmt.Sprintf("ndp: SLAAC prefix %s already has a permenant address %s", prefix, addressEndpoint.AddressWithPrefix())) 1153 } 1154 1155 // If we have already reached the maximum address generation attempts for the 1156 // prefix, do not generate another address. 1157 if state.generationAttempts == state.maxGenerationAttempts { 1158 return false 1159 } 1160 1161 var generatedAddr tcpip.AddressWithPrefix 1162 addrBytes := []byte(prefix.ID()) 1163 1164 for i := 0; ; i++ { 1165 // If we were unable to generate an address after the maximum SLAAC address 1166 // local regeneration attempts, do nothing further. 1167 if i == maxSLAACAddrLocalRegenAttempts { 1168 return false 1169 } 1170 1171 dadCounter := state.generationAttempts + state.stableAddr.localGenerationFailures 1172 if oIID := ndp.ep.protocol.options.OpaqueIIDOpts; oIID.NICNameFromID != nil { 1173 addrBytes = header.AppendOpaqueInterfaceIdentifier( 1174 addrBytes[:header.IIDOffsetInIPv6Address], 1175 prefix, 1176 oIID.NICNameFromID(ndp.ep.nic.ID(), ndp.ep.nic.Name()), 1177 dadCounter, 1178 oIID.SecretKey, 1179 ) 1180 } else if dadCounter == 0 { 1181 // Modified-EUI64 based IIDs have no way to resolve DAD conflicts, so if 1182 // the DAD counter is non-zero, we cannot use this method. 1183 // 1184 // Only attempt to generate an interface-specific IID if we have a valid 1185 // link address. 1186 // 1187 // TODO(b/141011931): Validate a LinkEndpoint's link address (provided by 1188 // LinkEndpoint.LinkAddress) before reaching this point. 1189 linkAddr := ndp.ep.nic.LinkAddress() 1190 if !header.IsValidUnicastEthernetAddress(linkAddr) { 1191 return false 1192 } 1193 1194 // Generate an address within prefix from the modified EUI-64 of ndp's 1195 // NIC's Ethernet MAC address. 1196 header.EthernetAdddressToModifiedEUI64IntoBuf(linkAddr, addrBytes[header.IIDOffsetInIPv6Address:]) 1197 } else { 1198 // We have no way to regenerate an address in response to an address 1199 // conflict when addresses are not generated with opaque IIDs. 1200 return false 1201 } 1202 1203 generatedAddr = tcpip.AddressWithPrefix{ 1204 Address: tcpip.Address(addrBytes), 1205 PrefixLen: validPrefixLenForAutoGen, 1206 } 1207 1208 if !ndp.ep.hasPermanentAddressRLocked(generatedAddr.Address) { 1209 break 1210 } 1211 1212 state.stableAddr.localGenerationFailures++ 1213 } 1214 1215 deprecated := state.preferredUntil != nil && !state.preferredUntil.After(ndp.ep.protocol.stack.Clock().NowMonotonic()) 1216 if addressEndpoint := ndp.addAndAcquireSLAACAddr(generatedAddr, stack.AddressConfigSlaac, deprecated); addressEndpoint != nil { 1217 state.stableAddr.addressEndpoint = addressEndpoint 1218 state.generationAttempts++ 1219 return true 1220 } 1221 1222 return false 1223 } 1224 1225 // regenerateSLAACAddr regenerates an address for a SLAAC prefix. 1226 // 1227 // If generating a new address for the prefix fails, the prefix is invalidated. 1228 // 1229 // The IPv6 endpoint that ndp belongs to MUST be locked. 1230 func (ndp *ndpState) regenerateSLAACAddr(prefix tcpip.Subnet) { 1231 state, ok := ndp.slaacPrefixes[prefix] 1232 if !ok { 1233 panic(fmt.Sprintf("ndp: SLAAC prefix state not found to regenerate address for %s", prefix)) 1234 } 1235 1236 if ndp.generateSLAACAddr(prefix, &state) { 1237 ndp.slaacPrefixes[prefix] = state 1238 return 1239 } 1240 1241 // We were unable to generate a permanent address for the SLAAC prefix so 1242 // invalidate the prefix as there is no reason to maintain state for a 1243 // SLAAC prefix we do not have an address for. 1244 ndp.invalidateSLAACPrefix(prefix, state) 1245 } 1246 1247 // generateTempSLAACAddr generates a new temporary SLAAC address. 1248 // 1249 // If resetGenAttempts is true, the prefix's generation counter is reset. 1250 // 1251 // Returns true if a new address was generated. 1252 func (ndp *ndpState) generateTempSLAACAddr(prefix tcpip.Subnet, prefixState *slaacPrefixState, resetGenAttempts bool) bool { 1253 // Are we configured to auto-generate new temporary global addresses for the 1254 // prefix? 1255 if !ndp.configs.AutoGenTempGlobalAddresses || prefix == header.IPv6LinkLocalPrefix.Subnet() { 1256 return false 1257 } 1258 1259 if resetGenAttempts { 1260 prefixState.generationAttempts = 0 1261 prefixState.maxGenerationAttempts = ndp.configs.AutoGenAddressConflictRetries + 1 1262 } 1263 1264 // If we have already reached the maximum address generation attempts for the 1265 // prefix, do not generate another address. 1266 if prefixState.generationAttempts == prefixState.maxGenerationAttempts { 1267 return false 1268 } 1269 1270 stableAddr := prefixState.stableAddr.addressEndpoint.AddressWithPrefix().Address 1271 now := ndp.ep.protocol.stack.Clock().NowMonotonic() 1272 1273 // As per RFC 4941 section 3.3 step 4, the valid lifetime of a temporary 1274 // address is the lower of the valid lifetime of the stable address or the 1275 // maximum temporary address valid lifetime. 1276 vl := ndp.configs.MaxTempAddrValidLifetime 1277 if prefixState.validUntil != nil { 1278 if prefixVL := prefixState.validUntil.Sub(now); vl > prefixVL { 1279 vl = prefixVL 1280 } 1281 } 1282 1283 if vl <= 0 { 1284 // Cannot create an address without a valid lifetime. 1285 return false 1286 } 1287 1288 // As per RFC 4941 section 3.3 step 4, the preferred lifetime of a temporary 1289 // address is the lower of the preferred lifetime of the stable address or the 1290 // maximum temporary address preferred lifetime - the temporary address desync 1291 // factor. 1292 pl := ndp.configs.MaxTempAddrPreferredLifetime - ndp.temporaryAddressDesyncFactor 1293 if prefixState.preferredUntil != nil { 1294 if prefixPL := prefixState.preferredUntil.Sub(now); pl > prefixPL { 1295 // Respect the preferred lifetime of the prefix, as per RFC 4941 section 1296 // 3.3 step 4. 1297 pl = prefixPL 1298 } 1299 } 1300 1301 // As per RFC 4941 section 3.3 step 5, a temporary address is created only if 1302 // the calculated preferred lifetime is greater than the advance regeneration 1303 // duration. In particular, we MUST NOT create a temporary address with a zero 1304 // Preferred Lifetime. 1305 if pl <= ndp.configs.RegenAdvanceDuration { 1306 return false 1307 } 1308 1309 // Attempt to generate a new address that is not already assigned to the IPv6 1310 // endpoint. 1311 var generatedAddr tcpip.AddressWithPrefix 1312 for i := 0; ; i++ { 1313 // If we were unable to generate an address after the maximum SLAAC address 1314 // local regeneration attempts, do nothing further. 1315 if i == maxSLAACAddrLocalRegenAttempts { 1316 return false 1317 } 1318 1319 generatedAddr = header.GenerateTempIPv6SLAACAddr(ndp.temporaryIIDHistory[:], stableAddr) 1320 if !ndp.ep.hasPermanentAddressRLocked(generatedAddr.Address) { 1321 break 1322 } 1323 } 1324 1325 // As per RFC RFC 4941 section 3.3 step 5, we MUST NOT create a temporary 1326 // address with a zero preferred lifetime. The checks above ensure this 1327 // so we know the address is not deprecated. 1328 addressEndpoint := ndp.addAndAcquireSLAACAddr(generatedAddr, stack.AddressConfigSlaacTemp, false /* deprecated */) 1329 if addressEndpoint == nil { 1330 return false 1331 } 1332 1333 state := tempSLAACAddrState{ 1334 deprecationJob: ndp.ep.protocol.stack.NewJob(&ndp.ep.mu, func() { 1335 prefixState, ok := ndp.slaacPrefixes[prefix] 1336 if !ok { 1337 panic(fmt.Sprintf("ndp: must have a slaacPrefixes entry for %s to deprecate temporary address %s", prefix, generatedAddr)) 1338 } 1339 1340 tempAddrState, ok := prefixState.tempAddrs[generatedAddr.Address] 1341 if !ok { 1342 panic(fmt.Sprintf("ndp: must have a tempAddr entry to deprecate temporary address %s", generatedAddr)) 1343 } 1344 1345 ndp.deprecateSLAACAddress(tempAddrState.addressEndpoint) 1346 }), 1347 invalidationJob: ndp.ep.protocol.stack.NewJob(&ndp.ep.mu, func() { 1348 prefixState, ok := ndp.slaacPrefixes[prefix] 1349 if !ok { 1350 panic(fmt.Sprintf("ndp: must have a slaacPrefixes entry for %s to invalidate temporary address %s", prefix, generatedAddr)) 1351 } 1352 1353 tempAddrState, ok := prefixState.tempAddrs[generatedAddr.Address] 1354 if !ok { 1355 panic(fmt.Sprintf("ndp: must have a tempAddr entry to invalidate temporary address %s", generatedAddr)) 1356 } 1357 1358 ndp.invalidateTempSLAACAddr(prefixState.tempAddrs, generatedAddr.Address, tempAddrState) 1359 }), 1360 regenJob: ndp.ep.protocol.stack.NewJob(&ndp.ep.mu, func() { 1361 prefixState, ok := ndp.slaacPrefixes[prefix] 1362 if !ok { 1363 panic(fmt.Sprintf("ndp: must have a slaacPrefixes entry for %s to regenerate temporary address after %s", prefix, generatedAddr)) 1364 } 1365 1366 tempAddrState, ok := prefixState.tempAddrs[generatedAddr.Address] 1367 if !ok { 1368 panic(fmt.Sprintf("ndp: must have a tempAddr entry to regenerate temporary address after %s", generatedAddr)) 1369 } 1370 1371 // If an address has already been regenerated for this address, don't 1372 // regenerate another address. 1373 if tempAddrState.regenerated { 1374 return 1375 } 1376 1377 // Reset the generation attempts counter as we are starting the generation 1378 // of a new address for the SLAAC prefix. 1379 tempAddrState.regenerated = ndp.generateTempSLAACAddr(prefix, &prefixState, true /* resetGenAttempts */) 1380 prefixState.tempAddrs[generatedAddr.Address] = tempAddrState 1381 ndp.slaacPrefixes[prefix] = prefixState 1382 }), 1383 createdAt: now, 1384 addressEndpoint: addressEndpoint, 1385 } 1386 1387 state.deprecationJob.Schedule(pl) 1388 state.invalidationJob.Schedule(vl) 1389 state.regenJob.Schedule(pl - ndp.configs.RegenAdvanceDuration) 1390 1391 prefixState.generationAttempts++ 1392 prefixState.tempAddrs[generatedAddr.Address] = state 1393 1394 return true 1395 } 1396 1397 // regenerateTempSLAACAddr regenerates a temporary address for a SLAAC prefix. 1398 // 1399 // The IPv6 endpoint that ndp belongs to MUST be locked. 1400 func (ndp *ndpState) regenerateTempSLAACAddr(prefix tcpip.Subnet, resetGenAttempts bool) { 1401 state, ok := ndp.slaacPrefixes[prefix] 1402 if !ok { 1403 panic(fmt.Sprintf("ndp: SLAAC prefix state not found to regenerate temporary address for %s", prefix)) 1404 } 1405 1406 ndp.generateTempSLAACAddr(prefix, &state, resetGenAttempts) 1407 ndp.slaacPrefixes[prefix] = state 1408 } 1409 1410 // refreshSLAACPrefixLifetimes refreshes the lifetimes of a SLAAC prefix. 1411 // 1412 // pl is the new preferred lifetime. vl is the new valid lifetime. 1413 // 1414 // The IPv6 endpoint that ndp belongs to MUST be locked. 1415 func (ndp *ndpState) refreshSLAACPrefixLifetimes(prefix tcpip.Subnet, prefixState *slaacPrefixState, pl, vl time.Duration) { 1416 // If the preferred lifetime is zero, then the prefix should be deprecated. 1417 deprecated := pl == 0 1418 if deprecated { 1419 ndp.deprecateSLAACAddress(prefixState.stableAddr.addressEndpoint) 1420 } else { 1421 prefixState.stableAddr.addressEndpoint.SetDeprecated(false) 1422 } 1423 1424 // If prefix was preferred for some finite lifetime before, cancel the 1425 // deprecation job so it can be reset. 1426 prefixState.deprecationJob.Cancel() 1427 1428 now := ndp.ep.protocol.stack.Clock().NowMonotonic() 1429 1430 // Schedule the deprecation job if prefix has a finite preferred lifetime. 1431 if pl < header.NDPInfiniteLifetime { 1432 if !deprecated { 1433 prefixState.deprecationJob.Schedule(pl) 1434 } 1435 t := now.Add(pl) 1436 prefixState.preferredUntil = &t 1437 } else { 1438 prefixState.preferredUntil = nil 1439 } 1440 1441 // As per RFC 4862 section 5.5.3.e, update the valid lifetime for prefix: 1442 // 1443 // 1) If the received Valid Lifetime is greater than 2 hours or greater than 1444 // RemainingLifetime, set the valid lifetime of the prefix to the 1445 // advertised Valid Lifetime. 1446 // 1447 // 2) If RemainingLifetime is less than or equal to 2 hours, ignore the 1448 // advertised Valid Lifetime. 1449 // 1450 // 3) Otherwise, reset the valid lifetime of the prefix to 2 hours. 1451 1452 if vl >= header.NDPInfiniteLifetime { 1453 // Handle the infinite valid lifetime separately as we do not schedule a 1454 // job in this case. 1455 prefixState.invalidationJob.Cancel() 1456 prefixState.validUntil = nil 1457 } else { 1458 var effectiveVl time.Duration 1459 var rl time.Duration 1460 1461 // If the prefix was originally set to be valid forever, assume the 1462 // remaining time to be the maximum possible value. 1463 if prefixState.validUntil == nil { 1464 rl = header.NDPInfiniteLifetime 1465 } else { 1466 rl = prefixState.validUntil.Sub(now) 1467 } 1468 1469 if vl > MinPrefixInformationValidLifetimeForUpdate || vl > rl { 1470 effectiveVl = vl 1471 } else if rl > MinPrefixInformationValidLifetimeForUpdate { 1472 effectiveVl = MinPrefixInformationValidLifetimeForUpdate 1473 } 1474 1475 if effectiveVl != 0 { 1476 prefixState.invalidationJob.Cancel() 1477 prefixState.invalidationJob.Schedule(effectiveVl) 1478 t := now.Add(effectiveVl) 1479 prefixState.validUntil = &t 1480 } 1481 } 1482 1483 // If DAD is not yet complete on the stable address, there is no need to do 1484 // work with temporary addresses. 1485 if prefixState.stableAddr.addressEndpoint.GetKind() != stack.Permanent { 1486 return 1487 } 1488 1489 // Note, we do not need to update the entries in the temporary address map 1490 // after updating the jobs because the jobs are held as pointers. 1491 var regenForAddr tcpip.Address 1492 allAddressesRegenerated := true 1493 for tempAddr, tempAddrState := range prefixState.tempAddrs { 1494 // As per RFC 4941 section 3.3 step 4, the valid lifetime of a temporary 1495 // address is the lower of the valid lifetime of the stable address or the 1496 // maximum temporary address valid lifetime. Note, the valid lifetime of a 1497 // temporary address is relative to the address's creation time. 1498 validUntil := tempAddrState.createdAt.Add(ndp.configs.MaxTempAddrValidLifetime) 1499 if prefixState.validUntil != nil && prefixState.validUntil.Before(validUntil) { 1500 validUntil = *prefixState.validUntil 1501 } 1502 1503 // If the address is no longer valid, invalidate it immediately. Otherwise, 1504 // reset the invalidation job. 1505 newValidLifetime := validUntil.Sub(now) 1506 if newValidLifetime <= 0 { 1507 ndp.invalidateTempSLAACAddr(prefixState.tempAddrs, tempAddr, tempAddrState) 1508 continue 1509 } 1510 tempAddrState.invalidationJob.Cancel() 1511 tempAddrState.invalidationJob.Schedule(newValidLifetime) 1512 1513 // As per RFC 4941 section 3.3 step 4, the preferred lifetime of a temporary 1514 // address is the lower of the preferred lifetime of the stable address or 1515 // the maximum temporary address preferred lifetime - the temporary address 1516 // desync factor. Note, the preferred lifetime of a temporary address is 1517 // relative to the address's creation time. 1518 preferredUntil := tempAddrState.createdAt.Add(ndp.configs.MaxTempAddrPreferredLifetime - ndp.temporaryAddressDesyncFactor) 1519 if prefixState.preferredUntil != nil && prefixState.preferredUntil.Before(preferredUntil) { 1520 preferredUntil = *prefixState.preferredUntil 1521 } 1522 1523 // If the address is no longer preferred, deprecate it immediately. 1524 // Otherwise, schedule the deprecation job again. 1525 newPreferredLifetime := preferredUntil.Sub(now) 1526 tempAddrState.deprecationJob.Cancel() 1527 1528 if newPreferredLifetime <= 0 { 1529 ndp.deprecateSLAACAddress(tempAddrState.addressEndpoint) 1530 } else { 1531 tempAddrState.addressEndpoint.SetDeprecated(false) 1532 tempAddrState.deprecationJob.Schedule(newPreferredLifetime) 1533 } 1534 1535 tempAddrState.regenJob.Cancel() 1536 if tempAddrState.regenerated { 1537 } else { 1538 allAddressesRegenerated = false 1539 1540 if newPreferredLifetime <= ndp.configs.RegenAdvanceDuration { 1541 // The new preferred lifetime is less than the advance regeneration 1542 // duration so regenerate an address for this temporary address 1543 // immediately after we finish iterating over the temporary addresses. 1544 regenForAddr = tempAddr 1545 } else { 1546 tempAddrState.regenJob.Schedule(newPreferredLifetime - ndp.configs.RegenAdvanceDuration) 1547 } 1548 } 1549 } 1550 1551 // Generate a new temporary address if all of the existing temporary addresses 1552 // have been regenerated, or we need to immediately regenerate an address 1553 // due to an update in preferred lifetime. 1554 // 1555 // If each temporay address has already been regenerated, no new temporary 1556 // address is generated. To ensure continuation of temporary SLAAC addresses, 1557 // we manually try to regenerate an address here. 1558 if len(regenForAddr) != 0 || allAddressesRegenerated { 1559 // Reset the generation attempts counter as we are starting the generation 1560 // of a new address for the SLAAC prefix. 1561 if state, ok := prefixState.tempAddrs[regenForAddr]; ndp.generateTempSLAACAddr(prefix, prefixState, true /* resetGenAttempts */) && ok { 1562 state.regenerated = true 1563 prefixState.tempAddrs[regenForAddr] = state 1564 } 1565 } 1566 } 1567 1568 // deprecateSLAACAddress marks the address as deprecated and notifies the NDP 1569 // dispatcher that address has been deprecated. 1570 // 1571 // deprecateSLAACAddress does nothing if the address is already deprecated. 1572 // 1573 // The IPv6 endpoint that ndp belongs to MUST be locked. 1574 func (ndp *ndpState) deprecateSLAACAddress(addressEndpoint stack.AddressEndpoint) { 1575 if addressEndpoint.Deprecated() { 1576 return 1577 } 1578 1579 addressEndpoint.SetDeprecated(true) 1580 if ndpDisp := ndp.ep.protocol.options.NDPDisp; ndpDisp != nil { 1581 ndpDisp.OnAutoGenAddressDeprecated(ndp.ep.nic.ID(), addressEndpoint.AddressWithPrefix()) 1582 } 1583 } 1584 1585 // invalidateSLAACPrefix invalidates a SLAAC prefix. 1586 // 1587 // The IPv6 endpoint that ndp belongs to MUST be locked. 1588 func (ndp *ndpState) invalidateSLAACPrefix(prefix tcpip.Subnet, state slaacPrefixState) { 1589 ndp.cleanupSLAACPrefixResources(prefix, state) 1590 1591 if addressEndpoint := state.stableAddr.addressEndpoint; addressEndpoint != nil { 1592 if ndpDisp := ndp.ep.protocol.options.NDPDisp; ndpDisp != nil { 1593 ndpDisp.OnAutoGenAddressInvalidated(ndp.ep.nic.ID(), addressEndpoint.AddressWithPrefix()) 1594 } 1595 1596 if err := ndp.ep.removePermanentEndpointInnerLocked(addressEndpoint, &stack.DADAborted{}); err != nil { 1597 panic(fmt.Sprintf("ndp: error removing stable SLAAC address %s: %s", addressEndpoint.AddressWithPrefix(), err)) 1598 } 1599 } 1600 } 1601 1602 // cleanupSLAACAddrResourcesAndNotify cleans up an invalidated SLAAC address's 1603 // resources. 1604 // 1605 // The IPv6 endpoint that ndp belongs to MUST be locked. 1606 func (ndp *ndpState) cleanupSLAACAddrResourcesAndNotify(addr tcpip.AddressWithPrefix, invalidatePrefix bool) { 1607 if ndpDisp := ndp.ep.protocol.options.NDPDisp; ndpDisp != nil { 1608 ndpDisp.OnAutoGenAddressInvalidated(ndp.ep.nic.ID(), addr) 1609 } 1610 1611 prefix := addr.Subnet() 1612 state, ok := ndp.slaacPrefixes[prefix] 1613 if !ok || state.stableAddr.addressEndpoint == nil || addr.Address != state.stableAddr.addressEndpoint.AddressWithPrefix().Address { 1614 return 1615 } 1616 1617 if !invalidatePrefix { 1618 // If the prefix is not being invalidated, disassociate the address from the 1619 // prefix and do nothing further. 1620 state.stableAddr.addressEndpoint.DecRef() 1621 state.stableAddr.addressEndpoint = nil 1622 ndp.slaacPrefixes[prefix] = state 1623 return 1624 } 1625 1626 ndp.cleanupSLAACPrefixResources(prefix, state) 1627 } 1628 1629 // cleanupSLAACPrefixResources cleans up a SLAAC prefix's jobs and entry. 1630 // 1631 // Panics if the SLAAC prefix is not known. 1632 // 1633 // The IPv6 endpoint that ndp belongs to MUST be locked. 1634 func (ndp *ndpState) cleanupSLAACPrefixResources(prefix tcpip.Subnet, state slaacPrefixState) { 1635 // Invalidate all temporary addresses. 1636 for tempAddr, tempAddrState := range state.tempAddrs { 1637 ndp.invalidateTempSLAACAddr(state.tempAddrs, tempAddr, tempAddrState) 1638 } 1639 1640 if state.stableAddr.addressEndpoint != nil { 1641 state.stableAddr.addressEndpoint.DecRef() 1642 state.stableAddr.addressEndpoint = nil 1643 } 1644 state.deprecationJob.Cancel() 1645 state.invalidationJob.Cancel() 1646 delete(ndp.slaacPrefixes, prefix) 1647 } 1648 1649 // invalidateTempSLAACAddr invalidates a temporary SLAAC address. 1650 // 1651 // The IPv6 endpoint that ndp belongs to MUST be locked. 1652 func (ndp *ndpState) invalidateTempSLAACAddr(tempAddrs map[tcpip.Address]tempSLAACAddrState, tempAddr tcpip.Address, tempAddrState tempSLAACAddrState) { 1653 ndp.cleanupTempSLAACAddrResourcesAndNotifyInner(tempAddrs, tempAddr, tempAddrState) 1654 1655 if err := ndp.ep.removePermanentEndpointInnerLocked(tempAddrState.addressEndpoint, &stack.DADAborted{}); err != nil { 1656 panic(fmt.Sprintf("error removing temporary SLAAC address %s: %s", tempAddrState.addressEndpoint.AddressWithPrefix(), err)) 1657 } 1658 } 1659 1660 // cleanupTempSLAACAddrResourcesAndNotify cleans up an invalidated temporary 1661 // SLAAC address's resources from ndp and notifies the NDP dispatcher that the 1662 // address was invalidated. 1663 // 1664 // The IPv6 endpoint that ndp belongs to MUST be locked. 1665 func (ndp *ndpState) cleanupTempSLAACAddrResourcesAndNotify(addr tcpip.AddressWithPrefix) { 1666 prefix := addr.Subnet() 1667 state, ok := ndp.slaacPrefixes[prefix] 1668 if !ok { 1669 panic(fmt.Sprintf("ndp: must have a slaacPrefixes entry to clean up temp addr %s resources", addr)) 1670 } 1671 1672 tempAddrState, ok := state.tempAddrs[addr.Address] 1673 if !ok { 1674 panic(fmt.Sprintf("ndp: must have a tempAddr entry to clean up temp addr %s resources", addr)) 1675 } 1676 1677 ndp.cleanupTempSLAACAddrResourcesAndNotifyInner(state.tempAddrs, addr.Address, tempAddrState) 1678 } 1679 1680 // cleanupTempSLAACAddrResourcesAndNotifyInner is like 1681 // cleanupTempSLAACAddrResourcesAndNotify except it does not lookup the 1682 // temporary address's state in ndp - it assumes the passed state is valid. 1683 // 1684 // The IPv6 endpoint that ndp belongs to MUST be locked. 1685 func (ndp *ndpState) cleanupTempSLAACAddrResourcesAndNotifyInner(tempAddrs map[tcpip.Address]tempSLAACAddrState, tempAddr tcpip.Address, tempAddrState tempSLAACAddrState) { 1686 if ndpDisp := ndp.ep.protocol.options.NDPDisp; ndpDisp != nil { 1687 ndpDisp.OnAutoGenAddressInvalidated(ndp.ep.nic.ID(), tempAddrState.addressEndpoint.AddressWithPrefix()) 1688 } 1689 1690 tempAddrState.addressEndpoint.DecRef() 1691 tempAddrState.addressEndpoint = nil 1692 tempAddrState.deprecationJob.Cancel() 1693 tempAddrState.invalidationJob.Cancel() 1694 tempAddrState.regenJob.Cancel() 1695 delete(tempAddrs, tempAddr) 1696 } 1697 1698 // cleanupState cleans up ndp's state. 1699 // 1700 // This function invalidates all discovered on-link prefixes, discovered 1701 // routers, and auto-generated addresses. 1702 // 1703 // The IPv6 endpoint that ndp belongs to MUST be locked. 1704 func (ndp *ndpState) cleanupState() { 1705 for prefix, state := range ndp.slaacPrefixes { 1706 ndp.invalidateSLAACPrefix(prefix, state) 1707 } 1708 1709 for prefix := range ndp.onLinkPrefixes { 1710 ndp.invalidateOnLinkPrefix(prefix) 1711 } 1712 1713 if got := len(ndp.onLinkPrefixes); got != 0 { 1714 panic(fmt.Sprintf("ndp: still have discovered on-link prefixes after cleaning up; found = %d", got)) 1715 } 1716 1717 for route := range ndp.offLinkRoutes { 1718 ndp.invalidateOffLinkRoute(route) 1719 } 1720 1721 if got := len(ndp.offLinkRoutes); got != 0 { 1722 panic(fmt.Sprintf("ndp: still have discovered off-link routes after cleaning up; found = %d", got)) 1723 } 1724 1725 ndp.dhcpv6Configuration = 0 1726 } 1727 1728 // startSolicitingRouters starts soliciting routers, as per RFC 4861 section 1729 // 6.3.7. If routers are already being solicited, this function does nothing. 1730 // 1731 // If ndp is not configured to handle Router Advertisements, routers will not 1732 // be solicited as there is no point soliciting routers if we don't handle their 1733 // advertisements. 1734 // 1735 // The IPv6 endpoint that ndp belongs to MUST be locked. 1736 func (ndp *ndpState) startSolicitingRouters() { 1737 if ndp.rtrSolicitTimer.timer != nil { 1738 // We are already soliciting routers. 1739 return 1740 } 1741 1742 remaining := ndp.configs.MaxRtrSolicitations 1743 if remaining == 0 { 1744 return 1745 } 1746 1747 if !ndp.configs.HandleRAs.enabled(ndp.ep.Forwarding()) { 1748 return 1749 } 1750 1751 // Calculate the random delay before sending our first RS, as per RFC 1752 // 4861 section 6.3.7. 1753 var delay time.Duration 1754 if ndp.configs.MaxRtrSolicitationDelay > 0 { 1755 delay = time.Duration(ndp.ep.protocol.stack.Rand().Int63n(int64(ndp.configs.MaxRtrSolicitationDelay))) 1756 } 1757 1758 // Protected by ndp.ep.mu. 1759 done := false 1760 1761 ndp.rtrSolicitTimer = timer{ 1762 done: &done, 1763 timer: ndp.ep.protocol.stack.Clock().AfterFunc(delay, func() { 1764 // As per RFC 4861 section 4.1: 1765 // 1766 // IP Fields: 1767 // Source Address 1768 // An IP address assigned to the sending interface, or 1769 // the unspecified address if no address is assigned 1770 // to the sending interface. 1771 localAddr := header.IPv6Any 1772 if addressEndpoint := ndp.ep.AcquireOutgoingPrimaryAddress(header.IPv6AllRoutersLinkLocalMulticastAddress, false); addressEndpoint != nil { 1773 localAddr = addressEndpoint.AddressWithPrefix().Address 1774 addressEndpoint.DecRef() 1775 } 1776 1777 // As per RFC 4861 section 4.1, an NDP RS SHOULD include the source 1778 // link-layer address option if the source address of the NDP RS is 1779 // specified. This option MUST NOT be included if the source address is 1780 // unspecified. 1781 // 1782 // TODO(b/141011931): Validate a LinkEndpoint's link address (provided by 1783 // LinkEndpoint.LinkAddress) before reaching this point. 1784 var optsSerializer header.NDPOptionsSerializer 1785 linkAddress := ndp.ep.nic.LinkAddress() 1786 if localAddr != header.IPv6Any && header.IsValidUnicastEthernetAddress(linkAddress) { 1787 optsSerializer = header.NDPOptionsSerializer{ 1788 header.NDPSourceLinkLayerAddressOption(linkAddress), 1789 } 1790 } 1791 payloadSize := header.ICMPv6HeaderSize + header.NDPRSMinimumSize + optsSerializer.Length() 1792 icmpData := header.ICMPv6(buffer.NewView(payloadSize)) 1793 icmpData.SetType(header.ICMPv6RouterSolicit) 1794 rs := header.NDPRouterSolicit(icmpData.MessageBody()) 1795 rs.Options().Serialize(optsSerializer) 1796 icmpData.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ 1797 Header: icmpData, 1798 Src: localAddr, 1799 Dst: header.IPv6AllRoutersLinkLocalMulticastAddress, 1800 })) 1801 1802 pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 1803 ReserveHeaderBytes: int(ndp.ep.MaxHeaderLength()), 1804 Data: buffer.View(icmpData).ToVectorisedView(), 1805 }) 1806 1807 sent := ndp.ep.stats.icmp.packetsSent 1808 if err := addIPHeader(localAddr, header.IPv6AllRoutersLinkLocalMulticastAddress, pkt, stack.NetworkHeaderParams{ 1809 Protocol: header.ICMPv6ProtocolNumber, 1810 TTL: header.NDPHopLimit, 1811 }, nil /* extensionHeaders */); err != nil { 1812 panic(fmt.Sprintf("failed to add IP header: %s", err)) 1813 } 1814 1815 if err := ndp.ep.nic.WritePacketToRemote(header.EthernetAddressFromMulticastIPv6Address(header.IPv6AllRoutersLinkLocalMulticastAddress), ProtocolNumber, pkt); err != nil { 1816 sent.dropped.Increment() 1817 // Don't send any more messages if we had an error. 1818 remaining = 0 1819 } else { 1820 sent.routerSolicit.Increment() 1821 remaining-- 1822 } 1823 1824 ndp.ep.mu.Lock() 1825 defer ndp.ep.mu.Unlock() 1826 1827 if done { 1828 // Router solicitation was stopped. 1829 return 1830 } 1831 1832 if remaining == 0 { 1833 // We are done soliciting routers. 1834 ndp.stopSolicitingRouters() 1835 return 1836 } 1837 1838 ndp.rtrSolicitTimer.timer.Reset(ndp.configs.RtrSolicitationInterval) 1839 }), 1840 } 1841 } 1842 1843 // forwardingChanged handles a change in forwarding configuration. 1844 // 1845 // If transitioning to a host, router solicitation will be started. Otherwise, 1846 // router solicitation will be stopped if NDP is not configured to handle RAs 1847 // as a router. 1848 // 1849 // Precondition: ndp.ep.mu must be locked. 1850 func (ndp *ndpState) forwardingChanged(forwarding bool) { 1851 if forwarding { 1852 if ndp.configs.HandleRAs.enabled(forwarding) { 1853 return 1854 } 1855 1856 ndp.stopSolicitingRouters() 1857 return 1858 } 1859 1860 // Solicit routers when transitioning to a host. 1861 // 1862 // If the endpoint is not currently enabled, routers will be solicited when 1863 // the endpoint becomes enabled (if it is still a host). 1864 if ndp.ep.Enabled() { 1865 ndp.startSolicitingRouters() 1866 } 1867 } 1868 1869 // stopSolicitingRouters stops soliciting routers. If routers are not currently 1870 // being solicited, this function does nothing. 1871 // 1872 // The IPv6 endpoint that ndp belongs to MUST be locked. 1873 func (ndp *ndpState) stopSolicitingRouters() { 1874 if ndp.rtrSolicitTimer.timer == nil { 1875 // Nothing to do. 1876 return 1877 } 1878 1879 ndp.rtrSolicitTimer.timer.Stop() 1880 *ndp.rtrSolicitTimer.done = true 1881 ndp.rtrSolicitTimer = timer{} 1882 } 1883 1884 func (ndp *ndpState) init(ep *endpoint, dadOptions ip.DADOptions) { 1885 if ndp.offLinkRoutes != nil { 1886 panic("attempted to initialize NDP state twice") 1887 } 1888 1889 ndp.ep = ep 1890 ndp.configs = ep.protocol.options.NDPConfigs 1891 ndp.dad.Init(&ndp.ep.mu, ep.protocol.options.DADConfigs, dadOptions) 1892 ndp.offLinkRoutes = make(map[offLinkRoute]offLinkRouteState) 1893 ndp.onLinkPrefixes = make(map[tcpip.Subnet]onLinkPrefixState) 1894 ndp.slaacPrefixes = make(map[tcpip.Subnet]slaacPrefixState) 1895 1896 header.InitialTempIID(ndp.temporaryIIDHistory[:], ndp.ep.protocol.options.TempIIDSeed, ndp.ep.nic.ID()) 1897 ndp.temporaryAddressDesyncFactor = time.Duration(ep.protocol.stack.Rand().Int63n(int64(MaxDesyncFactor))) 1898 } 1899 1900 func (ndp *ndpState) SendDADMessage(addr tcpip.Address, nonce []byte) tcpip.Error { 1901 snmc := header.SolicitedNodeAddr(addr) 1902 return ndp.ep.sendNDPNS(header.IPv6Any, snmc, addr, header.EthernetAddressFromMulticastIPv6Address(snmc), header.NDPOptionsSerializer{ 1903 header.NDPNonceOption(nonce), 1904 }) 1905 } 1906 1907 func (e *endpoint) sendNDPNS(srcAddr, dstAddr, targetAddr tcpip.Address, remoteLinkAddr tcpip.LinkAddress, opts header.NDPOptionsSerializer) tcpip.Error { 1908 icmp := header.ICMPv6(buffer.NewView(header.ICMPv6NeighborSolicitMinimumSize + opts.Length())) 1909 icmp.SetType(header.ICMPv6NeighborSolicit) 1910 ns := header.NDPNeighborSolicit(icmp.MessageBody()) 1911 ns.SetTargetAddress(targetAddr) 1912 ns.Options().Serialize(opts) 1913 icmp.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ 1914 Header: icmp, 1915 Src: srcAddr, 1916 Dst: dstAddr, 1917 })) 1918 1919 pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 1920 ReserveHeaderBytes: int(e.MaxHeaderLength()), 1921 Data: buffer.View(icmp).ToVectorisedView(), 1922 }) 1923 1924 if err := addIPHeader(srcAddr, dstAddr, pkt, stack.NetworkHeaderParams{ 1925 Protocol: header.ICMPv6ProtocolNumber, 1926 TTL: header.NDPHopLimit, 1927 }, nil /* extensionHeaders */); err != nil { 1928 panic(fmt.Sprintf("failed to add IP header: %s", err)) 1929 } 1930 1931 sent := e.stats.icmp.packetsSent 1932 err := e.nic.WritePacketToRemote(remoteLinkAddr, ProtocolNumber, pkt) 1933 if err != nil { 1934 sent.dropped.Increment() 1935 } else { 1936 sent.neighborSolicit.Increment() 1937 } 1938 return err 1939 }