github.com/metacubex/gvisor@v0.0.0-20240320004321-933faba989ec/pkg/tcpip/stack/addressable_endpoint_state.go (about) 1 // Copyright 2020 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 stack 16 17 import ( 18 "fmt" 19 20 "github.com/metacubex/gvisor/pkg/tcpip" 21 "github.com/metacubex/gvisor/pkg/tcpip/header" 22 ) 23 24 func (lifetimes *AddressLifetimes) sanitize() { 25 if lifetimes.Deprecated { 26 lifetimes.PreferredUntil = tcpip.MonotonicTime{} 27 } 28 } 29 30 var _ AddressableEndpoint = (*AddressableEndpointState)(nil) 31 32 // AddressableEndpointState is an implementation of an AddressableEndpoint. 33 type AddressableEndpointState struct { 34 networkEndpoint NetworkEndpoint 35 options AddressableEndpointStateOptions 36 37 // Lock ordering (from outer to inner lock ordering): 38 // 39 // AddressableEndpointState.mu 40 // addressState.mu 41 mu addressableEndpointStateRWMutex 42 // +checklocks:mu 43 endpoints map[tcpip.Address]*addressState 44 // +checklocks:mu 45 primary []*addressState 46 } 47 48 // AddressableEndpointStateOptions contains options used to configure an 49 // AddressableEndpointState. 50 type AddressableEndpointStateOptions struct { 51 // HiddenWhileDisabled determines whether addresses should be returned to 52 // callers while the NetworkEndpoint this AddressableEndpointState belongs 53 // to is disabled. 54 HiddenWhileDisabled bool 55 } 56 57 // Init initializes the AddressableEndpointState with networkEndpoint. 58 // 59 // Must be called before calling any other function on m. 60 func (a *AddressableEndpointState) Init(networkEndpoint NetworkEndpoint, options AddressableEndpointStateOptions) { 61 a.networkEndpoint = networkEndpoint 62 a.options = options 63 64 a.mu.Lock() 65 defer a.mu.Unlock() 66 a.endpoints = make(map[tcpip.Address]*addressState) 67 } 68 69 // OnNetworkEndpointEnabledChanged must be called every time the 70 // NetworkEndpoint this AddressableEndpointState belongs to is enabled or 71 // disabled so that any AddressDispatchers can be notified of the NIC enabled 72 // change. 73 func (a *AddressableEndpointState) OnNetworkEndpointEnabledChanged() { 74 a.mu.RLock() 75 defer a.mu.RUnlock() 76 77 for _, ep := range a.endpoints { 78 ep.mu.Lock() 79 ep.notifyChangedLocked() 80 ep.mu.Unlock() 81 } 82 } 83 84 // GetAddress returns the AddressEndpoint for the passed address. 85 // 86 // GetAddress does not increment the address's reference count or check if the 87 // address is considered bound to the endpoint. 88 // 89 // Returns nil if the passed address is not associated with the endpoint. 90 func (a *AddressableEndpointState) GetAddress(addr tcpip.Address) AddressEndpoint { 91 a.mu.RLock() 92 defer a.mu.RUnlock() 93 94 ep, ok := a.endpoints[addr] 95 if !ok { 96 return nil 97 } 98 return ep 99 } 100 101 // ForEachEndpoint calls f for each address. 102 // 103 // Once f returns false, f will no longer be called. 104 func (a *AddressableEndpointState) ForEachEndpoint(f func(AddressEndpoint) bool) { 105 a.mu.RLock() 106 defer a.mu.RUnlock() 107 108 for _, ep := range a.endpoints { 109 if !f(ep) { 110 return 111 } 112 } 113 } 114 115 // ForEachPrimaryEndpoint calls f for each primary address. 116 // 117 // Once f returns false, f will no longer be called. 118 func (a *AddressableEndpointState) ForEachPrimaryEndpoint(f func(AddressEndpoint) bool) { 119 a.mu.RLock() 120 defer a.mu.RUnlock() 121 122 for _, ep := range a.primary { 123 if !f(ep) { 124 return 125 } 126 } 127 } 128 129 func (a *AddressableEndpointState) releaseAddressState(addrState *addressState) { 130 a.mu.Lock() 131 defer a.mu.Unlock() 132 a.releaseAddressStateLocked(addrState) 133 } 134 135 // releaseAddressStateLocked removes addrState from a's address state 136 // (primary and endpoints list). 137 // 138 // +checklocks:a.mu 139 func (a *AddressableEndpointState) releaseAddressStateLocked(addrState *addressState) { 140 oldPrimary := a.primary 141 for i, s := range a.primary { 142 if s == addrState { 143 a.primary = append(a.primary[:i], a.primary[i+1:]...) 144 oldPrimary[len(oldPrimary)-1] = nil 145 break 146 } 147 } 148 delete(a.endpoints, addrState.addr.Address) 149 } 150 151 // AddAndAcquirePermanentAddress implements AddressableEndpoint. 152 func (a *AddressableEndpointState) AddAndAcquirePermanentAddress(addr tcpip.AddressWithPrefix, properties AddressProperties) (AddressEndpoint, tcpip.Error) { 153 return a.AddAndAcquireAddress(addr, properties, Permanent) 154 } 155 156 // AddAndAcquireTemporaryAddress adds a temporary address. 157 // 158 // Returns *tcpip.ErrDuplicateAddress if the address exists. 159 // 160 // The temporary address's endpoint is acquired and returned. 161 func (a *AddressableEndpointState) AddAndAcquireTemporaryAddress(addr tcpip.AddressWithPrefix, peb PrimaryEndpointBehavior) (AddressEndpoint, tcpip.Error) { 162 return a.AddAndAcquireAddress(addr, AddressProperties{PEB: peb}, Temporary) 163 } 164 165 // AddAndAcquireAddress adds an address with the specified kind. 166 // 167 // Returns *tcpip.ErrDuplicateAddress if the address exists. 168 func (a *AddressableEndpointState) AddAndAcquireAddress(addr tcpip.AddressWithPrefix, properties AddressProperties, kind AddressKind) (AddressEndpoint, tcpip.Error) { 169 a.mu.Lock() 170 defer a.mu.Unlock() 171 ep, err := a.addAndAcquireAddressLocked(addr, properties, kind) 172 // From https://golang.org/doc/faq#nil_error: 173 // 174 // Under the covers, interfaces are implemented as two elements, a type T and 175 // a value V. 176 // 177 // An interface value is nil only if the V and T are both unset, (T=nil, V is 178 // not set), In particular, a nil interface will always hold a nil type. If we 179 // store a nil pointer of type *int inside an interface value, the inner type 180 // will be *int regardless of the value of the pointer: (T=*int, V=nil). Such 181 // an interface value will therefore be non-nil even when the pointer value V 182 // inside is nil. 183 // 184 // Since addAndAcquireAddressLocked returns a nil value with a non-nil type, 185 // we need to explicitly return nil below if ep is (a typed) nil. 186 if ep == nil { 187 return nil, err 188 } 189 return ep, err 190 } 191 192 // addAndAcquireAddressLocked adds, acquires and returns a permanent or 193 // temporary address. 194 // 195 // If the addressable endpoint already has the address in a non-permanent state, 196 // and addAndAcquireAddressLocked is adding a permanent address, that address is 197 // promoted in place and its properties set to the properties provided. If the 198 // address already exists in any other state, then *tcpip.ErrDuplicateAddress is 199 // returned, regardless the kind of address that is being added. 200 // 201 // +checklocks:a.mu 202 func (a *AddressableEndpointState) addAndAcquireAddressLocked(addr tcpip.AddressWithPrefix, properties AddressProperties, kind AddressKind) (*addressState, tcpip.Error) { 203 var permanent bool 204 switch kind { 205 case PermanentExpired: 206 panic(fmt.Sprintf("cannot add address %s in PermanentExpired state", addr)) 207 case Permanent, PermanentTentative: 208 permanent = true 209 case Temporary: 210 default: 211 panic(fmt.Sprintf("unknown address kind: %d", kind)) 212 } 213 // attemptAddToPrimary is false when the address is already in the primary 214 // address list. 215 attemptAddToPrimary := true 216 addrState, ok := a.endpoints[addr.Address] 217 if ok { 218 if !permanent { 219 // We are adding a non-permanent address but the address exists. No need 220 // to go any further since we can only promote existing temporary/expired 221 // addresses to permanent. 222 return nil, &tcpip.ErrDuplicateAddress{} 223 } 224 225 addrState.mu.RLock() 226 if addrState.refs.ReadRefs() == 0 { 227 panic(fmt.Sprintf("found an address that should have been released (ref count == 0); address = %s", addrState.addr)) 228 } 229 isPermanent := addrState.kind.IsPermanent() 230 addrState.mu.RUnlock() 231 232 if isPermanent { 233 // We are adding a permanent address but a permanent address already 234 // exists. 235 return nil, &tcpip.ErrDuplicateAddress{} 236 } 237 238 // We now promote the address. 239 for i, s := range a.primary { 240 if s == addrState { 241 switch properties.PEB { 242 case CanBePrimaryEndpoint: 243 // The address is already in the primary address list. 244 attemptAddToPrimary = false 245 case FirstPrimaryEndpoint: 246 if i == 0 { 247 // The address is already first in the primary address list. 248 attemptAddToPrimary = false 249 } else { 250 a.primary = append(a.primary[:i], a.primary[i+1:]...) 251 } 252 case NeverPrimaryEndpoint: 253 a.primary = append(a.primary[:i], a.primary[i+1:]...) 254 default: 255 panic(fmt.Sprintf("unrecognized primary endpoint behaviour = %d", properties.PEB)) 256 } 257 break 258 } 259 } 260 addrState.refs.IncRef() 261 } else { 262 addrState = &addressState{ 263 addressableEndpointState: a, 264 addr: addr, 265 temporary: properties.Temporary, 266 // Cache the subnet in addrState to avoid calls to addr.Subnet() as that 267 // results in allocations on every call. 268 subnet: addr.Subnet(), 269 } 270 addrState.refs.InitRefs() 271 a.endpoints[addr.Address] = addrState 272 // We never promote an address to temporary - it can only be added as such. 273 // If we are actually adding a permanent address, it is promoted below. 274 addrState.kind = Temporary 275 } 276 277 // At this point we have an address we are either promoting from an expired or 278 // temporary address to permanent, promoting an expired address to temporary, 279 // or we are adding a new temporary or permanent address. 280 // 281 // The address MUST be write locked at this point. 282 addrState.mu.Lock() 283 defer addrState.mu.Unlock() 284 285 if permanent { 286 if addrState.kind.IsPermanent() { 287 panic(fmt.Sprintf("only non-permanent addresses should be promoted to permanent; address = %s", addrState.addr)) 288 } 289 290 // Primary addresses are biased by 1. 291 addrState.refs.IncRef() 292 addrState.kind = kind 293 } 294 addrState.configType = properties.ConfigType 295 lifetimes := properties.Lifetimes 296 lifetimes.sanitize() 297 addrState.lifetimes = lifetimes 298 addrState.disp = properties.Disp 299 300 if attemptAddToPrimary { 301 switch properties.PEB { 302 case NeverPrimaryEndpoint: 303 case CanBePrimaryEndpoint: 304 a.primary = append(a.primary, addrState) 305 case FirstPrimaryEndpoint: 306 if cap(a.primary) == len(a.primary) { 307 a.primary = append([]*addressState{addrState}, a.primary...) 308 } else { 309 // Shift all the endpoints by 1 to make room for the new address at the 310 // front. We could have just created a new slice but this saves 311 // allocations when the slice has capacity for the new address. 312 primaryCount := len(a.primary) 313 a.primary = append(a.primary, nil) 314 if n := copy(a.primary[1:], a.primary); n != primaryCount { 315 panic(fmt.Sprintf("copied %d elements; expected = %d elements", n, primaryCount)) 316 } 317 a.primary[0] = addrState 318 } 319 default: 320 panic(fmt.Sprintf("unrecognized primary endpoint behaviour = %d", properties.PEB)) 321 } 322 } 323 324 addrState.notifyChangedLocked() 325 return addrState, nil 326 } 327 328 // RemovePermanentAddress implements AddressableEndpoint. 329 func (a *AddressableEndpointState) RemovePermanentAddress(addr tcpip.Address) tcpip.Error { 330 a.mu.Lock() 331 defer a.mu.Unlock() 332 return a.removePermanentAddressLocked(addr) 333 } 334 335 // removePermanentAddressLocked is like RemovePermanentAddress but with locking 336 // requirements. 337 // 338 // +checklocks:a.mu 339 func (a *AddressableEndpointState) removePermanentAddressLocked(addr tcpip.Address) tcpip.Error { 340 addrState, ok := a.endpoints[addr] 341 if !ok { 342 return &tcpip.ErrBadLocalAddress{} 343 } 344 345 return a.removePermanentEndpointLocked(addrState, AddressRemovalManualAction) 346 } 347 348 // RemovePermanentEndpoint removes the passed endpoint if it is associated with 349 // a and permanent. 350 func (a *AddressableEndpointState) RemovePermanentEndpoint(ep AddressEndpoint, reason AddressRemovalReason) tcpip.Error { 351 addrState, ok := ep.(*addressState) 352 if !ok || addrState.addressableEndpointState != a { 353 return &tcpip.ErrInvalidEndpointState{} 354 } 355 356 a.mu.Lock() 357 defer a.mu.Unlock() 358 return a.removePermanentEndpointLocked(addrState, reason) 359 } 360 361 // removePermanentAddressLocked is like RemovePermanentAddress but with locking 362 // requirements. 363 // 364 // +checklocks:a.mu 365 func (a *AddressableEndpointState) removePermanentEndpointLocked(addrState *addressState, reason AddressRemovalReason) tcpip.Error { 366 if !addrState.GetKind().IsPermanent() { 367 return &tcpip.ErrBadLocalAddress{} 368 } 369 370 addrState.remove(reason) 371 a.decAddressRefLocked(addrState) 372 return nil 373 } 374 375 // decAddressRef decrements the address's reference count and releases it once 376 // the reference count hits 0. 377 func (a *AddressableEndpointState) decAddressRef(addrState *addressState) { 378 a.mu.Lock() 379 defer a.mu.Unlock() 380 a.decAddressRefLocked(addrState) 381 } 382 383 // decAddressRefLocked is like decAddressRef but with locking requirements. 384 // 385 // +checklocks:a.mu 386 func (a *AddressableEndpointState) decAddressRefLocked(addrState *addressState) { 387 destroy := false 388 addrState.refs.DecRef(func() { 389 destroy = true 390 }) 391 392 if !destroy { 393 return 394 } 395 addrState.mu.Lock() 396 defer addrState.mu.Unlock() 397 // A non-expired permanent address must not have its reference count dropped 398 // to 0. 399 if addrState.kind.IsPermanent() { 400 panic(fmt.Sprintf("permanent addresses should be removed through the AddressableEndpoint: addr = %s, kind = %d", addrState.addr, addrState.kind)) 401 } 402 403 a.releaseAddressStateLocked(addrState) 404 } 405 406 // SetDeprecated implements stack.AddressableEndpoint. 407 func (a *AddressableEndpointState) SetDeprecated(addr tcpip.Address, deprecated bool) tcpip.Error { 408 a.mu.RLock() 409 defer a.mu.RUnlock() 410 411 addrState, ok := a.endpoints[addr] 412 if !ok { 413 return &tcpip.ErrBadLocalAddress{} 414 } 415 addrState.SetDeprecated(deprecated) 416 return nil 417 } 418 419 // SetLifetimes implements stack.AddressableEndpoint. 420 func (a *AddressableEndpointState) SetLifetimes(addr tcpip.Address, lifetimes AddressLifetimes) tcpip.Error { 421 a.mu.RLock() 422 defer a.mu.RUnlock() 423 424 addrState, ok := a.endpoints[addr] 425 if !ok { 426 return &tcpip.ErrBadLocalAddress{} 427 } 428 addrState.SetLifetimes(lifetimes) 429 return nil 430 } 431 432 // MainAddress implements AddressableEndpoint. 433 func (a *AddressableEndpointState) MainAddress() tcpip.AddressWithPrefix { 434 a.mu.RLock() 435 defer a.mu.RUnlock() 436 437 ep := a.acquirePrimaryAddressRLocked(tcpip.Address{}, tcpip.Address{} /* srcHint */, func(ep *addressState) bool { 438 switch kind := ep.GetKind(); kind { 439 case Permanent: 440 return a.networkEndpoint.Enabled() || !a.options.HiddenWhileDisabled 441 case PermanentTentative, PermanentExpired, Temporary: 442 return false 443 default: 444 panic(fmt.Sprintf("unknown address kind: %d", kind)) 445 } 446 }) 447 if ep == nil { 448 return tcpip.AddressWithPrefix{} 449 } 450 addr := ep.AddressWithPrefix() 451 // Note that when ep must have a ref count >=2, because its ref count 452 // must be >=1 in order to be found and the ref count was incremented 453 // when a reference was acquired. The only way for the ref count to 454 // drop below 2 is for the endpoint to be removed, which requires a 455 // write lock; so we're guaranteed to be able to decrement the ref 456 // count and not need to remove the endpoint from a.primary. 457 ep.decRefMustNotFree() 458 return addr 459 } 460 461 // acquirePrimaryAddressRLocked returns an acquired primary address that is 462 // valid according to isValid. 463 // 464 // +checklocksread:a.mu 465 func (a *AddressableEndpointState) acquirePrimaryAddressRLocked(remoteAddr, srcHint tcpip.Address, isValid func(*addressState) bool) *addressState { 466 // TODO: Move this out into IPv4-specific code. 467 // IPv6 handles source IP selection elsewhere. We have to do source 468 // selection only for IPv4, in which case ep is never deprecated. Thus 469 // we don't have to worry about refcounts. 470 if remoteAddr.Len() == header.IPv4AddressSize && remoteAddr != (tcpip.Address{}) { 471 var best *addressState 472 var bestLen uint8 473 for _, state := range a.primary { 474 if !isValid(state) { 475 continue 476 } 477 // Source hint takes precedent over prefix matching. 478 if state.addr.Address == srcHint && srcHint != (tcpip.Address{}) { 479 best = state 480 break 481 } 482 stateLen := state.addr.Address.MatchingPrefix(remoteAddr) 483 if best == nil || bestLen < stateLen { 484 best = state 485 bestLen = stateLen 486 } 487 } 488 if best != nil && best.TryIncRef() { 489 return best 490 } 491 } 492 493 var deprecatedEndpoint *addressState 494 for _, ep := range a.primary { 495 if !isValid(ep) { 496 continue 497 } 498 499 if !ep.Deprecated() { 500 if ep.TryIncRef() { 501 // ep is not deprecated, so return it immediately. 502 // 503 // If we kept track of a deprecated endpoint, decrement its reference 504 // count since it was incremented when we decided to keep track of it. 505 if deprecatedEndpoint != nil { 506 // Note that when deprecatedEndpoint was found, its ref count 507 // must have necessarily been >=1, and after incrementing it 508 // must be >=2. The only way for the ref count to drop below 2 is 509 // for the endpoint to be removed, which requires a write lock; 510 // so we're guaranteed to be able to decrement the ref count 511 // and not need to remove the endpoint from a.primary. 512 deprecatedEndpoint.decRefMustNotFree() 513 } 514 515 return ep 516 } 517 } else if deprecatedEndpoint == nil && ep.TryIncRef() { 518 // We prefer an endpoint that is not deprecated, but we keep track of 519 // ep in case a doesn't have any non-deprecated endpoints. 520 // 521 // If we end up finding a more preferred endpoint, ep's reference count 522 // will be decremented. 523 deprecatedEndpoint = ep 524 } 525 } 526 527 return deprecatedEndpoint 528 } 529 530 // AcquireAssignedAddressOrMatching returns an address endpoint that is 531 // considered assigned to the addressable endpoint. 532 // 533 // If the address is an exact match with an existing address, that address is 534 // returned. Otherwise, if f is provided, f is called with each address and 535 // the address that f returns true for is returned. 536 // 537 // If there is no matching address, a temporary address will be returned if 538 // allowTemp is true. 539 // 540 // Regardless how the address was obtained, it will be acquired before it is 541 // returned. 542 func (a *AddressableEndpointState) AcquireAssignedAddressOrMatching(localAddr tcpip.Address, f func(AddressEndpoint) bool, allowTemp bool, tempPEB PrimaryEndpointBehavior) AddressEndpoint { 543 lookup := func() *addressState { 544 if addrState, ok := a.endpoints[localAddr]; ok { 545 if !addrState.IsAssigned(allowTemp) { 546 return nil 547 } 548 549 if !addrState.TryIncRef() { 550 panic(fmt.Sprintf("failed to increase the reference count for address = %s", addrState.addr)) 551 } 552 553 return addrState 554 } 555 556 if f != nil { 557 for _, addrState := range a.endpoints { 558 if addrState.IsAssigned(allowTemp) && f(addrState) && addrState.TryIncRef() { 559 return addrState 560 } 561 } 562 } 563 return nil 564 } 565 // Avoid exclusive lock on mu unless we need to add a new address. 566 a.mu.RLock() 567 ep := lookup() 568 a.mu.RUnlock() 569 570 if ep != nil { 571 return ep 572 } 573 574 if !allowTemp { 575 return nil 576 } 577 578 // Acquire state lock in exclusive mode as we need to add a new temporary 579 // endpoint. 580 a.mu.Lock() 581 defer a.mu.Unlock() 582 583 // Do the lookup again in case another goroutine added the address in the time 584 // we released and acquired the lock. 585 ep = lookup() 586 if ep != nil { 587 return ep 588 } 589 590 // Proceed to add a new temporary endpoint. 591 addr := localAddr.WithPrefix() 592 ep, err := a.addAndAcquireAddressLocked(addr, AddressProperties{PEB: tempPEB}, Temporary) 593 if err != nil { 594 // addAndAcquireAddressLocked only returns an error if the address is 595 // already assigned but we just checked above if the address exists so we 596 // expect no error. 597 panic(fmt.Sprintf("a.addAndAcquireAddressLocked(%s, AddressProperties{PEB: %s}, false): %s", addr, tempPEB, err)) 598 } 599 600 // From https://golang.org/doc/faq#nil_error: 601 // 602 // Under the covers, interfaces are implemented as two elements, a type T and 603 // a value V. 604 // 605 // An interface value is nil only if the V and T are both unset, (T=nil, V is 606 // not set), In particular, a nil interface will always hold a nil type. If we 607 // store a nil pointer of type *int inside an interface value, the inner type 608 // will be *int regardless of the value of the pointer: (T=*int, V=nil). Such 609 // an interface value will therefore be non-nil even when the pointer value V 610 // inside is nil. 611 // 612 // Since addAndAcquireAddressLocked returns a nil value with a non-nil type, 613 // we need to explicitly return nil below if ep is (a typed) nil. 614 if ep == nil { 615 return nil 616 } 617 return ep 618 } 619 620 // AcquireAssignedAddress implements AddressableEndpoint. 621 func (a *AddressableEndpointState) AcquireAssignedAddress(localAddr tcpip.Address, allowTemp bool, tempPEB PrimaryEndpointBehavior) AddressEndpoint { 622 return a.AcquireAssignedAddressOrMatching(localAddr, nil, allowTemp, tempPEB) 623 } 624 625 // AcquireOutgoingPrimaryAddress implements AddressableEndpoint. 626 func (a *AddressableEndpointState) AcquireOutgoingPrimaryAddress(remoteAddr tcpip.Address, srcHint tcpip.Address, allowExpired bool) AddressEndpoint { 627 a.mu.Lock() 628 defer a.mu.Unlock() 629 630 ep := a.acquirePrimaryAddressRLocked(remoteAddr, srcHint, func(ep *addressState) bool { 631 return ep.IsAssigned(allowExpired) 632 }) 633 634 // From https://golang.org/doc/faq#nil_error: 635 // 636 // Under the covers, interfaces are implemented as two elements, a type T and 637 // a value V. 638 // 639 // An interface value is nil only if the V and T are both unset, (T=nil, V is 640 // not set), In particular, a nil interface will always hold a nil type. If we 641 // store a nil pointer of type *int inside an interface value, the inner type 642 // will be *int regardless of the value of the pointer: (T=*int, V=nil). Such 643 // an interface value will therefore be non-nil even when the pointer value V 644 // inside is nil. 645 // 646 // Since acquirePrimaryAddressLocked returns a nil value with a non-nil type, 647 // we need to explicitly return nil below if ep is (a typed) nil. 648 if ep == nil { 649 return nil 650 } 651 652 return ep 653 } 654 655 // PrimaryAddresses implements AddressableEndpoint. 656 func (a *AddressableEndpointState) PrimaryAddresses() []tcpip.AddressWithPrefix { 657 a.mu.RLock() 658 defer a.mu.RUnlock() 659 660 var addrs []tcpip.AddressWithPrefix 661 if a.options.HiddenWhileDisabled && !a.networkEndpoint.Enabled() { 662 return addrs 663 } 664 for _, ep := range a.primary { 665 switch kind := ep.GetKind(); kind { 666 // Don't include tentative, expired or temporary endpoints 667 // to avoid confusion and prevent the caller from using 668 // those. 669 case PermanentTentative, PermanentExpired, Temporary: 670 continue 671 case Permanent: 672 default: 673 panic(fmt.Sprintf("address %s has unknown kind %d", ep.AddressWithPrefix(), kind)) 674 } 675 676 addrs = append(addrs, ep.AddressWithPrefix()) 677 } 678 679 return addrs 680 } 681 682 // PermanentAddresses implements AddressableEndpoint. 683 func (a *AddressableEndpointState) PermanentAddresses() []tcpip.AddressWithPrefix { 684 a.mu.RLock() 685 defer a.mu.RUnlock() 686 687 var addrs []tcpip.AddressWithPrefix 688 for _, ep := range a.endpoints { 689 if !ep.GetKind().IsPermanent() { 690 continue 691 } 692 693 addrs = append(addrs, ep.AddressWithPrefix()) 694 } 695 696 return addrs 697 } 698 699 // Cleanup forcefully leaves all groups and removes all permanent addresses. 700 func (a *AddressableEndpointState) Cleanup() { 701 a.mu.Lock() 702 defer a.mu.Unlock() 703 704 for _, ep := range a.endpoints { 705 // removePermanentEndpointLocked returns *tcpip.ErrBadLocalAddress if ep is 706 // not a permanent address. 707 switch err := a.removePermanentEndpointLocked(ep, AddressRemovalInterfaceRemoved); err.(type) { 708 case nil, *tcpip.ErrBadLocalAddress: 709 default: 710 panic(fmt.Sprintf("unexpected error from removePermanentEndpointLocked(%s): %s", ep.addr, err)) 711 } 712 } 713 } 714 715 var _ AddressEndpoint = (*addressState)(nil) 716 717 // addressState holds state for an address. 718 type addressState struct { 719 addressableEndpointState *AddressableEndpointState 720 addr tcpip.AddressWithPrefix 721 subnet tcpip.Subnet 722 temporary bool 723 724 // Lock ordering (from outer to inner lock ordering): 725 // 726 // AddressableEndpointState.mu 727 // addressState.mu 728 mu addressStateRWMutex 729 refs addressStateRefs 730 // checklocks:mu 731 kind AddressKind 732 // checklocks:mu 733 configType AddressConfigType 734 // lifetimes holds this address' lifetimes. 735 // 736 // Invariant: if lifetimes.deprecated is true, then lifetimes.PreferredUntil 737 // must be the zero value. Note that the converse does not need to be 738 // upheld! 739 // 740 // checklocks:mu 741 lifetimes AddressLifetimes 742 // The enclosing mutex must be write-locked before calling methods on the 743 // dispatcher. 744 // 745 // checklocks:mu 746 disp AddressDispatcher 747 } 748 749 // AddressWithPrefix implements AddressEndpoint. 750 func (a *addressState) AddressWithPrefix() tcpip.AddressWithPrefix { 751 return a.addr 752 } 753 754 // Subnet implements AddressEndpoint. 755 func (a *addressState) Subnet() tcpip.Subnet { 756 return a.subnet 757 } 758 759 // GetKind implements AddressEndpoint. 760 func (a *addressState) GetKind() AddressKind { 761 a.mu.RLock() 762 defer a.mu.RUnlock() 763 return a.kind 764 } 765 766 // SetKind implements AddressEndpoint. 767 func (a *addressState) SetKind(kind AddressKind) { 768 a.mu.Lock() 769 defer a.mu.Unlock() 770 771 prevKind := a.kind 772 a.kind = kind 773 if kind == PermanentExpired { 774 a.notifyRemovedLocked(AddressRemovalManualAction) 775 } else if prevKind != kind && a.addressableEndpointState.networkEndpoint.Enabled() { 776 a.notifyChangedLocked() 777 } 778 } 779 780 // notifyRemovedLocked notifies integrators of address removal. 781 // 782 // +checklocks:a.mu 783 func (a *addressState) notifyRemovedLocked(reason AddressRemovalReason) { 784 if disp := a.disp; disp != nil { 785 a.disp.OnRemoved(reason) 786 a.disp = nil 787 } 788 } 789 790 func (a *addressState) remove(reason AddressRemovalReason) { 791 a.mu.Lock() 792 defer a.mu.Unlock() 793 794 a.kind = PermanentExpired 795 a.notifyRemovedLocked(reason) 796 } 797 798 // IsAssigned implements AddressEndpoint. 799 func (a *addressState) IsAssigned(allowExpired bool) bool { 800 switch kind := a.GetKind(); kind { 801 case PermanentTentative: 802 return false 803 case PermanentExpired: 804 return allowExpired 805 case Permanent, Temporary: 806 return true 807 default: 808 panic(fmt.Sprintf("address %s has unknown kind %d", a.AddressWithPrefix(), kind)) 809 } 810 } 811 812 // IncRef implements AddressEndpoint. 813 func (a *addressState) TryIncRef() bool { 814 return a.refs.TryIncRef() 815 } 816 817 // DecRef implements AddressEndpoint. 818 func (a *addressState) DecRef() { 819 a.addressableEndpointState.decAddressRef(a) 820 } 821 822 // decRefMustNotFree decreases the reference count with the guarantee that the 823 // reference count will be greater than 0 after the decrement. 824 // 825 // Panics if the ref count is less than 2 after acquiring the lock in this 826 // function. 827 func (a *addressState) decRefMustNotFree() { 828 a.refs.DecRef(func() { 829 panic(fmt.Sprintf("cannot decrease addressState %s without freeing the endpoint", a.addr)) 830 }) 831 } 832 833 // ConfigType implements AddressEndpoint. 834 func (a *addressState) ConfigType() AddressConfigType { 835 a.mu.RLock() 836 defer a.mu.RUnlock() 837 return a.configType 838 } 839 840 // notifyChangedLocked notifies integrators of address property changes. 841 // 842 // +checklocks:a.mu 843 func (a *addressState) notifyChangedLocked() { 844 if a.disp == nil { 845 return 846 } 847 848 state := AddressDisabled 849 if a.addressableEndpointState.networkEndpoint.Enabled() { 850 switch a.kind { 851 case Permanent: 852 state = AddressAssigned 853 case PermanentTentative: 854 state = AddressTentative 855 case Temporary, PermanentExpired: 856 return 857 default: 858 panic(fmt.Sprintf("unrecognized address kind = %d", a.kind)) 859 } 860 } 861 862 a.disp.OnChanged(a.lifetimes, state) 863 } 864 865 // SetDeprecated implements AddressEndpoint. 866 func (a *addressState) SetDeprecated(d bool) { 867 a.mu.Lock() 868 defer a.mu.Unlock() 869 870 var changed bool 871 if a.lifetimes.Deprecated != d { 872 a.lifetimes.Deprecated = d 873 changed = true 874 } 875 if d { 876 a.lifetimes.PreferredUntil = tcpip.MonotonicTime{} 877 } 878 if changed { 879 a.notifyChangedLocked() 880 } 881 } 882 883 // Deprecated implements AddressEndpoint. 884 func (a *addressState) Deprecated() bool { 885 a.mu.RLock() 886 defer a.mu.RUnlock() 887 return a.lifetimes.Deprecated 888 } 889 890 // SetLifetimes implements AddressEndpoint. 891 func (a *addressState) SetLifetimes(lifetimes AddressLifetimes) { 892 a.mu.Lock() 893 defer a.mu.Unlock() 894 895 lifetimes.sanitize() 896 897 var changed bool 898 if a.lifetimes != lifetimes { 899 changed = true 900 } 901 a.lifetimes = lifetimes 902 if changed { 903 a.notifyChangedLocked() 904 } 905 } 906 907 // Lifetimes implements AddressEndpoint. 908 func (a *addressState) Lifetimes() AddressLifetimes { 909 a.mu.RLock() 910 defer a.mu.RUnlock() 911 return a.lifetimes 912 } 913 914 // Temporary implements AddressEndpoint. 915 func (a *addressState) Temporary() bool { 916 return a.temporary 917 } 918 919 // RegisterDispatcher implements AddressEndpoint. 920 func (a *addressState) RegisterDispatcher(disp AddressDispatcher) { 921 a.mu.Lock() 922 defer a.mu.Unlock() 923 if disp != nil { 924 a.disp = disp 925 a.notifyChangedLocked() 926 } 927 }