github.com/FlowerWrong/netstack@v0.0.0-20191009141956-e5848263af28/tcpip/transport/udp/udp_test.go (about) 1 // Copyright 2018 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 udp_test 16 17 import ( 18 "bytes" 19 "fmt" 20 "math/rand" 21 "testing" 22 "time" 23 24 "github.com/FlowerWrong/netstack/tcpip" 25 "github.com/FlowerWrong/netstack/tcpip/buffer" 26 "github.com/FlowerWrong/netstack/tcpip/checker" 27 "github.com/FlowerWrong/netstack/tcpip/header" 28 "github.com/FlowerWrong/netstack/tcpip/link/channel" 29 "github.com/FlowerWrong/netstack/tcpip/link/loopback" 30 "github.com/FlowerWrong/netstack/tcpip/link/sniffer" 31 "github.com/FlowerWrong/netstack/tcpip/network/ipv4" 32 "github.com/FlowerWrong/netstack/tcpip/network/ipv6" 33 "github.com/FlowerWrong/netstack/tcpip/stack" 34 "github.com/FlowerWrong/netstack/tcpip/transport/udp" 35 "github.com/FlowerWrong/netstack/waiter" 36 ) 37 38 // Addresses and ports used for testing. It is recommended that tests stick to 39 // using these addresses as it allows using the testFlow helper. 40 // Naming rules: 'stack*'' denotes local addresses and ports, while 'test*' 41 // represents the remote endpoint. 42 const ( 43 v4MappedAddrPrefix = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff" 44 stackV6Addr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" 45 testV6Addr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02" 46 stackV4MappedAddr = v4MappedAddrPrefix + stackAddr 47 testV4MappedAddr = v4MappedAddrPrefix + testAddr 48 multicastV4MappedAddr = v4MappedAddrPrefix + multicastAddr 49 broadcastV4MappedAddr = v4MappedAddrPrefix + broadcastAddr 50 v4MappedWildcardAddr = v4MappedAddrPrefix + "\x00\x00\x00\x00" 51 52 stackAddr = "\x0a\x00\x00\x01" 53 stackPort = 1234 54 testAddr = "\x0a\x00\x00\x02" 55 testPort = 4096 56 multicastAddr = "\xe8\x2b\xd3\xea" 57 multicastV6Addr = "\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 58 broadcastAddr = header.IPv4Broadcast 59 60 // defaultMTU is the MTU, in bytes, used throughout the tests, except 61 // where another value is explicitly used. It is chosen to match the MTU 62 // of loopback interfaces on linux systems. 63 defaultMTU = 65536 64 ) 65 66 // header4Tuple stores the 4-tuple {src-IP, src-port, dst-IP, dst-port} used in 67 // a packet header. These values are used to populate a header or verify one. 68 // Note that because they are used in packet headers, the addresses are never in 69 // a V4-mapped format. 70 type header4Tuple struct { 71 srcAddr tcpip.FullAddress 72 dstAddr tcpip.FullAddress 73 } 74 75 // testFlow implements a helper type used for sending and receiving test 76 // packets. A given test flow value defines 1) the socket endpoint used for the 77 // test and 2) the type of packet send or received on the endpoint. E.g., a 78 // multicastV6Only flow is a V6 multicast packet passing through a V6-only 79 // endpoint. The type provides helper methods to characterize the flow (e.g., 80 // isV4) as well as return a proper header4Tuple for it. 81 type testFlow int 82 83 const ( 84 unicastV4 testFlow = iota // V4 unicast on a V4 socket 85 unicastV4in6 // V4-mapped unicast on a V6-dual socket 86 unicastV6 // V6 unicast on a V6 socket 87 unicastV6Only // V6 unicast on a V6-only socket 88 multicastV4 // V4 multicast on a V4 socket 89 multicastV4in6 // V4-mapped multicast on a V6-dual socket 90 multicastV6 // V6 multicast on a V6 socket 91 multicastV6Only // V6 multicast on a V6-only socket 92 broadcast // V4 broadcast on a V4 socket 93 broadcastIn6 // V4-mapped broadcast on a V6-dual socket 94 ) 95 96 func (flow testFlow) String() string { 97 switch flow { 98 case unicastV4: 99 return "unicastV4" 100 case unicastV6: 101 return "unicastV6" 102 case unicastV6Only: 103 return "unicastV6Only" 104 case unicastV4in6: 105 return "unicastV4in6" 106 case multicastV4: 107 return "multicastV4" 108 case multicastV6: 109 return "multicastV6" 110 case multicastV6Only: 111 return "multicastV6Only" 112 case multicastV4in6: 113 return "multicastV4in6" 114 case broadcast: 115 return "broadcast" 116 case broadcastIn6: 117 return "broadcastIn6" 118 default: 119 return "unknown" 120 } 121 } 122 123 // packetDirection explains if a flow is incoming (read) or outgoing (write). 124 type packetDirection int 125 126 const ( 127 incoming packetDirection = iota 128 outgoing 129 ) 130 131 // header4Tuple returns the header4Tuple for the given flow and direction. Note 132 // that the tuple contains no mapped addresses as those only exist at the socket 133 // level but not at the packet header level. 134 func (flow testFlow) header4Tuple(d packetDirection) header4Tuple { 135 var h header4Tuple 136 if flow.isV4() { 137 if d == outgoing { 138 h = header4Tuple{ 139 srcAddr: tcpip.FullAddress{Addr: stackAddr, Port: stackPort}, 140 dstAddr: tcpip.FullAddress{Addr: testAddr, Port: testPort}, 141 } 142 } else { 143 h = header4Tuple{ 144 srcAddr: tcpip.FullAddress{Addr: testAddr, Port: testPort}, 145 dstAddr: tcpip.FullAddress{Addr: stackAddr, Port: stackPort}, 146 } 147 } 148 if flow.isMulticast() { 149 h.dstAddr.Addr = multicastAddr 150 } else if flow.isBroadcast() { 151 h.dstAddr.Addr = broadcastAddr 152 } 153 } else { // IPv6 154 if d == outgoing { 155 h = header4Tuple{ 156 srcAddr: tcpip.FullAddress{Addr: stackV6Addr, Port: stackPort}, 157 dstAddr: tcpip.FullAddress{Addr: testV6Addr, Port: testPort}, 158 } 159 } else { 160 h = header4Tuple{ 161 srcAddr: tcpip.FullAddress{Addr: testV6Addr, Port: testPort}, 162 dstAddr: tcpip.FullAddress{Addr: stackV6Addr, Port: stackPort}, 163 } 164 } 165 if flow.isMulticast() { 166 h.dstAddr.Addr = multicastV6Addr 167 } 168 } 169 return h 170 } 171 172 func (flow testFlow) getMcastAddr() tcpip.Address { 173 if flow.isV4() { 174 return multicastAddr 175 } 176 return multicastV6Addr 177 } 178 179 // mapAddrIfApplicable converts the given V4 address into its V4-mapped version 180 // if it is applicable to the flow. 181 func (flow testFlow) mapAddrIfApplicable(v4Addr tcpip.Address) tcpip.Address { 182 if flow.isMapped() { 183 return v4MappedAddrPrefix + v4Addr 184 } 185 return v4Addr 186 } 187 188 // netProto returns the protocol number used for the network packet. 189 func (flow testFlow) netProto() tcpip.NetworkProtocolNumber { 190 if flow.isV4() { 191 return ipv4.ProtocolNumber 192 } 193 return ipv6.ProtocolNumber 194 } 195 196 // sockProto returns the protocol number used when creating the socket 197 // endpoint for this flow. 198 func (flow testFlow) sockProto() tcpip.NetworkProtocolNumber { 199 switch flow { 200 case unicastV4in6, unicastV6, unicastV6Only, multicastV4in6, multicastV6, multicastV6Only, broadcastIn6: 201 return ipv6.ProtocolNumber 202 case unicastV4, multicastV4, broadcast: 203 return ipv4.ProtocolNumber 204 default: 205 panic(fmt.Sprintf("invalid testFlow given: %d", flow)) 206 } 207 } 208 209 func (flow testFlow) checkerFn() func(*testing.T, []byte, ...checker.NetworkChecker) { 210 if flow.isV4() { 211 return checker.IPv4 212 } 213 return checker.IPv6 214 } 215 216 func (flow testFlow) isV6() bool { return !flow.isV4() } 217 func (flow testFlow) isV4() bool { 218 return flow.sockProto() == ipv4.ProtocolNumber || flow.isMapped() 219 } 220 221 func (flow testFlow) isV6Only() bool { 222 switch flow { 223 case unicastV6Only, multicastV6Only: 224 return true 225 case unicastV4, unicastV4in6, unicastV6, multicastV4, multicastV4in6, multicastV6, broadcast, broadcastIn6: 226 return false 227 default: 228 panic(fmt.Sprintf("invalid testFlow given: %d", flow)) 229 } 230 } 231 232 func (flow testFlow) isMulticast() bool { 233 switch flow { 234 case multicastV4, multicastV4in6, multicastV6, multicastV6Only: 235 return true 236 case unicastV4, unicastV4in6, unicastV6, unicastV6Only, broadcast, broadcastIn6: 237 return false 238 default: 239 panic(fmt.Sprintf("invalid testFlow given: %d", flow)) 240 } 241 } 242 243 func (flow testFlow) isBroadcast() bool { 244 switch flow { 245 case broadcast, broadcastIn6: 246 return true 247 case unicastV4, unicastV4in6, unicastV6, unicastV6Only, multicastV4, multicastV4in6, multicastV6, multicastV6Only: 248 return false 249 default: 250 panic(fmt.Sprintf("invalid testFlow given: %d", flow)) 251 } 252 } 253 254 func (flow testFlow) isMapped() bool { 255 switch flow { 256 case unicastV4in6, multicastV4in6, broadcastIn6: 257 return true 258 case unicastV4, unicastV6, unicastV6Only, multicastV4, multicastV6, multicastV6Only, broadcast: 259 return false 260 default: 261 panic(fmt.Sprintf("invalid testFlow given: %d", flow)) 262 } 263 } 264 265 type testContext struct { 266 t *testing.T 267 linkEP *channel.Endpoint 268 s *stack.Stack 269 270 ep tcpip.Endpoint 271 wq waiter.Queue 272 } 273 274 func newDualTestContext(t *testing.T, mtu uint32) *testContext { 275 t.Helper() 276 277 s := stack.New(stack.Options{ 278 NetworkProtocols: []stack.NetworkProtocol{ipv4.NewProtocol(), ipv6.NewProtocol()}, 279 TransportProtocols: []stack.TransportProtocol{udp.NewProtocol()}, 280 }) 281 ep := channel.New(256, mtu, "") 282 wep := stack.LinkEndpoint(ep) 283 284 if testing.Verbose() { 285 wep = sniffer.New(ep) 286 } 287 if err := s.CreateNIC(1, wep); err != nil { 288 t.Fatalf("CreateNIC failed: %v", err) 289 } 290 291 if err := s.AddAddress(1, ipv4.ProtocolNumber, stackAddr); err != nil { 292 t.Fatalf("AddAddress failed: %v", err) 293 } 294 295 if err := s.AddAddress(1, ipv6.ProtocolNumber, stackV6Addr); err != nil { 296 t.Fatalf("AddAddress failed: %v", err) 297 } 298 299 s.SetRouteTable([]tcpip.Route{ 300 { 301 Destination: header.IPv4EmptySubnet, 302 NIC: 1, 303 }, 304 { 305 Destination: header.IPv6EmptySubnet, 306 NIC: 1, 307 }, 308 }) 309 310 return &testContext{ 311 t: t, 312 s: s, 313 linkEP: ep, 314 } 315 } 316 317 func (c *testContext) cleanup() { 318 if c.ep != nil { 319 c.ep.Close() 320 } 321 } 322 323 func (c *testContext) createEndpoint(proto tcpip.NetworkProtocolNumber) { 324 c.t.Helper() 325 326 var err *tcpip.Error 327 c.ep, err = c.s.NewEndpoint(udp.ProtocolNumber, proto, &c.wq) 328 if err != nil { 329 c.t.Fatal("NewEndpoint failed: ", err) 330 } 331 } 332 333 func (c *testContext) createEndpointForFlow(flow testFlow) { 334 c.t.Helper() 335 336 c.createEndpoint(flow.sockProto()) 337 if flow.isV6Only() { 338 if err := c.ep.SetSockOpt(tcpip.V6OnlyOption(1)); err != nil { 339 c.t.Fatalf("SetSockOpt failed: %v", err) 340 } 341 } else if flow.isBroadcast() { 342 if err := c.ep.SetSockOpt(tcpip.BroadcastOption(1)); err != nil { 343 c.t.Fatal("SetSockOpt failed:", err) 344 } 345 } 346 } 347 348 // getPacketAndVerify reads a packet from the link endpoint and verifies the 349 // header against expected values from the given test flow. In addition, it 350 // calls any extra checker functions provided. 351 func (c *testContext) getPacketAndVerify(flow testFlow, checkers ...checker.NetworkChecker) []byte { 352 c.t.Helper() 353 354 select { 355 case p := <-c.linkEP.C: 356 if p.Proto != flow.netProto() { 357 c.t.Fatalf("Bad network protocol: got %v, wanted %v", p.Proto, flow.netProto()) 358 } 359 b := make([]byte, len(p.Header)+len(p.Payload)) 360 copy(b, p.Header) 361 copy(b[len(p.Header):], p.Payload) 362 363 h := flow.header4Tuple(outgoing) 364 checkers := append( 365 checkers, 366 checker.SrcAddr(h.srcAddr.Addr), 367 checker.DstAddr(h.dstAddr.Addr), 368 checker.UDP(checker.DstPort(h.dstAddr.Port)), 369 ) 370 flow.checkerFn()(c.t, b, checkers...) 371 return b 372 373 case <-time.After(2 * time.Second): 374 c.t.Fatalf("Packet wasn't written out") 375 } 376 377 return nil 378 } 379 380 // injectPacket creates a packet of the given flow and with the given payload, 381 // and injects it into the link endpoint. 382 func (c *testContext) injectPacket(flow testFlow, payload []byte) { 383 c.t.Helper() 384 385 h := flow.header4Tuple(incoming) 386 if flow.isV4() { 387 c.injectV4Packet(payload, &h) 388 } else { 389 c.injectV6Packet(payload, &h) 390 } 391 } 392 393 // injectV6Packet creates a V6 test packet with the given payload and header 394 // values, and injects it into the link endpoint. 395 func (c *testContext) injectV6Packet(payload []byte, h *header4Tuple) { 396 // Allocate a buffer for data and headers. 397 buf := buffer.NewView(header.UDPMinimumSize + header.IPv6MinimumSize + len(payload)) 398 copy(buf[len(buf)-len(payload):], payload) 399 400 // Initialize the IP header. 401 ip := header.IPv6(buf) 402 ip.Encode(&header.IPv6Fields{ 403 PayloadLength: uint16(header.UDPMinimumSize + len(payload)), 404 NextHeader: uint8(udp.ProtocolNumber), 405 HopLimit: 65, 406 SrcAddr: h.srcAddr.Addr, 407 DstAddr: h.dstAddr.Addr, 408 }) 409 410 // Initialize the UDP header. 411 u := header.UDP(buf[header.IPv6MinimumSize:]) 412 u.Encode(&header.UDPFields{ 413 SrcPort: h.srcAddr.Port, 414 DstPort: h.dstAddr.Port, 415 Length: uint16(header.UDPMinimumSize + len(payload)), 416 }) 417 418 // Calculate the UDP pseudo-header checksum. 419 xsum := header.PseudoHeaderChecksum(udp.ProtocolNumber, h.srcAddr.Addr, h.dstAddr.Addr, uint16(len(u))) 420 421 // Calculate the UDP checksum and set it. 422 xsum = header.Checksum(payload, xsum) 423 u.SetChecksum(^u.CalculateChecksum(xsum)) 424 425 // Inject packet. 426 c.linkEP.Inject(ipv6.ProtocolNumber, buf.ToVectorisedView()) 427 } 428 429 // injectV6Packet creates a V4 test packet with the given payload and header 430 // values, and injects it into the link endpoint. 431 func (c *testContext) injectV4Packet(payload []byte, h *header4Tuple) { 432 // Allocate a buffer for data and headers. 433 buf := buffer.NewView(header.UDPMinimumSize + header.IPv4MinimumSize + len(payload)) 434 copy(buf[len(buf)-len(payload):], payload) 435 436 // Initialize the IP header. 437 ip := header.IPv4(buf) 438 ip.Encode(&header.IPv4Fields{ 439 IHL: header.IPv4MinimumSize, 440 TotalLength: uint16(len(buf)), 441 TTL: 65, 442 Protocol: uint8(udp.ProtocolNumber), 443 SrcAddr: h.srcAddr.Addr, 444 DstAddr: h.dstAddr.Addr, 445 }) 446 ip.SetChecksum(^ip.CalculateChecksum()) 447 448 // Initialize the UDP header. 449 u := header.UDP(buf[header.IPv4MinimumSize:]) 450 u.Encode(&header.UDPFields{ 451 SrcPort: h.srcAddr.Port, 452 DstPort: h.dstAddr.Port, 453 Length: uint16(header.UDPMinimumSize + len(payload)), 454 }) 455 456 // Calculate the UDP pseudo-header checksum. 457 xsum := header.PseudoHeaderChecksum(udp.ProtocolNumber, h.srcAddr.Addr, h.dstAddr.Addr, uint16(len(u))) 458 459 // Calculate the UDP checksum and set it. 460 xsum = header.Checksum(payload, xsum) 461 u.SetChecksum(^u.CalculateChecksum(xsum)) 462 463 // Inject packet. 464 c.linkEP.Inject(ipv4.ProtocolNumber, buf.ToVectorisedView()) 465 } 466 467 func newPayload() []byte { 468 return newMinPayload(30) 469 } 470 471 func newMinPayload(minSize int) []byte { 472 b := make([]byte, minSize+rand.Intn(100)) 473 for i := range b { 474 b[i] = byte(rand.Intn(256)) 475 } 476 return b 477 } 478 479 func TestBindToDeviceOption(t *testing.T) { 480 s := stack.New(stack.Options{ 481 NetworkProtocols: []stack.NetworkProtocol{ipv4.NewProtocol()}, 482 TransportProtocols: []stack.TransportProtocol{udp.NewProtocol()}}) 483 484 ep, err := s.NewEndpoint(udp.ProtocolNumber, ipv4.ProtocolNumber, &waiter.Queue{}) 485 if err != nil { 486 t.Fatalf("NewEndpoint failed; %v", err) 487 } 488 defer ep.Close() 489 490 if err := s.CreateNamedNIC(321, "my_device", loopback.New()); err != nil { 491 t.Errorf("CreateNamedNIC failed: %v", err) 492 } 493 494 // Make an nameless NIC. 495 if err := s.CreateNIC(54321, loopback.New()); err != nil { 496 t.Errorf("CreateNIC failed: %v", err) 497 } 498 499 // strPtr is used instead of taking the address of string literals, which is 500 // a compiler error. 501 strPtr := func(s string) *string { 502 return &s 503 } 504 505 testActions := []struct { 506 name string 507 setBindToDevice *string 508 setBindToDeviceError *tcpip.Error 509 getBindToDevice tcpip.BindToDeviceOption 510 }{ 511 {"GetDefaultValue", nil, nil, ""}, 512 {"BindToNonExistent", strPtr("non_existent_device"), tcpip.ErrUnknownDevice, ""}, 513 {"BindToExistent", strPtr("my_device"), nil, "my_device"}, 514 {"UnbindToDevice", strPtr(""), nil, ""}, 515 } 516 for _, testAction := range testActions { 517 t.Run(testAction.name, func(t *testing.T) { 518 if testAction.setBindToDevice != nil { 519 bindToDevice := tcpip.BindToDeviceOption(*testAction.setBindToDevice) 520 if got, want := ep.SetSockOpt(bindToDevice), testAction.setBindToDeviceError; got != want { 521 t.Errorf("SetSockOpt(%v) got %v, want %v", bindToDevice, got, want) 522 } 523 } 524 bindToDevice := tcpip.BindToDeviceOption("to be modified by GetSockOpt") 525 if ep.GetSockOpt(&bindToDevice) != nil { 526 t.Errorf("GetSockOpt got %v, want %v", ep.GetSockOpt(&bindToDevice), nil) 527 } 528 if got, want := bindToDevice, testAction.getBindToDevice; got != want { 529 t.Errorf("bindToDevice got %q, want %q", got, want) 530 } 531 }) 532 } 533 } 534 535 // testReadInternal sends a packet of the given test flow into the stack by 536 // injecting it into the link endpoint. It then attempts to read it from the 537 // UDP endpoint and depending on if this was expected to succeed verifies its 538 // correctness. 539 func testReadInternal(c *testContext, flow testFlow, packetShouldBeDropped bool) { 540 c.t.Helper() 541 542 payload := newPayload() 543 c.injectPacket(flow, payload) 544 545 // Try to receive the data. 546 we, ch := waiter.NewChannelEntry(nil) 547 c.wq.EventRegister(&we, waiter.EventIn) 548 defer c.wq.EventUnregister(&we) 549 550 var addr tcpip.FullAddress 551 v, _, err := c.ep.Read(&addr) 552 if err == tcpip.ErrWouldBlock { 553 // Wait for data to become available. 554 select { 555 case <-ch: 556 v, _, err = c.ep.Read(&addr) 557 558 case <-time.After(300 * time.Millisecond): 559 if packetShouldBeDropped { 560 return // expected to time out 561 } 562 c.t.Fatal("timed out waiting for data") 563 } 564 } 565 566 if err != nil { 567 c.t.Fatal("Read failed:", err) 568 } 569 570 if packetShouldBeDropped { 571 c.t.Fatalf("Read unexpectedly received data from %s", addr.Addr) 572 } 573 574 // Check the peer address. 575 h := flow.header4Tuple(incoming) 576 if addr.Addr != h.srcAddr.Addr { 577 c.t.Fatalf("unexpected remote address: got %s, want %s", addr.Addr, h.srcAddr) 578 } 579 580 // Check the payload. 581 if !bytes.Equal(payload, v) { 582 c.t.Fatalf("bad payload: got %x, want %x", v, payload) 583 } 584 } 585 586 // testRead sends a packet of the given test flow into the stack by injecting it 587 // into the link endpoint. It then reads it from the UDP endpoint and verifies 588 // its correctness. 589 func testRead(c *testContext, flow testFlow) { 590 c.t.Helper() 591 testReadInternal(c, flow, false /* packetShouldBeDropped */) 592 } 593 594 // testFailingRead sends a packet of the given test flow into the stack by 595 // injecting it into the link endpoint. It then tries to read it from the UDP 596 // endpoint and expects this to fail. 597 func testFailingRead(c *testContext, flow testFlow) { 598 c.t.Helper() 599 testReadInternal(c, flow, true /* packetShouldBeDropped */) 600 } 601 602 func TestBindEphemeralPort(t *testing.T) { 603 c := newDualTestContext(t, defaultMTU) 604 defer c.cleanup() 605 606 c.createEndpoint(ipv6.ProtocolNumber) 607 608 if err := c.ep.Bind(tcpip.FullAddress{}); err != nil { 609 t.Fatalf("ep.Bind(...) failed: %v", err) 610 } 611 } 612 613 func TestBindReservedPort(t *testing.T) { 614 c := newDualTestContext(t, defaultMTU) 615 defer c.cleanup() 616 617 c.createEndpoint(ipv6.ProtocolNumber) 618 619 if err := c.ep.Connect(tcpip.FullAddress{Addr: testV6Addr, Port: testPort}); err != nil { 620 c.t.Fatalf("Connect failed: %v", err) 621 } 622 623 addr, err := c.ep.GetLocalAddress() 624 if err != nil { 625 t.Fatalf("GetLocalAddress failed: %v", err) 626 } 627 628 // We can't bind the address reserved by the connected endpoint above. 629 { 630 ep, err := c.s.NewEndpoint(udp.ProtocolNumber, ipv6.ProtocolNumber, &c.wq) 631 if err != nil { 632 t.Fatalf("NewEndpoint failed: %v", err) 633 } 634 defer ep.Close() 635 if got, want := ep.Bind(addr), tcpip.ErrPortInUse; got != want { 636 t.Fatalf("got ep.Bind(...) = %v, want = %v", got, want) 637 } 638 } 639 640 func() { 641 ep, err := c.s.NewEndpoint(udp.ProtocolNumber, ipv4.ProtocolNumber, &c.wq) 642 if err != nil { 643 t.Fatalf("NewEndpoint failed: %v", err) 644 } 645 defer ep.Close() 646 // We can't bind ipv4-any on the port reserved by the connected endpoint 647 // above, since the endpoint is dual-stack. 648 if got, want := ep.Bind(tcpip.FullAddress{Port: addr.Port}), tcpip.ErrPortInUse; got != want { 649 t.Fatalf("got ep.Bind(...) = %v, want = %v", got, want) 650 } 651 // We can bind an ipv4 address on this port, though. 652 if err := ep.Bind(tcpip.FullAddress{Addr: stackAddr, Port: addr.Port}); err != nil { 653 t.Fatalf("ep.Bind(...) failed: %v", err) 654 } 655 }() 656 657 // Once the connected endpoint releases its port reservation, we are able to 658 // bind ipv4-any once again. 659 c.ep.Close() 660 func() { 661 ep, err := c.s.NewEndpoint(udp.ProtocolNumber, ipv4.ProtocolNumber, &c.wq) 662 if err != nil { 663 t.Fatalf("NewEndpoint failed: %v", err) 664 } 665 defer ep.Close() 666 if err := ep.Bind(tcpip.FullAddress{Port: addr.Port}); err != nil { 667 t.Fatalf("ep.Bind(...) failed: %v", err) 668 } 669 }() 670 } 671 672 func TestV4ReadOnV6(t *testing.T) { 673 c := newDualTestContext(t, defaultMTU) 674 defer c.cleanup() 675 676 c.createEndpointForFlow(unicastV4in6) 677 678 // Bind to wildcard. 679 if err := c.ep.Bind(tcpip.FullAddress{Port: stackPort}); err != nil { 680 c.t.Fatalf("Bind failed: %v", err) 681 } 682 683 // Test acceptance. 684 testRead(c, unicastV4in6) 685 } 686 687 func TestV4ReadOnBoundToV4MappedWildcard(t *testing.T) { 688 c := newDualTestContext(t, defaultMTU) 689 defer c.cleanup() 690 691 c.createEndpointForFlow(unicastV4in6) 692 693 // Bind to v4 mapped wildcard. 694 if err := c.ep.Bind(tcpip.FullAddress{Addr: v4MappedWildcardAddr, Port: stackPort}); err != nil { 695 c.t.Fatalf("Bind failed: %v", err) 696 } 697 698 // Test acceptance. 699 testRead(c, unicastV4in6) 700 } 701 702 func TestV4ReadOnBoundToV4Mapped(t *testing.T) { 703 c := newDualTestContext(t, defaultMTU) 704 defer c.cleanup() 705 706 c.createEndpointForFlow(unicastV4in6) 707 708 // Bind to local address. 709 if err := c.ep.Bind(tcpip.FullAddress{Addr: stackV4MappedAddr, Port: stackPort}); err != nil { 710 c.t.Fatalf("Bind failed: %v", err) 711 } 712 713 // Test acceptance. 714 testRead(c, unicastV4in6) 715 } 716 717 func TestV6ReadOnV6(t *testing.T) { 718 c := newDualTestContext(t, defaultMTU) 719 defer c.cleanup() 720 721 c.createEndpointForFlow(unicastV6) 722 723 // Bind to wildcard. 724 if err := c.ep.Bind(tcpip.FullAddress{Port: stackPort}); err != nil { 725 c.t.Fatalf("Bind failed: %v", err) 726 } 727 728 // Test acceptance. 729 testRead(c, unicastV6) 730 } 731 732 func TestV4ReadOnV4(t *testing.T) { 733 c := newDualTestContext(t, defaultMTU) 734 defer c.cleanup() 735 736 c.createEndpointForFlow(unicastV4) 737 738 // Bind to wildcard. 739 if err := c.ep.Bind(tcpip.FullAddress{Port: stackPort}); err != nil { 740 c.t.Fatalf("Bind failed: %v", err) 741 } 742 743 // Test acceptance. 744 testRead(c, unicastV4) 745 } 746 747 // TestReadOnBoundToMulticast checks that an endpoint can bind to a multicast 748 // address and receive data sent to that address. 749 func TestReadOnBoundToMulticast(t *testing.T) { 750 // FIXME(b/128189410): multicastV4in6 currently doesn't work as 751 // AddMembershipOption doesn't handle V4in6 addresses. 752 for _, flow := range []testFlow{multicastV4, multicastV6, multicastV6Only} { 753 t.Run(fmt.Sprintf("flow:%s", flow), func(t *testing.T) { 754 c := newDualTestContext(t, defaultMTU) 755 defer c.cleanup() 756 757 c.createEndpointForFlow(flow) 758 759 // Bind to multicast address. 760 mcastAddr := flow.mapAddrIfApplicable(flow.getMcastAddr()) 761 if err := c.ep.Bind(tcpip.FullAddress{Addr: mcastAddr, Port: stackPort}); err != nil { 762 c.t.Fatal("Bind failed:", err) 763 } 764 765 // Join multicast group. 766 ifoptSet := tcpip.AddMembershipOption{NIC: 1, MulticastAddr: mcastAddr} 767 if err := c.ep.SetSockOpt(ifoptSet); err != nil { 768 c.t.Fatal("SetSockOpt failed:", err) 769 } 770 771 // Check that we receive multicast packets but not unicast or broadcast 772 // ones. 773 testRead(c, flow) 774 testFailingRead(c, broadcast) 775 testFailingRead(c, unicastV4) 776 }) 777 } 778 } 779 780 // TestV4ReadOnBoundToBroadcast checks that an endpoint can bind to a broadcast 781 // address and can receive only broadcast data. 782 func TestV4ReadOnBoundToBroadcast(t *testing.T) { 783 for _, flow := range []testFlow{broadcast, broadcastIn6} { 784 t.Run(fmt.Sprintf("flow:%s", flow), func(t *testing.T) { 785 c := newDualTestContext(t, defaultMTU) 786 defer c.cleanup() 787 788 c.createEndpointForFlow(flow) 789 790 // Bind to broadcast address. 791 bcastAddr := flow.mapAddrIfApplicable(broadcastAddr) 792 if err := c.ep.Bind(tcpip.FullAddress{Addr: bcastAddr, Port: stackPort}); err != nil { 793 c.t.Fatalf("Bind failed: %s", err) 794 } 795 796 // Check that we receive broadcast packets but not unicast ones. 797 testRead(c, flow) 798 testFailingRead(c, unicastV4) 799 }) 800 } 801 } 802 803 // TestV4ReadBroadcastOnBoundToWildcard checks that an endpoint can bind to ANY 804 // and receive broadcast and unicast data. 805 func TestV4ReadBroadcastOnBoundToWildcard(t *testing.T) { 806 for _, flow := range []testFlow{broadcast, broadcastIn6} { 807 t.Run(fmt.Sprintf("flow:%s", flow), func(t *testing.T) { 808 c := newDualTestContext(t, defaultMTU) 809 defer c.cleanup() 810 811 c.createEndpointForFlow(flow) 812 813 // Bind to wildcard. 814 if err := c.ep.Bind(tcpip.FullAddress{Port: stackPort}); err != nil { 815 c.t.Fatalf("Bind failed: %s (", err) 816 } 817 818 // Check that we receive both broadcast and unicast packets. 819 testRead(c, flow) 820 testRead(c, unicastV4) 821 }) 822 } 823 } 824 825 // testFailingWrite sends a packet of the given test flow into the UDP endpoint 826 // and verifies it fails with the provided error code. 827 func testFailingWrite(c *testContext, flow testFlow, wantErr *tcpip.Error) { 828 c.t.Helper() 829 830 h := flow.header4Tuple(outgoing) 831 writeDstAddr := flow.mapAddrIfApplicable(h.dstAddr.Addr) 832 833 payload := buffer.View(newPayload()) 834 _, _, gotErr := c.ep.Write(tcpip.SlicePayload(payload), tcpip.WriteOptions{ 835 To: &tcpip.FullAddress{Addr: writeDstAddr, Port: h.dstAddr.Port}, 836 }) 837 if gotErr != wantErr { 838 c.t.Fatalf("Write returned unexpected error: got %v, want %v", gotErr, wantErr) 839 } 840 } 841 842 // testWrite sends a packet of the given test flow from the UDP endpoint to the 843 // flow's destination address:port. It then receives it from the link endpoint 844 // and verifies its correctness including any additional checker functions 845 // provided. 846 func testWrite(c *testContext, flow testFlow, checkers ...checker.NetworkChecker) uint16 { 847 c.t.Helper() 848 return testWriteInternal(c, flow, true, checkers...) 849 } 850 851 // testWriteWithoutDestination sends a packet of the given test flow from the 852 // UDP endpoint without giving a destination address:port. It then receives it 853 // from the link endpoint and verifies its correctness including any additional 854 // checker functions provided. 855 func testWriteWithoutDestination(c *testContext, flow testFlow, checkers ...checker.NetworkChecker) uint16 { 856 c.t.Helper() 857 return testWriteInternal(c, flow, false, checkers...) 858 } 859 860 func testWriteInternal(c *testContext, flow testFlow, setDest bool, checkers ...checker.NetworkChecker) uint16 { 861 c.t.Helper() 862 863 writeOpts := tcpip.WriteOptions{} 864 if setDest { 865 h := flow.header4Tuple(outgoing) 866 writeDstAddr := flow.mapAddrIfApplicable(h.dstAddr.Addr) 867 writeOpts = tcpip.WriteOptions{ 868 To: &tcpip.FullAddress{Addr: writeDstAddr, Port: h.dstAddr.Port}, 869 } 870 } 871 payload := buffer.View(newPayload()) 872 n, _, err := c.ep.Write(tcpip.SlicePayload(payload), writeOpts) 873 if err != nil { 874 c.t.Fatalf("Write failed: %v", err) 875 } 876 if n != int64(len(payload)) { 877 c.t.Fatalf("Bad number of bytes written: got %v, want %v", n, len(payload)) 878 } 879 880 // Received the packet and check the payload. 881 b := c.getPacketAndVerify(flow, checkers...) 882 var udp header.UDP 883 if flow.isV4() { 884 udp = header.UDP(header.IPv4(b).Payload()) 885 } else { 886 udp = header.UDP(header.IPv6(b).Payload()) 887 } 888 if !bytes.Equal(payload, udp.Payload()) { 889 c.t.Fatalf("Bad payload: got %x, want %x", udp.Payload(), payload) 890 } 891 892 return udp.SourcePort() 893 } 894 895 func testDualWrite(c *testContext) uint16 { 896 c.t.Helper() 897 898 v4Port := testWrite(c, unicastV4in6) 899 v6Port := testWrite(c, unicastV6) 900 if v4Port != v6Port { 901 c.t.Fatalf("expected v4 and v6 ports to be equal: got v4Port = %d, v6Port = %d", v4Port, v6Port) 902 } 903 904 return v4Port 905 } 906 907 func TestDualWriteUnbound(t *testing.T) { 908 c := newDualTestContext(t, defaultMTU) 909 defer c.cleanup() 910 911 c.createEndpoint(ipv6.ProtocolNumber) 912 913 testDualWrite(c) 914 } 915 916 func TestDualWriteBoundToWildcard(t *testing.T) { 917 c := newDualTestContext(t, defaultMTU) 918 defer c.cleanup() 919 920 c.createEndpoint(ipv6.ProtocolNumber) 921 922 // Bind to wildcard. 923 if err := c.ep.Bind(tcpip.FullAddress{Port: stackPort}); err != nil { 924 c.t.Fatalf("Bind failed: %v", err) 925 } 926 927 p := testDualWrite(c) 928 if p != stackPort { 929 c.t.Fatalf("Bad port: got %v, want %v", p, stackPort) 930 } 931 } 932 933 func TestDualWriteConnectedToV6(t *testing.T) { 934 c := newDualTestContext(t, defaultMTU) 935 defer c.cleanup() 936 937 c.createEndpoint(ipv6.ProtocolNumber) 938 939 // Connect to v6 address. 940 if err := c.ep.Connect(tcpip.FullAddress{Addr: testV6Addr, Port: testPort}); err != nil { 941 c.t.Fatalf("Bind failed: %v", err) 942 } 943 944 testWrite(c, unicastV6) 945 946 // Write to V4 mapped address. 947 testFailingWrite(c, unicastV4in6, tcpip.ErrNetworkUnreachable) 948 } 949 950 func TestDualWriteConnectedToV4Mapped(t *testing.T) { 951 c := newDualTestContext(t, defaultMTU) 952 defer c.cleanup() 953 954 c.createEndpoint(ipv6.ProtocolNumber) 955 956 // Connect to v4 mapped address. 957 if err := c.ep.Connect(tcpip.FullAddress{Addr: testV4MappedAddr, Port: testPort}); err != nil { 958 c.t.Fatalf("Bind failed: %v", err) 959 } 960 961 testWrite(c, unicastV4in6) 962 963 // Write to v6 address. 964 testFailingWrite(c, unicastV6, tcpip.ErrInvalidEndpointState) 965 } 966 967 func TestV4WriteOnV6Only(t *testing.T) { 968 c := newDualTestContext(t, defaultMTU) 969 defer c.cleanup() 970 971 c.createEndpointForFlow(unicastV6Only) 972 973 // Write to V4 mapped address. 974 testFailingWrite(c, unicastV4in6, tcpip.ErrNoRoute) 975 } 976 977 func TestV6WriteOnBoundToV4Mapped(t *testing.T) { 978 c := newDualTestContext(t, defaultMTU) 979 defer c.cleanup() 980 981 c.createEndpoint(ipv6.ProtocolNumber) 982 983 // Bind to v4 mapped address. 984 if err := c.ep.Bind(tcpip.FullAddress{Addr: stackV4MappedAddr, Port: stackPort}); err != nil { 985 c.t.Fatalf("Bind failed: %v", err) 986 } 987 988 // Write to v6 address. 989 testFailingWrite(c, unicastV6, tcpip.ErrInvalidEndpointState) 990 } 991 992 func TestV6WriteOnConnected(t *testing.T) { 993 c := newDualTestContext(t, defaultMTU) 994 defer c.cleanup() 995 996 c.createEndpoint(ipv6.ProtocolNumber) 997 998 // Connect to v6 address. 999 if err := c.ep.Connect(tcpip.FullAddress{Addr: testV6Addr, Port: testPort}); err != nil { 1000 c.t.Fatalf("Connect failed: %v", err) 1001 } 1002 1003 testWriteWithoutDestination(c, unicastV6) 1004 } 1005 1006 func TestV4WriteOnConnected(t *testing.T) { 1007 c := newDualTestContext(t, defaultMTU) 1008 defer c.cleanup() 1009 1010 c.createEndpoint(ipv6.ProtocolNumber) 1011 1012 // Connect to v4 mapped address. 1013 if err := c.ep.Connect(tcpip.FullAddress{Addr: testV4MappedAddr, Port: testPort}); err != nil { 1014 c.t.Fatalf("Connect failed: %v", err) 1015 } 1016 1017 testWriteWithoutDestination(c, unicastV4) 1018 } 1019 1020 // TestWriteOnBoundToV4Multicast checks that we can send packets out of a socket 1021 // that is bound to a V4 multicast address. 1022 func TestWriteOnBoundToV4Multicast(t *testing.T) { 1023 for _, flow := range []testFlow{unicastV4, multicastV4, broadcast} { 1024 t.Run(fmt.Sprintf("%s", flow), func(t *testing.T) { 1025 c := newDualTestContext(t, defaultMTU) 1026 defer c.cleanup() 1027 1028 c.createEndpointForFlow(flow) 1029 1030 // Bind to V4 mcast address. 1031 if err := c.ep.Bind(tcpip.FullAddress{Addr: multicastAddr, Port: stackPort}); err != nil { 1032 c.t.Fatal("Bind failed:", err) 1033 } 1034 1035 testWrite(c, flow) 1036 }) 1037 } 1038 } 1039 1040 // TestWriteOnBoundToV4MappedMulticast checks that we can send packets out of a 1041 // socket that is bound to a V4-mapped multicast address. 1042 func TestWriteOnBoundToV4MappedMulticast(t *testing.T) { 1043 for _, flow := range []testFlow{unicastV4in6, multicastV4in6, broadcastIn6} { 1044 t.Run(fmt.Sprintf("%s", flow), func(t *testing.T) { 1045 c := newDualTestContext(t, defaultMTU) 1046 defer c.cleanup() 1047 1048 c.createEndpointForFlow(flow) 1049 1050 // Bind to V4Mapped mcast address. 1051 if err := c.ep.Bind(tcpip.FullAddress{Addr: multicastV4MappedAddr, Port: stackPort}); err != nil { 1052 c.t.Fatalf("Bind failed: %s", err) 1053 } 1054 1055 testWrite(c, flow) 1056 }) 1057 } 1058 } 1059 1060 // TestWriteOnBoundToV6Multicast checks that we can send packets out of a 1061 // socket that is bound to a V6 multicast address. 1062 func TestWriteOnBoundToV6Multicast(t *testing.T) { 1063 for _, flow := range []testFlow{unicastV6, multicastV6} { 1064 t.Run(fmt.Sprintf("%s", flow), func(t *testing.T) { 1065 c := newDualTestContext(t, defaultMTU) 1066 defer c.cleanup() 1067 1068 c.createEndpointForFlow(flow) 1069 1070 // Bind to V6 mcast address. 1071 if err := c.ep.Bind(tcpip.FullAddress{Addr: multicastV6Addr, Port: stackPort}); err != nil { 1072 c.t.Fatalf("Bind failed: %s", err) 1073 } 1074 1075 testWrite(c, flow) 1076 }) 1077 } 1078 } 1079 1080 // TestWriteOnBoundToV6Multicast checks that we can send packets out of a 1081 // V6-only socket that is bound to a V6 multicast address. 1082 func TestWriteOnBoundToV6OnlyMulticast(t *testing.T) { 1083 for _, flow := range []testFlow{unicastV6Only, multicastV6Only} { 1084 t.Run(fmt.Sprintf("%s", flow), func(t *testing.T) { 1085 c := newDualTestContext(t, defaultMTU) 1086 defer c.cleanup() 1087 1088 c.createEndpointForFlow(flow) 1089 1090 // Bind to V6 mcast address. 1091 if err := c.ep.Bind(tcpip.FullAddress{Addr: multicastV6Addr, Port: stackPort}); err != nil { 1092 c.t.Fatalf("Bind failed: %s", err) 1093 } 1094 1095 testWrite(c, flow) 1096 }) 1097 } 1098 } 1099 1100 // TestWriteOnBoundToBroadcast checks that we can send packets out of a 1101 // socket that is bound to the broadcast address. 1102 func TestWriteOnBoundToBroadcast(t *testing.T) { 1103 for _, flow := range []testFlow{unicastV4, multicastV4, broadcast} { 1104 t.Run(fmt.Sprintf("%s", flow), func(t *testing.T) { 1105 c := newDualTestContext(t, defaultMTU) 1106 defer c.cleanup() 1107 1108 c.createEndpointForFlow(flow) 1109 1110 // Bind to V4 broadcast address. 1111 if err := c.ep.Bind(tcpip.FullAddress{Addr: broadcastAddr, Port: stackPort}); err != nil { 1112 c.t.Fatal("Bind failed:", err) 1113 } 1114 1115 testWrite(c, flow) 1116 }) 1117 } 1118 } 1119 1120 // TestWriteOnBoundToV4MappedBroadcast checks that we can send packets out of a 1121 // socket that is bound to the V4-mapped broadcast address. 1122 func TestWriteOnBoundToV4MappedBroadcast(t *testing.T) { 1123 for _, flow := range []testFlow{unicastV4in6, multicastV4in6, broadcastIn6} { 1124 t.Run(fmt.Sprintf("%s", flow), func(t *testing.T) { 1125 c := newDualTestContext(t, defaultMTU) 1126 defer c.cleanup() 1127 1128 c.createEndpointForFlow(flow) 1129 1130 // Bind to V4Mapped mcast address. 1131 if err := c.ep.Bind(tcpip.FullAddress{Addr: broadcastV4MappedAddr, Port: stackPort}); err != nil { 1132 c.t.Fatalf("Bind failed: %s", err) 1133 } 1134 1135 testWrite(c, flow) 1136 }) 1137 } 1138 } 1139 1140 func TestReadIncrementsPacketsReceived(t *testing.T) { 1141 c := newDualTestContext(t, defaultMTU) 1142 defer c.cleanup() 1143 1144 // Create IPv4 UDP endpoint 1145 c.createEndpoint(ipv6.ProtocolNumber) 1146 1147 // Bind to wildcard. 1148 if err := c.ep.Bind(tcpip.FullAddress{Port: stackPort}); err != nil { 1149 c.t.Fatalf("Bind failed: %v", err) 1150 } 1151 1152 testRead(c, unicastV4) 1153 1154 var want uint64 = 1 1155 if got := c.s.Stats().UDP.PacketsReceived.Value(); got != want { 1156 c.t.Fatalf("Read did not increment PacketsReceived: got %v, want %v", got, want) 1157 } 1158 } 1159 1160 func TestWriteIncrementsPacketsSent(t *testing.T) { 1161 c := newDualTestContext(t, defaultMTU) 1162 defer c.cleanup() 1163 1164 c.createEndpoint(ipv6.ProtocolNumber) 1165 1166 testDualWrite(c) 1167 1168 var want uint64 = 2 1169 if got := c.s.Stats().UDP.PacketsSent.Value(); got != want { 1170 c.t.Fatalf("Write did not increment PacketsSent: got %v, want %v", got, want) 1171 } 1172 } 1173 1174 func TestTTL(t *testing.T) { 1175 for _, flow := range []testFlow{unicastV4, unicastV4in6, unicastV6, unicastV6Only, multicastV4, multicastV4in6, multicastV6, broadcast, broadcastIn6} { 1176 t.Run(fmt.Sprintf("flow:%s", flow), func(t *testing.T) { 1177 c := newDualTestContext(t, defaultMTU) 1178 defer c.cleanup() 1179 1180 c.createEndpointForFlow(flow) 1181 1182 const multicastTTL = 42 1183 if err := c.ep.SetSockOpt(tcpip.MulticastTTLOption(multicastTTL)); err != nil { 1184 c.t.Fatalf("SetSockOpt failed: %v", err) 1185 } 1186 1187 var wantTTL uint8 1188 if flow.isMulticast() { 1189 wantTTL = multicastTTL 1190 } else { 1191 var p stack.NetworkProtocol 1192 if flow.isV4() { 1193 p = ipv4.NewProtocol() 1194 } else { 1195 p = ipv6.NewProtocol() 1196 } 1197 ep, err := p.NewEndpoint(0, tcpip.AddressWithPrefix{}, nil, nil, nil) 1198 if err != nil { 1199 t.Fatal(err) 1200 } 1201 wantTTL = ep.DefaultTTL() 1202 ep.Close() 1203 } 1204 1205 testWrite(c, flow, checker.TTL(wantTTL)) 1206 }) 1207 } 1208 } 1209 1210 func TestSetTTL(t *testing.T) { 1211 for _, flow := range []testFlow{unicastV4, unicastV4in6, unicastV6, unicastV6Only, broadcast, broadcastIn6} { 1212 t.Run(fmt.Sprintf("flow:%s", flow), func(t *testing.T) { 1213 for _, wantTTL := range []uint8{1, 2, 50, 64, 128, 254, 255} { 1214 t.Run(fmt.Sprintf("TTL:%d", wantTTL), func(t *testing.T) { 1215 c := newDualTestContext(t, defaultMTU) 1216 defer c.cleanup() 1217 1218 c.createEndpointForFlow(flow) 1219 1220 if err := c.ep.SetSockOpt(tcpip.TTLOption(wantTTL)); err != nil { 1221 c.t.Fatalf("SetSockOpt failed: %v", err) 1222 } 1223 1224 var p stack.NetworkProtocol 1225 if flow.isV4() { 1226 p = ipv4.NewProtocol() 1227 } else { 1228 p = ipv6.NewProtocol() 1229 } 1230 ep, err := p.NewEndpoint(0, tcpip.AddressWithPrefix{}, nil, nil, nil) 1231 if err != nil { 1232 t.Fatal(err) 1233 } 1234 ep.Close() 1235 1236 testWrite(c, flow, checker.TTL(wantTTL)) 1237 }) 1238 } 1239 }) 1240 } 1241 } 1242 1243 func TestMulticastInterfaceOption(t *testing.T) { 1244 for _, flow := range []testFlow{multicastV4, multicastV4in6, multicastV6, multicastV6Only} { 1245 t.Run(fmt.Sprintf("flow:%s", flow), func(t *testing.T) { 1246 for _, bindTyp := range []string{"bound", "unbound"} { 1247 t.Run(bindTyp, func(t *testing.T) { 1248 for _, optTyp := range []string{"use local-addr", "use NICID", "use local-addr and NIC"} { 1249 t.Run(optTyp, func(t *testing.T) { 1250 h := flow.header4Tuple(outgoing) 1251 mcastAddr := h.dstAddr.Addr 1252 localIfAddr := h.srcAddr.Addr 1253 1254 var ifoptSet tcpip.MulticastInterfaceOption 1255 switch optTyp { 1256 case "use local-addr": 1257 ifoptSet.InterfaceAddr = localIfAddr 1258 case "use NICID": 1259 ifoptSet.NIC = 1 1260 case "use local-addr and NIC": 1261 ifoptSet.InterfaceAddr = localIfAddr 1262 ifoptSet.NIC = 1 1263 default: 1264 t.Fatal("unknown test variant") 1265 } 1266 1267 c := newDualTestContext(t, defaultMTU) 1268 defer c.cleanup() 1269 1270 c.createEndpoint(flow.sockProto()) 1271 1272 if bindTyp == "bound" { 1273 // Bind the socket by connecting to the multicast address. 1274 // This may have an influence on how the multicast interface 1275 // is set. 1276 addr := tcpip.FullAddress{ 1277 Addr: flow.mapAddrIfApplicable(mcastAddr), 1278 Port: stackPort, 1279 } 1280 if err := c.ep.Connect(addr); err != nil { 1281 c.t.Fatalf("Connect failed: %v", err) 1282 } 1283 } 1284 1285 if err := c.ep.SetSockOpt(ifoptSet); err != nil { 1286 c.t.Fatalf("SetSockOpt failed: %v", err) 1287 } 1288 1289 // Verify multicast interface addr and NIC were set correctly. 1290 // Note that NIC must be 1 since this is our outgoing interface. 1291 ifoptWant := tcpip.MulticastInterfaceOption{NIC: 1, InterfaceAddr: ifoptSet.InterfaceAddr} 1292 var ifoptGot tcpip.MulticastInterfaceOption 1293 if err := c.ep.GetSockOpt(&ifoptGot); err != nil { 1294 c.t.Fatalf("GetSockOpt failed: %v", err) 1295 } 1296 if ifoptGot != ifoptWant { 1297 c.t.Errorf("got GetSockOpt() = %#v, want = %#v", ifoptGot, ifoptWant) 1298 } 1299 }) 1300 } 1301 }) 1302 } 1303 }) 1304 } 1305 } 1306 1307 // TestV4UnknownDestination verifies that we generate an ICMPv4 Destination 1308 // Unreachable message when a udp datagram is received on ports for which there 1309 // is no bound udp socket. 1310 func TestV4UnknownDestination(t *testing.T) { 1311 c := newDualTestContext(t, defaultMTU) 1312 defer c.cleanup() 1313 1314 testCases := []struct { 1315 flow testFlow 1316 icmpRequired bool 1317 // largePayload if true, will result in a payload large enough 1318 // so that the final generated IPv4 packet is larger than 1319 // header.IPv4MinimumProcessableDatagramSize. 1320 largePayload bool 1321 }{ 1322 {unicastV4, true, false}, 1323 {unicastV4, true, true}, 1324 {multicastV4, false, false}, 1325 {multicastV4, false, true}, 1326 {broadcast, false, false}, 1327 {broadcast, false, true}, 1328 } 1329 for _, tc := range testCases { 1330 t.Run(fmt.Sprintf("flow:%s icmpRequired:%t largePayload:%t", tc.flow, tc.icmpRequired, tc.largePayload), func(t *testing.T) { 1331 payload := newPayload() 1332 if tc.largePayload { 1333 payload = newMinPayload(576) 1334 } 1335 c.injectPacket(tc.flow, payload) 1336 if !tc.icmpRequired { 1337 select { 1338 case p := <-c.linkEP.C: 1339 t.Fatalf("unexpected packet received: %+v", p) 1340 case <-time.After(1 * time.Second): 1341 return 1342 } 1343 } 1344 1345 select { 1346 case p := <-c.linkEP.C: 1347 var pkt []byte 1348 pkt = append(pkt, p.Header...) 1349 pkt = append(pkt, p.Payload...) 1350 if got, want := len(pkt), header.IPv4MinimumProcessableDatagramSize; got > want { 1351 t.Fatalf("got an ICMP packet of size: %d, want: sz <= %d", got, want) 1352 } 1353 1354 hdr := header.IPv4(pkt) 1355 checker.IPv4(t, hdr, checker.ICMPv4( 1356 checker.ICMPv4Type(header.ICMPv4DstUnreachable), 1357 checker.ICMPv4Code(header.ICMPv4PortUnreachable))) 1358 1359 icmpPkt := header.ICMPv4(hdr.Payload()) 1360 payloadIPHeader := header.IPv4(icmpPkt.Payload()) 1361 wantLen := len(payload) 1362 if tc.largePayload { 1363 wantLen = header.IPv4MinimumProcessableDatagramSize - header.IPv4MinimumSize*2 - header.ICMPv4MinimumSize - header.UDPMinimumSize 1364 } 1365 1366 // In case of large payloads the IP packet may be truncated. Update 1367 // the length field before retrieving the udp datagram payload. 1368 payloadIPHeader.SetTotalLength(uint16(wantLen + header.UDPMinimumSize + header.IPv4MinimumSize)) 1369 1370 origDgram := header.UDP(payloadIPHeader.Payload()) 1371 if got, want := len(origDgram.Payload()), wantLen; got != want { 1372 t.Fatalf("unexpected payload length got: %d, want: %d", got, want) 1373 } 1374 if got, want := origDgram.Payload(), payload[:wantLen]; !bytes.Equal(got, want) { 1375 t.Fatalf("unexpected payload got: %d, want: %d", got, want) 1376 } 1377 case <-time.After(1 * time.Second): 1378 t.Fatalf("packet wasn't written out") 1379 } 1380 }) 1381 } 1382 } 1383 1384 // TestV6UnknownDestination verifies that we generate an ICMPv6 Destination 1385 // Unreachable message when a udp datagram is received on ports for which there 1386 // is no bound udp socket. 1387 func TestV6UnknownDestination(t *testing.T) { 1388 c := newDualTestContext(t, defaultMTU) 1389 defer c.cleanup() 1390 1391 testCases := []struct { 1392 flow testFlow 1393 icmpRequired bool 1394 // largePayload if true will result in a payload large enough to 1395 // create an IPv6 packet > header.IPv6MinimumMTU bytes. 1396 largePayload bool 1397 }{ 1398 {unicastV6, true, false}, 1399 {unicastV6, true, true}, 1400 {multicastV6, false, false}, 1401 {multicastV6, false, true}, 1402 } 1403 for _, tc := range testCases { 1404 t.Run(fmt.Sprintf("flow:%s icmpRequired:%t largePayload:%t", tc.flow, tc.icmpRequired, tc.largePayload), func(t *testing.T) { 1405 payload := newPayload() 1406 if tc.largePayload { 1407 payload = newMinPayload(1280) 1408 } 1409 c.injectPacket(tc.flow, payload) 1410 if !tc.icmpRequired { 1411 select { 1412 case p := <-c.linkEP.C: 1413 t.Fatalf("unexpected packet received: %+v", p) 1414 case <-time.After(1 * time.Second): 1415 return 1416 } 1417 } 1418 1419 select { 1420 case p := <-c.linkEP.C: 1421 var pkt []byte 1422 pkt = append(pkt, p.Header...) 1423 pkt = append(pkt, p.Payload...) 1424 if got, want := len(pkt), header.IPv6MinimumMTU; got > want { 1425 t.Fatalf("got an ICMP packet of size: %d, want: sz <= %d", got, want) 1426 } 1427 1428 hdr := header.IPv6(pkt) 1429 checker.IPv6(t, hdr, checker.ICMPv6( 1430 checker.ICMPv6Type(header.ICMPv6DstUnreachable), 1431 checker.ICMPv6Code(header.ICMPv6PortUnreachable))) 1432 1433 icmpPkt := header.ICMPv6(hdr.Payload()) 1434 payloadIPHeader := header.IPv6(icmpPkt.Payload()) 1435 wantLen := len(payload) 1436 if tc.largePayload { 1437 wantLen = header.IPv6MinimumMTU - header.IPv6MinimumSize*2 - header.ICMPv6MinimumSize - header.UDPMinimumSize 1438 } 1439 // In case of large payloads the IP packet may be truncated. Update 1440 // the length field before retrieving the udp datagram payload. 1441 payloadIPHeader.SetPayloadLength(uint16(wantLen + header.UDPMinimumSize)) 1442 1443 origDgram := header.UDP(payloadIPHeader.Payload()) 1444 if got, want := len(origDgram.Payload()), wantLen; got != want { 1445 t.Fatalf("unexpected payload length got: %d, want: %d", got, want) 1446 } 1447 if got, want := origDgram.Payload(), payload[:wantLen]; !bytes.Equal(got, want) { 1448 t.Fatalf("unexpected payload got: %v, want: %v", got, want) 1449 } 1450 case <-time.After(1 * time.Second): 1451 t.Fatalf("packet wasn't written out") 1452 } 1453 }) 1454 } 1455 }