github.com/ttpreport/gvisor-ligolo@v0.0.0-20240123134145-a858404967ba/pkg/tcpip/stack/route.go (about)

     1  // Copyright 2018 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/ttpreport/gvisor-ligolo/pkg/tcpip"
    21  	"github.com/ttpreport/gvisor-ligolo/pkg/tcpip/header"
    22  )
    23  
    24  // Route represents a route through the networking stack to a given destination.
    25  //
    26  // It is safe to call Route's methods from multiple goroutines.
    27  type Route struct {
    28  	routeInfo routeInfo
    29  
    30  	// localAddressNIC is the interface the address is associated with.
    31  	// TODO(gvisor.dev/issue/4548): Remove this field once we can query the
    32  	// address's assigned status without the NIC.
    33  	localAddressNIC *nic
    34  
    35  	// mu protects annotated fields below.
    36  	mu routeRWMutex
    37  
    38  	// localAddressEndpoint is the local address this route is associated with.
    39  	// +checklocks:mu
    40  	localAddressEndpoint AssignableAddressEndpoint
    41  
    42  	// remoteLinkAddress is the link-layer (MAC) address of the next hop.
    43  	// +checklocks:mu
    44  	remoteLinkAddress tcpip.LinkAddress
    45  
    46  	// outgoingNIC is the interface this route uses to write packets.
    47  	outgoingNIC *nic
    48  
    49  	// linkRes is set if link address resolution is enabled for this protocol on
    50  	// the route's NIC.
    51  	linkRes *linkResolver
    52  
    53  	// neighborEntry is the cached result of fetching a neighbor entry from the
    54  	// neighbor cache.
    55  	// +checklocks:mu
    56  	neighborEntry *neighborEntry
    57  }
    58  
    59  // +stateify savable
    60  type routeInfo struct {
    61  	RemoteAddress tcpip.Address
    62  
    63  	LocalAddress tcpip.Address
    64  
    65  	LocalLinkAddress tcpip.LinkAddress
    66  
    67  	NextHop tcpip.Address
    68  
    69  	NetProto tcpip.NetworkProtocolNumber
    70  
    71  	Loop PacketLooping
    72  }
    73  
    74  // RemoteAddress returns the route's destination.
    75  func (r *Route) RemoteAddress() tcpip.Address {
    76  	return r.routeInfo.RemoteAddress
    77  }
    78  
    79  // LocalAddress returns the route's local address.
    80  func (r *Route) LocalAddress() tcpip.Address {
    81  	return r.routeInfo.LocalAddress
    82  }
    83  
    84  // LocalLinkAddress returns the route's local link-layer address.
    85  func (r *Route) LocalLinkAddress() tcpip.LinkAddress {
    86  	return r.routeInfo.LocalLinkAddress
    87  }
    88  
    89  // NextHop returns the next node in the route's path to the destination.
    90  func (r *Route) NextHop() tcpip.Address {
    91  	return r.routeInfo.NextHop
    92  }
    93  
    94  // NetProto returns the route's network-layer protocol number.
    95  func (r *Route) NetProto() tcpip.NetworkProtocolNumber {
    96  	return r.routeInfo.NetProto
    97  }
    98  
    99  // Loop returns the route's required packet looping.
   100  func (r *Route) Loop() PacketLooping {
   101  	return r.routeInfo.Loop
   102  }
   103  
   104  // RouteInfo contains all of Route's exported fields.
   105  //
   106  // +stateify savable
   107  type RouteInfo struct {
   108  	routeInfo
   109  
   110  	// RemoteLinkAddress is the link-layer (MAC) address of the next hop in the
   111  	// route.
   112  	RemoteLinkAddress tcpip.LinkAddress
   113  }
   114  
   115  // Fields returns a RouteInfo with all of the known values for the route's
   116  // fields.
   117  //
   118  // If any fields are unknown (e.g. remote link address when it is waiting for
   119  // link address resolution), they will be unset.
   120  func (r *Route) Fields() RouteInfo {
   121  	r.mu.RLock()
   122  	defer r.mu.RUnlock()
   123  	return r.fieldsLocked()
   124  }
   125  
   126  // +checklocksread:r.mu
   127  func (r *Route) fieldsLocked() RouteInfo {
   128  	return RouteInfo{
   129  		routeInfo:         r.routeInfo,
   130  		RemoteLinkAddress: r.remoteLinkAddress,
   131  	}
   132  }
   133  
   134  // constructAndValidateRoute validates and initializes a route. It takes
   135  // ownership of the provided local address.
   136  //
   137  // Returns an empty route if validation fails.
   138  func constructAndValidateRoute(netProto tcpip.NetworkProtocolNumber, addressEndpoint AssignableAddressEndpoint, localAddressNIC, outgoingNIC *nic, gateway, localAddr, remoteAddr tcpip.Address, handleLocal, multicastLoop bool) *Route {
   139  	if localAddr.BitLen() == 0 {
   140  		localAddr = addressEndpoint.AddressWithPrefix().Address
   141  	}
   142  
   143  	if localAddressNIC != outgoingNIC && header.IsV6LinkLocalUnicastAddress(localAddr) {
   144  		addressEndpoint.DecRef()
   145  		return nil
   146  	}
   147  
   148  	// If no remote address is provided, use the local address.
   149  	if remoteAddr.BitLen() == 0 {
   150  		remoteAddr = localAddr
   151  	}
   152  
   153  	r := makeRoute(
   154  		netProto,
   155  		gateway,
   156  		localAddr,
   157  		remoteAddr,
   158  		outgoingNIC,
   159  		localAddressNIC,
   160  		addressEndpoint,
   161  		handleLocal,
   162  		multicastLoop,
   163  	)
   164  
   165  	return r
   166  }
   167  
   168  // makeRoute initializes a new route. It takes ownership of the provided
   169  // AssignableAddressEndpoint.
   170  func makeRoute(netProto tcpip.NetworkProtocolNumber, gateway, localAddr, remoteAddr tcpip.Address, outgoingNIC, localAddressNIC *nic, localAddressEndpoint AssignableAddressEndpoint, handleLocal, multicastLoop bool) *Route {
   171  	if localAddressNIC.stack != outgoingNIC.stack {
   172  		panic(fmt.Sprintf("cannot create a route with NICs from different stacks"))
   173  	}
   174  
   175  	if localAddr.BitLen() == 0 {
   176  		localAddr = localAddressEndpoint.AddressWithPrefix().Address
   177  	}
   178  
   179  	loop := PacketOut
   180  
   181  	// TODO(gvisor.dev/issue/4689): Loopback interface loops back packets at the
   182  	// link endpoint level. We can remove this check once loopback interfaces
   183  	// loop back packets at the network layer.
   184  	if !outgoingNIC.IsLoopback() {
   185  		if handleLocal && localAddr != (tcpip.Address{}) && remoteAddr == localAddr {
   186  			loop = PacketLoop
   187  		} else if multicastLoop && (header.IsV4MulticastAddress(remoteAddr) || header.IsV6MulticastAddress(remoteAddr)) {
   188  			loop |= PacketLoop
   189  		} else if remoteAddr == header.IPv4Broadcast {
   190  			loop |= PacketLoop
   191  		} else if subnet := localAddressEndpoint.AddressWithPrefix().Subnet(); subnet.IsBroadcast(remoteAddr) {
   192  			loop |= PacketLoop
   193  		}
   194  	}
   195  
   196  	r := makeRouteInner(netProto, localAddr, remoteAddr, outgoingNIC, localAddressNIC, localAddressEndpoint, loop)
   197  	if r.Loop()&PacketOut == 0 {
   198  		// Packet will not leave the stack, no need for a gateway or a remote link
   199  		// address.
   200  		return r
   201  	}
   202  
   203  	if r.outgoingNIC.NetworkLinkEndpoint.Capabilities()&CapabilityResolutionRequired != 0 {
   204  		if linkRes, ok := r.outgoingNIC.linkAddrResolvers[r.NetProto()]; ok {
   205  			r.linkRes = linkRes
   206  		}
   207  	}
   208  
   209  	if gateway.BitLen() > 0 {
   210  		r.routeInfo.NextHop = gateway
   211  		return r
   212  	}
   213  
   214  	if r.linkRes == nil {
   215  		return r
   216  	}
   217  
   218  	if linkAddr, ok := r.linkRes.resolver.ResolveStaticAddress(r.RemoteAddress()); ok {
   219  		r.ResolveWith(linkAddr)
   220  		return r
   221  	}
   222  
   223  	if subnet := localAddressEndpoint.Subnet(); subnet.IsBroadcast(remoteAddr) {
   224  		r.ResolveWith(header.EthernetBroadcastAddress)
   225  		return r
   226  	}
   227  
   228  	if r.RemoteAddress() == r.LocalAddress() {
   229  		// Local link address is already known.
   230  		r.ResolveWith(r.LocalLinkAddress())
   231  	}
   232  
   233  	return r
   234  }
   235  
   236  func makeRouteInner(netProto tcpip.NetworkProtocolNumber, localAddr, remoteAddr tcpip.Address, outgoingNIC, localAddressNIC *nic, localAddressEndpoint AssignableAddressEndpoint, loop PacketLooping) *Route {
   237  	r := &Route{
   238  		routeInfo: routeInfo{
   239  			NetProto:         netProto,
   240  			LocalAddress:     localAddr,
   241  			LocalLinkAddress: outgoingNIC.NetworkLinkEndpoint.LinkAddress(),
   242  			RemoteAddress:    remoteAddr,
   243  			Loop:             loop,
   244  		},
   245  		localAddressNIC: localAddressNIC,
   246  		outgoingNIC:     outgoingNIC,
   247  	}
   248  
   249  	r.mu.Lock()
   250  	r.localAddressEndpoint = localAddressEndpoint
   251  	r.mu.Unlock()
   252  
   253  	return r
   254  }
   255  
   256  // makeLocalRoute initializes a new local route. It takes ownership of the
   257  // provided AssignableAddressEndpoint.
   258  //
   259  // A local route is a route to a destination that is local to the stack.
   260  func makeLocalRoute(netProto tcpip.NetworkProtocolNumber, localAddr, remoteAddr tcpip.Address, outgoingNIC, localAddressNIC *nic, localAddressEndpoint AssignableAddressEndpoint) *Route {
   261  	loop := PacketLoop
   262  	// TODO(gvisor.dev/issue/4689): Loopback interface loops back packets at the
   263  	// link endpoint level. We can remove this check once loopback interfaces
   264  	// loop back packets at the network layer.
   265  	if outgoingNIC.IsLoopback() {
   266  		loop = PacketOut
   267  	}
   268  	return makeRouteInner(netProto, localAddr, remoteAddr, outgoingNIC, localAddressNIC, localAddressEndpoint, loop)
   269  }
   270  
   271  // RemoteLinkAddress returns the link-layer (MAC) address of the next hop in
   272  // the route.
   273  func (r *Route) RemoteLinkAddress() tcpip.LinkAddress {
   274  	r.mu.RLock()
   275  	defer r.mu.RUnlock()
   276  	return r.remoteLinkAddress
   277  }
   278  
   279  // NICID returns the id of the NIC from which this route originates.
   280  func (r *Route) NICID() tcpip.NICID {
   281  	return r.outgoingNIC.ID()
   282  }
   283  
   284  // MaxHeaderLength forwards the call to the network endpoint's implementation.
   285  func (r *Route) MaxHeaderLength() uint16 {
   286  	return r.outgoingNIC.getNetworkEndpoint(r.NetProto()).MaxHeaderLength()
   287  }
   288  
   289  // Stats returns a mutable copy of current stats.
   290  func (r *Route) Stats() tcpip.Stats {
   291  	return r.outgoingNIC.stack.Stats()
   292  }
   293  
   294  // PseudoHeaderChecksum forwards the call to the network endpoint's
   295  // implementation.
   296  func (r *Route) PseudoHeaderChecksum(protocol tcpip.TransportProtocolNumber, totalLen uint16) uint16 {
   297  	return header.PseudoHeaderChecksum(protocol, r.LocalAddress(), r.RemoteAddress(), totalLen)
   298  }
   299  
   300  // RequiresTXTransportChecksum returns false if the route does not require
   301  // transport checksums to be populated.
   302  func (r *Route) RequiresTXTransportChecksum() bool {
   303  	if r.local() {
   304  		return false
   305  	}
   306  	return r.outgoingNIC.NetworkLinkEndpoint.Capabilities()&CapabilityTXChecksumOffload == 0
   307  }
   308  
   309  // HasGvisorGSOCapability returns true if the route supports gVisor GSO.
   310  func (r *Route) HasGvisorGSOCapability() bool {
   311  	if gso, ok := r.outgoingNIC.NetworkLinkEndpoint.(GSOEndpoint); ok {
   312  		return gso.SupportedGSO() == GvisorGSOSupported
   313  	}
   314  	return false
   315  }
   316  
   317  // HasHostGSOCapability returns true if the route supports host GSO.
   318  func (r *Route) HasHostGSOCapability() bool {
   319  	if gso, ok := r.outgoingNIC.NetworkLinkEndpoint.(GSOEndpoint); ok {
   320  		return gso.SupportedGSO() == HostGSOSupported
   321  	}
   322  	return false
   323  }
   324  
   325  // HasSaveRestoreCapability returns true if the route supports save/restore.
   326  func (r *Route) HasSaveRestoreCapability() bool {
   327  	return r.outgoingNIC.NetworkLinkEndpoint.Capabilities()&CapabilitySaveRestore != 0
   328  }
   329  
   330  // HasDisconnectOkCapability returns true if the route supports disconnecting.
   331  func (r *Route) HasDisconnectOkCapability() bool {
   332  	return r.outgoingNIC.NetworkLinkEndpoint.Capabilities()&CapabilityDisconnectOk != 0
   333  }
   334  
   335  // GSOMaxSize returns the maximum GSO packet size.
   336  func (r *Route) GSOMaxSize() uint32 {
   337  	if gso, ok := r.outgoingNIC.NetworkLinkEndpoint.(GSOEndpoint); ok {
   338  		return gso.GSOMaxSize()
   339  	}
   340  	return 0
   341  }
   342  
   343  // ResolveWith immediately resolves a route with the specified remote link
   344  // address.
   345  func (r *Route) ResolveWith(addr tcpip.LinkAddress) {
   346  	r.mu.Lock()
   347  	defer r.mu.Unlock()
   348  	r.remoteLinkAddress = addr
   349  }
   350  
   351  // ResolvedFieldsResult is the result of a route resolution attempt.
   352  type ResolvedFieldsResult struct {
   353  	RouteInfo RouteInfo
   354  	Err       tcpip.Error
   355  }
   356  
   357  // ResolvedFields attempts to resolve the remote link address if it is not
   358  // known.
   359  //
   360  // If a callback is provided, it will be called before ResolvedFields returns
   361  // when address resolution is not required. If address resolution is required,
   362  // the callback will be called once address resolution is complete, regardless
   363  // of success or failure.
   364  //
   365  // Note, the route will not cache the remote link address when address
   366  // resolution completes.
   367  func (r *Route) ResolvedFields(afterResolve func(ResolvedFieldsResult)) tcpip.Error {
   368  	_, _, err := r.resolvedFields(afterResolve)
   369  	return err
   370  }
   371  
   372  // resolvedFields is like ResolvedFields but also returns a notification channel
   373  // when address resolution is required. This channel will become readable once
   374  // address resolution is complete.
   375  //
   376  // The route's fields will also be returned, regardless of whether address
   377  // resolution is required or not.
   378  func (r *Route) resolvedFields(afterResolve func(ResolvedFieldsResult)) (RouteInfo, <-chan struct{}, tcpip.Error) {
   379  	r.mu.RLock()
   380  	fields := r.fieldsLocked()
   381  	resolutionRequired := r.isResolutionRequiredRLocked()
   382  	r.mu.RUnlock()
   383  	if !resolutionRequired {
   384  		if afterResolve != nil {
   385  			afterResolve(ResolvedFieldsResult{RouteInfo: fields, Err: nil})
   386  		}
   387  		return fields, nil, nil
   388  	}
   389  
   390  	// If specified, the local address used for link address resolution must be an
   391  	// address on the outgoing interface.
   392  	var linkAddressResolutionRequestLocalAddr tcpip.Address
   393  	if r.localAddressNIC == r.outgoingNIC {
   394  		linkAddressResolutionRequestLocalAddr = r.LocalAddress()
   395  	}
   396  
   397  	nEntry := r.getCachedNeighborEntry()
   398  	if nEntry != nil {
   399  		if addr, ok := nEntry.getRemoteLinkAddress(); ok {
   400  			fields.RemoteLinkAddress = addr
   401  			if afterResolve != nil {
   402  				afterResolve(ResolvedFieldsResult{RouteInfo: fields, Err: nil})
   403  			}
   404  			return fields, nil, nil
   405  		}
   406  	}
   407  	afterResolveFields := fields
   408  	entry, ch, err := r.linkRes.neigh.entry(r.nextHop(), linkAddressResolutionRequestLocalAddr, func(lrr LinkResolutionResult) {
   409  		if afterResolve != nil {
   410  			if lrr.Err == nil {
   411  				afterResolveFields.RemoteLinkAddress = lrr.LinkAddress
   412  			}
   413  
   414  			afterResolve(ResolvedFieldsResult{RouteInfo: afterResolveFields, Err: lrr.Err})
   415  		}
   416  	})
   417  	if err == nil {
   418  		fields.RemoteLinkAddress, _ = entry.getRemoteLinkAddress()
   419  	}
   420  	r.setCachedNeighborEntry(entry)
   421  	return fields, ch, err
   422  }
   423  
   424  func (r *Route) getCachedNeighborEntry() *neighborEntry {
   425  	r.mu.RLock()
   426  	defer r.mu.RUnlock()
   427  	return r.neighborEntry
   428  }
   429  
   430  func (r *Route) setCachedNeighborEntry(entry *neighborEntry) {
   431  	r.mu.Lock()
   432  	defer r.mu.Unlock()
   433  	r.neighborEntry = entry
   434  }
   435  
   436  func (r *Route) nextHop() tcpip.Address {
   437  	if r.NextHop().BitLen() == 0 {
   438  		return r.RemoteAddress()
   439  	}
   440  	return r.NextHop()
   441  }
   442  
   443  // local returns true if the route is a local route.
   444  func (r *Route) local() bool {
   445  	return r.Loop() == PacketLoop || r.outgoingNIC.IsLoopback()
   446  }
   447  
   448  // IsResolutionRequired returns true if Resolve() must be called to resolve
   449  // the link address before the route can be written to.
   450  //
   451  // The NICs the route is associated with must not be locked.
   452  func (r *Route) IsResolutionRequired() bool {
   453  	r.mu.RLock()
   454  	defer r.mu.RUnlock()
   455  	return r.isResolutionRequiredRLocked()
   456  }
   457  
   458  // +checklocksread:r.mu
   459  func (r *Route) isResolutionRequiredRLocked() bool {
   460  	return len(r.remoteLinkAddress) == 0 && r.linkRes != nil && r.isValidForOutgoingRLocked() && !r.local()
   461  }
   462  
   463  func (r *Route) isValidForOutgoing() bool {
   464  	r.mu.RLock()
   465  	defer r.mu.RUnlock()
   466  	return r.isValidForOutgoingRLocked()
   467  }
   468  
   469  // +checklocksread:r.mu
   470  func (r *Route) isValidForOutgoingRLocked() bool {
   471  	if !r.outgoingNIC.Enabled() {
   472  		return false
   473  	}
   474  
   475  	localAddressEndpoint := r.localAddressEndpoint
   476  	if localAddressEndpoint == nil || !r.localAddressNIC.isValidForOutgoing(localAddressEndpoint) {
   477  		return false
   478  	}
   479  
   480  	// If the source NIC and outgoing NIC are different, make sure the stack has
   481  	// forwarding enabled, or the packet will be handled locally.
   482  	if r.outgoingNIC != r.localAddressNIC && !isNICForwarding(r.localAddressNIC, r.NetProto()) && (!r.outgoingNIC.stack.handleLocal || !r.outgoingNIC.hasAddress(r.NetProto(), r.RemoteAddress())) {
   483  		return false
   484  	}
   485  
   486  	return true
   487  }
   488  
   489  // WritePacket writes the packet through the given route.
   490  func (r *Route) WritePacket(params NetworkHeaderParams, pkt PacketBufferPtr) tcpip.Error {
   491  	if !r.isValidForOutgoing() {
   492  		return &tcpip.ErrInvalidEndpointState{}
   493  	}
   494  
   495  	return r.outgoingNIC.getNetworkEndpoint(r.NetProto()).WritePacket(r, params, pkt)
   496  }
   497  
   498  // WriteHeaderIncludedPacket writes a packet already containing a network
   499  // header through the given route.
   500  func (r *Route) WriteHeaderIncludedPacket(pkt PacketBufferPtr) tcpip.Error {
   501  	if !r.isValidForOutgoing() {
   502  		return &tcpip.ErrInvalidEndpointState{}
   503  	}
   504  
   505  	return r.outgoingNIC.getNetworkEndpoint(r.NetProto()).WriteHeaderIncludedPacket(r, pkt)
   506  }
   507  
   508  // DefaultTTL returns the default TTL of the underlying network endpoint.
   509  func (r *Route) DefaultTTL() uint8 {
   510  	return r.outgoingNIC.getNetworkEndpoint(r.NetProto()).DefaultTTL()
   511  }
   512  
   513  // MTU returns the MTU of the underlying network endpoint.
   514  func (r *Route) MTU() uint32 {
   515  	return r.outgoingNIC.getNetworkEndpoint(r.NetProto()).MTU()
   516  }
   517  
   518  // Release decrements the reference counter of the resources associated with the
   519  // route.
   520  func (r *Route) Release() {
   521  	r.mu.Lock()
   522  	defer r.mu.Unlock()
   523  
   524  	if ep := r.localAddressEndpoint; ep != nil {
   525  		ep.DecRef()
   526  	}
   527  }
   528  
   529  // Acquire increments the reference counter of the resources associated with the
   530  // route.
   531  func (r *Route) Acquire() {
   532  	r.mu.RLock()
   533  	defer r.mu.RUnlock()
   534  	r.acquireLocked()
   535  }
   536  
   537  // +checklocksread:r.mu
   538  func (r *Route) acquireLocked() {
   539  	if ep := r.localAddressEndpoint; ep != nil {
   540  		if !ep.IncRef() {
   541  			panic(fmt.Sprintf("failed to increment reference count for local address endpoint = %s", r.LocalAddress()))
   542  		}
   543  	}
   544  }
   545  
   546  // Stack returns the instance of the Stack that owns this route.
   547  func (r *Route) Stack() *Stack {
   548  	return r.outgoingNIC.stack
   549  }
   550  
   551  func (r *Route) isV4Broadcast(addr tcpip.Address) bool {
   552  	if addr == header.IPv4Broadcast {
   553  		return true
   554  	}
   555  
   556  	r.mu.RLock()
   557  	localAddressEndpoint := r.localAddressEndpoint
   558  	r.mu.RUnlock()
   559  	if localAddressEndpoint == nil {
   560  		return false
   561  	}
   562  
   563  	subnet := localAddressEndpoint.Subnet()
   564  	return subnet.IsBroadcast(addr)
   565  }
   566  
   567  // IsOutboundBroadcast returns true if the route is for an outbound broadcast
   568  // packet.
   569  func (r *Route) IsOutboundBroadcast() bool {
   570  	// Only IPv4 has a notion of broadcast.
   571  	return r.isV4Broadcast(r.RemoteAddress())
   572  }
   573  
   574  // ConfirmReachable informs the network/link layer that the neighbour used for
   575  // the route is reachable.
   576  //
   577  // "Reachable" is defined as having full-duplex communication between the
   578  // local and remote ends of the route.
   579  func (r *Route) ConfirmReachable() {
   580  	if entry := r.getCachedNeighborEntry(); entry != nil {
   581  		entry.handleUpperLevelConfirmation()
   582  	}
   583  }