github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/tcpip/tests/integration/iptables_test.go (about)

     1  // Copyright 2021 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 iptables_test
    16  
    17  import (
    18  	"testing"
    19  
    20  	"github.com/SagerNet/gvisor/pkg/tcpip"
    21  	"github.com/SagerNet/gvisor/pkg/tcpip/buffer"
    22  	"github.com/SagerNet/gvisor/pkg/tcpip/checker"
    23  	"github.com/SagerNet/gvisor/pkg/tcpip/header"
    24  	"github.com/SagerNet/gvisor/pkg/tcpip/link/channel"
    25  	"github.com/SagerNet/gvisor/pkg/tcpip/network/ipv4"
    26  	"github.com/SagerNet/gvisor/pkg/tcpip/network/ipv6"
    27  	"github.com/SagerNet/gvisor/pkg/tcpip/stack"
    28  	"github.com/SagerNet/gvisor/pkg/tcpip/tests/utils"
    29  	"github.com/SagerNet/gvisor/pkg/tcpip/testutil"
    30  	"github.com/SagerNet/gvisor/pkg/tcpip/transport/udp"
    31  )
    32  
    33  type inputIfNameMatcher struct {
    34  	name string
    35  }
    36  
    37  var _ stack.Matcher = (*inputIfNameMatcher)(nil)
    38  
    39  func (*inputIfNameMatcher) Name() string {
    40  	return "inputIfNameMatcher"
    41  }
    42  
    43  func (im *inputIfNameMatcher) Match(hook stack.Hook, _ *stack.PacketBuffer, inNicName, _ string) (bool, bool) {
    44  	return (hook == stack.Input && im.name != "" && im.name == inNicName), false
    45  }
    46  
    47  const (
    48  	nicID          = 1
    49  	nicName        = "nic1"
    50  	anotherNicName = "nic2"
    51  	linkAddr       = tcpip.LinkAddress("\x0a\x0b\x0c\x0d\x0e\x0e")
    52  	srcAddrV4      = "\x0a\x00\x00\x01"
    53  	dstAddrV4      = "\x0a\x00\x00\x02"
    54  	srcAddrV6      = "\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"
    55  	dstAddrV6      = "\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"
    56  	payloadSize    = 20
    57  )
    58  
    59  func genStackV6(t *testing.T) (*stack.Stack, *channel.Endpoint) {
    60  	t.Helper()
    61  	s := stack.New(stack.Options{
    62  		NetworkProtocols: []stack.NetworkProtocolFactory{ipv6.NewProtocol},
    63  	})
    64  	e := channel.New(0, header.IPv6MinimumMTU, linkAddr)
    65  	nicOpts := stack.NICOptions{Name: nicName}
    66  	if err := s.CreateNICWithOptions(nicID, e, nicOpts); err != nil {
    67  		t.Fatalf("CreateNICWithOptions(%d, _, %#v) = %s", nicID, nicOpts, err)
    68  	}
    69  	if err := s.AddAddress(nicID, header.IPv6ProtocolNumber, dstAddrV6); err != nil {
    70  		t.Fatalf("AddAddress(%d, %d, %s) = %s", nicID, header.IPv6ProtocolNumber, dstAddrV6, err)
    71  	}
    72  	return s, e
    73  }
    74  
    75  func genStackV4(t *testing.T) (*stack.Stack, *channel.Endpoint) {
    76  	t.Helper()
    77  	s := stack.New(stack.Options{
    78  		NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol},
    79  	})
    80  	e := channel.New(0, header.IPv4MinimumMTU, linkAddr)
    81  	nicOpts := stack.NICOptions{Name: nicName}
    82  	if err := s.CreateNICWithOptions(nicID, e, nicOpts); err != nil {
    83  		t.Fatalf("CreateNICWithOptions(%d, _, %#v) = %s", nicID, nicOpts, err)
    84  	}
    85  	if err := s.AddAddress(nicID, header.IPv4ProtocolNumber, dstAddrV4); err != nil {
    86  		t.Fatalf("AddAddress(%d, %d, %s) = %s", nicID, header.IPv4ProtocolNumber, dstAddrV4, err)
    87  	}
    88  	return s, e
    89  }
    90  
    91  func genPacketV6() *stack.PacketBuffer {
    92  	pktSize := header.IPv6MinimumSize + payloadSize
    93  	hdr := buffer.NewPrependable(pktSize)
    94  	ip := header.IPv6(hdr.Prepend(pktSize))
    95  	ip.Encode(&header.IPv6Fields{
    96  		PayloadLength:     payloadSize,
    97  		TransportProtocol: 99,
    98  		HopLimit:          255,
    99  		SrcAddr:           srcAddrV6,
   100  		DstAddr:           dstAddrV6,
   101  	})
   102  	vv := hdr.View().ToVectorisedView()
   103  	return stack.NewPacketBuffer(stack.PacketBufferOptions{Data: vv})
   104  }
   105  
   106  func genPacketV4() *stack.PacketBuffer {
   107  	pktSize := header.IPv4MinimumSize + payloadSize
   108  	hdr := buffer.NewPrependable(pktSize)
   109  	ip := header.IPv4(hdr.Prepend(pktSize))
   110  	ip.Encode(&header.IPv4Fields{
   111  		TOS:            0,
   112  		TotalLength:    uint16(pktSize),
   113  		ID:             1,
   114  		Flags:          0,
   115  		FragmentOffset: 16,
   116  		TTL:            48,
   117  		Protocol:       99,
   118  		SrcAddr:        srcAddrV4,
   119  		DstAddr:        dstAddrV4,
   120  	})
   121  	ip.SetChecksum(0)
   122  	ip.SetChecksum(^ip.CalculateChecksum())
   123  	vv := hdr.View().ToVectorisedView()
   124  	return stack.NewPacketBuffer(stack.PacketBufferOptions{Data: vv})
   125  }
   126  
   127  func TestIPTablesStatsForInput(t *testing.T) {
   128  	tests := []struct {
   129  		name               string
   130  		setupStack         func(*testing.T) (*stack.Stack, *channel.Endpoint)
   131  		setupFilter        func(*testing.T, *stack.Stack)
   132  		genPacket          func() *stack.PacketBuffer
   133  		proto              tcpip.NetworkProtocolNumber
   134  		expectReceived     int
   135  		expectInputDropped int
   136  	}{
   137  		{
   138  			name:               "IPv6 Accept",
   139  			setupStack:         genStackV6,
   140  			setupFilter:        func(*testing.T, *stack.Stack) { /* no filter */ },
   141  			genPacket:          genPacketV6,
   142  			proto:              header.IPv6ProtocolNumber,
   143  			expectReceived:     1,
   144  			expectInputDropped: 0,
   145  		},
   146  		{
   147  			name:               "IPv4 Accept",
   148  			setupStack:         genStackV4,
   149  			setupFilter:        func(*testing.T, *stack.Stack) { /* no filter */ },
   150  			genPacket:          genPacketV4,
   151  			proto:              header.IPv4ProtocolNumber,
   152  			expectReceived:     1,
   153  			expectInputDropped: 0,
   154  		},
   155  		{
   156  			name:       "IPv6 Drop (input interface matches)",
   157  			setupStack: genStackV6,
   158  			setupFilter: func(t *testing.T, s *stack.Stack) {
   159  				t.Helper()
   160  				ipt := s.IPTables()
   161  				filter := ipt.GetTable(stack.FilterID, true /* ipv6 */)
   162  				ruleIdx := filter.BuiltinChains[stack.Input]
   163  				filter.Rules[ruleIdx].Filter = stack.IPHeaderFilter{InputInterface: nicName}
   164  				filter.Rules[ruleIdx].Target = &stack.DropTarget{}
   165  				filter.Rules[ruleIdx].Matchers = []stack.Matcher{&inputIfNameMatcher{nicName}}
   166  				// Make sure the packet is not dropped by the next rule.
   167  				filter.Rules[ruleIdx+1].Target = &stack.AcceptTarget{}
   168  				if err := ipt.ReplaceTable(stack.FilterID, filter, true /* ipv6 */); err != nil {
   169  					t.Fatalf("ipt.ReplaceTable(%d, _, %t): %s", stack.FilterID, true, err)
   170  				}
   171  			},
   172  			genPacket:          genPacketV6,
   173  			proto:              header.IPv6ProtocolNumber,
   174  			expectReceived:     1,
   175  			expectInputDropped: 1,
   176  		},
   177  		{
   178  			name:       "IPv4 Drop (input interface matches)",
   179  			setupStack: genStackV4,
   180  			setupFilter: func(t *testing.T, s *stack.Stack) {
   181  				t.Helper()
   182  				ipt := s.IPTables()
   183  				filter := ipt.GetTable(stack.FilterID, false /* ipv6 */)
   184  				ruleIdx := filter.BuiltinChains[stack.Input]
   185  				filter.Rules[ruleIdx].Filter = stack.IPHeaderFilter{InputInterface: nicName}
   186  				filter.Rules[ruleIdx].Target = &stack.DropTarget{}
   187  				filter.Rules[ruleIdx].Matchers = []stack.Matcher{&inputIfNameMatcher{nicName}}
   188  				filter.Rules[ruleIdx+1].Target = &stack.AcceptTarget{}
   189  				if err := ipt.ReplaceTable(stack.FilterID, filter, false /* ipv6 */); err != nil {
   190  					t.Fatalf("ipt.ReplaceTable(%d, _, %t): %s", stack.FilterID, false, err)
   191  				}
   192  			},
   193  			genPacket:          genPacketV4,
   194  			proto:              header.IPv4ProtocolNumber,
   195  			expectReceived:     1,
   196  			expectInputDropped: 1,
   197  		},
   198  		{
   199  			name:       "IPv6 Accept (input interface does not match)",
   200  			setupStack: genStackV6,
   201  			setupFilter: func(t *testing.T, s *stack.Stack) {
   202  				t.Helper()
   203  				ipt := s.IPTables()
   204  				filter := ipt.GetTable(stack.FilterID, true /* ipv6 */)
   205  				ruleIdx := filter.BuiltinChains[stack.Input]
   206  				filter.Rules[ruleIdx].Filter = stack.IPHeaderFilter{InputInterface: anotherNicName}
   207  				filter.Rules[ruleIdx].Target = &stack.DropTarget{}
   208  				filter.Rules[ruleIdx+1].Target = &stack.AcceptTarget{}
   209  				if err := ipt.ReplaceTable(stack.FilterID, filter, true /* ipv6 */); err != nil {
   210  					t.Fatalf("ipt.ReplaceTable(%d, _, %t): %s", stack.FilterID, true, err)
   211  				}
   212  			},
   213  			genPacket:          genPacketV6,
   214  			proto:              header.IPv6ProtocolNumber,
   215  			expectReceived:     1,
   216  			expectInputDropped: 0,
   217  		},
   218  		{
   219  			name:       "IPv4 Accept (input interface does not match)",
   220  			setupStack: genStackV4,
   221  			setupFilter: func(t *testing.T, s *stack.Stack) {
   222  				t.Helper()
   223  				ipt := s.IPTables()
   224  				filter := ipt.GetTable(stack.FilterID, false /* ipv6 */)
   225  				ruleIdx := filter.BuiltinChains[stack.Input]
   226  				filter.Rules[ruleIdx].Filter = stack.IPHeaderFilter{InputInterface: anotherNicName}
   227  				filter.Rules[ruleIdx].Target = &stack.DropTarget{}
   228  				filter.Rules[ruleIdx+1].Target = &stack.AcceptTarget{}
   229  				if err := ipt.ReplaceTable(stack.FilterID, filter, false /* ipv6 */); err != nil {
   230  					t.Fatalf("ipt.ReplaceTable(%d, _, %t): %s", stack.FilterID, false, err)
   231  				}
   232  			},
   233  			genPacket:          genPacketV4,
   234  			proto:              header.IPv4ProtocolNumber,
   235  			expectReceived:     1,
   236  			expectInputDropped: 0,
   237  		},
   238  		{
   239  			name:       "IPv6 Drop (input interface does not match but invert is true)",
   240  			setupStack: genStackV6,
   241  			setupFilter: func(t *testing.T, s *stack.Stack) {
   242  				t.Helper()
   243  				ipt := s.IPTables()
   244  				filter := ipt.GetTable(stack.FilterID, true /* ipv6 */)
   245  				ruleIdx := filter.BuiltinChains[stack.Input]
   246  				filter.Rules[ruleIdx].Filter = stack.IPHeaderFilter{
   247  					InputInterface:       anotherNicName,
   248  					InputInterfaceInvert: true,
   249  				}
   250  				filter.Rules[ruleIdx].Target = &stack.DropTarget{}
   251  				filter.Rules[ruleIdx+1].Target = &stack.AcceptTarget{}
   252  				if err := ipt.ReplaceTable(stack.FilterID, filter, true /* ipv6 */); err != nil {
   253  					t.Fatalf("ipt.ReplaceTable(%d, _, %t): %s", stack.FilterID, true, err)
   254  				}
   255  			},
   256  			genPacket:          genPacketV6,
   257  			proto:              header.IPv6ProtocolNumber,
   258  			expectReceived:     1,
   259  			expectInputDropped: 1,
   260  		},
   261  		{
   262  			name:       "IPv4 Drop (input interface does not match but invert is true)",
   263  			setupStack: genStackV4,
   264  			setupFilter: func(t *testing.T, s *stack.Stack) {
   265  				t.Helper()
   266  				ipt := s.IPTables()
   267  				filter := ipt.GetTable(stack.FilterID, false /* ipv6 */)
   268  				ruleIdx := filter.BuiltinChains[stack.Input]
   269  				filter.Rules[ruleIdx].Filter = stack.IPHeaderFilter{
   270  					InputInterface:       anotherNicName,
   271  					InputInterfaceInvert: true,
   272  				}
   273  				filter.Rules[ruleIdx].Target = &stack.DropTarget{}
   274  				filter.Rules[ruleIdx+1].Target = &stack.AcceptTarget{}
   275  				if err := ipt.ReplaceTable(stack.FilterID, filter, false /* ipv6 */); err != nil {
   276  					t.Fatalf("ipt.ReplaceTable(%d, _, %t): %s", stack.FilterID, false, err)
   277  				}
   278  			},
   279  			genPacket:          genPacketV4,
   280  			proto:              header.IPv4ProtocolNumber,
   281  			expectReceived:     1,
   282  			expectInputDropped: 1,
   283  		},
   284  		{
   285  			name:       "IPv6 Accept (input interface does not match using a matcher)",
   286  			setupStack: genStackV6,
   287  			setupFilter: func(t *testing.T, s *stack.Stack) {
   288  				t.Helper()
   289  				ipt := s.IPTables()
   290  				filter := ipt.GetTable(stack.FilterID, true /* ipv6 */)
   291  				ruleIdx := filter.BuiltinChains[stack.Input]
   292  				filter.Rules[ruleIdx].Target = &stack.DropTarget{}
   293  				filter.Rules[ruleIdx].Matchers = []stack.Matcher{&inputIfNameMatcher{anotherNicName}}
   294  				filter.Rules[ruleIdx+1].Target = &stack.AcceptTarget{}
   295  				if err := ipt.ReplaceTable(stack.FilterID, filter, true /* ipv6 */); err != nil {
   296  					t.Fatalf("ipt.ReplaceTable(%d, _, %t): %s", stack.FilterID, true, err)
   297  				}
   298  			},
   299  			genPacket:          genPacketV6,
   300  			proto:              header.IPv6ProtocolNumber,
   301  			expectReceived:     1,
   302  			expectInputDropped: 0,
   303  		},
   304  		{
   305  			name:       "IPv4 Accept (input interface does not match using a matcher)",
   306  			setupStack: genStackV4,
   307  			setupFilter: func(t *testing.T, s *stack.Stack) {
   308  				t.Helper()
   309  				ipt := s.IPTables()
   310  				filter := ipt.GetTable(stack.FilterID, false /* ipv6 */)
   311  				ruleIdx := filter.BuiltinChains[stack.Input]
   312  				filter.Rules[ruleIdx].Target = &stack.DropTarget{}
   313  				filter.Rules[ruleIdx].Matchers = []stack.Matcher{&inputIfNameMatcher{anotherNicName}}
   314  				filter.Rules[ruleIdx+1].Target = &stack.AcceptTarget{}
   315  				if err := ipt.ReplaceTable(stack.FilterID, filter, false /* ipv6 */); err != nil {
   316  					t.Fatalf("ipt.ReplaceTable(%d, _, %t): %s", stack.FilterID, false, err)
   317  				}
   318  			},
   319  			genPacket:          genPacketV4,
   320  			proto:              header.IPv4ProtocolNumber,
   321  			expectReceived:     1,
   322  			expectInputDropped: 0,
   323  		},
   324  	}
   325  
   326  	for _, test := range tests {
   327  		t.Run(test.name, func(t *testing.T) {
   328  			s, e := test.setupStack(t)
   329  			test.setupFilter(t, s)
   330  			e.InjectInbound(test.proto, test.genPacket())
   331  
   332  			if got := int(s.Stats().IP.PacketsReceived.Value()); got != test.expectReceived {
   333  				t.Errorf("got PacketReceived = %d, want = %d", got, test.expectReceived)
   334  			}
   335  			if got := int(s.Stats().IP.IPTablesInputDropped.Value()); got != test.expectInputDropped {
   336  				t.Errorf("got IPTablesInputDropped = %d, want = %d", got, test.expectInputDropped)
   337  			}
   338  		})
   339  	}
   340  }
   341  
   342  var _ stack.LinkEndpoint = (*channelEndpointWithoutWritePacket)(nil)
   343  
   344  // channelEndpointWithoutWritePacket is a channel endpoint that does not support
   345  // stack.LinkEndpoint.WritePacket.
   346  type channelEndpointWithoutWritePacket struct {
   347  	*channel.Endpoint
   348  
   349  	t *testing.T
   350  }
   351  
   352  func (c *channelEndpointWithoutWritePacket) WritePacket(stack.RouteInfo, tcpip.NetworkProtocolNumber, *stack.PacketBuffer) tcpip.Error {
   353  	c.t.Error("unexpectedly called WritePacket; all writes should go through WritePackets")
   354  	return &tcpip.ErrNotSupported{}
   355  }
   356  
   357  var _ stack.Matcher = (*udpSourcePortMatcher)(nil)
   358  
   359  type udpSourcePortMatcher struct {
   360  	port uint16
   361  }
   362  
   363  func (*udpSourcePortMatcher) Name() string {
   364  	return "udpSourcePortMatcher"
   365  }
   366  
   367  func (m *udpSourcePortMatcher) Match(_ stack.Hook, pkt *stack.PacketBuffer, _, _ string) (matches, hotdrop bool) {
   368  	udp := header.UDP(pkt.TransportHeader().View())
   369  	if len(udp) < header.UDPMinimumSize {
   370  		// Drop immediately as the packet is invalid.
   371  		return false, true
   372  	}
   373  
   374  	return udp.SourcePort() == m.port, false
   375  }
   376  
   377  func TestIPTableWritePackets(t *testing.T) {
   378  	const (
   379  		nicID = 1
   380  
   381  		dropLocalPort = utils.LocalPort - 1
   382  		acceptPackets = 2
   383  		dropPackets   = 3
   384  	)
   385  
   386  	udpHdr := func(hdr buffer.View, srcAddr, dstAddr tcpip.Address, srcPort, dstPort uint16) {
   387  		u := header.UDP(hdr)
   388  		u.Encode(&header.UDPFields{
   389  			SrcPort: srcPort,
   390  			DstPort: dstPort,
   391  			Length:  header.UDPMinimumSize,
   392  		})
   393  		sum := header.PseudoHeaderChecksum(udp.ProtocolNumber, srcAddr, dstAddr, header.UDPMinimumSize)
   394  		sum = header.Checksum(hdr, sum)
   395  		u.SetChecksum(^u.CalculateChecksum(sum))
   396  	}
   397  
   398  	tests := []struct {
   399  		name                string
   400  		setupFilter         func(*testing.T, *stack.Stack)
   401  		genPacket           func(*stack.Route) stack.PacketBufferList
   402  		proto               tcpip.NetworkProtocolNumber
   403  		remoteAddr          tcpip.Address
   404  		expectSent          uint64
   405  		expectOutputDropped uint64
   406  	}{
   407  		{
   408  			name:        "IPv4 Accept",
   409  			setupFilter: func(*testing.T, *stack.Stack) { /* no filter */ },
   410  			genPacket: func(r *stack.Route) stack.PacketBufferList {
   411  				var pkts stack.PacketBufferList
   412  
   413  				pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
   414  					ReserveHeaderBytes: int(r.MaxHeaderLength() + header.UDPMinimumSize),
   415  				})
   416  				hdr := pkt.TransportHeader().Push(header.UDPMinimumSize)
   417  				udpHdr(hdr, r.LocalAddress(), r.RemoteAddress(), utils.LocalPort, utils.RemotePort)
   418  				pkts.PushFront(pkt)
   419  
   420  				return pkts
   421  			},
   422  			proto:               header.IPv4ProtocolNumber,
   423  			remoteAddr:          dstAddrV4,
   424  			expectSent:          1,
   425  			expectOutputDropped: 0,
   426  		},
   427  		{
   428  			name: "IPv4 Drop Other Port",
   429  			setupFilter: func(t *testing.T, s *stack.Stack) {
   430  				t.Helper()
   431  
   432  				table := stack.Table{
   433  					Rules: []stack.Rule{
   434  						{
   435  							Target: &stack.AcceptTarget{NetworkProtocol: header.IPv4ProtocolNumber},
   436  						},
   437  						{
   438  							Target: &stack.AcceptTarget{NetworkProtocol: header.IPv4ProtocolNumber},
   439  						},
   440  						{
   441  							Matchers: []stack.Matcher{&udpSourcePortMatcher{port: dropLocalPort}},
   442  							Target:   &stack.DropTarget{NetworkProtocol: header.IPv4ProtocolNumber},
   443  						},
   444  						{
   445  							Target: &stack.AcceptTarget{NetworkProtocol: header.IPv4ProtocolNumber},
   446  						},
   447  						{
   448  							Target: &stack.ErrorTarget{NetworkProtocol: header.IPv4ProtocolNumber},
   449  						},
   450  					},
   451  					BuiltinChains: [stack.NumHooks]int{
   452  						stack.Prerouting:  stack.HookUnset,
   453  						stack.Input:       0,
   454  						stack.Forward:     1,
   455  						stack.Output:      2,
   456  						stack.Postrouting: stack.HookUnset,
   457  					},
   458  					Underflows: [stack.NumHooks]int{
   459  						stack.Prerouting:  stack.HookUnset,
   460  						stack.Input:       0,
   461  						stack.Forward:     1,
   462  						stack.Output:      2,
   463  						stack.Postrouting: stack.HookUnset,
   464  					},
   465  				}
   466  
   467  				if err := s.IPTables().ReplaceTable(stack.FilterID, table, false /* ipv4 */); err != nil {
   468  					t.Fatalf("ReplaceTable(%d, _, false): %s", stack.FilterID, err)
   469  				}
   470  			},
   471  			genPacket: func(r *stack.Route) stack.PacketBufferList {
   472  				var pkts stack.PacketBufferList
   473  
   474  				for i := 0; i < acceptPackets; i++ {
   475  					pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
   476  						ReserveHeaderBytes: int(r.MaxHeaderLength() + header.UDPMinimumSize),
   477  					})
   478  					hdr := pkt.TransportHeader().Push(header.UDPMinimumSize)
   479  					udpHdr(hdr, r.LocalAddress(), r.RemoteAddress(), utils.LocalPort, utils.RemotePort)
   480  					pkts.PushFront(pkt)
   481  				}
   482  				for i := 0; i < dropPackets; i++ {
   483  					pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
   484  						ReserveHeaderBytes: int(r.MaxHeaderLength() + header.UDPMinimumSize),
   485  					})
   486  					hdr := pkt.TransportHeader().Push(header.UDPMinimumSize)
   487  					udpHdr(hdr, r.LocalAddress(), r.RemoteAddress(), dropLocalPort, utils.RemotePort)
   488  					pkts.PushFront(pkt)
   489  				}
   490  
   491  				return pkts
   492  			},
   493  			proto:               header.IPv4ProtocolNumber,
   494  			remoteAddr:          dstAddrV4,
   495  			expectSent:          acceptPackets,
   496  			expectOutputDropped: dropPackets,
   497  		},
   498  		{
   499  			name:        "IPv6 Accept",
   500  			setupFilter: func(*testing.T, *stack.Stack) { /* no filter */ },
   501  			genPacket: func(r *stack.Route) stack.PacketBufferList {
   502  				var pkts stack.PacketBufferList
   503  
   504  				pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
   505  					ReserveHeaderBytes: int(r.MaxHeaderLength() + header.UDPMinimumSize),
   506  				})
   507  				hdr := pkt.TransportHeader().Push(header.UDPMinimumSize)
   508  				udpHdr(hdr, r.LocalAddress(), r.RemoteAddress(), utils.LocalPort, utils.RemotePort)
   509  				pkts.PushFront(pkt)
   510  
   511  				return pkts
   512  			},
   513  			proto:               header.IPv6ProtocolNumber,
   514  			remoteAddr:          dstAddrV6,
   515  			expectSent:          1,
   516  			expectOutputDropped: 0,
   517  		},
   518  		{
   519  			name: "IPv6 Drop Other Port",
   520  			setupFilter: func(t *testing.T, s *stack.Stack) {
   521  				t.Helper()
   522  
   523  				table := stack.Table{
   524  					Rules: []stack.Rule{
   525  						{
   526  							Target: &stack.AcceptTarget{NetworkProtocol: header.IPv6ProtocolNumber},
   527  						},
   528  						{
   529  							Target: &stack.AcceptTarget{NetworkProtocol: header.IPv6ProtocolNumber},
   530  						},
   531  						{
   532  							Matchers: []stack.Matcher{&udpSourcePortMatcher{port: dropLocalPort}},
   533  							Target:   &stack.DropTarget{NetworkProtocol: header.IPv6ProtocolNumber},
   534  						},
   535  						{
   536  							Target: &stack.AcceptTarget{NetworkProtocol: header.IPv6ProtocolNumber},
   537  						},
   538  						{
   539  							Target: &stack.ErrorTarget{NetworkProtocol: header.IPv6ProtocolNumber},
   540  						},
   541  					},
   542  					BuiltinChains: [stack.NumHooks]int{
   543  						stack.Prerouting:  stack.HookUnset,
   544  						stack.Input:       0,
   545  						stack.Forward:     1,
   546  						stack.Output:      2,
   547  						stack.Postrouting: stack.HookUnset,
   548  					},
   549  					Underflows: [stack.NumHooks]int{
   550  						stack.Prerouting:  stack.HookUnset,
   551  						stack.Input:       0,
   552  						stack.Forward:     1,
   553  						stack.Output:      2,
   554  						stack.Postrouting: stack.HookUnset,
   555  					},
   556  				}
   557  
   558  				if err := s.IPTables().ReplaceTable(stack.FilterID, table, true /* ipv6 */); err != nil {
   559  					t.Fatalf("ReplaceTable(%d, _, true): %s", stack.FilterID, err)
   560  				}
   561  			},
   562  			genPacket: func(r *stack.Route) stack.PacketBufferList {
   563  				var pkts stack.PacketBufferList
   564  
   565  				for i := 0; i < acceptPackets; i++ {
   566  					pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
   567  						ReserveHeaderBytes: int(r.MaxHeaderLength() + header.UDPMinimumSize),
   568  					})
   569  					hdr := pkt.TransportHeader().Push(header.UDPMinimumSize)
   570  					udpHdr(hdr, r.LocalAddress(), r.RemoteAddress(), utils.LocalPort, utils.RemotePort)
   571  					pkts.PushFront(pkt)
   572  				}
   573  				for i := 0; i < dropPackets; i++ {
   574  					pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
   575  						ReserveHeaderBytes: int(r.MaxHeaderLength() + header.UDPMinimumSize),
   576  					})
   577  					hdr := pkt.TransportHeader().Push(header.UDPMinimumSize)
   578  					udpHdr(hdr, r.LocalAddress(), r.RemoteAddress(), dropLocalPort, utils.RemotePort)
   579  					pkts.PushFront(pkt)
   580  				}
   581  
   582  				return pkts
   583  			},
   584  			proto:               header.IPv6ProtocolNumber,
   585  			remoteAddr:          dstAddrV6,
   586  			expectSent:          acceptPackets,
   587  			expectOutputDropped: dropPackets,
   588  		},
   589  	}
   590  
   591  	for _, test := range tests {
   592  		t.Run(test.name, func(t *testing.T) {
   593  			s := stack.New(stack.Options{
   594  				NetworkProtocols:   []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol},
   595  				TransportProtocols: []stack.TransportProtocolFactory{udp.NewProtocol},
   596  			})
   597  			e := channelEndpointWithoutWritePacket{
   598  				Endpoint: channel.New(4, header.IPv6MinimumMTU, linkAddr),
   599  				t:        t,
   600  			}
   601  			if err := s.CreateNIC(nicID, &e); err != nil {
   602  				t.Fatalf("CreateNIC(%d, _) = %s", nicID, err)
   603  			}
   604  			if err := s.AddAddress(nicID, header.IPv6ProtocolNumber, srcAddrV6); err != nil {
   605  				t.Fatalf("AddAddress(%d, %d, %s) = %s", nicID, header.IPv6ProtocolNumber, srcAddrV6, err)
   606  			}
   607  			if err := s.AddAddress(nicID, header.IPv4ProtocolNumber, srcAddrV4); err != nil {
   608  				t.Fatalf("AddAddress(%d, %d, %s) = %s", nicID, header.IPv4ProtocolNumber, srcAddrV4, err)
   609  			}
   610  
   611  			s.SetRouteTable([]tcpip.Route{
   612  				{
   613  					Destination: header.IPv4EmptySubnet,
   614  					NIC:         nicID,
   615  				},
   616  				{
   617  					Destination: header.IPv6EmptySubnet,
   618  					NIC:         nicID,
   619  				},
   620  			})
   621  
   622  			test.setupFilter(t, s)
   623  
   624  			r, err := s.FindRoute(nicID, "", test.remoteAddr, test.proto, false)
   625  			if err != nil {
   626  				t.Fatalf("FindRoute(%d, '', %s, %d, false): %s", nicID, test.remoteAddr, test.proto, err)
   627  			}
   628  			defer r.Release()
   629  
   630  			pkts := test.genPacket(r)
   631  			pktsLen := pkts.Len()
   632  			if n, err := r.WritePackets(pkts, stack.NetworkHeaderParams{
   633  				Protocol: header.UDPProtocolNumber,
   634  				TTL:      64,
   635  			}); err != nil {
   636  				t.Fatalf("WritePackets(...): %s", err)
   637  			} else if n != pktsLen {
   638  				t.Fatalf("got WritePackets(...) = %d, want = %d", n, pktsLen)
   639  			}
   640  
   641  			if got := s.Stats().IP.PacketsSent.Value(); got != test.expectSent {
   642  				t.Errorf("got PacketSent = %d, want = %d", got, test.expectSent)
   643  			}
   644  			if got := s.Stats().IP.IPTablesOutputDropped.Value(); got != test.expectOutputDropped {
   645  				t.Errorf("got IPTablesOutputDropped = %d, want = %d", got, test.expectOutputDropped)
   646  			}
   647  		})
   648  	}
   649  }
   650  
   651  const ttl = 64
   652  
   653  var (
   654  	ipv4GlobalMulticastAddr = testutil.MustParse4("224.0.1.10")
   655  	ipv6GlobalMulticastAddr = testutil.MustParse6("ff0e::a")
   656  )
   657  
   658  func rxICMPv4EchoReply(e *channel.Endpoint, src, dst tcpip.Address) {
   659  	utils.RxICMPv4EchoReply(e, src, dst, ttl)
   660  }
   661  
   662  func rxICMPv6EchoReply(e *channel.Endpoint, src, dst tcpip.Address) {
   663  	utils.RxICMPv6EchoReply(e, src, dst, ttl)
   664  }
   665  
   666  func forwardedICMPv4EchoReplyChecker(t *testing.T, b []byte, src, dst tcpip.Address) {
   667  	checker.IPv4(t, b,
   668  		checker.SrcAddr(src),
   669  		checker.DstAddr(dst),
   670  		checker.TTL(ttl-1),
   671  		checker.ICMPv4(
   672  			checker.ICMPv4Type(header.ICMPv4EchoReply)))
   673  }
   674  
   675  func forwardedICMPv6EchoReplyChecker(t *testing.T, b []byte, src, dst tcpip.Address) {
   676  	checker.IPv6(t, b,
   677  		checker.SrcAddr(src),
   678  		checker.DstAddr(dst),
   679  		checker.TTL(ttl-1),
   680  		checker.ICMPv6(
   681  			checker.ICMPv6Type(header.ICMPv6EchoReply)))
   682  }
   683  
   684  func boolToInt(v bool) uint64 {
   685  	if v {
   686  		return 1
   687  	}
   688  	return 0
   689  }
   690  
   691  func setupDropFilter(hook stack.Hook, f stack.IPHeaderFilter) func(*testing.T, *stack.Stack, tcpip.NetworkProtocolNumber) {
   692  	return func(t *testing.T, s *stack.Stack, netProto tcpip.NetworkProtocolNumber) {
   693  		t.Helper()
   694  
   695  		ipv6 := netProto == ipv6.ProtocolNumber
   696  
   697  		ipt := s.IPTables()
   698  		filter := ipt.GetTable(stack.FilterID, ipv6)
   699  		ruleIdx := filter.BuiltinChains[hook]
   700  		filter.Rules[ruleIdx].Filter = f
   701  		filter.Rules[ruleIdx].Target = &stack.DropTarget{NetworkProtocol: netProto}
   702  		// Make sure the packet is not dropped by the next rule.
   703  		filter.Rules[ruleIdx+1].Target = &stack.AcceptTarget{NetworkProtocol: netProto}
   704  		if err := ipt.ReplaceTable(stack.FilterID, filter, ipv6); err != nil {
   705  			t.Fatalf("ipt.ReplaceTable(%d, _, %t): %s", stack.FilterID, ipv6, err)
   706  		}
   707  	}
   708  }
   709  
   710  func TestForwardingHook(t *testing.T) {
   711  	const (
   712  		nicID1 = 1
   713  		nicID2 = 2
   714  
   715  		nic1Name = "nic1"
   716  		nic2Name = "nic2"
   717  
   718  		otherNICName = "otherNIC"
   719  	)
   720  
   721  	tests := []struct {
   722  		name             string
   723  		netProto         tcpip.NetworkProtocolNumber
   724  		local            bool
   725  		srcAddr, dstAddr tcpip.Address
   726  		rx               func(*channel.Endpoint, tcpip.Address, tcpip.Address)
   727  		checker          func(*testing.T, []byte)
   728  	}{
   729  		{
   730  			name:     "IPv4 remote",
   731  			netProto: ipv4.ProtocolNumber,
   732  			local:    false,
   733  			srcAddr:  utils.RemoteIPv4Addr,
   734  			dstAddr:  utils.Ipv4Addr2.AddressWithPrefix.Address,
   735  			rx:       rxICMPv4EchoReply,
   736  			checker: func(t *testing.T, b []byte) {
   737  				forwardedICMPv4EchoReplyChecker(t, b, utils.RemoteIPv4Addr, utils.Ipv4Addr2.AddressWithPrefix.Address)
   738  			},
   739  		},
   740  		{
   741  			name:     "IPv4 local",
   742  			netProto: ipv4.ProtocolNumber,
   743  			local:    true,
   744  			srcAddr:  utils.RemoteIPv4Addr,
   745  			dstAddr:  utils.Ipv4Addr.Address,
   746  			rx:       rxICMPv4EchoReply,
   747  		},
   748  		{
   749  			name:     "IPv6 remote",
   750  			netProto: ipv6.ProtocolNumber,
   751  			local:    false,
   752  			srcAddr:  utils.RemoteIPv6Addr,
   753  			dstAddr:  utils.Ipv6Addr2.AddressWithPrefix.Address,
   754  			rx:       rxICMPv6EchoReply,
   755  			checker: func(t *testing.T, b []byte) {
   756  				forwardedICMPv6EchoReplyChecker(t, b, utils.RemoteIPv6Addr, utils.Ipv6Addr2.AddressWithPrefix.Address)
   757  			},
   758  		},
   759  		{
   760  			name:     "IPv6 local",
   761  			netProto: ipv6.ProtocolNumber,
   762  			local:    true,
   763  			srcAddr:  utils.RemoteIPv6Addr,
   764  			dstAddr:  utils.Ipv6Addr.Address,
   765  			rx:       rxICMPv6EchoReply,
   766  		},
   767  	}
   768  
   769  	subTests := []struct {
   770  		name          string
   771  		setupFilter   func(*testing.T, *stack.Stack, tcpip.NetworkProtocolNumber)
   772  		expectForward bool
   773  	}{
   774  		{
   775  			name:          "Accept",
   776  			setupFilter:   func(*testing.T, *stack.Stack, tcpip.NetworkProtocolNumber) { /* no filter */ },
   777  			expectForward: true,
   778  		},
   779  
   780  		{
   781  			name:          "Drop",
   782  			setupFilter:   setupDropFilter(stack.Forward, stack.IPHeaderFilter{}),
   783  			expectForward: false,
   784  		},
   785  		{
   786  			name:          "Drop with input NIC filtering",
   787  			setupFilter:   setupDropFilter(stack.Forward, stack.IPHeaderFilter{InputInterface: nic1Name}),
   788  			expectForward: false,
   789  		},
   790  		{
   791  			name:          "Drop with output NIC filtering",
   792  			setupFilter:   setupDropFilter(stack.Forward, stack.IPHeaderFilter{OutputInterface: nic2Name}),
   793  			expectForward: false,
   794  		},
   795  		{
   796  			name:          "Drop with input and output NIC filtering",
   797  			setupFilter:   setupDropFilter(stack.Forward, stack.IPHeaderFilter{InputInterface: nic1Name, OutputInterface: nic2Name}),
   798  			expectForward: false,
   799  		},
   800  
   801  		{
   802  			name:          "Drop with other input NIC filtering",
   803  			setupFilter:   setupDropFilter(stack.Forward, stack.IPHeaderFilter{InputInterface: otherNICName}),
   804  			expectForward: true,
   805  		},
   806  		{
   807  			name:          "Drop with other output NIC filtering",
   808  			setupFilter:   setupDropFilter(stack.Forward, stack.IPHeaderFilter{OutputInterface: otherNICName}),
   809  			expectForward: true,
   810  		},
   811  		{
   812  			name:          "Drop with other input and output NIC filtering",
   813  			setupFilter:   setupDropFilter(stack.Forward, stack.IPHeaderFilter{InputInterface: otherNICName, OutputInterface: nic2Name}),
   814  			expectForward: true,
   815  		},
   816  		{
   817  			name:          "Drop with input and other output NIC filtering",
   818  			setupFilter:   setupDropFilter(stack.Forward, stack.IPHeaderFilter{InputInterface: nic1Name, OutputInterface: otherNICName}),
   819  			expectForward: true,
   820  		},
   821  		{
   822  			name:          "Drop with other input and other output NIC filtering",
   823  			setupFilter:   setupDropFilter(stack.Forward, stack.IPHeaderFilter{InputInterface: otherNICName, OutputInterface: otherNICName}),
   824  			expectForward: true,
   825  		},
   826  
   827  		{
   828  			name:          "Drop with inverted input NIC filtering",
   829  			setupFilter:   setupDropFilter(stack.Forward, stack.IPHeaderFilter{InputInterface: nic1Name, InputInterfaceInvert: true}),
   830  			expectForward: true,
   831  		},
   832  		{
   833  			name:          "Drop with inverted output NIC filtering",
   834  			setupFilter:   setupDropFilter(stack.Forward, stack.IPHeaderFilter{OutputInterface: nic2Name, OutputInterfaceInvert: true}),
   835  			expectForward: true,
   836  		},
   837  	}
   838  
   839  	for _, test := range tests {
   840  		t.Run(test.name, func(t *testing.T) {
   841  			for _, subTest := range subTests {
   842  				t.Run(subTest.name, func(t *testing.T) {
   843  					s := stack.New(stack.Options{
   844  						NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol},
   845  					})
   846  
   847  					subTest.setupFilter(t, s, test.netProto)
   848  
   849  					e1 := channel.New(1, header.IPv6MinimumMTU, "")
   850  					if err := s.CreateNICWithOptions(nicID1, e1, stack.NICOptions{Name: nic1Name}); err != nil {
   851  						t.Fatalf("s.CreateNICWithOptions(%d, _, _): %s", nicID1, err)
   852  					}
   853  
   854  					e2 := channel.New(1, header.IPv6MinimumMTU, "")
   855  					if err := s.CreateNICWithOptions(nicID2, e2, stack.NICOptions{Name: nic2Name}); err != nil {
   856  						t.Fatalf("s.CreateNICWithOptions(%d, _, _): %s", nicID2, err)
   857  					}
   858  
   859  					if err := s.AddAddress(nicID2, ipv4.ProtocolNumber, utils.Ipv4Addr.Address); err != nil {
   860  						t.Fatalf("s.AddAddress(%d, %d, %s): %s", nicID2, ipv4.ProtocolNumber, utils.Ipv4Addr.Address, err)
   861  					}
   862  					if err := s.AddAddress(nicID2, ipv6.ProtocolNumber, utils.Ipv6Addr.Address); err != nil {
   863  						t.Fatalf("s.AddAddress(%d, %d, %s): %s", nicID2, ipv6.ProtocolNumber, utils.Ipv6Addr.Address, err)
   864  					}
   865  
   866  					if err := s.SetForwardingDefaultAndAllNICs(ipv4.ProtocolNumber, true); err != nil {
   867  						t.Fatalf("s.SetForwardingDefaultAndAllNICs(%d, true): %s", ipv4.ProtocolNumber, err)
   868  					}
   869  					if err := s.SetForwardingDefaultAndAllNICs(ipv6.ProtocolNumber, true); err != nil {
   870  						t.Fatalf("s.SetForwardingDefaultAndAllNICs(%d, true): %s", ipv6.ProtocolNumber, err)
   871  					}
   872  
   873  					s.SetRouteTable([]tcpip.Route{
   874  						{
   875  							Destination: header.IPv4EmptySubnet,
   876  							NIC:         nicID2,
   877  						},
   878  						{
   879  							Destination: header.IPv6EmptySubnet,
   880  							NIC:         nicID2,
   881  						},
   882  					})
   883  
   884  					test.rx(e1, test.srcAddr, test.dstAddr)
   885  
   886  					expectTransmitPacket := subTest.expectForward && !test.local
   887  
   888  					ep1, err := s.GetNetworkEndpoint(nicID1, test.netProto)
   889  					if err != nil {
   890  						t.Fatalf("s.GetNetworkEndpoint(%d, %d): %s", nicID1, test.netProto, err)
   891  					}
   892  					ep1Stats := ep1.Stats()
   893  					ipEP1Stats, ok := ep1Stats.(stack.IPNetworkEndpointStats)
   894  					if !ok {
   895  						t.Fatalf("got ep1Stats = %T, want = stack.IPNetworkEndpointStats", ep1Stats)
   896  					}
   897  					ip1Stats := ipEP1Stats.IPStats()
   898  
   899  					if got := ip1Stats.PacketsReceived.Value(); got != 1 {
   900  						t.Errorf("got ip1Stats.PacketsReceived.Value() = %d, want = 1", got)
   901  					}
   902  					if got := ip1Stats.ValidPacketsReceived.Value(); got != 1 {
   903  						t.Errorf("got ip1Stats.ValidPacketsReceived.Value() = %d, want = 1", got)
   904  					}
   905  					if got, want := ip1Stats.IPTablesForwardDropped.Value(), boolToInt(!subTest.expectForward); got != want {
   906  						t.Errorf("got ip1Stats.IPTablesForwardDropped.Value() = %d, want = %d", got, want)
   907  					}
   908  					if got := ip1Stats.PacketsSent.Value(); got != 0 {
   909  						t.Errorf("got ip1Stats.PacketsSent.Value() = %d, want = 0", got)
   910  					}
   911  
   912  					ep2, err := s.GetNetworkEndpoint(nicID2, test.netProto)
   913  					if err != nil {
   914  						t.Fatalf("s.GetNetworkEndpoint(%d, %d): %s", nicID2, test.netProto, err)
   915  					}
   916  					ep2Stats := ep2.Stats()
   917  					ipEP2Stats, ok := ep2Stats.(stack.IPNetworkEndpointStats)
   918  					if !ok {
   919  						t.Fatalf("got ep2Stats = %T, want = stack.IPNetworkEndpointStats", ep2Stats)
   920  					}
   921  					ip2Stats := ipEP2Stats.IPStats()
   922  					if got := ip2Stats.PacketsReceived.Value(); got != 0 {
   923  						t.Errorf("got ip2Stats.PacketsReceived.Value() = %d, want = 0", got)
   924  					}
   925  					if got, want := ip2Stats.ValidPacketsReceived.Value(), boolToInt(subTest.expectForward && test.local); got != want {
   926  						t.Errorf("got ip2Stats.ValidPacketsReceived.Value() = %d, want = %d", got, want)
   927  					}
   928  					if got, want := ip2Stats.PacketsSent.Value(), boolToInt(expectTransmitPacket); got != want {
   929  						t.Errorf("got ip2Stats.PacketsSent.Value() = %d, want = %d", got, want)
   930  					}
   931  
   932  					p, ok := e2.Read()
   933  					if ok != expectTransmitPacket {
   934  						t.Fatalf("got e2.Read() = (%#v, %t), want = (_, %t)", p, ok, expectTransmitPacket)
   935  					}
   936  					if expectTransmitPacket {
   937  						test.checker(t, stack.PayloadSince(p.Pkt.NetworkHeader()))
   938  					}
   939  				})
   940  			}
   941  		})
   942  	}
   943  }
   944  
   945  func TestInputHookWithLocalForwarding(t *testing.T) {
   946  	const (
   947  		nicID1 = 1
   948  		nicID2 = 2
   949  
   950  		nic1Name = "nic1"
   951  		nic2Name = "nic2"
   952  
   953  		otherNICName = "otherNIC"
   954  	)
   955  
   956  	tests := []struct {
   957  		name     string
   958  		netProto tcpip.NetworkProtocolNumber
   959  		rx       func(*channel.Endpoint)
   960  		checker  func(*testing.T, []byte)
   961  	}{
   962  		{
   963  			name:     "IPv4",
   964  			netProto: ipv4.ProtocolNumber,
   965  			rx: func(e *channel.Endpoint) {
   966  				utils.RxICMPv4EchoRequest(e, utils.RemoteIPv4Addr, utils.Ipv4Addr2.AddressWithPrefix.Address, ttl)
   967  			},
   968  			checker: func(t *testing.T, b []byte) {
   969  				checker.IPv4(t, b,
   970  					checker.SrcAddr(utils.Ipv4Addr2.AddressWithPrefix.Address),
   971  					checker.DstAddr(utils.RemoteIPv4Addr),
   972  					checker.ICMPv4(
   973  						checker.ICMPv4Type(header.ICMPv4EchoReply)))
   974  			},
   975  		},
   976  		{
   977  			name:     "IPv6",
   978  			netProto: ipv6.ProtocolNumber,
   979  			rx: func(e *channel.Endpoint) {
   980  				utils.RxICMPv6EchoRequest(e, utils.RemoteIPv6Addr, utils.Ipv6Addr2.AddressWithPrefix.Address, ttl)
   981  			},
   982  			checker: func(t *testing.T, b []byte) {
   983  				checker.IPv6(t, b,
   984  					checker.SrcAddr(utils.Ipv6Addr2.AddressWithPrefix.Address),
   985  					checker.DstAddr(utils.RemoteIPv6Addr),
   986  					checker.ICMPv6(
   987  						checker.ICMPv6Type(header.ICMPv6EchoReply)))
   988  			},
   989  		},
   990  	}
   991  
   992  	subTests := []struct {
   993  		name        string
   994  		setupFilter func(*testing.T, *stack.Stack, tcpip.NetworkProtocolNumber)
   995  		expectDrop  bool
   996  	}{
   997  		{
   998  			name:        "Accept",
   999  			setupFilter: func(*testing.T, *stack.Stack, tcpip.NetworkProtocolNumber) { /* no filter */ },
  1000  			expectDrop:  false,
  1001  		},
  1002  
  1003  		{
  1004  			name:        "Drop",
  1005  			setupFilter: setupDropFilter(stack.Input, stack.IPHeaderFilter{}),
  1006  			expectDrop:  true,
  1007  		},
  1008  		{
  1009  			name:        "Drop with input NIC filtering on arrival NIC",
  1010  			setupFilter: setupDropFilter(stack.Input, stack.IPHeaderFilter{InputInterface: nic1Name}),
  1011  			expectDrop:  true,
  1012  		},
  1013  		{
  1014  			name:        "Drop with input NIC filtering on delivered NIC",
  1015  			setupFilter: setupDropFilter(stack.Input, stack.IPHeaderFilter{InputInterface: nic2Name}),
  1016  			expectDrop:  false,
  1017  		},
  1018  
  1019  		{
  1020  			name:        "Drop with input NIC filtering on other NIC",
  1021  			setupFilter: setupDropFilter(stack.Input, stack.IPHeaderFilter{InputInterface: otherNICName}),
  1022  			expectDrop:  false,
  1023  		},
  1024  	}
  1025  
  1026  	for _, test := range tests {
  1027  		t.Run(test.name, func(t *testing.T) {
  1028  			for _, subTest := range subTests {
  1029  				t.Run(subTest.name, func(t *testing.T) {
  1030  					s := stack.New(stack.Options{
  1031  						NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol},
  1032  					})
  1033  
  1034  					subTest.setupFilter(t, s, test.netProto)
  1035  
  1036  					e1 := channel.New(1, header.IPv6MinimumMTU, "")
  1037  					if err := s.CreateNICWithOptions(nicID1, e1, stack.NICOptions{Name: nic1Name}); err != nil {
  1038  						t.Fatalf("s.CreateNICWithOptions(%d, _, _): %s", nicID1, err)
  1039  					}
  1040  					if err := s.AddProtocolAddress(nicID1, utils.Ipv4Addr1); err != nil {
  1041  						t.Fatalf("s.AddProtocolAddress(%d, %#v): %s", nicID1, utils.Ipv4Addr1, err)
  1042  					}
  1043  					if err := s.AddProtocolAddress(nicID1, utils.Ipv6Addr1); err != nil {
  1044  						t.Fatalf("s.AddProtocolAddress(%d, %#v): %s", nicID1, utils.Ipv6Addr1, err)
  1045  					}
  1046  
  1047  					e2 := channel.New(1, header.IPv6MinimumMTU, "")
  1048  					if err := s.CreateNICWithOptions(nicID2, e2, stack.NICOptions{Name: nic2Name}); err != nil {
  1049  						t.Fatalf("s.CreateNICWithOptions(%d, _, _): %s", nicID2, err)
  1050  					}
  1051  					if err := s.AddProtocolAddress(nicID2, utils.Ipv4Addr2); err != nil {
  1052  						t.Fatalf("s.AddProtocolAddress(%d, %#v): %s", nicID2, utils.Ipv4Addr2, err)
  1053  					}
  1054  					if err := s.AddProtocolAddress(nicID2, utils.Ipv6Addr2); err != nil {
  1055  						t.Fatalf("s.AddProtocolAddress(%d, %#v): %s", nicID2, utils.Ipv6Addr2, err)
  1056  					}
  1057  
  1058  					if err := s.SetForwardingDefaultAndAllNICs(ipv4.ProtocolNumber, true); err != nil {
  1059  						t.Fatalf("s.SetForwardingDefaultAndAllNICs(%d, true): %s", ipv4.ProtocolNumber, err)
  1060  					}
  1061  					if err := s.SetForwardingDefaultAndAllNICs(ipv6.ProtocolNumber, true); err != nil {
  1062  						t.Fatalf("s.SetForwardingDefaultAndAllNICs(%d, true): %s", ipv6.ProtocolNumber, err)
  1063  					}
  1064  
  1065  					s.SetRouteTable([]tcpip.Route{
  1066  						{
  1067  							Destination: header.IPv4EmptySubnet,
  1068  							NIC:         nicID1,
  1069  						},
  1070  						{
  1071  							Destination: header.IPv6EmptySubnet,
  1072  							NIC:         nicID1,
  1073  						},
  1074  					})
  1075  
  1076  					test.rx(e1)
  1077  
  1078  					ep1, err := s.GetNetworkEndpoint(nicID1, test.netProto)
  1079  					if err != nil {
  1080  						t.Fatalf("s.GetNetworkEndpoint(%d, %d): %s", nicID1, test.netProto, err)
  1081  					}
  1082  					ep1Stats := ep1.Stats()
  1083  					ipEP1Stats, ok := ep1Stats.(stack.IPNetworkEndpointStats)
  1084  					if !ok {
  1085  						t.Fatalf("got ep1Stats = %T, want = stack.IPNetworkEndpointStats", ep1Stats)
  1086  					}
  1087  					ip1Stats := ipEP1Stats.IPStats()
  1088  
  1089  					if got := ip1Stats.PacketsReceived.Value(); got != 1 {
  1090  						t.Errorf("got ip1Stats.PacketsReceived.Value() = %d, want = 1", got)
  1091  					}
  1092  					if got := ip1Stats.ValidPacketsReceived.Value(); got != 1 {
  1093  						t.Errorf("got ip1Stats.ValidPacketsReceived.Value() = %d, want = 1", got)
  1094  					}
  1095  					if got, want := ip1Stats.PacketsSent.Value(), boolToInt(!subTest.expectDrop); got != want {
  1096  						t.Errorf("got ip1Stats.PacketsSent.Value() = %d, want = %d", got, want)
  1097  					}
  1098  
  1099  					ep2, err := s.GetNetworkEndpoint(nicID2, test.netProto)
  1100  					if err != nil {
  1101  						t.Fatalf("s.GetNetworkEndpoint(%d, %d): %s", nicID2, test.netProto, err)
  1102  					}
  1103  					ep2Stats := ep2.Stats()
  1104  					ipEP2Stats, ok := ep2Stats.(stack.IPNetworkEndpointStats)
  1105  					if !ok {
  1106  						t.Fatalf("got ep2Stats = %T, want = stack.IPNetworkEndpointStats", ep2Stats)
  1107  					}
  1108  					ip2Stats := ipEP2Stats.IPStats()
  1109  					if got := ip2Stats.PacketsReceived.Value(); got != 0 {
  1110  						t.Errorf("got ip2Stats.PacketsReceived.Value() = %d, want = 0", got)
  1111  					}
  1112  					if got := ip2Stats.ValidPacketsReceived.Value(); got != 1 {
  1113  						t.Errorf("got ip2Stats.ValidPacketsReceived.Value() = %d, want = 1", got)
  1114  					}
  1115  					if got, want := ip2Stats.IPTablesInputDropped.Value(), boolToInt(subTest.expectDrop); got != want {
  1116  						t.Errorf("got ip2Stats.IPTablesInputDropped.Value() = %d, want = %d", got, want)
  1117  					}
  1118  					if got := ip2Stats.PacketsSent.Value(); got != 0 {
  1119  						t.Errorf("got ip2Stats.PacketsSent.Value() = %d, want = 0", got)
  1120  					}
  1121  
  1122  					if p, ok := e1.Read(); ok == subTest.expectDrop {
  1123  						t.Errorf("got e1.Read() = (%#v, %t), want = (_, %t)", p, ok, !subTest.expectDrop)
  1124  					} else if !subTest.expectDrop {
  1125  						test.checker(t, stack.PayloadSince(p.Pkt.NetworkHeader()))
  1126  					}
  1127  					if p, ok := e2.Read(); ok {
  1128  						t.Errorf("got e1.Read() = (%#v, true), want = (_, false)", p)
  1129  					}
  1130  				})
  1131  			}
  1132  		})
  1133  	}
  1134  }