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