github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/tcpip/tests/integration/loopback_test.go (about) 1 // Copyright 2020 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 loopback_test 16 17 import ( 18 "bytes" 19 "testing" 20 "time" 21 22 "github.com/google/go-cmp/cmp" 23 "github.com/SagerNet/gvisor/pkg/tcpip" 24 "github.com/SagerNet/gvisor/pkg/tcpip/buffer" 25 "github.com/SagerNet/gvisor/pkg/tcpip/checker" 26 "github.com/SagerNet/gvisor/pkg/tcpip/header" 27 "github.com/SagerNet/gvisor/pkg/tcpip/link/channel" 28 "github.com/SagerNet/gvisor/pkg/tcpip/link/loopback" 29 "github.com/SagerNet/gvisor/pkg/tcpip/network/ipv4" 30 "github.com/SagerNet/gvisor/pkg/tcpip/network/ipv6" 31 "github.com/SagerNet/gvisor/pkg/tcpip/stack" 32 "github.com/SagerNet/gvisor/pkg/tcpip/tests/utils" 33 "github.com/SagerNet/gvisor/pkg/tcpip/testutil" 34 "github.com/SagerNet/gvisor/pkg/tcpip/transport/icmp" 35 "github.com/SagerNet/gvisor/pkg/tcpip/transport/tcp" 36 "github.com/SagerNet/gvisor/pkg/tcpip/transport/udp" 37 "github.com/SagerNet/gvisor/pkg/waiter" 38 ) 39 40 var _ ipv6.NDPDispatcher = (*ndpDispatcher)(nil) 41 42 type ndpDispatcher struct{} 43 44 func (*ndpDispatcher) OnDuplicateAddressDetectionResult(tcpip.NICID, tcpip.Address, stack.DADResult) { 45 } 46 47 func (*ndpDispatcher) OnOffLinkRouteUpdated(tcpip.NICID, tcpip.Subnet, tcpip.Address, header.NDPRoutePreference) { 48 } 49 50 func (*ndpDispatcher) OnOffLinkRouteInvalidated(tcpip.NICID, tcpip.Subnet, tcpip.Address) {} 51 52 func (*ndpDispatcher) OnOnLinkPrefixDiscovered(tcpip.NICID, tcpip.Subnet) { 53 } 54 55 func (*ndpDispatcher) OnOnLinkPrefixInvalidated(tcpip.NICID, tcpip.Subnet) {} 56 57 func (*ndpDispatcher) OnAutoGenAddress(tcpip.NICID, tcpip.AddressWithPrefix) { 58 } 59 60 func (*ndpDispatcher) OnAutoGenAddressDeprecated(tcpip.NICID, tcpip.AddressWithPrefix) {} 61 62 func (*ndpDispatcher) OnAutoGenAddressInvalidated(tcpip.NICID, tcpip.AddressWithPrefix) {} 63 64 func (*ndpDispatcher) OnRecursiveDNSServerOption(tcpip.NICID, []tcpip.Address, time.Duration) {} 65 66 func (*ndpDispatcher) OnDNSSearchListOption(tcpip.NICID, []string, time.Duration) {} 67 68 func (*ndpDispatcher) OnDHCPv6Configuration(tcpip.NICID, ipv6.DHCPv6ConfigurationFromNDPRA) {} 69 70 // TestInitialLoopbackAddresses tests that the loopback interface does not 71 // auto-generate a link-local address when it is brought up. 72 func TestInitialLoopbackAddresses(t *testing.T) { 73 const nicID = 1 74 75 s := stack.New(stack.Options{ 76 NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocolWithOptions(ipv6.Options{ 77 NDPDisp: &ndpDispatcher{}, 78 AutoGenLinkLocal: true, 79 OpaqueIIDOpts: ipv6.OpaqueInterfaceIdentifierOptions{ 80 NICNameFromID: func(nicID tcpip.NICID, nicName string) string { 81 t.Fatalf("should not attempt to get name for NIC with ID = %d; nicName = %s", nicID, nicName) 82 return "" 83 }, 84 }, 85 })}, 86 }) 87 88 if err := s.CreateNIC(nicID, loopback.New()); err != nil { 89 t.Fatalf("CreateNIC(%d, _): %s", nicID, err) 90 } 91 92 nicsInfo := s.NICInfo() 93 if nicInfo, ok := nicsInfo[nicID]; !ok { 94 t.Fatalf("did not find NIC with ID = %d in s.NICInfo() = %#v", nicID, nicsInfo) 95 } else if got := len(nicInfo.ProtocolAddresses); got != 0 { 96 t.Fatalf("got len(nicInfo.ProtocolAddresses) = %d, want = 0; nicInfo.ProtocolAddresses = %#v", got, nicInfo.ProtocolAddresses) 97 } 98 } 99 100 // TestLoopbackAcceptAllInSubnetUDP tests that a loopback interface considers 101 // itself bound to all addresses in the subnet of an assigned address and UDP 102 // traffic is sent/received correctly. 103 func TestLoopbackAcceptAllInSubnetUDP(t *testing.T) { 104 const ( 105 nicID = 1 106 localPort = 80 107 ) 108 109 data := []byte{1, 2, 3, 4} 110 111 ipv4ProtocolAddress := tcpip.ProtocolAddress{ 112 Protocol: header.IPv4ProtocolNumber, 113 AddressWithPrefix: utils.Ipv4Addr, 114 } 115 ipv4Bytes := []byte(ipv4ProtocolAddress.AddressWithPrefix.Address) 116 ipv4Bytes[len(ipv4Bytes)-1]++ 117 otherIPv4Address := tcpip.Address(ipv4Bytes) 118 119 ipv6ProtocolAddress := tcpip.ProtocolAddress{ 120 Protocol: header.IPv6ProtocolNumber, 121 AddressWithPrefix: utils.Ipv6Addr, 122 } 123 ipv6Bytes := []byte(utils.Ipv6Addr.Address) 124 ipv6Bytes[len(ipv6Bytes)-1]++ 125 otherIPv6Address := tcpip.Address(ipv6Bytes) 126 127 tests := []struct { 128 name string 129 addAddress tcpip.ProtocolAddress 130 bindAddr tcpip.Address 131 dstAddr tcpip.Address 132 expectRx bool 133 }{ 134 { 135 name: "IPv4 bind to wildcard and send to assigned address", 136 addAddress: ipv4ProtocolAddress, 137 dstAddr: ipv4ProtocolAddress.AddressWithPrefix.Address, 138 expectRx: true, 139 }, 140 { 141 name: "IPv4 bind to wildcard and send to other subnet-local address", 142 addAddress: ipv4ProtocolAddress, 143 dstAddr: otherIPv4Address, 144 expectRx: true, 145 }, 146 { 147 name: "IPv4 bind to wildcard send to other address", 148 addAddress: ipv4ProtocolAddress, 149 dstAddr: utils.RemoteIPv4Addr, 150 expectRx: false, 151 }, 152 { 153 name: "IPv4 bind to other subnet-local address and send to assigned address", 154 addAddress: ipv4ProtocolAddress, 155 bindAddr: otherIPv4Address, 156 dstAddr: ipv4ProtocolAddress.AddressWithPrefix.Address, 157 expectRx: false, 158 }, 159 { 160 name: "IPv4 bind and send to other subnet-local address", 161 addAddress: ipv4ProtocolAddress, 162 bindAddr: otherIPv4Address, 163 dstAddr: otherIPv4Address, 164 expectRx: true, 165 }, 166 { 167 name: "IPv4 bind to assigned address and send to other subnet-local address", 168 addAddress: ipv4ProtocolAddress, 169 bindAddr: ipv4ProtocolAddress.AddressWithPrefix.Address, 170 dstAddr: otherIPv4Address, 171 expectRx: false, 172 }, 173 174 { 175 name: "IPv6 bind and send to assigned address", 176 addAddress: ipv6ProtocolAddress, 177 bindAddr: utils.Ipv6Addr.Address, 178 dstAddr: utils.Ipv6Addr.Address, 179 expectRx: true, 180 }, 181 { 182 name: "IPv6 bind to wildcard and send to other subnet-local address", 183 addAddress: ipv6ProtocolAddress, 184 dstAddr: otherIPv6Address, 185 expectRx: false, 186 }, 187 } 188 189 for _, test := range tests { 190 t.Run(test.name, func(t *testing.T) { 191 s := stack.New(stack.Options{ 192 NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol}, 193 TransportProtocols: []stack.TransportProtocolFactory{udp.NewProtocol}, 194 }) 195 if err := s.CreateNIC(nicID, loopback.New()); err != nil { 196 t.Fatalf("CreateNIC(%d, _): %s", nicID, err) 197 } 198 if err := s.AddProtocolAddress(nicID, test.addAddress); err != nil { 199 t.Fatalf("AddProtocolAddress(%d, %+v): %s", nicID, test.addAddress, err) 200 } 201 s.SetRouteTable([]tcpip.Route{ 202 { 203 Destination: header.IPv4EmptySubnet, 204 NIC: nicID, 205 }, 206 { 207 Destination: header.IPv6EmptySubnet, 208 NIC: nicID, 209 }, 210 }) 211 212 var wq waiter.Queue 213 rep, err := s.NewEndpoint(udp.ProtocolNumber, test.addAddress.Protocol, &wq) 214 if err != nil { 215 t.Fatalf("NewEndpoint(%d, %d, _): %s", udp.ProtocolNumber, test.addAddress.Protocol, err) 216 } 217 defer rep.Close() 218 219 bindAddr := tcpip.FullAddress{Addr: test.bindAddr, Port: localPort} 220 if err := rep.Bind(bindAddr); err != nil { 221 t.Fatalf("rep.Bind(%+v): %s", bindAddr, err) 222 } 223 224 sep, err := s.NewEndpoint(udp.ProtocolNumber, test.addAddress.Protocol, &wq) 225 if err != nil { 226 t.Fatalf("NewEndpoint(%d, %d, _): %s", udp.ProtocolNumber, test.addAddress.Protocol, err) 227 } 228 defer sep.Close() 229 230 wopts := tcpip.WriteOptions{ 231 To: &tcpip.FullAddress{ 232 Addr: test.dstAddr, 233 Port: localPort, 234 }, 235 } 236 var r bytes.Reader 237 r.Reset(data) 238 n, err := sep.Write(&r, wopts) 239 if err != nil { 240 t.Fatalf("sep.Write(_, _): %s", err) 241 } 242 if want := int64(len(data)); n != want { 243 t.Fatalf("got sep.Write(_, _) = (%d, nil), want = (%d, nil)", n, want) 244 } 245 246 var buf bytes.Buffer 247 opts := tcpip.ReadOptions{NeedRemoteAddr: true} 248 if res, err := rep.Read(&buf, opts); test.expectRx { 249 if err != nil { 250 t.Fatalf("rep.Read(_, %#v): %s", opts, err) 251 } 252 if diff := cmp.Diff(tcpip.ReadResult{ 253 Count: buf.Len(), 254 Total: buf.Len(), 255 RemoteAddr: tcpip.FullAddress{ 256 Addr: test.addAddress.AddressWithPrefix.Address, 257 }, 258 }, res, 259 checker.IgnoreCmpPath("ControlMessages", "RemoteAddr.NIC", "RemoteAddr.Port"), 260 ); diff != "" { 261 t.Errorf("rep.Read: unexpected result (-want +got):\n%s", diff) 262 } 263 if diff := cmp.Diff(data, buf.Bytes()); diff != "" { 264 t.Errorf("got UDP payload mismatch (-want +got):\n%s", diff) 265 } 266 } else if _, ok := err.(*tcpip.ErrWouldBlock); !ok { 267 t.Fatalf("got rep.Read = (%v, %s) [with data %x], want = (_, %s)", res, err, buf.Bytes(), &tcpip.ErrWouldBlock{}) 268 } 269 }) 270 } 271 } 272 273 // TestLoopbackSubnetLifetimeBoundToAddr tests that the lifetime of an address 274 // in a loopback interface's associated subnet is bound to the permanently bound 275 // address. 276 func TestLoopbackSubnetLifetimeBoundToAddr(t *testing.T) { 277 const nicID = 1 278 279 protoAddr := tcpip.ProtocolAddress{ 280 Protocol: ipv4.ProtocolNumber, 281 AddressWithPrefix: utils.Ipv4Addr, 282 } 283 addrBytes := []byte(utils.Ipv4Addr.Address) 284 addrBytes[len(addrBytes)-1]++ 285 otherAddr := tcpip.Address(addrBytes) 286 287 s := stack.New(stack.Options{ 288 NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol}, 289 }) 290 if err := s.CreateNIC(nicID, loopback.New()); err != nil { 291 t.Fatalf("s.CreateNIC(%d, _): %s", nicID, err) 292 } 293 if err := s.AddProtocolAddress(nicID, protoAddr); err != nil { 294 t.Fatalf("s.AddProtocolAddress(%d, %#v): %s", nicID, protoAddr, err) 295 } 296 s.SetRouteTable([]tcpip.Route{ 297 { 298 Destination: header.IPv4EmptySubnet, 299 NIC: nicID, 300 }, 301 }) 302 303 r, err := s.FindRoute(nicID, otherAddr, utils.RemoteIPv4Addr, ipv4.ProtocolNumber, false /* multicastLoop */) 304 if err != nil { 305 t.Fatalf("s.FindRoute(%d, %s, %s, %d, false): %s", nicID, otherAddr, utils.RemoteIPv4Addr, ipv4.ProtocolNumber, err) 306 } 307 defer r.Release() 308 309 params := stack.NetworkHeaderParams{ 310 Protocol: 111, 311 TTL: 64, 312 TOS: stack.DefaultTOS, 313 } 314 data := buffer.View([]byte{1, 2, 3, 4}) 315 if err := r.WritePacket(params, stack.NewPacketBuffer(stack.PacketBufferOptions{ 316 ReserveHeaderBytes: int(r.MaxHeaderLength()), 317 Data: data.ToVectorisedView(), 318 })); err != nil { 319 t.Fatalf("r.WritePacket(%#v, _): %s", params, err) 320 } 321 322 // Removing the address should make the endpoint invalid. 323 if err := s.RemoveAddress(nicID, protoAddr.AddressWithPrefix.Address); err != nil { 324 t.Fatalf("s.RemoveAddress(%d, %s): %s", nicID, protoAddr.AddressWithPrefix.Address, err) 325 } 326 { 327 err := r.WritePacket(params, stack.NewPacketBuffer(stack.PacketBufferOptions{ 328 ReserveHeaderBytes: int(r.MaxHeaderLength()), 329 Data: data.ToVectorisedView(), 330 })) 331 if _, ok := err.(*tcpip.ErrInvalidEndpointState); !ok { 332 t.Fatalf("got r.WritePacket(%#v, _) = %s, want = %s", params, err, &tcpip.ErrInvalidEndpointState{}) 333 } 334 } 335 } 336 337 // TestLoopbackAcceptAllInSubnetTCP tests that a loopback interface considers 338 // itself bound to all addresses in the subnet of an assigned address and TCP 339 // traffic is sent/received correctly. 340 func TestLoopbackAcceptAllInSubnetTCP(t *testing.T) { 341 const ( 342 nicID = 1 343 localPort = 80 344 ) 345 346 ipv4ProtocolAddress := tcpip.ProtocolAddress{ 347 Protocol: header.IPv4ProtocolNumber, 348 AddressWithPrefix: utils.Ipv4Addr, 349 } 350 ipv4ProtocolAddress.AddressWithPrefix.PrefixLen = 8 351 ipv4Bytes := []byte(ipv4ProtocolAddress.AddressWithPrefix.Address) 352 ipv4Bytes[len(ipv4Bytes)-1]++ 353 otherIPv4Address := tcpip.Address(ipv4Bytes) 354 355 ipv6ProtocolAddress := tcpip.ProtocolAddress{ 356 Protocol: header.IPv6ProtocolNumber, 357 AddressWithPrefix: utils.Ipv6Addr, 358 } 359 ipv6Bytes := []byte(utils.Ipv6Addr.Address) 360 ipv6Bytes[len(ipv6Bytes)-1]++ 361 otherIPv6Address := tcpip.Address(ipv6Bytes) 362 363 tests := []struct { 364 name string 365 addAddress tcpip.ProtocolAddress 366 bindAddr tcpip.Address 367 dstAddr tcpip.Address 368 expectAccept bool 369 }{ 370 { 371 name: "IPv4 bind to wildcard and send to assigned address", 372 addAddress: ipv4ProtocolAddress, 373 dstAddr: ipv4ProtocolAddress.AddressWithPrefix.Address, 374 expectAccept: true, 375 }, 376 { 377 name: "IPv4 bind to wildcard and send to other subnet-local address", 378 addAddress: ipv4ProtocolAddress, 379 dstAddr: otherIPv4Address, 380 expectAccept: true, 381 }, 382 { 383 name: "IPv4 bind to wildcard send to other address", 384 addAddress: ipv4ProtocolAddress, 385 dstAddr: utils.RemoteIPv4Addr, 386 expectAccept: false, 387 }, 388 { 389 name: "IPv4 bind to other subnet-local address and send to assigned address", 390 addAddress: ipv4ProtocolAddress, 391 bindAddr: otherIPv4Address, 392 dstAddr: ipv4ProtocolAddress.AddressWithPrefix.Address, 393 expectAccept: false, 394 }, 395 { 396 name: "IPv4 bind and send to other subnet-local address", 397 addAddress: ipv4ProtocolAddress, 398 bindAddr: otherIPv4Address, 399 dstAddr: otherIPv4Address, 400 expectAccept: true, 401 }, 402 { 403 name: "IPv4 bind to assigned address and send to other subnet-local address", 404 addAddress: ipv4ProtocolAddress, 405 bindAddr: ipv4ProtocolAddress.AddressWithPrefix.Address, 406 dstAddr: otherIPv4Address, 407 expectAccept: false, 408 }, 409 410 { 411 name: "IPv6 bind and send to assigned address", 412 addAddress: ipv6ProtocolAddress, 413 bindAddr: utils.Ipv6Addr.Address, 414 dstAddr: utils.Ipv6Addr.Address, 415 expectAccept: true, 416 }, 417 { 418 name: "IPv6 bind to wildcard and send to other subnet-local address", 419 addAddress: ipv6ProtocolAddress, 420 dstAddr: otherIPv6Address, 421 expectAccept: false, 422 }, 423 } 424 425 for _, test := range tests { 426 t.Run(test.name, func(t *testing.T) { 427 s := stack.New(stack.Options{ 428 NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol}, 429 TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol}, 430 }) 431 if err := s.CreateNIC(nicID, loopback.New()); err != nil { 432 t.Fatalf("CreateNIC(%d, _): %s", nicID, err) 433 } 434 if err := s.AddProtocolAddress(nicID, test.addAddress); err != nil { 435 t.Fatalf("AddProtocolAddress(%d, %#v): %s", nicID, test.addAddress, err) 436 } 437 s.SetRouteTable([]tcpip.Route{ 438 { 439 Destination: header.IPv4EmptySubnet, 440 NIC: nicID, 441 }, 442 { 443 Destination: header.IPv6EmptySubnet, 444 NIC: nicID, 445 }, 446 }) 447 448 var wq waiter.Queue 449 we, ch := waiter.NewChannelEntry(nil) 450 wq.EventRegister(&we, waiter.ReadableEvents) 451 defer wq.EventUnregister(&we) 452 listeningEndpoint, err := s.NewEndpoint(tcp.ProtocolNumber, test.addAddress.Protocol, &wq) 453 if err != nil { 454 t.Fatalf("NewEndpoint(%d, %d, _): %s", udp.ProtocolNumber, test.addAddress.Protocol, err) 455 } 456 defer listeningEndpoint.Close() 457 458 bindAddr := tcpip.FullAddress{Addr: test.bindAddr, Port: localPort} 459 if err := listeningEndpoint.Bind(bindAddr); err != nil { 460 t.Fatalf("listeningEndpoint.Bind(%#v): %s", bindAddr, err) 461 } 462 463 if err := listeningEndpoint.Listen(1); err != nil { 464 t.Fatalf("listeningEndpoint.Listen(1): %s", err) 465 } 466 467 connectingEndpoint, err := s.NewEndpoint(tcp.ProtocolNumber, test.addAddress.Protocol, &wq) 468 if err != nil { 469 t.Fatalf("s.NewEndpoint(%d, %d, _): %s", udp.ProtocolNumber, test.addAddress.Protocol, err) 470 } 471 defer connectingEndpoint.Close() 472 473 connectAddr := tcpip.FullAddress{ 474 Addr: test.dstAddr, 475 Port: localPort, 476 } 477 { 478 err := connectingEndpoint.Connect(connectAddr) 479 if _, ok := err.(*tcpip.ErrConnectStarted); !ok { 480 t.Fatalf("connectingEndpoint.Connect(%#v): %s", connectAddr, err) 481 } 482 } 483 484 if !test.expectAccept { 485 _, _, err := listeningEndpoint.Accept(nil) 486 if _, ok := err.(*tcpip.ErrWouldBlock); !ok { 487 t.Fatalf("got listeningEndpoint.Accept(nil) = %s, want = %s", err, &tcpip.ErrWouldBlock{}) 488 } 489 return 490 } 491 492 // Wait for the listening endpoint to be "readable". That is, wait for a 493 // new connection. 494 <-ch 495 var addr tcpip.FullAddress 496 if _, _, err := listeningEndpoint.Accept(&addr); err != nil { 497 t.Fatalf("listeningEndpoint.Accept(nil): %s", err) 498 } 499 if addr.Addr != test.addAddress.AddressWithPrefix.Address { 500 t.Errorf("got addr.Addr = %s, want = %s", addr.Addr, test.addAddress.AddressWithPrefix.Address) 501 } 502 }) 503 } 504 } 505 506 func TestExternalLoopbackTraffic(t *testing.T) { 507 const ( 508 nicID1 = 1 509 nicID2 = 2 510 511 numPackets = 1 512 ttl = 64 513 ) 514 ipv4Loopback := testutil.MustParse4("127.0.0.1") 515 516 loopbackSourcedICMPv4 := func(e *channel.Endpoint) { 517 utils.RxICMPv4EchoRequest(e, ipv4Loopback, utils.Ipv4Addr.Address, ttl) 518 } 519 520 loopbackSourcedICMPv6 := func(e *channel.Endpoint) { 521 utils.RxICMPv6EchoRequest(e, header.IPv6Loopback, utils.Ipv6Addr.Address, ttl) 522 } 523 524 loopbackDestinedICMPv4 := func(e *channel.Endpoint) { 525 utils.RxICMPv4EchoRequest(e, utils.RemoteIPv4Addr, ipv4Loopback, ttl) 526 } 527 528 loopbackDestinedICMPv6 := func(e *channel.Endpoint) { 529 utils.RxICMPv6EchoRequest(e, utils.RemoteIPv6Addr, header.IPv6Loopback, ttl) 530 } 531 532 invalidSrcAddrStat := func(s tcpip.IPStats) *tcpip.StatCounter { 533 return s.InvalidSourceAddressesReceived 534 } 535 536 invalidDestAddrStat := func(s tcpip.IPStats) *tcpip.StatCounter { 537 return s.InvalidDestinationAddressesReceived 538 } 539 540 tests := []struct { 541 name string 542 allowExternalLoopback bool 543 forwarding bool 544 rxICMP func(*channel.Endpoint) 545 invalidAddressStat func(tcpip.IPStats) *tcpip.StatCounter 546 shouldAccept bool 547 }{ 548 { 549 name: "IPv4 external loopback sourced traffic without forwarding and drop external loopback disabled", 550 allowExternalLoopback: true, 551 forwarding: false, 552 rxICMP: loopbackSourcedICMPv4, 553 invalidAddressStat: invalidSrcAddrStat, 554 shouldAccept: true, 555 }, 556 { 557 name: "IPv4 external loopback sourced traffic without forwarding and drop external loopback enabled", 558 allowExternalLoopback: false, 559 forwarding: false, 560 rxICMP: loopbackSourcedICMPv4, 561 invalidAddressStat: invalidSrcAddrStat, 562 shouldAccept: false, 563 }, 564 { 565 name: "IPv4 external loopback sourced traffic with forwarding and drop external loopback disabled", 566 allowExternalLoopback: true, 567 forwarding: true, 568 rxICMP: loopbackSourcedICMPv4, 569 invalidAddressStat: invalidSrcAddrStat, 570 shouldAccept: true, 571 }, 572 { 573 name: "IPv4 external loopback sourced traffic with forwarding and drop external loopback enabled", 574 allowExternalLoopback: false, 575 forwarding: true, 576 rxICMP: loopbackSourcedICMPv4, 577 invalidAddressStat: invalidSrcAddrStat, 578 shouldAccept: false, 579 }, 580 { 581 name: "IPv4 external loopback destined traffic without forwarding and drop external loopback disabled", 582 allowExternalLoopback: true, 583 forwarding: false, 584 rxICMP: loopbackDestinedICMPv4, 585 invalidAddressStat: invalidDestAddrStat, 586 shouldAccept: false, 587 }, 588 { 589 name: "IPv4 external loopback destined traffic without forwarding and drop external loopback enabled", 590 allowExternalLoopback: false, 591 forwarding: false, 592 rxICMP: loopbackDestinedICMPv4, 593 invalidAddressStat: invalidDestAddrStat, 594 shouldAccept: false, 595 }, 596 { 597 name: "IPv4 external loopback destined traffic with forwarding and drop external loopback disabled", 598 allowExternalLoopback: true, 599 forwarding: true, 600 rxICMP: loopbackDestinedICMPv4, 601 invalidAddressStat: invalidDestAddrStat, 602 shouldAccept: true, 603 }, 604 { 605 name: "IPv4 external loopback destined traffic with forwarding and drop external loopback enabled", 606 allowExternalLoopback: false, 607 forwarding: true, 608 rxICMP: loopbackDestinedICMPv4, 609 invalidAddressStat: invalidDestAddrStat, 610 shouldAccept: false, 611 }, 612 613 { 614 name: "IPv6 external loopback sourced traffic without forwarding and drop external loopback disabled", 615 allowExternalLoopback: true, 616 forwarding: false, 617 rxICMP: loopbackSourcedICMPv6, 618 invalidAddressStat: invalidSrcAddrStat, 619 shouldAccept: true, 620 }, 621 { 622 name: "IPv6 external loopback sourced traffic without forwarding and drop external loopback enabled", 623 allowExternalLoopback: false, 624 forwarding: false, 625 rxICMP: loopbackSourcedICMPv6, 626 invalidAddressStat: invalidSrcAddrStat, 627 shouldAccept: false, 628 }, 629 { 630 name: "IPv6 external loopback sourced traffic with forwarding and drop external loopback disabled", 631 allowExternalLoopback: true, 632 forwarding: true, 633 rxICMP: loopbackSourcedICMPv6, 634 invalidAddressStat: invalidSrcAddrStat, 635 shouldAccept: true, 636 }, 637 { 638 name: "IPv6 external loopback sourced traffic with forwarding and drop external loopback enabled", 639 allowExternalLoopback: false, 640 forwarding: true, 641 rxICMP: loopbackSourcedICMPv6, 642 invalidAddressStat: invalidSrcAddrStat, 643 shouldAccept: false, 644 }, 645 { 646 name: "IPv6 external loopback destined traffic without forwarding and drop external loopback disabled", 647 allowExternalLoopback: true, 648 forwarding: false, 649 rxICMP: loopbackDestinedICMPv6, 650 invalidAddressStat: invalidDestAddrStat, 651 shouldAccept: false, 652 }, 653 { 654 name: "IPv6 external loopback destined traffic without forwarding and drop external loopback enabled", 655 allowExternalLoopback: false, 656 forwarding: false, 657 rxICMP: loopbackDestinedICMPv6, 658 invalidAddressStat: invalidDestAddrStat, 659 shouldAccept: false, 660 }, 661 { 662 name: "IPv6 external loopback destined traffic with forwarding and drop external loopback disabled", 663 allowExternalLoopback: true, 664 forwarding: true, 665 rxICMP: loopbackDestinedICMPv6, 666 invalidAddressStat: invalidDestAddrStat, 667 shouldAccept: true, 668 }, 669 { 670 name: "IPv6 external loopback destined traffic with forwarding and drop external loopback enabled", 671 allowExternalLoopback: false, 672 forwarding: true, 673 rxICMP: loopbackDestinedICMPv6, 674 invalidAddressStat: invalidDestAddrStat, 675 shouldAccept: false, 676 }, 677 } 678 679 for _, test := range tests { 680 t.Run(test.name, func(t *testing.T) { 681 s := stack.New(stack.Options{ 682 NetworkProtocols: []stack.NetworkProtocolFactory{ 683 ipv4.NewProtocolWithOptions(ipv4.Options{ 684 AllowExternalLoopbackTraffic: test.allowExternalLoopback, 685 }), 686 ipv6.NewProtocolWithOptions(ipv6.Options{ 687 AllowExternalLoopbackTraffic: test.allowExternalLoopback, 688 }), 689 }, 690 TransportProtocols: []stack.TransportProtocolFactory{icmp.NewProtocol4, icmp.NewProtocol6}, 691 }) 692 e := channel.New(1, header.IPv6MinimumMTU, "") 693 if err := s.CreateNIC(nicID1, e); err != nil { 694 t.Fatalf("CreateNIC(%d, _): %s", nicID1, err) 695 } 696 if err := s.AddAddressWithPrefix(nicID1, ipv4.ProtocolNumber, utils.Ipv4Addr); err != nil { 697 t.Fatalf("AddAddressWithPrefix(%d, %d, %s): %s", nicID1, ipv4.ProtocolNumber, utils.Ipv4Addr, err) 698 } 699 if err := s.AddAddressWithPrefix(nicID1, ipv6.ProtocolNumber, utils.Ipv6Addr); err != nil { 700 t.Fatalf("AddAddressWithPrefix(%d, %d, %s): %s", nicID1, ipv6.ProtocolNumber, utils.Ipv6Addr, err) 701 } 702 703 if err := s.CreateNIC(nicID2, loopback.New()); err != nil { 704 t.Fatalf("CreateNIC(%d, _): %s", nicID2, err) 705 } 706 if err := s.AddAddress(nicID2, ipv4.ProtocolNumber, ipv4Loopback); err != nil { 707 t.Fatalf("AddAddress(%d, %d, %s): %s", nicID2, ipv4.ProtocolNumber, ipv4Loopback, err) 708 } 709 if err := s.AddAddress(nicID2, ipv6.ProtocolNumber, header.IPv6Loopback); err != nil { 710 t.Fatalf("AddAddress(%d, %d, %s): %s", nicID2, ipv6.ProtocolNumber, header.IPv6Loopback, err) 711 } 712 713 if test.forwarding { 714 if err := s.SetForwardingDefaultAndAllNICs(ipv4.ProtocolNumber, true); err != nil { 715 t.Fatalf("SetForwardingDefaultAndAllNICs(%d, true): %s", ipv4.ProtocolNumber, err) 716 } 717 if err := s.SetForwardingDefaultAndAllNICs(ipv6.ProtocolNumber, true); err != nil { 718 t.Fatalf("SetForwardingDefaultAndAllNICs(%d, true): %s", ipv6.ProtocolNumber, err) 719 } 720 } 721 722 s.SetRouteTable([]tcpip.Route{ 723 tcpip.Route{ 724 Destination: header.IPv4EmptySubnet, 725 NIC: nicID1, 726 }, 727 tcpip.Route{ 728 Destination: header.IPv6EmptySubnet, 729 NIC: nicID1, 730 }, 731 tcpip.Route{ 732 Destination: ipv4Loopback.WithPrefix().Subnet(), 733 NIC: nicID2, 734 }, 735 tcpip.Route{ 736 Destination: header.IPv6Loopback.WithPrefix().Subnet(), 737 NIC: nicID2, 738 }, 739 }) 740 741 stats := s.Stats().IP 742 invalidAddressStat := test.invalidAddressStat(stats) 743 deliveredPacketsStat := stats.PacketsDelivered 744 if got := invalidAddressStat.Value(); got != 0 { 745 t.Fatalf("got invalidAddressStat.Value() = %d, want = 0", got) 746 } 747 if got := deliveredPacketsStat.Value(); got != 0 { 748 t.Fatalf("got deliveredPacketsStat.Value() = %d, want = 0", got) 749 } 750 test.rxICMP(e) 751 var expectedInvalidPackets uint64 752 if !test.shouldAccept { 753 expectedInvalidPackets = numPackets 754 } 755 if got := invalidAddressStat.Value(); got != expectedInvalidPackets { 756 t.Fatalf("got invalidAddressStat.Value() = %d, want = %d", got, expectedInvalidPackets) 757 } 758 if got, want := deliveredPacketsStat.Value(), numPackets-expectedInvalidPackets; got != want { 759 t.Fatalf("got deliveredPacketsStat.Value() = %d, want = %d", got, want) 760 } 761 }) 762 } 763 }