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 }