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