summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/stack/stack.go
diff options
context:
space:
mode:
authorTamir Duberstein <tamird@google.com>2019-02-28 14:37:42 -0800
committerShentubot <shentubot@google.com>2019-02-28 14:38:32 -0800
commit383078688353feb4ae3714aa4b1d79aea519f7a4 (patch)
treedfef76346275ca81cad9289092e0bd9ae0e315e4 /pkg/tcpip/stack/stack.go
parent05d721f9eec3ad0a430906b968a2876bf37c44a7 (diff)
Map IPv{4,6} addresses to ethernet addresses
...in accordance with RFCs 1112 and 2464. Fixes IPv4 multicast when IP_MULTICAST_IF is specified. Don't return ErrNoRoute when no route is needed. Don't set Route.NextHop when no route is needed. PiperOrigin-RevId: 236199813 Change-Id: I48ed33e1b7f760deaa37e18ad7f1b8b62819ab43
Diffstat (limited to 'pkg/tcpip/stack/stack.go')
-rw-r--r--pkg/tcpip/stack/stack.go56
1 files changed, 23 insertions, 33 deletions
diff --git a/pkg/tcpip/stack/stack.go b/pkg/tcpip/stack/stack.go
index 797489ad9..cfda7ec3c 100644
--- a/pkg/tcpip/stack/stack.go
+++ b/pkg/tcpip/stack/stack.go
@@ -752,49 +752,39 @@ func (s *Stack) FindRoute(id tcpip.NICID, localAddr, remoteAddr tcpip.Address, n
s.mu.RLock()
defer s.mu.RUnlock()
- // We don't require a route in the table to send a broadcast, multicast or
- // IPv6 link-local packet out on a NIC.
isBroadcast := remoteAddr == header.IPv4Broadcast
isMulticast := header.IsV4MulticastAddress(remoteAddr) || header.IsV6MulticastAddress(remoteAddr)
- if id != 0 && (isBroadcast || isMulticast || header.IsV6LinkLocalAddress(remoteAddr)) {
+ needRoute := !(isBroadcast || isMulticast || header.IsV6LinkLocalAddress(remoteAddr))
+ if id != 0 && !needRoute {
if nic, ok := s.nics[id]; ok {
if ref := s.getRefEP(nic, localAddr, netProto); ref != nil {
return makeRoute(netProto, ref.ep.ID().LocalAddress, remoteAddr, nic.linkEP.LinkAddress(), ref), nil
}
}
- return Route{}, tcpip.ErrNoRoute
- }
-
- // TODO: Route multicast packets with no specified local
- // address or NIC.
-
- for i := range s.routeTable {
- if (id != 0 && id != s.routeTable[i].NIC) || (len(remoteAddr) != 0 && !s.routeTable[i].Match(remoteAddr)) {
- continue
- }
-
- nic := s.nics[s.routeTable[i].NIC]
- if nic == nil {
- continue
- }
-
- ref := s.getRefEP(nic, localAddr, netProto)
- if ref == nil {
- continue
- }
-
- if len(remoteAddr) == 0 {
- // If no remote address was provided, then the route
- // provided will refer to the link local address.
- remoteAddr = ref.ep.ID().LocalAddress
+ } else {
+ for _, route := range s.routeTable {
+ if (id != 0 && id != route.NIC) || (len(remoteAddr) != 0 && !route.Match(remoteAddr)) {
+ continue
+ }
+ if nic, ok := s.nics[route.NIC]; ok {
+ if ref := s.getRefEP(nic, localAddr, netProto); ref != nil {
+ if len(remoteAddr) == 0 {
+ // If no remote address was provided, then the route
+ // provided will refer to the link local address.
+ remoteAddr = ref.ep.ID().LocalAddress
+ }
+
+ r := makeRoute(netProto, ref.ep.ID().LocalAddress, remoteAddr, nic.linkEP.LinkAddress(), ref)
+ if needRoute {
+ r.NextHop = route.Gateway
+ }
+ return r, nil
+ }
+ }
}
-
- r := makeRoute(netProto, ref.ep.ID().LocalAddress, remoteAddr, nic.linkEP.LinkAddress(), ref)
- r.NextHop = s.routeTable[i].Gateway
- return r, nil
}
- if isMulticast {
+ if !needRoute {
return Route{}, tcpip.ErrNetworkUnreachable
}