2020-08-24 12:27:01 -07:00
|
|
|
// Copyright 2020 The gVisor Authors.
|
|
|
|
|
//
|
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
|
//
|
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
//
|
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
2021-02-17 12:53:05 -08:00
|
|
|
package loopback_test
|
2020-08-24 12:27:01 -07:00
|
|
|
|
|
|
|
|
import (
|
2021-01-07 14:14:58 -08:00
|
|
|
"bytes"
|
2020-08-24 12:27:01 -07:00
|
|
|
"testing"
|
2020-09-29 13:44:03 -07:00
|
|
|
"time"
|
2020-08-24 12:27:01 -07:00
|
|
|
|
|
|
|
|
"github.com/google/go-cmp/cmp"
|
2023-06-01 21:25:01 -07:00
|
|
|
"gvisor.dev/gvisor/pkg/buffer"
|
2020-08-24 12:27:01 -07:00
|
|
|
"gvisor.dev/gvisor/pkg/tcpip"
|
2021-01-07 14:14:58 -08:00
|
|
|
"gvisor.dev/gvisor/pkg/tcpip/checker"
|
2020-08-24 12:27:01 -07:00
|
|
|
"gvisor.dev/gvisor/pkg/tcpip/header"
|
2021-03-17 11:10:04 -07:00
|
|
|
"gvisor.dev/gvisor/pkg/tcpip/link/channel"
|
2020-08-24 12:27:01 -07:00
|
|
|
"gvisor.dev/gvisor/pkg/tcpip/link/loopback"
|
|
|
|
|
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
|
|
|
|
|
"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
|
|
|
|
|
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
2021-02-17 12:53:05 -08:00
|
|
|
"gvisor.dev/gvisor/pkg/tcpip/tests/utils"
|
2021-04-15 15:09:09 -07:00
|
|
|
"gvisor.dev/gvisor/pkg/tcpip/testutil"
|
2021-03-17 11:10:04 -07:00
|
|
|
"gvisor.dev/gvisor/pkg/tcpip/transport/icmp"
|
2020-11-18 12:43:51 -08:00
|
|
|
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
|
2020-08-24 12:27:01 -07:00
|
|
|
"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
|
|
|
|
|
"gvisor.dev/gvisor/pkg/waiter"
|
|
|
|
|
)
|
|
|
|
|
|
2020-09-29 13:44:03 -07:00
|
|
|
var _ ipv6.NDPDispatcher = (*ndpDispatcher)(nil)
|
|
|
|
|
|
|
|
|
|
type ndpDispatcher struct{}
|
|
|
|
|
|
2021-03-04 11:37:12 -08:00
|
|
|
func (*ndpDispatcher) OnDuplicateAddressDetectionResult(tcpip.NICID, tcpip.Address, stack.DADResult) {
|
2020-09-29 13:44:03 -07:00
|
|
|
}
|
|
|
|
|
|
2021-06-18 12:41:08 -07:00
|
|
|
func (*ndpDispatcher) OnOffLinkRouteUpdated(tcpip.NICID, tcpip.Subnet, tcpip.Address, header.NDPRoutePreference) {
|
2020-09-29 13:44:03 -07:00
|
|
|
}
|
|
|
|
|
|
2021-06-14 15:27:01 -07:00
|
|
|
func (*ndpDispatcher) OnOffLinkRouteInvalidated(tcpip.NICID, tcpip.Subnet, tcpip.Address) {}
|
2020-09-29 13:44:03 -07:00
|
|
|
|
2021-06-14 12:15:06 -07:00
|
|
|
func (*ndpDispatcher) OnOnLinkPrefixDiscovered(tcpip.NICID, tcpip.Subnet) {
|
2020-09-29 13:44:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (*ndpDispatcher) OnOnLinkPrefixInvalidated(tcpip.NICID, tcpip.Subnet) {}
|
|
|
|
|
|
2022-07-07 19:56:11 -07:00
|
|
|
func (*ndpDispatcher) OnAutoGenAddress(tcpip.NICID, tcpip.AddressWithPrefix) stack.AddressDispatcher {
|
|
|
|
|
return nil
|
2020-09-29 13:44:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (*ndpDispatcher) OnAutoGenAddressDeprecated(tcpip.NICID, tcpip.AddressWithPrefix) {}
|
|
|
|
|
|
|
|
|
|
func (*ndpDispatcher) OnAutoGenAddressInvalidated(tcpip.NICID, tcpip.AddressWithPrefix) {}
|
|
|
|
|
|
|
|
|
|
func (*ndpDispatcher) OnRecursiveDNSServerOption(tcpip.NICID, []tcpip.Address, time.Duration) {}
|
|
|
|
|
|
|
|
|
|
func (*ndpDispatcher) OnDNSSearchListOption(tcpip.NICID, []string, time.Duration) {}
|
|
|
|
|
|
|
|
|
|
func (*ndpDispatcher) OnDHCPv6Configuration(tcpip.NICID, ipv6.DHCPv6ConfigurationFromNDPRA) {}
|
|
|
|
|
|
|
|
|
|
// TestInitialLoopbackAddresses tests that the loopback interface does not
|
|
|
|
|
// auto-generate a link-local address when it is brought up.
|
|
|
|
|
func TestInitialLoopbackAddresses(t *testing.T) {
|
|
|
|
|
const nicID = 1
|
|
|
|
|
|
|
|
|
|
s := stack.New(stack.Options{
|
|
|
|
|
NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocolWithOptions(ipv6.Options{
|
2020-11-24 01:17:25 -08:00
|
|
|
NDPDisp: &ndpDispatcher{},
|
|
|
|
|
AutoGenLinkLocal: true,
|
2020-09-29 13:44:03 -07:00
|
|
|
OpaqueIIDOpts: ipv6.OpaqueInterfaceIdentifierOptions{
|
|
|
|
|
NICNameFromID: func(nicID tcpip.NICID, nicName string) string {
|
|
|
|
|
t.Fatalf("should not attempt to get name for NIC with ID = %d; nicName = %s", nicID, nicName)
|
|
|
|
|
return ""
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
})},
|
|
|
|
|
})
|
2022-12-08 16:35:30 -08:00
|
|
|
defer s.Destroy()
|
2020-09-29 13:44:03 -07:00
|
|
|
|
|
|
|
|
if err := s.CreateNIC(nicID, loopback.New()); err != nil {
|
|
|
|
|
t.Fatalf("CreateNIC(%d, _): %s", nicID, err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nicsInfo := s.NICInfo()
|
|
|
|
|
if nicInfo, ok := nicsInfo[nicID]; !ok {
|
|
|
|
|
t.Fatalf("did not find NIC with ID = %d in s.NICInfo() = %#v", nicID, nicsInfo)
|
|
|
|
|
} else if got := len(nicInfo.ProtocolAddresses); got != 0 {
|
|
|
|
|
t.Fatalf("got len(nicInfo.ProtocolAddresses) = %d, want = 0; nicInfo.ProtocolAddresses = %#v", got, nicInfo.ProtocolAddresses)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-18 12:43:51 -08:00
|
|
|
// TestLoopbackAcceptAllInSubnetUDP tests that a loopback interface considers
|
|
|
|
|
// itself bound to all addresses in the subnet of an assigned address and UDP
|
|
|
|
|
// traffic is sent/received correctly.
|
|
|
|
|
func TestLoopbackAcceptAllInSubnetUDP(t *testing.T) {
|
2020-08-24 12:27:01 -07:00
|
|
|
const (
|
|
|
|
|
nicID = 1
|
|
|
|
|
localPort = 80
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
data := []byte{1, 2, 3, 4}
|
|
|
|
|
|
|
|
|
|
ipv4ProtocolAddress := tcpip.ProtocolAddress{
|
|
|
|
|
Protocol: header.IPv4ProtocolNumber,
|
2021-02-17 12:53:05 -08:00
|
|
|
AddressWithPrefix: utils.Ipv4Addr,
|
2020-08-24 12:27:01 -07:00
|
|
|
}
|
2023-05-16 11:32:52 -07:00
|
|
|
addrCopy := ipv4ProtocolAddress.AddressWithPrefix.Address
|
|
|
|
|
ipv4Bytes := addrCopy.AsSlice()
|
2020-08-24 12:27:01 -07:00
|
|
|
ipv4Bytes[len(ipv4Bytes)-1]++
|
2023-05-15 18:03:37 -07:00
|
|
|
otherIPv4Address := tcpip.AddrFromSlice(ipv4Bytes)
|
2020-08-24 12:27:01 -07:00
|
|
|
|
|
|
|
|
ipv6ProtocolAddress := tcpip.ProtocolAddress{
|
|
|
|
|
Protocol: header.IPv6ProtocolNumber,
|
2021-02-17 12:53:05 -08:00
|
|
|
AddressWithPrefix: utils.Ipv6Addr,
|
2020-08-24 12:27:01 -07:00
|
|
|
}
|
2023-05-16 11:32:52 -07:00
|
|
|
addrCopy = utils.Ipv6Addr.Address
|
|
|
|
|
ipv6Bytes := addrCopy.AsSlice()
|
2020-08-24 12:27:01 -07:00
|
|
|
ipv6Bytes[len(ipv6Bytes)-1]++
|
2023-05-15 18:03:37 -07:00
|
|
|
otherIPv6Address := tcpip.AddrFromSlice(ipv6Bytes)
|
2020-08-24 12:27:01 -07:00
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
|
|
|
|
addAddress tcpip.ProtocolAddress
|
|
|
|
|
bindAddr tcpip.Address
|
|
|
|
|
dstAddr tcpip.Address
|
|
|
|
|
expectRx bool
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "IPv4 bind to wildcard and send to assigned address",
|
|
|
|
|
addAddress: ipv4ProtocolAddress,
|
2020-11-18 12:43:51 -08:00
|
|
|
dstAddr: ipv4ProtocolAddress.AddressWithPrefix.Address,
|
2020-08-24 12:27:01 -07:00
|
|
|
expectRx: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "IPv4 bind to wildcard and send to other subnet-local address",
|
|
|
|
|
addAddress: ipv4ProtocolAddress,
|
|
|
|
|
dstAddr: otherIPv4Address,
|
|
|
|
|
expectRx: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "IPv4 bind to wildcard send to other address",
|
|
|
|
|
addAddress: ipv4ProtocolAddress,
|
2021-02-17 12:53:05 -08:00
|
|
|
dstAddr: utils.RemoteIPv4Addr,
|
2020-08-24 12:27:01 -07:00
|
|
|
expectRx: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "IPv4 bind to other subnet-local address and send to assigned address",
|
|
|
|
|
addAddress: ipv4ProtocolAddress,
|
|
|
|
|
bindAddr: otherIPv4Address,
|
2020-11-18 12:43:51 -08:00
|
|
|
dstAddr: ipv4ProtocolAddress.AddressWithPrefix.Address,
|
2020-08-24 12:27:01 -07:00
|
|
|
expectRx: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "IPv4 bind and send to other subnet-local address",
|
|
|
|
|
addAddress: ipv4ProtocolAddress,
|
|
|
|
|
bindAddr: otherIPv4Address,
|
|
|
|
|
dstAddr: otherIPv4Address,
|
|
|
|
|
expectRx: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "IPv4 bind to assigned address and send to other subnet-local address",
|
|
|
|
|
addAddress: ipv4ProtocolAddress,
|
2020-11-18 12:43:51 -08:00
|
|
|
bindAddr: ipv4ProtocolAddress.AddressWithPrefix.Address,
|
2020-08-24 12:27:01 -07:00
|
|
|
dstAddr: otherIPv4Address,
|
|
|
|
|
expectRx: false,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
name: "IPv6 bind and send to assigned address",
|
|
|
|
|
addAddress: ipv6ProtocolAddress,
|
2021-02-17 12:53:05 -08:00
|
|
|
bindAddr: utils.Ipv6Addr.Address,
|
|
|
|
|
dstAddr: utils.Ipv6Addr.Address,
|
2020-08-24 12:27:01 -07:00
|
|
|
expectRx: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "IPv6 bind to wildcard and send to other subnet-local address",
|
|
|
|
|
addAddress: ipv6ProtocolAddress,
|
|
|
|
|
dstAddr: otherIPv6Address,
|
|
|
|
|
expectRx: false,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
|
t.Run(test.name, func(t *testing.T) {
|
|
|
|
|
s := stack.New(stack.Options{
|
2020-09-28 16:22:09 -07:00
|
|
|
NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol},
|
|
|
|
|
TransportProtocols: []stack.TransportProtocolFactory{udp.NewProtocol},
|
2020-08-24 12:27:01 -07:00
|
|
|
})
|
2022-12-08 16:35:30 -08:00
|
|
|
defer s.Destroy()
|
2020-08-24 12:27:01 -07:00
|
|
|
if err := s.CreateNIC(nicID, loopback.New()); err != nil {
|
|
|
|
|
t.Fatalf("CreateNIC(%d, _): %s", nicID, err)
|
|
|
|
|
}
|
2021-09-15 14:57:10 -07:00
|
|
|
if err := s.AddProtocolAddress(nicID, test.addAddress, stack.AddressProperties{}); err != nil {
|
|
|
|
|
t.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", nicID, test.addAddress, err)
|
2020-08-24 12:27:01 -07:00
|
|
|
}
|
|
|
|
|
s.SetRouteTable([]tcpip.Route{
|
2021-01-12 12:36:17 -08:00
|
|
|
{
|
2020-08-24 12:27:01 -07:00
|
|
|
Destination: header.IPv4EmptySubnet,
|
|
|
|
|
NIC: nicID,
|
|
|
|
|
},
|
2021-01-12 12:36:17 -08:00
|
|
|
{
|
2020-08-24 12:27:01 -07:00
|
|
|
Destination: header.IPv6EmptySubnet,
|
|
|
|
|
NIC: nicID,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
2020-11-05 15:49:51 -08:00
|
|
|
var wq waiter.Queue
|
2020-08-24 12:27:01 -07:00
|
|
|
rep, err := s.NewEndpoint(udp.ProtocolNumber, test.addAddress.Protocol, &wq)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("NewEndpoint(%d, %d, _): %s", udp.ProtocolNumber, test.addAddress.Protocol, err)
|
|
|
|
|
}
|
|
|
|
|
defer rep.Close()
|
|
|
|
|
|
|
|
|
|
bindAddr := tcpip.FullAddress{Addr: test.bindAddr, Port: localPort}
|
|
|
|
|
if err := rep.Bind(bindAddr); err != nil {
|
|
|
|
|
t.Fatalf("rep.Bind(%+v): %s", bindAddr, err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sep, err := s.NewEndpoint(udp.ProtocolNumber, test.addAddress.Protocol, &wq)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("NewEndpoint(%d, %d, _): %s", udp.ProtocolNumber, test.addAddress.Protocol, err)
|
|
|
|
|
}
|
|
|
|
|
defer sep.Close()
|
|
|
|
|
|
|
|
|
|
wopts := tcpip.WriteOptions{
|
|
|
|
|
To: &tcpip.FullAddress{
|
|
|
|
|
Addr: test.dstAddr,
|
|
|
|
|
Port: localPort,
|
|
|
|
|
},
|
|
|
|
|
}
|
2021-01-22 12:24:20 -08:00
|
|
|
var r bytes.Reader
|
|
|
|
|
r.Reset(data)
|
|
|
|
|
n, err := sep.Write(&r, wopts)
|
2020-08-24 12:27:01 -07:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("sep.Write(_, _): %s", err)
|
|
|
|
|
}
|
|
|
|
|
if want := int64(len(data)); n != want {
|
2021-01-13 16:02:26 -08:00
|
|
|
t.Fatalf("got sep.Write(_, _) = (%d, nil), want = (%d, nil)", n, want)
|
2020-08-24 12:27:01 -07:00
|
|
|
}
|
|
|
|
|
|
2021-01-07 14:14:58 -08:00
|
|
|
var buf bytes.Buffer
|
|
|
|
|
opts := tcpip.ReadOptions{NeedRemoteAddr: true}
|
2021-01-15 15:47:13 -08:00
|
|
|
if res, err := rep.Read(&buf, opts); test.expectRx {
|
2020-08-24 12:27:01 -07:00
|
|
|
if err != nil {
|
2021-01-15 15:47:13 -08:00
|
|
|
t.Fatalf("rep.Read(_, %#v): %s", opts, err)
|
2020-08-24 12:27:01 -07:00
|
|
|
}
|
2021-01-07 14:14:58 -08:00
|
|
|
if diff := cmp.Diff(tcpip.ReadResult{
|
|
|
|
|
Count: buf.Len(),
|
|
|
|
|
Total: buf.Len(),
|
|
|
|
|
RemoteAddr: tcpip.FullAddress{
|
|
|
|
|
Addr: test.addAddress.AddressWithPrefix.Address,
|
|
|
|
|
},
|
|
|
|
|
}, res,
|
|
|
|
|
checker.IgnoreCmpPath("ControlMessages", "RemoteAddr.NIC", "RemoteAddr.Port"),
|
|
|
|
|
); diff != "" {
|
|
|
|
|
t.Errorf("rep.Read: unexpected result (-want +got):\n%s", diff)
|
|
|
|
|
}
|
|
|
|
|
if diff := cmp.Diff(data, buf.Bytes()); diff != "" {
|
2020-08-24 12:27:01 -07:00
|
|
|
t.Errorf("got UDP payload mismatch (-want +got):\n%s", diff)
|
|
|
|
|
}
|
2021-01-28 17:57:42 -08:00
|
|
|
} else if _, ok := err.(*tcpip.ErrWouldBlock); !ok {
|
|
|
|
|
t.Fatalf("got rep.Read = (%v, %s) [with data %x], want = (_, %s)", res, err, buf.Bytes(), &tcpip.ErrWouldBlock{})
|
2020-08-24 12:27:01 -07:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-09-16 14:54:40 -07:00
|
|
|
|
|
|
|
|
// TestLoopbackSubnetLifetimeBoundToAddr tests that the lifetime of an address
|
|
|
|
|
// in a loopback interface's associated subnet is bound to the permanently bound
|
|
|
|
|
// address.
|
|
|
|
|
func TestLoopbackSubnetLifetimeBoundToAddr(t *testing.T) {
|
|
|
|
|
const nicID = 1
|
|
|
|
|
|
|
|
|
|
protoAddr := tcpip.ProtocolAddress{
|
|
|
|
|
Protocol: ipv4.ProtocolNumber,
|
2021-02-17 12:53:05 -08:00
|
|
|
AddressWithPrefix: utils.Ipv4Addr,
|
2020-09-16 14:54:40 -07:00
|
|
|
}
|
2023-05-16 11:32:52 -07:00
|
|
|
addrCopy := utils.Ipv4Addr.Address
|
|
|
|
|
addrBytes := addrCopy.AsSlice()
|
2020-09-16 14:54:40 -07:00
|
|
|
addrBytes[len(addrBytes)-1]++
|
2023-05-15 18:03:37 -07:00
|
|
|
otherAddr := tcpip.AddrFromSlice(addrBytes)
|
2020-09-16 14:54:40 -07:00
|
|
|
|
|
|
|
|
s := stack.New(stack.Options{
|
2020-09-28 16:22:09 -07:00
|
|
|
NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol},
|
2020-09-16 14:54:40 -07:00
|
|
|
})
|
2022-12-08 16:35:30 -08:00
|
|
|
defer s.Destroy()
|
2020-09-16 14:54:40 -07:00
|
|
|
if err := s.CreateNIC(nicID, loopback.New()); err != nil {
|
|
|
|
|
t.Fatalf("s.CreateNIC(%d, _): %s", nicID, err)
|
|
|
|
|
}
|
2021-09-15 14:57:10 -07:00
|
|
|
if err := s.AddProtocolAddress(nicID, protoAddr, stack.AddressProperties{}); err != nil {
|
|
|
|
|
t.Fatalf("s.AddProtocolAddress(%d, %+v, {}): %s", nicID, protoAddr, err)
|
2020-09-16 14:54:40 -07:00
|
|
|
}
|
|
|
|
|
s.SetRouteTable([]tcpip.Route{
|
2021-01-12 12:36:17 -08:00
|
|
|
{
|
2020-09-16 14:54:40 -07:00
|
|
|
Destination: header.IPv4EmptySubnet,
|
|
|
|
|
NIC: nicID,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
2021-02-17 12:53:05 -08:00
|
|
|
r, err := s.FindRoute(nicID, otherAddr, utils.RemoteIPv4Addr, ipv4.ProtocolNumber, false /* multicastLoop */)
|
2020-09-16 14:54:40 -07:00
|
|
|
if err != nil {
|
2021-02-17 12:53:05 -08:00
|
|
|
t.Fatalf("s.FindRoute(%d, %s, %s, %d, false): %s", nicID, otherAddr, utils.RemoteIPv4Addr, ipv4.ProtocolNumber, err)
|
2020-09-16 14:54:40 -07:00
|
|
|
}
|
|
|
|
|
defer r.Release()
|
|
|
|
|
|
|
|
|
|
params := stack.NetworkHeaderParams{
|
|
|
|
|
Protocol: 111,
|
|
|
|
|
TTL: 64,
|
|
|
|
|
TOS: stack.DefaultTOS,
|
|
|
|
|
}
|
2022-06-07 10:33:35 -07:00
|
|
|
data := []byte{1, 2, 3, 4}
|
2021-04-21 18:07:13 -07:00
|
|
|
if err := r.WritePacket(params, stack.NewPacketBuffer(stack.PacketBufferOptions{
|
2020-09-16 14:54:40 -07:00
|
|
|
ReserveHeaderBytes: int(r.MaxHeaderLength()),
|
2023-06-01 21:25:01 -07:00
|
|
|
Payload: buffer.MakeWithData(data),
|
2020-09-16 14:54:40 -07:00
|
|
|
})); err != nil {
|
2021-04-21 18:07:13 -07:00
|
|
|
t.Fatalf("r.WritePacket(%#v, _): %s", params, err)
|
2020-09-16 14:54:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Removing the address should make the endpoint invalid.
|
|
|
|
|
if err := s.RemoveAddress(nicID, protoAddr.AddressWithPrefix.Address); err != nil {
|
|
|
|
|
t.Fatalf("s.RemoveAddress(%d, %s): %s", nicID, protoAddr.AddressWithPrefix.Address, err)
|
|
|
|
|
}
|
2021-01-28 17:57:42 -08:00
|
|
|
{
|
2021-04-21 18:07:13 -07:00
|
|
|
err := r.WritePacket(params, stack.NewPacketBuffer(stack.PacketBufferOptions{
|
2021-01-28 17:57:42 -08:00
|
|
|
ReserveHeaderBytes: int(r.MaxHeaderLength()),
|
2023-06-01 21:25:01 -07:00
|
|
|
Payload: buffer.MakeWithData(data),
|
2021-01-28 17:57:42 -08:00
|
|
|
}))
|
|
|
|
|
if _, ok := err.(*tcpip.ErrInvalidEndpointState); !ok {
|
2021-04-21 18:07:13 -07:00
|
|
|
t.Fatalf("got r.WritePacket(%#v, _) = %s, want = %s", params, err, &tcpip.ErrInvalidEndpointState{})
|
2021-01-28 17:57:42 -08:00
|
|
|
}
|
2020-09-16 14:54:40 -07:00
|
|
|
}
|
|
|
|
|
}
|
2020-11-18 12:43:51 -08:00
|
|
|
|
|
|
|
|
// TestLoopbackAcceptAllInSubnetTCP tests that a loopback interface considers
|
|
|
|
|
// itself bound to all addresses in the subnet of an assigned address and TCP
|
|
|
|
|
// traffic is sent/received correctly.
|
|
|
|
|
func TestLoopbackAcceptAllInSubnetTCP(t *testing.T) {
|
|
|
|
|
const (
|
|
|
|
|
nicID = 1
|
|
|
|
|
localPort = 80
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
ipv4ProtocolAddress := tcpip.ProtocolAddress{
|
|
|
|
|
Protocol: header.IPv4ProtocolNumber,
|
2021-02-17 12:53:05 -08:00
|
|
|
AddressWithPrefix: utils.Ipv4Addr,
|
2020-11-18 12:43:51 -08:00
|
|
|
}
|
|
|
|
|
ipv4ProtocolAddress.AddressWithPrefix.PrefixLen = 8
|
2023-05-16 11:32:52 -07:00
|
|
|
addrCopy := ipv4ProtocolAddress.AddressWithPrefix.Address
|
|
|
|
|
ipv4Bytes := addrCopy.AsSlice()
|
2020-11-18 12:43:51 -08:00
|
|
|
ipv4Bytes[len(ipv4Bytes)-1]++
|
2023-05-15 18:03:37 -07:00
|
|
|
otherIPv4Address := tcpip.AddrFromSlice(ipv4Bytes)
|
2020-11-18 12:43:51 -08:00
|
|
|
|
|
|
|
|
ipv6ProtocolAddress := tcpip.ProtocolAddress{
|
|
|
|
|
Protocol: header.IPv6ProtocolNumber,
|
2021-02-17 12:53:05 -08:00
|
|
|
AddressWithPrefix: utils.Ipv6Addr,
|
2020-11-18 12:43:51 -08:00
|
|
|
}
|
2023-05-16 11:32:52 -07:00
|
|
|
addrCopy = utils.Ipv6Addr.Address
|
|
|
|
|
ipv6Bytes := addrCopy.AsSlice()
|
2020-11-18 12:43:51 -08:00
|
|
|
ipv6Bytes[len(ipv6Bytes)-1]++
|
2023-05-15 18:03:37 -07:00
|
|
|
otherIPv6Address := tcpip.AddrFromSlice(ipv6Bytes)
|
2020-11-18 12:43:51 -08:00
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
|
|
|
|
addAddress tcpip.ProtocolAddress
|
|
|
|
|
bindAddr tcpip.Address
|
|
|
|
|
dstAddr tcpip.Address
|
|
|
|
|
expectAccept bool
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "IPv4 bind to wildcard and send to assigned address",
|
|
|
|
|
addAddress: ipv4ProtocolAddress,
|
|
|
|
|
dstAddr: ipv4ProtocolAddress.AddressWithPrefix.Address,
|
|
|
|
|
expectAccept: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "IPv4 bind to wildcard and send to other subnet-local address",
|
|
|
|
|
addAddress: ipv4ProtocolAddress,
|
|
|
|
|
dstAddr: otherIPv4Address,
|
|
|
|
|
expectAccept: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "IPv4 bind to wildcard send to other address",
|
|
|
|
|
addAddress: ipv4ProtocolAddress,
|
2021-02-17 12:53:05 -08:00
|
|
|
dstAddr: utils.RemoteIPv4Addr,
|
2020-11-18 12:43:51 -08:00
|
|
|
expectAccept: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "IPv4 bind to other subnet-local address and send to assigned address",
|
|
|
|
|
addAddress: ipv4ProtocolAddress,
|
|
|
|
|
bindAddr: otherIPv4Address,
|
|
|
|
|
dstAddr: ipv4ProtocolAddress.AddressWithPrefix.Address,
|
|
|
|
|
expectAccept: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "IPv4 bind and send to other subnet-local address",
|
|
|
|
|
addAddress: ipv4ProtocolAddress,
|
|
|
|
|
bindAddr: otherIPv4Address,
|
|
|
|
|
dstAddr: otherIPv4Address,
|
|
|
|
|
expectAccept: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "IPv4 bind to assigned address and send to other subnet-local address",
|
|
|
|
|
addAddress: ipv4ProtocolAddress,
|
|
|
|
|
bindAddr: ipv4ProtocolAddress.AddressWithPrefix.Address,
|
|
|
|
|
dstAddr: otherIPv4Address,
|
|
|
|
|
expectAccept: false,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
name: "IPv6 bind and send to assigned address",
|
|
|
|
|
addAddress: ipv6ProtocolAddress,
|
2021-02-17 12:53:05 -08:00
|
|
|
bindAddr: utils.Ipv6Addr.Address,
|
|
|
|
|
dstAddr: utils.Ipv6Addr.Address,
|
2020-11-18 12:43:51 -08:00
|
|
|
expectAccept: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "IPv6 bind to wildcard and send to other subnet-local address",
|
|
|
|
|
addAddress: ipv6ProtocolAddress,
|
|
|
|
|
dstAddr: otherIPv6Address,
|
|
|
|
|
expectAccept: false,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
|
t.Run(test.name, func(t *testing.T) {
|
|
|
|
|
s := stack.New(stack.Options{
|
|
|
|
|
NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol},
|
|
|
|
|
TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol},
|
|
|
|
|
})
|
2022-12-08 16:35:30 -08:00
|
|
|
defer s.Destroy()
|
2020-11-18 12:43:51 -08:00
|
|
|
if err := s.CreateNIC(nicID, loopback.New()); err != nil {
|
|
|
|
|
t.Fatalf("CreateNIC(%d, _): %s", nicID, err)
|
|
|
|
|
}
|
2021-09-15 14:57:10 -07:00
|
|
|
if err := s.AddProtocolAddress(nicID, test.addAddress, stack.AddressProperties{}); err != nil {
|
|
|
|
|
t.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", nicID, test.addAddress, err)
|
2020-11-18 12:43:51 -08:00
|
|
|
}
|
|
|
|
|
s.SetRouteTable([]tcpip.Route{
|
2021-01-12 12:36:17 -08:00
|
|
|
{
|
2020-11-18 12:43:51 -08:00
|
|
|
Destination: header.IPv4EmptySubnet,
|
|
|
|
|
NIC: nicID,
|
|
|
|
|
},
|
2021-01-12 12:36:17 -08:00
|
|
|
{
|
2020-11-18 12:43:51 -08:00
|
|
|
Destination: header.IPv6EmptySubnet,
|
|
|
|
|
NIC: nicID,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
var wq waiter.Queue
|
2021-11-13 12:51:42 -08:00
|
|
|
we, ch := waiter.NewChannelEntry(waiter.ReadableEvents)
|
|
|
|
|
wq.EventRegister(&we)
|
2020-11-18 12:43:51 -08:00
|
|
|
defer wq.EventUnregister(&we)
|
|
|
|
|
listeningEndpoint, err := s.NewEndpoint(tcp.ProtocolNumber, test.addAddress.Protocol, &wq)
|
|
|
|
|
if err != nil {
|
2022-08-31 13:02:23 -07:00
|
|
|
t.Fatalf("NewEndpoint(%d, %d, _): %s", tcp.ProtocolNumber, test.addAddress.Protocol, err)
|
2020-11-18 12:43:51 -08:00
|
|
|
}
|
|
|
|
|
defer listeningEndpoint.Close()
|
|
|
|
|
|
|
|
|
|
bindAddr := tcpip.FullAddress{Addr: test.bindAddr, Port: localPort}
|
|
|
|
|
if err := listeningEndpoint.Bind(bindAddr); err != nil {
|
|
|
|
|
t.Fatalf("listeningEndpoint.Bind(%#v): %s", bindAddr, err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := listeningEndpoint.Listen(1); err != nil {
|
|
|
|
|
t.Fatalf("listeningEndpoint.Listen(1): %s", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
connectingEndpoint, err := s.NewEndpoint(tcp.ProtocolNumber, test.addAddress.Protocol, &wq)
|
|
|
|
|
if err != nil {
|
2022-08-31 13:02:23 -07:00
|
|
|
t.Fatalf("s.NewEndpoint(%d, %d, _): %s", tcp.ProtocolNumber, test.addAddress.Protocol, err)
|
2020-11-18 12:43:51 -08:00
|
|
|
}
|
|
|
|
|
defer connectingEndpoint.Close()
|
|
|
|
|
|
|
|
|
|
connectAddr := tcpip.FullAddress{
|
|
|
|
|
Addr: test.dstAddr,
|
|
|
|
|
Port: localPort,
|
|
|
|
|
}
|
2021-01-28 17:57:42 -08:00
|
|
|
{
|
|
|
|
|
err := connectingEndpoint.Connect(connectAddr)
|
|
|
|
|
if _, ok := err.(*tcpip.ErrConnectStarted); !ok {
|
|
|
|
|
t.Fatalf("connectingEndpoint.Connect(%#v): %s", connectAddr, err)
|
|
|
|
|
}
|
2020-11-18 12:43:51 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !test.expectAccept {
|
2021-01-28 17:57:42 -08:00
|
|
|
_, _, err := listeningEndpoint.Accept(nil)
|
|
|
|
|
if _, ok := err.(*tcpip.ErrWouldBlock); !ok {
|
|
|
|
|
t.Fatalf("got listeningEndpoint.Accept(nil) = %s, want = %s", err, &tcpip.ErrWouldBlock{})
|
2020-11-18 12:43:51 -08:00
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Wait for the listening endpoint to be "readable". That is, wait for a
|
|
|
|
|
// new connection.
|
|
|
|
|
<-ch
|
|
|
|
|
var addr tcpip.FullAddress
|
|
|
|
|
if _, _, err := listeningEndpoint.Accept(&addr); err != nil {
|
|
|
|
|
t.Fatalf("listeningEndpoint.Accept(nil): %s", err)
|
|
|
|
|
}
|
|
|
|
|
if addr.Addr != test.addAddress.AddressWithPrefix.Address {
|
|
|
|
|
t.Errorf("got addr.Addr = %s, want = %s", addr.Addr, test.addAddress.AddressWithPrefix.Address)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-03-17 11:10:04 -07:00
|
|
|
|
|
|
|
|
func TestExternalLoopbackTraffic(t *testing.T) {
|
|
|
|
|
const (
|
|
|
|
|
nicID1 = 1
|
|
|
|
|
nicID2 = 2
|
|
|
|
|
|
|
|
|
|
numPackets = 1
|
2021-04-08 15:28:58 -07:00
|
|
|
ttl = 64
|
2021-03-17 11:10:04 -07:00
|
|
|
)
|
2021-04-15 15:09:09 -07:00
|
|
|
ipv4Loopback := testutil.MustParse4("127.0.0.1")
|
2021-03-17 11:10:04 -07:00
|
|
|
|
|
|
|
|
loopbackSourcedICMPv4 := func(e *channel.Endpoint) {
|
2021-04-08 15:28:58 -07:00
|
|
|
utils.RxICMPv4EchoRequest(e, ipv4Loopback, utils.Ipv4Addr.Address, ttl)
|
2021-03-17 11:10:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
loopbackSourcedICMPv6 := func(e *channel.Endpoint) {
|
2021-04-08 15:28:58 -07:00
|
|
|
utils.RxICMPv6EchoRequest(e, header.IPv6Loopback, utils.Ipv6Addr.Address, ttl)
|
2021-03-17 11:10:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
loopbackDestinedICMPv4 := func(e *channel.Endpoint) {
|
2021-04-08 15:28:58 -07:00
|
|
|
utils.RxICMPv4EchoRequest(e, utils.RemoteIPv4Addr, ipv4Loopback, ttl)
|
2021-03-17 11:10:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
loopbackDestinedICMPv6 := func(e *channel.Endpoint) {
|
2021-04-08 15:28:58 -07:00
|
|
|
utils.RxICMPv6EchoRequest(e, utils.RemoteIPv6Addr, header.IPv6Loopback, ttl)
|
2021-03-17 11:10:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
invalidSrcAddrStat := func(s tcpip.IPStats) *tcpip.StatCounter {
|
|
|
|
|
return s.InvalidSourceAddressesReceived
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
invalidDestAddrStat := func(s tcpip.IPStats) *tcpip.StatCounter {
|
|
|
|
|
return s.InvalidDestinationAddressesReceived
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tests := []struct {
|
2021-03-23 09:54:57 -07:00
|
|
|
name string
|
|
|
|
|
allowExternalLoopback bool
|
|
|
|
|
forwarding bool
|
|
|
|
|
rxICMP func(*channel.Endpoint)
|
|
|
|
|
invalidAddressStat func(tcpip.IPStats) *tcpip.StatCounter
|
|
|
|
|
shouldAccept bool
|
2021-03-17 11:10:04 -07:00
|
|
|
}{
|
|
|
|
|
{
|
2021-03-23 09:54:57 -07:00
|
|
|
name: "IPv4 external loopback sourced traffic without forwarding and drop external loopback disabled",
|
|
|
|
|
allowExternalLoopback: true,
|
|
|
|
|
forwarding: false,
|
|
|
|
|
rxICMP: loopbackSourcedICMPv4,
|
|
|
|
|
invalidAddressStat: invalidSrcAddrStat,
|
|
|
|
|
shouldAccept: true,
|
2021-03-17 11:10:04 -07:00
|
|
|
},
|
|
|
|
|
{
|
2021-03-23 09:54:57 -07:00
|
|
|
name: "IPv4 external loopback sourced traffic without forwarding and drop external loopback enabled",
|
|
|
|
|
allowExternalLoopback: false,
|
|
|
|
|
forwarding: false,
|
|
|
|
|
rxICMP: loopbackSourcedICMPv4,
|
|
|
|
|
invalidAddressStat: invalidSrcAddrStat,
|
|
|
|
|
shouldAccept: false,
|
2021-03-17 11:10:04 -07:00
|
|
|
},
|
|
|
|
|
{
|
2021-03-23 09:54:57 -07:00
|
|
|
name: "IPv4 external loopback sourced traffic with forwarding and drop external loopback disabled",
|
|
|
|
|
allowExternalLoopback: true,
|
|
|
|
|
forwarding: true,
|
|
|
|
|
rxICMP: loopbackSourcedICMPv4,
|
|
|
|
|
invalidAddressStat: invalidSrcAddrStat,
|
|
|
|
|
shouldAccept: true,
|
2021-03-17 11:10:04 -07:00
|
|
|
},
|
|
|
|
|
{
|
2021-03-23 09:54:57 -07:00
|
|
|
name: "IPv4 external loopback sourced traffic with forwarding and drop external loopback enabled",
|
|
|
|
|
allowExternalLoopback: false,
|
|
|
|
|
forwarding: true,
|
|
|
|
|
rxICMP: loopbackSourcedICMPv4,
|
|
|
|
|
invalidAddressStat: invalidSrcAddrStat,
|
|
|
|
|
shouldAccept: false,
|
2021-03-17 11:10:04 -07:00
|
|
|
},
|
|
|
|
|
{
|
2021-03-23 09:54:57 -07:00
|
|
|
name: "IPv4 external loopback destined traffic without forwarding and drop external loopback disabled",
|
|
|
|
|
allowExternalLoopback: true,
|
|
|
|
|
forwarding: false,
|
|
|
|
|
rxICMP: loopbackDestinedICMPv4,
|
|
|
|
|
invalidAddressStat: invalidDestAddrStat,
|
|
|
|
|
shouldAccept: false,
|
2021-03-17 11:10:04 -07:00
|
|
|
},
|
|
|
|
|
{
|
2021-03-23 09:54:57 -07:00
|
|
|
name: "IPv4 external loopback destined traffic without forwarding and drop external loopback enabled",
|
|
|
|
|
allowExternalLoopback: false,
|
|
|
|
|
forwarding: false,
|
|
|
|
|
rxICMP: loopbackDestinedICMPv4,
|
|
|
|
|
invalidAddressStat: invalidDestAddrStat,
|
|
|
|
|
shouldAccept: false,
|
2021-03-17 11:10:04 -07:00
|
|
|
},
|
|
|
|
|
{
|
2021-03-23 09:54:57 -07:00
|
|
|
name: "IPv4 external loopback destined traffic with forwarding and drop external loopback disabled",
|
|
|
|
|
allowExternalLoopback: true,
|
|
|
|
|
forwarding: true,
|
|
|
|
|
rxICMP: loopbackDestinedICMPv4,
|
|
|
|
|
invalidAddressStat: invalidDestAddrStat,
|
|
|
|
|
shouldAccept: true,
|
2021-03-17 11:10:04 -07:00
|
|
|
},
|
|
|
|
|
{
|
2021-03-23 09:54:57 -07:00
|
|
|
name: "IPv4 external loopback destined traffic with forwarding and drop external loopback enabled",
|
|
|
|
|
allowExternalLoopback: false,
|
|
|
|
|
forwarding: true,
|
|
|
|
|
rxICMP: loopbackDestinedICMPv4,
|
|
|
|
|
invalidAddressStat: invalidDestAddrStat,
|
|
|
|
|
shouldAccept: false,
|
2021-03-17 11:10:04 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
{
|
2021-03-23 09:54:57 -07:00
|
|
|
name: "IPv6 external loopback sourced traffic without forwarding and drop external loopback disabled",
|
|
|
|
|
allowExternalLoopback: true,
|
|
|
|
|
forwarding: false,
|
|
|
|
|
rxICMP: loopbackSourcedICMPv6,
|
|
|
|
|
invalidAddressStat: invalidSrcAddrStat,
|
|
|
|
|
shouldAccept: true,
|
2021-03-17 11:10:04 -07:00
|
|
|
},
|
|
|
|
|
{
|
2021-03-23 09:54:57 -07:00
|
|
|
name: "IPv6 external loopback sourced traffic without forwarding and drop external loopback enabled",
|
|
|
|
|
allowExternalLoopback: false,
|
|
|
|
|
forwarding: false,
|
|
|
|
|
rxICMP: loopbackSourcedICMPv6,
|
|
|
|
|
invalidAddressStat: invalidSrcAddrStat,
|
|
|
|
|
shouldAccept: false,
|
2021-03-17 11:10:04 -07:00
|
|
|
},
|
|
|
|
|
{
|
2021-03-23 09:54:57 -07:00
|
|
|
name: "IPv6 external loopback sourced traffic with forwarding and drop external loopback disabled",
|
|
|
|
|
allowExternalLoopback: true,
|
|
|
|
|
forwarding: true,
|
|
|
|
|
rxICMP: loopbackSourcedICMPv6,
|
|
|
|
|
invalidAddressStat: invalidSrcAddrStat,
|
|
|
|
|
shouldAccept: true,
|
2021-03-17 11:10:04 -07:00
|
|
|
},
|
|
|
|
|
{
|
2021-03-23 09:54:57 -07:00
|
|
|
name: "IPv6 external loopback sourced traffic with forwarding and drop external loopback enabled",
|
|
|
|
|
allowExternalLoopback: false,
|
|
|
|
|
forwarding: true,
|
|
|
|
|
rxICMP: loopbackSourcedICMPv6,
|
|
|
|
|
invalidAddressStat: invalidSrcAddrStat,
|
|
|
|
|
shouldAccept: false,
|
2021-03-17 11:10:04 -07:00
|
|
|
},
|
|
|
|
|
{
|
2021-03-23 09:54:57 -07:00
|
|
|
name: "IPv6 external loopback destined traffic without forwarding and drop external loopback disabled",
|
|
|
|
|
allowExternalLoopback: true,
|
|
|
|
|
forwarding: false,
|
|
|
|
|
rxICMP: loopbackDestinedICMPv6,
|
|
|
|
|
invalidAddressStat: invalidDestAddrStat,
|
|
|
|
|
shouldAccept: false,
|
2021-03-17 11:10:04 -07:00
|
|
|
},
|
|
|
|
|
{
|
2021-03-23 09:54:57 -07:00
|
|
|
name: "IPv6 external loopback destined traffic without forwarding and drop external loopback enabled",
|
|
|
|
|
allowExternalLoopback: false,
|
|
|
|
|
forwarding: false,
|
|
|
|
|
rxICMP: loopbackDestinedICMPv6,
|
|
|
|
|
invalidAddressStat: invalidDestAddrStat,
|
|
|
|
|
shouldAccept: false,
|
2021-03-17 11:10:04 -07:00
|
|
|
},
|
|
|
|
|
{
|
2021-03-23 09:54:57 -07:00
|
|
|
name: "IPv6 external loopback destined traffic with forwarding and drop external loopback disabled",
|
|
|
|
|
allowExternalLoopback: true,
|
|
|
|
|
forwarding: true,
|
|
|
|
|
rxICMP: loopbackDestinedICMPv6,
|
|
|
|
|
invalidAddressStat: invalidDestAddrStat,
|
|
|
|
|
shouldAccept: true,
|
2021-03-17 11:10:04 -07:00
|
|
|
},
|
|
|
|
|
{
|
2021-03-23 09:54:57 -07:00
|
|
|
name: "IPv6 external loopback destined traffic with forwarding and drop external loopback enabled",
|
|
|
|
|
allowExternalLoopback: false,
|
|
|
|
|
forwarding: true,
|
|
|
|
|
rxICMP: loopbackDestinedICMPv6,
|
|
|
|
|
invalidAddressStat: invalidDestAddrStat,
|
|
|
|
|
shouldAccept: false,
|
2021-03-17 11:10:04 -07:00
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
|
t.Run(test.name, func(t *testing.T) {
|
|
|
|
|
s := stack.New(stack.Options{
|
|
|
|
|
NetworkProtocols: []stack.NetworkProtocolFactory{
|
|
|
|
|
ipv4.NewProtocolWithOptions(ipv4.Options{
|
2021-03-23 09:54:57 -07:00
|
|
|
AllowExternalLoopbackTraffic: test.allowExternalLoopback,
|
2021-03-17 11:10:04 -07:00
|
|
|
}),
|
|
|
|
|
ipv6.NewProtocolWithOptions(ipv6.Options{
|
2021-03-23 09:54:57 -07:00
|
|
|
AllowExternalLoopbackTraffic: test.allowExternalLoopback,
|
2021-03-17 11:10:04 -07:00
|
|
|
}),
|
|
|
|
|
},
|
|
|
|
|
TransportProtocols: []stack.TransportProtocolFactory{icmp.NewProtocol4, icmp.NewProtocol6},
|
|
|
|
|
})
|
2022-12-08 16:35:30 -08:00
|
|
|
defer s.Destroy()
|
2021-03-17 11:10:04 -07:00
|
|
|
e := channel.New(1, header.IPv6MinimumMTU, "")
|
|
|
|
|
if err := s.CreateNIC(nicID1, e); err != nil {
|
|
|
|
|
t.Fatalf("CreateNIC(%d, _): %s", nicID1, err)
|
|
|
|
|
}
|
2021-09-15 14:57:10 -07:00
|
|
|
v4Addr := tcpip.ProtocolAddress{
|
|
|
|
|
Protocol: ipv4.ProtocolNumber,
|
|
|
|
|
AddressWithPrefix: utils.Ipv4Addr,
|
2021-03-17 11:10:04 -07:00
|
|
|
}
|
2021-09-15 14:57:10 -07:00
|
|
|
if err := s.AddProtocolAddress(nicID1, v4Addr, stack.AddressProperties{}); err != nil {
|
|
|
|
|
t.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", nicID1, v4Addr, err)
|
|
|
|
|
}
|
|
|
|
|
v6Addr := tcpip.ProtocolAddress{
|
|
|
|
|
Protocol: ipv6.ProtocolNumber,
|
|
|
|
|
AddressWithPrefix: utils.Ipv6Addr,
|
|
|
|
|
}
|
|
|
|
|
if err := s.AddProtocolAddress(nicID1, v6Addr, stack.AddressProperties{}); err != nil {
|
|
|
|
|
t.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", nicID1, v6Addr, err)
|
2021-03-17 11:10:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := s.CreateNIC(nicID2, loopback.New()); err != nil {
|
|
|
|
|
t.Fatalf("CreateNIC(%d, _): %s", nicID2, err)
|
|
|
|
|
}
|
2021-09-15 14:57:10 -07:00
|
|
|
protocolAddrV4 := tcpip.ProtocolAddress{
|
|
|
|
|
Protocol: ipv4.ProtocolNumber,
|
|
|
|
|
AddressWithPrefix: tcpip.AddressWithPrefix{
|
|
|
|
|
Address: ipv4Loopback,
|
|
|
|
|
PrefixLen: 8,
|
|
|
|
|
},
|
2021-03-17 11:10:04 -07:00
|
|
|
}
|
2021-09-15 14:57:10 -07:00
|
|
|
if err := s.AddProtocolAddress(nicID2, protocolAddrV4, stack.AddressProperties{}); err != nil {
|
|
|
|
|
t.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", nicID2, protocolAddrV4, err)
|
|
|
|
|
}
|
|
|
|
|
protocolAddrV6 := tcpip.ProtocolAddress{
|
|
|
|
|
Protocol: ipv6.ProtocolNumber,
|
|
|
|
|
AddressWithPrefix: header.IPv6Loopback.WithPrefix(),
|
|
|
|
|
}
|
|
|
|
|
if err := s.AddProtocolAddress(nicID2, protocolAddrV6, stack.AddressProperties{}); err != nil {
|
|
|
|
|
t.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", nicID2, protocolAddrV6, err)
|
2021-03-17 11:10:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if test.forwarding {
|
2021-05-13 11:22:25 -07:00
|
|
|
if err := s.SetForwardingDefaultAndAllNICs(ipv4.ProtocolNumber, true); err != nil {
|
|
|
|
|
t.Fatalf("SetForwardingDefaultAndAllNICs(%d, true): %s", ipv4.ProtocolNumber, err)
|
2021-03-17 11:10:04 -07:00
|
|
|
}
|
2021-05-13 11:22:25 -07:00
|
|
|
if err := s.SetForwardingDefaultAndAllNICs(ipv6.ProtocolNumber, true); err != nil {
|
|
|
|
|
t.Fatalf("SetForwardingDefaultAndAllNICs(%d, true): %s", ipv6.ProtocolNumber, err)
|
2021-03-17 11:10:04 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s.SetRouteTable([]tcpip.Route{
|
2022-05-18 00:52:48 -07:00
|
|
|
{
|
2021-03-17 11:10:04 -07:00
|
|
|
Destination: header.IPv4EmptySubnet,
|
|
|
|
|
NIC: nicID1,
|
|
|
|
|
},
|
2022-05-18 00:52:48 -07:00
|
|
|
{
|
2021-03-17 11:10:04 -07:00
|
|
|
Destination: header.IPv6EmptySubnet,
|
|
|
|
|
NIC: nicID1,
|
|
|
|
|
},
|
2022-05-18 00:52:48 -07:00
|
|
|
{
|
2021-03-17 11:10:04 -07:00
|
|
|
Destination: ipv4Loopback.WithPrefix().Subnet(),
|
|
|
|
|
NIC: nicID2,
|
|
|
|
|
},
|
2022-05-18 00:52:48 -07:00
|
|
|
{
|
2021-03-17 11:10:04 -07:00
|
|
|
Destination: header.IPv6Loopback.WithPrefix().Subnet(),
|
|
|
|
|
NIC: nicID2,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
stats := s.Stats().IP
|
|
|
|
|
invalidAddressStat := test.invalidAddressStat(stats)
|
|
|
|
|
deliveredPacketsStat := stats.PacketsDelivered
|
|
|
|
|
if got := invalidAddressStat.Value(); got != 0 {
|
|
|
|
|
t.Fatalf("got invalidAddressStat.Value() = %d, want = 0", got)
|
|
|
|
|
}
|
|
|
|
|
if got := deliveredPacketsStat.Value(); got != 0 {
|
|
|
|
|
t.Fatalf("got deliveredPacketsStat.Value() = %d, want = 0", got)
|
|
|
|
|
}
|
|
|
|
|
test.rxICMP(e)
|
|
|
|
|
var expectedInvalidPackets uint64
|
|
|
|
|
if !test.shouldAccept {
|
|
|
|
|
expectedInvalidPackets = numPackets
|
|
|
|
|
}
|
|
|
|
|
if got := invalidAddressStat.Value(); got != expectedInvalidPackets {
|
|
|
|
|
t.Fatalf("got invalidAddressStat.Value() = %d, want = %d", got, expectedInvalidPackets)
|
|
|
|
|
}
|
|
|
|
|
if got, want := deliveredPacketsStat.Value(), numPackets-expectedInvalidPackets; got != want {
|
|
|
|
|
t.Fatalf("got deliveredPacketsStat.Value() = %d, want = %d", got, want)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|