gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/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  	"gvisor.dev/gvisor/pkg/tcpip"
    21  	"gvisor.dev/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  // If readOnly is true, the address will be returned without an extra reference.
   541  // In this case it is not safe to modify the endpoint, only read attributes like
   542  // subnet.
   543  //
   544  // Regardless how the address was obtained, it will be acquired before it is
   545  // returned.
   546  func (a *AddressableEndpointState) AcquireAssignedAddressOrMatching(localAddr tcpip.Address, f func(AddressEndpoint) bool, allowTemp bool, tempPEB PrimaryEndpointBehavior, readOnly bool) AddressEndpoint {
   547  	lookup := func() *addressState {
   548  		if addrState, ok := a.endpoints[localAddr]; ok {
   549  			if !addrState.IsAssigned(allowTemp) {
   550  				return nil
   551  			}
   552  
   553  			if !readOnly && !addrState.TryIncRef() {
   554  				panic(fmt.Sprintf("failed to increase the reference count for address = %s", addrState.addr))
   555  			}
   556  
   557  			return addrState
   558  		}
   559  
   560  		if f != nil {
   561  			for _, addrState := range a.endpoints {
   562  				if addrState.IsAssigned(allowTemp) && f(addrState) {
   563  					if !readOnly && !addrState.TryIncRef() {
   564  						continue
   565  					}
   566  					return addrState
   567  				}
   568  			}
   569  		}
   570  		return nil
   571  	}
   572  	// Avoid exclusive lock on mu unless we need to add a new address.
   573  	a.mu.RLock()
   574  	ep := lookup()
   575  	a.mu.RUnlock()
   576  
   577  	if ep != nil {
   578  		return ep
   579  	}
   580  
   581  	if !allowTemp {
   582  		return nil
   583  	}
   584  
   585  	// Acquire state lock in exclusive mode as we need to add a new temporary
   586  	// endpoint.
   587  	a.mu.Lock()
   588  	defer a.mu.Unlock()
   589  
   590  	// Do the lookup again in case another goroutine added the address in the time
   591  	// we released and acquired the lock.
   592  	ep = lookup()
   593  	if ep != nil {
   594  		return ep
   595  	}
   596  
   597  	// Proceed to add a new temporary endpoint.
   598  	addr := localAddr.WithPrefix()
   599  	ep, err := a.addAndAcquireAddressLocked(addr, AddressProperties{PEB: tempPEB}, Temporary)
   600  	if err != nil {
   601  		// addAndAcquireAddressLocked only returns an error if the address is
   602  		// already assigned but we just checked above if the address exists so we
   603  		// expect no error.
   604  		panic(fmt.Sprintf("a.addAndAcquireAddressLocked(%s, AddressProperties{PEB: %s}, false): %s", addr, tempPEB, err))
   605  	}
   606  
   607  	// From https://golang.org/doc/faq#nil_error:
   608  	//
   609  	// Under the covers, interfaces are implemented as two elements, a type T and
   610  	// a value V.
   611  	//
   612  	// An interface value is nil only if the V and T are both unset, (T=nil, V is
   613  	// not set), In particular, a nil interface will always hold a nil type. If we
   614  	// store a nil pointer of type *int inside an interface value, the inner type
   615  	// will be *int regardless of the value of the pointer: (T=*int, V=nil). Such
   616  	// an interface value will therefore be non-nil even when the pointer value V
   617  	// inside is nil.
   618  	//
   619  	// Since addAndAcquireAddressLocked returns a nil value with a non-nil type,
   620  	// we need to explicitly return nil below if ep is (a typed) nil.
   621  	if ep == nil {
   622  		return nil
   623  	}
   624  	if readOnly {
   625  		if ep.addressableEndpointState == a {
   626  			// Checklocks doesn't understand that we are logically guaranteed to have
   627  			// ep.mu locked already. We need to use checklocksignore to appease the
   628  			// analyzer.
   629  			ep.addressableEndpointState.decAddressRefLocked(ep) // +checklocksignore
   630  		} else {
   631  			ep.DecRef()
   632  		}
   633  	}
   634  	return ep
   635  }
   636  
   637  // AcquireAssignedAddress implements AddressableEndpoint.
   638  func (a *AddressableEndpointState) AcquireAssignedAddress(localAddr tcpip.Address, allowTemp bool, tempPEB PrimaryEndpointBehavior, readOnly bool) AddressEndpoint {
   639  	return a.AcquireAssignedAddressOrMatching(localAddr, nil, allowTemp, tempPEB, readOnly)
   640  }
   641  
   642  // AcquireOutgoingPrimaryAddress implements AddressableEndpoint.
   643  func (a *AddressableEndpointState) AcquireOutgoingPrimaryAddress(remoteAddr tcpip.Address, srcHint tcpip.Address, allowExpired bool) AddressEndpoint {
   644  	a.mu.Lock()
   645  	defer a.mu.Unlock()
   646  
   647  	ep := a.acquirePrimaryAddressRLocked(remoteAddr, srcHint, func(ep *addressState) bool {
   648  		return ep.IsAssigned(allowExpired)
   649  	})
   650  
   651  	// From https://golang.org/doc/faq#nil_error:
   652  	//
   653  	// Under the covers, interfaces are implemented as two elements, a type T and
   654  	// a value V.
   655  	//
   656  	// An interface value is nil only if the V and T are both unset, (T=nil, V is
   657  	// not set), In particular, a nil interface will always hold a nil type. If we
   658  	// store a nil pointer of type *int inside an interface value, the inner type
   659  	// will be *int regardless of the value of the pointer: (T=*int, V=nil). Such
   660  	// an interface value will therefore be non-nil even when the pointer value V
   661  	// inside is nil.
   662  	//
   663  	// Since acquirePrimaryAddressLocked returns a nil value with a non-nil type,
   664  	// we need to explicitly return nil below if ep is (a typed) nil.
   665  	if ep == nil {
   666  		return nil
   667  	}
   668  
   669  	return ep
   670  }
   671  
   672  // PrimaryAddresses implements AddressableEndpoint.
   673  func (a *AddressableEndpointState) PrimaryAddresses() []tcpip.AddressWithPrefix {
   674  	a.mu.RLock()
   675  	defer a.mu.RUnlock()
   676  
   677  	var addrs []tcpip.AddressWithPrefix
   678  	if a.options.HiddenWhileDisabled && !a.networkEndpoint.Enabled() {
   679  		return addrs
   680  	}
   681  	for _, ep := range a.primary {
   682  		switch kind := ep.GetKind(); kind {
   683  		// Don't include tentative, expired or temporary endpoints
   684  		// to avoid confusion and prevent the caller from using
   685  		// those.
   686  		case PermanentTentative, PermanentExpired, Temporary:
   687  			continue
   688  		case Permanent:
   689  		default:
   690  			panic(fmt.Sprintf("address %s has unknown kind %d", ep.AddressWithPrefix(), kind))
   691  		}
   692  
   693  		addrs = append(addrs, ep.AddressWithPrefix())
   694  	}
   695  
   696  	return addrs
   697  }
   698  
   699  // PermanentAddresses implements AddressableEndpoint.
   700  func (a *AddressableEndpointState) PermanentAddresses() []tcpip.AddressWithPrefix {
   701  	a.mu.RLock()
   702  	defer a.mu.RUnlock()
   703  
   704  	var addrs []tcpip.AddressWithPrefix
   705  	for _, ep := range a.endpoints {
   706  		if !ep.GetKind().IsPermanent() {
   707  			continue
   708  		}
   709  
   710  		addrs = append(addrs, ep.AddressWithPrefix())
   711  	}
   712  
   713  	return addrs
   714  }
   715  
   716  // Cleanup forcefully leaves all groups and removes all permanent addresses.
   717  func (a *AddressableEndpointState) Cleanup() {
   718  	a.mu.Lock()
   719  	defer a.mu.Unlock()
   720  
   721  	for _, ep := range a.endpoints {
   722  		// removePermanentEndpointLocked returns *tcpip.ErrBadLocalAddress if ep is
   723  		// not a permanent address.
   724  		switch err := a.removePermanentEndpointLocked(ep, AddressRemovalInterfaceRemoved); err.(type) {
   725  		case nil, *tcpip.ErrBadLocalAddress:
   726  		default:
   727  			panic(fmt.Sprintf("unexpected error from removePermanentEndpointLocked(%s): %s", ep.addr, err))
   728  		}
   729  	}
   730  }
   731  
   732  var _ AddressEndpoint = (*addressState)(nil)
   733  
   734  // addressState holds state for an address.
   735  type addressState struct {
   736  	addressableEndpointState *AddressableEndpointState
   737  	addr                     tcpip.AddressWithPrefix
   738  	subnet                   tcpip.Subnet
   739  	temporary                bool
   740  
   741  	// Lock ordering (from outer to inner lock ordering):
   742  	//
   743  	// AddressableEndpointState.mu
   744  	//   addressState.mu
   745  	mu   addressStateRWMutex
   746  	refs addressStateRefs
   747  	// checklocks:mu
   748  	kind AddressKind
   749  	// checklocks:mu
   750  	configType AddressConfigType
   751  	// lifetimes holds this address' lifetimes.
   752  	//
   753  	// Invariant: if lifetimes.deprecated is true, then lifetimes.PreferredUntil
   754  	// must be the zero value. Note that the converse does not need to be
   755  	// upheld!
   756  	//
   757  	// checklocks:mu
   758  	lifetimes AddressLifetimes
   759  	// The enclosing mutex must be write-locked before calling methods on the
   760  	// dispatcher.
   761  	//
   762  	// checklocks:mu
   763  	disp AddressDispatcher
   764  }
   765  
   766  // AddressWithPrefix implements AddressEndpoint.
   767  func (a *addressState) AddressWithPrefix() tcpip.AddressWithPrefix {
   768  	return a.addr
   769  }
   770  
   771  // Subnet implements AddressEndpoint.
   772  func (a *addressState) Subnet() tcpip.Subnet {
   773  	return a.subnet
   774  }
   775  
   776  // GetKind implements AddressEndpoint.
   777  func (a *addressState) GetKind() AddressKind {
   778  	a.mu.RLock()
   779  	defer a.mu.RUnlock()
   780  	return a.kind
   781  }
   782  
   783  // SetKind implements AddressEndpoint.
   784  func (a *addressState) SetKind(kind AddressKind) {
   785  	a.mu.Lock()
   786  	defer a.mu.Unlock()
   787  
   788  	prevKind := a.kind
   789  	a.kind = kind
   790  	if kind == PermanentExpired {
   791  		a.notifyRemovedLocked(AddressRemovalManualAction)
   792  	} else if prevKind != kind && a.addressableEndpointState.networkEndpoint.Enabled() {
   793  		a.notifyChangedLocked()
   794  	}
   795  }
   796  
   797  // notifyRemovedLocked notifies integrators of address removal.
   798  //
   799  // +checklocks:a.mu
   800  func (a *addressState) notifyRemovedLocked(reason AddressRemovalReason) {
   801  	if disp := a.disp; disp != nil {
   802  		a.disp.OnRemoved(reason)
   803  		a.disp = nil
   804  	}
   805  }
   806  
   807  func (a *addressState) remove(reason AddressRemovalReason) {
   808  	a.mu.Lock()
   809  	defer a.mu.Unlock()
   810  
   811  	a.kind = PermanentExpired
   812  	a.notifyRemovedLocked(reason)
   813  }
   814  
   815  // IsAssigned implements AddressEndpoint.
   816  func (a *addressState) IsAssigned(allowExpired bool) bool {
   817  	switch kind := a.GetKind(); kind {
   818  	case PermanentTentative:
   819  		return false
   820  	case PermanentExpired:
   821  		return allowExpired
   822  	case Permanent, Temporary:
   823  		return true
   824  	default:
   825  		panic(fmt.Sprintf("address %s has unknown kind %d", a.AddressWithPrefix(), kind))
   826  	}
   827  }
   828  
   829  // IncRef implements AddressEndpoint.
   830  func (a *addressState) TryIncRef() bool {
   831  	return a.refs.TryIncRef()
   832  }
   833  
   834  // DecRef implements AddressEndpoint.
   835  func (a *addressState) DecRef() {
   836  	a.addressableEndpointState.decAddressRef(a)
   837  }
   838  
   839  // decRefMustNotFree decreases the reference count with the guarantee that the
   840  // reference count will be greater than 0 after the decrement.
   841  //
   842  // Panics if the ref count is less than 2 after acquiring the lock in this
   843  // function.
   844  func (a *addressState) decRefMustNotFree() {
   845  	a.refs.DecRef(func() {
   846  		panic(fmt.Sprintf("cannot decrease addressState %s without freeing the endpoint", a.addr))
   847  	})
   848  }
   849  
   850  // ConfigType implements AddressEndpoint.
   851  func (a *addressState) ConfigType() AddressConfigType {
   852  	a.mu.RLock()
   853  	defer a.mu.RUnlock()
   854  	return a.configType
   855  }
   856  
   857  // notifyChangedLocked notifies integrators of address property changes.
   858  //
   859  // +checklocks:a.mu
   860  func (a *addressState) notifyChangedLocked() {
   861  	if a.disp == nil {
   862  		return
   863  	}
   864  
   865  	state := AddressDisabled
   866  	if a.addressableEndpointState.networkEndpoint.Enabled() {
   867  		switch a.kind {
   868  		case Permanent:
   869  			state = AddressAssigned
   870  		case PermanentTentative:
   871  			state = AddressTentative
   872  		case Temporary, PermanentExpired:
   873  			return
   874  		default:
   875  			panic(fmt.Sprintf("unrecognized address kind = %d", a.kind))
   876  		}
   877  	}
   878  
   879  	a.disp.OnChanged(a.lifetimes, state)
   880  }
   881  
   882  // SetDeprecated implements AddressEndpoint.
   883  func (a *addressState) SetDeprecated(d bool) {
   884  	a.mu.Lock()
   885  	defer a.mu.Unlock()
   886  
   887  	var changed bool
   888  	if a.lifetimes.Deprecated != d {
   889  		a.lifetimes.Deprecated = d
   890  		changed = true
   891  	}
   892  	if d {
   893  		a.lifetimes.PreferredUntil = tcpip.MonotonicTime{}
   894  	}
   895  	if changed {
   896  		a.notifyChangedLocked()
   897  	}
   898  }
   899  
   900  // Deprecated implements AddressEndpoint.
   901  func (a *addressState) Deprecated() bool {
   902  	a.mu.RLock()
   903  	defer a.mu.RUnlock()
   904  	return a.lifetimes.Deprecated
   905  }
   906  
   907  // SetLifetimes implements AddressEndpoint.
   908  func (a *addressState) SetLifetimes(lifetimes AddressLifetimes) {
   909  	a.mu.Lock()
   910  	defer a.mu.Unlock()
   911  
   912  	lifetimes.sanitize()
   913  
   914  	var changed bool
   915  	if a.lifetimes != lifetimes {
   916  		changed = true
   917  	}
   918  	a.lifetimes = lifetimes
   919  	if changed {
   920  		a.notifyChangedLocked()
   921  	}
   922  }
   923  
   924  // Lifetimes implements AddressEndpoint.
   925  func (a *addressState) Lifetimes() AddressLifetimes {
   926  	a.mu.RLock()
   927  	defer a.mu.RUnlock()
   928  	return a.lifetimes
   929  }
   930  
   931  // Temporary implements AddressEndpoint.
   932  func (a *addressState) Temporary() bool {
   933  	return a.temporary
   934  }
   935  
   936  // RegisterDispatcher implements AddressEndpoint.
   937  func (a *addressState) RegisterDispatcher(disp AddressDispatcher) {
   938  	a.mu.Lock()
   939  	defer a.mu.Unlock()
   940  	if disp != nil {
   941  		a.disp = disp
   942  		a.notifyChangedLocked()
   943  	}
   944  }