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