diff options
Diffstat (limited to 'pkg/tcpip/tests/integration/loopback_test.go')
-rw-r--r-- | pkg/tcpip/tests/integration/loopback_test.go | 782 |
1 files changed, 0 insertions, 782 deletions
diff --git a/pkg/tcpip/tests/integration/loopback_test.go b/pkg/tcpip/tests/integration/loopback_test.go deleted file mode 100644 index f33223e79..000000000 --- a/pkg/tcpip/tests/integration/loopback_test.go +++ /dev/null @@ -1,782 +0,0 @@ -// 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. - -package loopback_test - -import ( - "bytes" - "testing" - "time" - - "github.com/google/go-cmp/cmp" - "gvisor.dev/gvisor/pkg/tcpip" - "gvisor.dev/gvisor/pkg/tcpip/buffer" - "gvisor.dev/gvisor/pkg/tcpip/checker" - "gvisor.dev/gvisor/pkg/tcpip/header" - "gvisor.dev/gvisor/pkg/tcpip/link/channel" - "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" - "gvisor.dev/gvisor/pkg/tcpip/tests/utils" - "gvisor.dev/gvisor/pkg/tcpip/testutil" - "gvisor.dev/gvisor/pkg/tcpip/transport/icmp" - "gvisor.dev/gvisor/pkg/tcpip/transport/tcp" - "gvisor.dev/gvisor/pkg/tcpip/transport/udp" - "gvisor.dev/gvisor/pkg/waiter" -) - -var _ ipv6.NDPDispatcher = (*ndpDispatcher)(nil) - -type ndpDispatcher struct{} - -func (*ndpDispatcher) OnDuplicateAddressDetectionResult(tcpip.NICID, tcpip.Address, stack.DADResult) { -} - -func (*ndpDispatcher) OnOffLinkRouteUpdated(tcpip.NICID, tcpip.Subnet, tcpip.Address, header.NDPRoutePreference) { -} - -func (*ndpDispatcher) OnOffLinkRouteInvalidated(tcpip.NICID, tcpip.Subnet, tcpip.Address) {} - -func (*ndpDispatcher) OnOnLinkPrefixDiscovered(tcpip.NICID, tcpip.Subnet) { -} - -func (*ndpDispatcher) OnOnLinkPrefixInvalidated(tcpip.NICID, tcpip.Subnet) {} - -func (*ndpDispatcher) OnAutoGenAddress(tcpip.NICID, tcpip.AddressWithPrefix) { -} - -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{ - NDPDisp: &ndpDispatcher{}, - AutoGenLinkLocal: true, - 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 "" - }, - }, - })}, - }) - - 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) - } -} - -// 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) { - const ( - nicID = 1 - localPort = 80 - ) - - data := []byte{1, 2, 3, 4} - - ipv4ProtocolAddress := tcpip.ProtocolAddress{ - Protocol: header.IPv4ProtocolNumber, - AddressWithPrefix: utils.Ipv4Addr, - } - ipv4Bytes := []byte(ipv4ProtocolAddress.AddressWithPrefix.Address) - ipv4Bytes[len(ipv4Bytes)-1]++ - otherIPv4Address := tcpip.Address(ipv4Bytes) - - ipv6ProtocolAddress := tcpip.ProtocolAddress{ - Protocol: header.IPv6ProtocolNumber, - AddressWithPrefix: utils.Ipv6Addr, - } - ipv6Bytes := []byte(utils.Ipv6Addr.Address) - ipv6Bytes[len(ipv6Bytes)-1]++ - otherIPv6Address := tcpip.Address(ipv6Bytes) - - 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, - dstAddr: ipv4ProtocolAddress.AddressWithPrefix.Address, - 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, - dstAddr: utils.RemoteIPv4Addr, - expectRx: false, - }, - { - name: "IPv4 bind to other subnet-local address and send to assigned address", - addAddress: ipv4ProtocolAddress, - bindAddr: otherIPv4Address, - dstAddr: ipv4ProtocolAddress.AddressWithPrefix.Address, - 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, - bindAddr: ipv4ProtocolAddress.AddressWithPrefix.Address, - dstAddr: otherIPv4Address, - expectRx: false, - }, - - { - name: "IPv6 bind and send to assigned address", - addAddress: ipv6ProtocolAddress, - bindAddr: utils.Ipv6Addr.Address, - dstAddr: utils.Ipv6Addr.Address, - 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{ - NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol}, - TransportProtocols: []stack.TransportProtocolFactory{udp.NewProtocol}, - }) - if err := s.CreateNIC(nicID, loopback.New()); err != nil { - t.Fatalf("CreateNIC(%d, _): %s", nicID, err) - } - if err := s.AddProtocolAddress(nicID, test.addAddress, stack.AddressProperties{}); err != nil { - t.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", nicID, test.addAddress, err) - } - s.SetRouteTable([]tcpip.Route{ - { - Destination: header.IPv4EmptySubnet, - NIC: nicID, - }, - { - Destination: header.IPv6EmptySubnet, - NIC: nicID, - }, - }) - - var wq waiter.Queue - 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, - }, - } - var r bytes.Reader - r.Reset(data) - n, err := sep.Write(&r, wopts) - if err != nil { - t.Fatalf("sep.Write(_, _): %s", err) - } - if want := int64(len(data)); n != want { - t.Fatalf("got sep.Write(_, _) = (%d, nil), want = (%d, nil)", n, want) - } - - var buf bytes.Buffer - opts := tcpip.ReadOptions{NeedRemoteAddr: true} - if res, err := rep.Read(&buf, opts); test.expectRx { - if err != nil { - t.Fatalf("rep.Read(_, %#v): %s", opts, err) - } - 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 != "" { - t.Errorf("got UDP payload mismatch (-want +got):\n%s", diff) - } - } 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{}) - } - }) - } -} - -// 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, - AddressWithPrefix: utils.Ipv4Addr, - } - addrBytes := []byte(utils.Ipv4Addr.Address) - addrBytes[len(addrBytes)-1]++ - otherAddr := tcpip.Address(addrBytes) - - s := stack.New(stack.Options{ - NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol}, - }) - if err := s.CreateNIC(nicID, loopback.New()); err != nil { - t.Fatalf("s.CreateNIC(%d, _): %s", nicID, err) - } - if err := s.AddProtocolAddress(nicID, protoAddr, stack.AddressProperties{}); err != nil { - t.Fatalf("s.AddProtocolAddress(%d, %+v, {}): %s", nicID, protoAddr, err) - } - s.SetRouteTable([]tcpip.Route{ - { - Destination: header.IPv4EmptySubnet, - NIC: nicID, - }, - }) - - r, err := s.FindRoute(nicID, otherAddr, utils.RemoteIPv4Addr, ipv4.ProtocolNumber, false /* multicastLoop */) - if err != nil { - t.Fatalf("s.FindRoute(%d, %s, %s, %d, false): %s", nicID, otherAddr, utils.RemoteIPv4Addr, ipv4.ProtocolNumber, err) - } - defer r.Release() - - params := stack.NetworkHeaderParams{ - Protocol: 111, - TTL: 64, - TOS: stack.DefaultTOS, - } - data := buffer.View([]byte{1, 2, 3, 4}) - if err := r.WritePacket(params, stack.NewPacketBuffer(stack.PacketBufferOptions{ - ReserveHeaderBytes: int(r.MaxHeaderLength()), - Data: data.ToVectorisedView(), - })); err != nil { - t.Fatalf("r.WritePacket(%#v, _): %s", params, err) - } - - // 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) - } - { - err := r.WritePacket(params, stack.NewPacketBuffer(stack.PacketBufferOptions{ - ReserveHeaderBytes: int(r.MaxHeaderLength()), - Data: data.ToVectorisedView(), - })) - if _, ok := err.(*tcpip.ErrInvalidEndpointState); !ok { - t.Fatalf("got r.WritePacket(%#v, _) = %s, want = %s", params, err, &tcpip.ErrInvalidEndpointState{}) - } - } -} - -// 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, - AddressWithPrefix: utils.Ipv4Addr, - } - ipv4ProtocolAddress.AddressWithPrefix.PrefixLen = 8 - ipv4Bytes := []byte(ipv4ProtocolAddress.AddressWithPrefix.Address) - ipv4Bytes[len(ipv4Bytes)-1]++ - otherIPv4Address := tcpip.Address(ipv4Bytes) - - ipv6ProtocolAddress := tcpip.ProtocolAddress{ - Protocol: header.IPv6ProtocolNumber, - AddressWithPrefix: utils.Ipv6Addr, - } - ipv6Bytes := []byte(utils.Ipv6Addr.Address) - ipv6Bytes[len(ipv6Bytes)-1]++ - otherIPv6Address := tcpip.Address(ipv6Bytes) - - 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, - dstAddr: utils.RemoteIPv4Addr, - 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, - bindAddr: utils.Ipv6Addr.Address, - dstAddr: utils.Ipv6Addr.Address, - 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}, - }) - if err := s.CreateNIC(nicID, loopback.New()); err != nil { - t.Fatalf("CreateNIC(%d, _): %s", nicID, err) - } - if err := s.AddProtocolAddress(nicID, test.addAddress, stack.AddressProperties{}); err != nil { - t.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", nicID, test.addAddress, err) - } - s.SetRouteTable([]tcpip.Route{ - { - Destination: header.IPv4EmptySubnet, - NIC: nicID, - }, - { - Destination: header.IPv6EmptySubnet, - NIC: nicID, - }, - }) - - var wq waiter.Queue - we, ch := waiter.NewChannelEntry(nil) - wq.EventRegister(&we, waiter.ReadableEvents) - defer wq.EventUnregister(&we) - listeningEndpoint, err := s.NewEndpoint(tcp.ProtocolNumber, test.addAddress.Protocol, &wq) - if err != nil { - t.Fatalf("NewEndpoint(%d, %d, _): %s", udp.ProtocolNumber, test.addAddress.Protocol, err) - } - 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 { - t.Fatalf("s.NewEndpoint(%d, %d, _): %s", udp.ProtocolNumber, test.addAddress.Protocol, err) - } - defer connectingEndpoint.Close() - - connectAddr := tcpip.FullAddress{ - Addr: test.dstAddr, - Port: localPort, - } - { - err := connectingEndpoint.Connect(connectAddr) - if _, ok := err.(*tcpip.ErrConnectStarted); !ok { - t.Fatalf("connectingEndpoint.Connect(%#v): %s", connectAddr, err) - } - } - - if !test.expectAccept { - _, _, err := listeningEndpoint.Accept(nil) - if _, ok := err.(*tcpip.ErrWouldBlock); !ok { - t.Fatalf("got listeningEndpoint.Accept(nil) = %s, want = %s", err, &tcpip.ErrWouldBlock{}) - } - 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) - } - }) - } -} - -func TestExternalLoopbackTraffic(t *testing.T) { - const ( - nicID1 = 1 - nicID2 = 2 - - numPackets = 1 - ttl = 64 - ) - ipv4Loopback := testutil.MustParse4("127.0.0.1") - - loopbackSourcedICMPv4 := func(e *channel.Endpoint) { - utils.RxICMPv4EchoRequest(e, ipv4Loopback, utils.Ipv4Addr.Address, ttl) - } - - loopbackSourcedICMPv6 := func(e *channel.Endpoint) { - utils.RxICMPv6EchoRequest(e, header.IPv6Loopback, utils.Ipv6Addr.Address, ttl) - } - - loopbackDestinedICMPv4 := func(e *channel.Endpoint) { - utils.RxICMPv4EchoRequest(e, utils.RemoteIPv4Addr, ipv4Loopback, ttl) - } - - loopbackDestinedICMPv6 := func(e *channel.Endpoint) { - utils.RxICMPv6EchoRequest(e, utils.RemoteIPv6Addr, header.IPv6Loopback, ttl) - } - - invalidSrcAddrStat := func(s tcpip.IPStats) *tcpip.StatCounter { - return s.InvalidSourceAddressesReceived - } - - invalidDestAddrStat := func(s tcpip.IPStats) *tcpip.StatCounter { - return s.InvalidDestinationAddressesReceived - } - - tests := []struct { - name string - allowExternalLoopback bool - forwarding bool - rxICMP func(*channel.Endpoint) - invalidAddressStat func(tcpip.IPStats) *tcpip.StatCounter - shouldAccept bool - }{ - { - name: "IPv4 external loopback sourced traffic without forwarding and drop external loopback disabled", - allowExternalLoopback: true, - forwarding: false, - rxICMP: loopbackSourcedICMPv4, - invalidAddressStat: invalidSrcAddrStat, - shouldAccept: true, - }, - { - name: "IPv4 external loopback sourced traffic without forwarding and drop external loopback enabled", - allowExternalLoopback: false, - forwarding: false, - rxICMP: loopbackSourcedICMPv4, - invalidAddressStat: invalidSrcAddrStat, - shouldAccept: false, - }, - { - name: "IPv4 external loopback sourced traffic with forwarding and drop external loopback disabled", - allowExternalLoopback: true, - forwarding: true, - rxICMP: loopbackSourcedICMPv4, - invalidAddressStat: invalidSrcAddrStat, - shouldAccept: true, - }, - { - name: "IPv4 external loopback sourced traffic with forwarding and drop external loopback enabled", - allowExternalLoopback: false, - forwarding: true, - rxICMP: loopbackSourcedICMPv4, - invalidAddressStat: invalidSrcAddrStat, - shouldAccept: false, - }, - { - name: "IPv4 external loopback destined traffic without forwarding and drop external loopback disabled", - allowExternalLoopback: true, - forwarding: false, - rxICMP: loopbackDestinedICMPv4, - invalidAddressStat: invalidDestAddrStat, - shouldAccept: false, - }, - { - name: "IPv4 external loopback destined traffic without forwarding and drop external loopback enabled", - allowExternalLoopback: false, - forwarding: false, - rxICMP: loopbackDestinedICMPv4, - invalidAddressStat: invalidDestAddrStat, - shouldAccept: false, - }, - { - name: "IPv4 external loopback destined traffic with forwarding and drop external loopback disabled", - allowExternalLoopback: true, - forwarding: true, - rxICMP: loopbackDestinedICMPv4, - invalidAddressStat: invalidDestAddrStat, - shouldAccept: true, - }, - { - name: "IPv4 external loopback destined traffic with forwarding and drop external loopback enabled", - allowExternalLoopback: false, - forwarding: true, - rxICMP: loopbackDestinedICMPv4, - invalidAddressStat: invalidDestAddrStat, - shouldAccept: false, - }, - - { - name: "IPv6 external loopback sourced traffic without forwarding and drop external loopback disabled", - allowExternalLoopback: true, - forwarding: false, - rxICMP: loopbackSourcedICMPv6, - invalidAddressStat: invalidSrcAddrStat, - shouldAccept: true, - }, - { - name: "IPv6 external loopback sourced traffic without forwarding and drop external loopback enabled", - allowExternalLoopback: false, - forwarding: false, - rxICMP: loopbackSourcedICMPv6, - invalidAddressStat: invalidSrcAddrStat, - shouldAccept: false, - }, - { - name: "IPv6 external loopback sourced traffic with forwarding and drop external loopback disabled", - allowExternalLoopback: true, - forwarding: true, - rxICMP: loopbackSourcedICMPv6, - invalidAddressStat: invalidSrcAddrStat, - shouldAccept: true, - }, - { - name: "IPv6 external loopback sourced traffic with forwarding and drop external loopback enabled", - allowExternalLoopback: false, - forwarding: true, - rxICMP: loopbackSourcedICMPv6, - invalidAddressStat: invalidSrcAddrStat, - shouldAccept: false, - }, - { - name: "IPv6 external loopback destined traffic without forwarding and drop external loopback disabled", - allowExternalLoopback: true, - forwarding: false, - rxICMP: loopbackDestinedICMPv6, - invalidAddressStat: invalidDestAddrStat, - shouldAccept: false, - }, - { - name: "IPv6 external loopback destined traffic without forwarding and drop external loopback enabled", - allowExternalLoopback: false, - forwarding: false, - rxICMP: loopbackDestinedICMPv6, - invalidAddressStat: invalidDestAddrStat, - shouldAccept: false, - }, - { - name: "IPv6 external loopback destined traffic with forwarding and drop external loopback disabled", - allowExternalLoopback: true, - forwarding: true, - rxICMP: loopbackDestinedICMPv6, - invalidAddressStat: invalidDestAddrStat, - shouldAccept: true, - }, - { - name: "IPv6 external loopback destined traffic with forwarding and drop external loopback enabled", - allowExternalLoopback: false, - forwarding: true, - rxICMP: loopbackDestinedICMPv6, - invalidAddressStat: invalidDestAddrStat, - shouldAccept: false, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - s := stack.New(stack.Options{ - NetworkProtocols: []stack.NetworkProtocolFactory{ - ipv4.NewProtocolWithOptions(ipv4.Options{ - AllowExternalLoopbackTraffic: test.allowExternalLoopback, - }), - ipv6.NewProtocolWithOptions(ipv6.Options{ - AllowExternalLoopbackTraffic: test.allowExternalLoopback, - }), - }, - TransportProtocols: []stack.TransportProtocolFactory{icmp.NewProtocol4, icmp.NewProtocol6}, - }) - e := channel.New(1, header.IPv6MinimumMTU, "") - if err := s.CreateNIC(nicID1, e); err != nil { - t.Fatalf("CreateNIC(%d, _): %s", nicID1, err) - } - v4Addr := tcpip.ProtocolAddress{ - Protocol: ipv4.ProtocolNumber, - AddressWithPrefix: utils.Ipv4Addr, - } - 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) - } - - if err := s.CreateNIC(nicID2, loopback.New()); err != nil { - t.Fatalf("CreateNIC(%d, _): %s", nicID2, err) - } - protocolAddrV4 := tcpip.ProtocolAddress{ - Protocol: ipv4.ProtocolNumber, - AddressWithPrefix: tcpip.AddressWithPrefix{ - Address: ipv4Loopback, - PrefixLen: 8, - }, - } - 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) - } - - if test.forwarding { - if err := s.SetForwardingDefaultAndAllNICs(ipv4.ProtocolNumber, true); err != nil { - t.Fatalf("SetForwardingDefaultAndAllNICs(%d, true): %s", ipv4.ProtocolNumber, err) - } - if err := s.SetForwardingDefaultAndAllNICs(ipv6.ProtocolNumber, true); err != nil { - t.Fatalf("SetForwardingDefaultAndAllNICs(%d, true): %s", ipv6.ProtocolNumber, err) - } - } - - s.SetRouteTable([]tcpip.Route{ - tcpip.Route{ - Destination: header.IPv4EmptySubnet, - NIC: nicID1, - }, - tcpip.Route{ - Destination: header.IPv6EmptySubnet, - NIC: nicID1, - }, - tcpip.Route{ - Destination: ipv4Loopback.WithPrefix().Subnet(), - NIC: nicID2, - }, - tcpip.Route{ - 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) - } - }) - } -} |