mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
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
This commit is contained in:
committed by
Shentubot
parent
05d721f9ee
commit
3830786883
@@ -160,9 +160,27 @@ func (*protocol) LinkAddressRequest(addr, localAddr tcpip.Address, linkEP stack.
|
||||
|
||||
// ResolveStaticAddress implements stack.LinkAddressResolver.
|
||||
func (*protocol) ResolveStaticAddress(addr tcpip.Address) (tcpip.LinkAddress, bool) {
|
||||
if addr == "\xff\xff\xff\xff" {
|
||||
if addr == header.IPv4Broadcast {
|
||||
return broadcastMAC, true
|
||||
}
|
||||
if header.IsV4MulticastAddress(addr) {
|
||||
// RFC 1112 Host Extensions for IP Multicasting
|
||||
//
|
||||
// 6.4. Extensions to an Ethernet Local Network Module:
|
||||
//
|
||||
// An IP host group address is mapped to an Ethernet multicast
|
||||
// address by placing the low-order 23-bits of the IP address
|
||||
// into the low-order 23 bits of the Ethernet multicast address
|
||||
// 01-00-5E-00-00-00 (hex).
|
||||
return tcpip.LinkAddress([]byte{
|
||||
0x01,
|
||||
0x00,
|
||||
0x5e,
|
||||
addr[header.IPv4AddressSize-3] & 0x7f,
|
||||
addr[header.IPv4AddressSize-2],
|
||||
addr[header.IPv4AddressSize-1],
|
||||
}), true
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
|
||||
@@ -206,6 +206,25 @@ func (*protocol) LinkAddressRequest(addr, localAddr tcpip.Address, linkEP stack.
|
||||
|
||||
// ResolveStaticAddress implements stack.LinkAddressResolver.
|
||||
func (*protocol) ResolveStaticAddress(addr tcpip.Address) (tcpip.LinkAddress, bool) {
|
||||
if header.IsV6MulticastAddress(addr) {
|
||||
// RFC 2464 Transmission of IPv6 Packets over Ethernet Networks
|
||||
//
|
||||
// 7. Address Mapping -- Multicast
|
||||
//
|
||||
// An IPv6 packet with a multicast destination address DST,
|
||||
// consisting of the sixteen octets DST[1] through DST[16], is
|
||||
// transmitted to the Ethernet multicast address whose first
|
||||
// two octets are the value 3333 hexadecimal and whose last
|
||||
// four octets are the last four octets of DST.
|
||||
return tcpip.LinkAddress([]byte{
|
||||
0x33,
|
||||
0x33,
|
||||
addr[header.IPv6AddressSize-4],
|
||||
addr[header.IPv6AddressSize-3],
|
||||
addr[header.IPv6AddressSize-2],
|
||||
addr[header.IPv6AddressSize-1],
|
||||
}), true
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
|
||||
+24
-34
@@ -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
|
||||
} 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -654,8 +654,8 @@ func TestBroadcastNeedsNoRoute(t *testing.T) {
|
||||
s.SetRouteTable([]tcpip.Route{})
|
||||
|
||||
// If there is no endpoint, it won't work.
|
||||
if _, err := s.FindRoute(1, header.IPv4Any, header.IPv4Broadcast, fakeNetNumber); err != tcpip.ErrNoRoute {
|
||||
t.Fatalf("got FindRoute(1, %v, %v, %v) = %v, want = %v", header.IPv4Any, header.IPv4Broadcast, fakeNetNumber, err, tcpip.ErrNoRoute)
|
||||
if _, err := s.FindRoute(1, header.IPv4Any, header.IPv4Broadcast, fakeNetNumber); err != tcpip.ErrNetworkUnreachable {
|
||||
t.Fatalf("got FindRoute(1, %v, %v, %v) = %v, want = %v", header.IPv4Any, header.IPv4Broadcast, fakeNetNumber, err, tcpip.ErrNetworkUnreachable)
|
||||
}
|
||||
|
||||
if err := s.AddAddress(1, fakeNetNumber, header.IPv4Any); err != nil {
|
||||
@@ -675,8 +675,8 @@ func TestBroadcastNeedsNoRoute(t *testing.T) {
|
||||
}
|
||||
|
||||
// If the NIC doesn't exist, it won't work.
|
||||
if _, err := s.FindRoute(2, header.IPv4Any, header.IPv4Broadcast, fakeNetNumber); err != tcpip.ErrNoRoute {
|
||||
t.Fatalf("got FindRoute(2, %v, %v, %v) = %v want = %v", header.IPv4Any, header.IPv4Broadcast, fakeNetNumber, err, tcpip.ErrNoRoute)
|
||||
if _, err := s.FindRoute(2, header.IPv4Any, header.IPv4Broadcast, fakeNetNumber); err != tcpip.ErrNetworkUnreachable {
|
||||
t.Fatalf("got FindRoute(2, %v, %v, %v) = %v want = %v", header.IPv4Any, header.IPv4Broadcast, fakeNetNumber, err, tcpip.ErrNetworkUnreachable)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -732,17 +732,21 @@ func TestMulticastOrIPv6LinkLocalNeedsNoRoute(t *testing.T) {
|
||||
anyAddr = header.IPv6Any
|
||||
}
|
||||
|
||||
want := tcpip.ErrNetworkUnreachable
|
||||
if tc.routeNeeded {
|
||||
want = tcpip.ErrNoRoute
|
||||
}
|
||||
|
||||
// If there is no endpoint, it won't work.
|
||||
if _, err := s.FindRoute(1, anyAddr, tc.address, fakeNetNumber); err != tcpip.ErrNoRoute {
|
||||
t.Fatalf("got FindRoute(1, %v, %v, %v) = %v, want = %v", anyAddr, tc.address, fakeNetNumber, err, tcpip.ErrNoRoute)
|
||||
if _, err := s.FindRoute(1, anyAddr, tc.address, fakeNetNumber); err != want {
|
||||
t.Fatalf("got FindRoute(1, %v, %v, %v) = %v, want = %v", anyAddr, tc.address, fakeNetNumber, err, want)
|
||||
}
|
||||
|
||||
if err := s.AddAddress(1, fakeNetNumber, anyAddr); err != nil {
|
||||
t.Fatalf("AddAddress(%v, %v) failed: %v", fakeNetNumber, anyAddr, err)
|
||||
}
|
||||
|
||||
r, err := s.FindRoute(1, anyAddr, tc.address, fakeNetNumber)
|
||||
if tc.routeNeeded {
|
||||
if r, err := s.FindRoute(1, anyAddr, tc.address, fakeNetNumber); tc.routeNeeded {
|
||||
// Route table is empty but we need a route, this should cause an error.
|
||||
if err != tcpip.ErrNoRoute {
|
||||
t.Fatalf("got FindRoute(1, %v, %v, %v) = %v, want = %v", anyAddr, tc.address, fakeNetNumber, err, tcpip.ErrNoRoute)
|
||||
@@ -759,8 +763,8 @@ func TestMulticastOrIPv6LinkLocalNeedsNoRoute(t *testing.T) {
|
||||
}
|
||||
}
|
||||
// If the NIC doesn't exist, it won't work.
|
||||
if _, err := s.FindRoute(2, anyAddr, tc.address, fakeNetNumber); err != tcpip.ErrNoRoute {
|
||||
t.Fatalf("got FindRoute(2, %v, %v, %v) = %v want = %v", anyAddr, tc.address, fakeNetNumber, err, tcpip.ErrNoRoute)
|
||||
if _, err := s.FindRoute(2, anyAddr, tc.address, fakeNetNumber); err != want {
|
||||
t.Fatalf("got FindRoute(2, %v, %v, %v) = %v want = %v", anyAddr, tc.address, fakeNetNumber, err, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user