github.com/flowerwrong/netstack@v0.0.0-20191009141956-e5848263af28/tcpip/transport/tcp/dual_stack_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 tcp_test 16 17 import ( 18 "testing" 19 "time" 20 21 "github.com/FlowerWrong/netstack/tcpip" 22 "github.com/FlowerWrong/netstack/tcpip/buffer" 23 "github.com/FlowerWrong/netstack/tcpip/checker" 24 "github.com/FlowerWrong/netstack/tcpip/header" 25 "github.com/FlowerWrong/netstack/tcpip/network/ipv4" 26 "github.com/FlowerWrong/netstack/tcpip/seqnum" 27 "github.com/FlowerWrong/netstack/tcpip/transport/tcp" 28 "github.com/FlowerWrong/netstack/tcpip/transport/tcp/testing/context" 29 "github.com/FlowerWrong/netstack/waiter" 30 ) 31 32 func TestV4MappedConnectOnV6Only(t *testing.T) { 33 c := context.New(t, defaultMTU) 34 defer c.Cleanup() 35 36 c.CreateV6Endpoint(true) 37 38 // Start connection attempt, it must fail. 39 err := c.EP.Connect(tcpip.FullAddress{Addr: context.TestV4MappedAddr, Port: context.TestPort}) 40 if err != tcpip.ErrNoRoute { 41 t.Fatalf("Unexpected return value from Connect: %v", err) 42 } 43 } 44 45 func testV4Connect(t *testing.T, c *context.Context) { 46 // Start connection attempt. 47 we, ch := waiter.NewChannelEntry(nil) 48 c.WQ.EventRegister(&we, waiter.EventOut) 49 defer c.WQ.EventUnregister(&we) 50 51 err := c.EP.Connect(tcpip.FullAddress{Addr: context.TestV4MappedAddr, Port: context.TestPort}) 52 if err != tcpip.ErrConnectStarted { 53 t.Fatalf("Unexpected return value from Connect: %v", err) 54 } 55 56 // Receive SYN packet. 57 b := c.GetPacket() 58 checker.IPv4(t, b, 59 checker.TCP( 60 checker.DstPort(context.TestPort), 61 checker.TCPFlags(header.TCPFlagSyn), 62 ), 63 ) 64 65 tcp := header.TCP(header.IPv4(b).Payload()) 66 c.IRS = seqnum.Value(tcp.SequenceNumber()) 67 68 iss := seqnum.Value(789) 69 c.SendPacket(nil, &context.Headers{ 70 SrcPort: tcp.DestinationPort(), 71 DstPort: tcp.SourcePort(), 72 Flags: header.TCPFlagSyn | header.TCPFlagAck, 73 SeqNum: iss, 74 AckNum: c.IRS.Add(1), 75 RcvWnd: 30000, 76 }) 77 78 // Receive ACK packet. 79 checker.IPv4(t, c.GetPacket(), 80 checker.TCP( 81 checker.DstPort(context.TestPort), 82 checker.TCPFlags(header.TCPFlagAck), 83 checker.SeqNum(uint32(c.IRS)+1), 84 checker.AckNum(uint32(iss)+1), 85 ), 86 ) 87 88 // Wait for connection to be established. 89 select { 90 case <-ch: 91 err = c.EP.GetSockOpt(tcpip.ErrorOption{}) 92 if err != nil { 93 t.Fatalf("Unexpected error when connecting: %v", err) 94 } 95 case <-time.After(1 * time.Second): 96 t.Fatalf("Timed out waiting for connection") 97 } 98 } 99 100 func TestV4MappedConnect(t *testing.T) { 101 c := context.New(t, defaultMTU) 102 defer c.Cleanup() 103 104 c.CreateV6Endpoint(false) 105 106 // Test the connection request. 107 testV4Connect(t, c) 108 } 109 110 func TestV4ConnectWhenBoundToWildcard(t *testing.T) { 111 c := context.New(t, defaultMTU) 112 defer c.Cleanup() 113 114 c.CreateV6Endpoint(false) 115 116 // Bind to wildcard. 117 if err := c.EP.Bind(tcpip.FullAddress{}); err != nil { 118 t.Fatalf("Bind failed: %v", err) 119 } 120 121 // Test the connection request. 122 testV4Connect(t, c) 123 } 124 125 func TestV4ConnectWhenBoundToV4MappedWildcard(t *testing.T) { 126 c := context.New(t, defaultMTU) 127 defer c.Cleanup() 128 129 c.CreateV6Endpoint(false) 130 131 // Bind to v4 mapped wildcard. 132 if err := c.EP.Bind(tcpip.FullAddress{Addr: context.V4MappedWildcardAddr}); err != nil { 133 t.Fatalf("Bind failed: %v", err) 134 } 135 136 // Test the connection request. 137 testV4Connect(t, c) 138 } 139 140 func TestV4ConnectWhenBoundToV4Mapped(t *testing.T) { 141 c := context.New(t, defaultMTU) 142 defer c.Cleanup() 143 144 c.CreateV6Endpoint(false) 145 146 // Bind to v4 mapped address. 147 if err := c.EP.Bind(tcpip.FullAddress{Addr: context.StackV4MappedAddr}); err != nil { 148 t.Fatalf("Bind failed: %v", err) 149 } 150 151 // Test the connection request. 152 testV4Connect(t, c) 153 } 154 155 func testV6Connect(t *testing.T, c *context.Context) { 156 // Start connection attempt to IPv6 address. 157 we, ch := waiter.NewChannelEntry(nil) 158 c.WQ.EventRegister(&we, waiter.EventOut) 159 defer c.WQ.EventUnregister(&we) 160 161 err := c.EP.Connect(tcpip.FullAddress{Addr: context.TestV6Addr, Port: context.TestPort}) 162 if err != tcpip.ErrConnectStarted { 163 t.Fatalf("Unexpected return value from Connect: %v", err) 164 } 165 166 // Receive SYN packet. 167 b := c.GetV6Packet() 168 checker.IPv6(t, b, 169 checker.TCP( 170 checker.DstPort(context.TestPort), 171 checker.TCPFlags(header.TCPFlagSyn), 172 ), 173 ) 174 175 tcp := header.TCP(header.IPv6(b).Payload()) 176 c.IRS = seqnum.Value(tcp.SequenceNumber()) 177 178 iss := seqnum.Value(789) 179 c.SendV6Packet(nil, &context.Headers{ 180 SrcPort: tcp.DestinationPort(), 181 DstPort: tcp.SourcePort(), 182 Flags: header.TCPFlagSyn | header.TCPFlagAck, 183 SeqNum: iss, 184 AckNum: c.IRS.Add(1), 185 RcvWnd: 30000, 186 }) 187 188 // Receive ACK packet. 189 checker.IPv6(t, c.GetV6Packet(), 190 checker.TCP( 191 checker.DstPort(context.TestPort), 192 checker.TCPFlags(header.TCPFlagAck), 193 checker.SeqNum(uint32(c.IRS)+1), 194 checker.AckNum(uint32(iss)+1), 195 ), 196 ) 197 198 // Wait for connection to be established. 199 select { 200 case <-ch: 201 err = c.EP.GetSockOpt(tcpip.ErrorOption{}) 202 if err != nil { 203 t.Fatalf("Unexpected error when connecting: %v", err) 204 } 205 case <-time.After(1 * time.Second): 206 t.Fatalf("Timed out waiting for connection") 207 } 208 } 209 210 func TestV6Connect(t *testing.T) { 211 c := context.New(t, defaultMTU) 212 defer c.Cleanup() 213 214 c.CreateV6Endpoint(false) 215 216 // Test the connection request. 217 testV6Connect(t, c) 218 } 219 220 func TestV6ConnectV6Only(t *testing.T) { 221 c := context.New(t, defaultMTU) 222 defer c.Cleanup() 223 224 c.CreateV6Endpoint(true) 225 226 // Test the connection request. 227 testV6Connect(t, c) 228 } 229 230 func TestV6ConnectWhenBoundToWildcard(t *testing.T) { 231 c := context.New(t, defaultMTU) 232 defer c.Cleanup() 233 234 c.CreateV6Endpoint(false) 235 236 // Bind to wildcard. 237 if err := c.EP.Bind(tcpip.FullAddress{}); err != nil { 238 t.Fatalf("Bind failed: %v", err) 239 } 240 241 // Test the connection request. 242 testV6Connect(t, c) 243 } 244 245 func TestV6ConnectWhenBoundToLocalAddress(t *testing.T) { 246 c := context.New(t, defaultMTU) 247 defer c.Cleanup() 248 249 c.CreateV6Endpoint(false) 250 251 // Bind to local address. 252 if err := c.EP.Bind(tcpip.FullAddress{Addr: context.StackV6Addr}); err != nil { 253 t.Fatalf("Bind failed: %v", err) 254 } 255 256 // Test the connection request. 257 testV6Connect(t, c) 258 } 259 260 func TestV4RefuseOnV6Only(t *testing.T) { 261 c := context.New(t, defaultMTU) 262 defer c.Cleanup() 263 264 c.CreateV6Endpoint(true) 265 266 // Bind to wildcard. 267 if err := c.EP.Bind(tcpip.FullAddress{Port: context.StackPort}); err != nil { 268 t.Fatalf("Bind failed: %v", err) 269 } 270 271 // Start listening. 272 if err := c.EP.Listen(10); err != nil { 273 t.Fatalf("Listen failed: %v", err) 274 } 275 276 // Send a SYN request. 277 irs := seqnum.Value(789) 278 c.SendPacket(nil, &context.Headers{ 279 SrcPort: context.TestPort, 280 DstPort: context.StackPort, 281 Flags: header.TCPFlagSyn, 282 SeqNum: irs, 283 RcvWnd: 30000, 284 }) 285 286 // Receive the RST reply. 287 checker.IPv4(t, c.GetPacket(), 288 checker.TCP( 289 checker.SrcPort(context.StackPort), 290 checker.DstPort(context.TestPort), 291 checker.TCPFlags(header.TCPFlagRst|header.TCPFlagAck), 292 checker.AckNum(uint32(irs)+1), 293 ), 294 ) 295 } 296 297 func TestV6RefuseOnBoundToV4Mapped(t *testing.T) { 298 c := context.New(t, defaultMTU) 299 defer c.Cleanup() 300 301 c.CreateV6Endpoint(false) 302 303 // Bind and listen. 304 if err := c.EP.Bind(tcpip.FullAddress{Addr: context.V4MappedWildcardAddr, Port: context.StackPort}); err != nil { 305 t.Fatalf("Bind failed: %v", err) 306 } 307 308 if err := c.EP.Listen(10); err != nil { 309 t.Fatalf("Listen failed: %v", err) 310 } 311 312 // Send a SYN request. 313 irs := seqnum.Value(789) 314 c.SendV6Packet(nil, &context.Headers{ 315 SrcPort: context.TestPort, 316 DstPort: context.StackPort, 317 Flags: header.TCPFlagSyn, 318 SeqNum: irs, 319 RcvWnd: 30000, 320 }) 321 322 // Receive the RST reply. 323 checker.IPv6(t, c.GetV6Packet(), 324 checker.TCP( 325 checker.SrcPort(context.StackPort), 326 checker.DstPort(context.TestPort), 327 checker.TCPFlags(header.TCPFlagRst|header.TCPFlagAck), 328 checker.AckNum(uint32(irs)+1), 329 ), 330 ) 331 } 332 333 func testV4Accept(t *testing.T, c *context.Context) { 334 c.SetGSOEnabled(true) 335 defer c.SetGSOEnabled(false) 336 337 // Start listening. 338 if err := c.EP.Listen(10); err != nil { 339 t.Fatalf("Listen failed: %v", err) 340 } 341 342 // Send a SYN request. 343 irs := seqnum.Value(789) 344 c.SendPacket(nil, &context.Headers{ 345 SrcPort: context.TestPort, 346 DstPort: context.StackPort, 347 Flags: header.TCPFlagSyn, 348 SeqNum: irs, 349 RcvWnd: 30000, 350 }) 351 352 // Receive the SYN-ACK reply. 353 b := c.GetPacket() 354 tcp := header.TCP(header.IPv4(b).Payload()) 355 iss := seqnum.Value(tcp.SequenceNumber()) 356 checker.IPv4(t, b, 357 checker.TCP( 358 checker.SrcPort(context.StackPort), 359 checker.DstPort(context.TestPort), 360 checker.TCPFlags(header.TCPFlagAck|header.TCPFlagSyn), 361 checker.AckNum(uint32(irs)+1), 362 ), 363 ) 364 365 // Send ACK. 366 c.SendPacket(nil, &context.Headers{ 367 SrcPort: context.TestPort, 368 DstPort: context.StackPort, 369 Flags: header.TCPFlagAck, 370 SeqNum: irs + 1, 371 AckNum: iss + 1, 372 RcvWnd: 30000, 373 }) 374 375 // Try to accept the connection. 376 we, ch := waiter.NewChannelEntry(nil) 377 c.WQ.EventRegister(&we, waiter.EventIn) 378 defer c.WQ.EventUnregister(&we) 379 380 nep, _, err := c.EP.Accept() 381 if err == tcpip.ErrWouldBlock { 382 // Wait for connection to be established. 383 select { 384 case <-ch: 385 nep, _, err = c.EP.Accept() 386 if err != nil { 387 t.Fatalf("Accept failed: %v", err) 388 } 389 390 case <-time.After(1 * time.Second): 391 t.Fatalf("Timed out waiting for accept") 392 } 393 } 394 395 // Make sure we get the same error when calling the original ep and the 396 // new one. This validates that v4-mapped endpoints are still able to 397 // query the V6Only flag, whereas pure v4 endpoints are not. 398 var v tcpip.V6OnlyOption 399 expected := c.EP.GetSockOpt(&v) 400 if err := nep.GetSockOpt(&v); err != expected { 401 t.Fatalf("GetSockOpt returned unexpected value: got %v, want %v", err, expected) 402 } 403 404 // Check the peer address. 405 addr, err := nep.GetRemoteAddress() 406 if err != nil { 407 t.Fatalf("GetRemoteAddress failed failed: %v", err) 408 } 409 410 if addr.Addr != context.TestAddr { 411 t.Fatalf("Unexpected remote address: got %v, want %v", addr.Addr, context.TestAddr) 412 } 413 414 data := "Don't panic" 415 nep.Write(tcpip.SlicePayload(buffer.NewViewFromBytes([]byte(data))), tcpip.WriteOptions{}) 416 b = c.GetPacket() 417 tcp = header.TCP(header.IPv4(b).Payload()) 418 if string(tcp.Payload()) != data { 419 t.Fatalf("Unexpected data: got %v, want %v", string(tcp.Payload()), data) 420 } 421 } 422 423 func TestV4AcceptOnV6(t *testing.T) { 424 c := context.New(t, defaultMTU) 425 defer c.Cleanup() 426 427 c.CreateV6Endpoint(false) 428 429 // Bind to wildcard. 430 if err := c.EP.Bind(tcpip.FullAddress{Port: context.StackPort}); err != nil { 431 t.Fatalf("Bind failed: %v", err) 432 } 433 434 // Test acceptance. 435 testV4Accept(t, c) 436 } 437 438 func TestV4AcceptOnBoundToV4MappedWildcard(t *testing.T) { 439 c := context.New(t, defaultMTU) 440 defer c.Cleanup() 441 442 c.CreateV6Endpoint(false) 443 444 // Bind to v4 mapped wildcard. 445 if err := c.EP.Bind(tcpip.FullAddress{Addr: context.V4MappedWildcardAddr, Port: context.StackPort}); err != nil { 446 t.Fatalf("Bind failed: %v", err) 447 } 448 449 // Test acceptance. 450 testV4Accept(t, c) 451 } 452 453 func TestV4AcceptOnBoundToV4Mapped(t *testing.T) { 454 c := context.New(t, defaultMTU) 455 defer c.Cleanup() 456 457 c.CreateV6Endpoint(false) 458 459 // Bind and listen. 460 if err := c.EP.Bind(tcpip.FullAddress{Addr: context.StackV4MappedAddr, Port: context.StackPort}); err != nil { 461 t.Fatalf("Bind failed: %v", err) 462 } 463 464 // Test acceptance. 465 testV4Accept(t, c) 466 } 467 468 func TestV6AcceptOnV6(t *testing.T) { 469 c := context.New(t, defaultMTU) 470 defer c.Cleanup() 471 472 c.CreateV6Endpoint(false) 473 474 // Bind and listen. 475 if err := c.EP.Bind(tcpip.FullAddress{Port: context.StackPort}); err != nil { 476 t.Fatalf("Bind failed: %v", err) 477 } 478 479 if err := c.EP.Listen(10); err != nil { 480 t.Fatalf("Listen failed: %v", err) 481 } 482 483 // Send a SYN request. 484 irs := seqnum.Value(789) 485 c.SendV6Packet(nil, &context.Headers{ 486 SrcPort: context.TestPort, 487 DstPort: context.StackPort, 488 Flags: header.TCPFlagSyn, 489 SeqNum: irs, 490 RcvWnd: 30000, 491 }) 492 493 // Receive the SYN-ACK reply. 494 b := c.GetV6Packet() 495 tcp := header.TCP(header.IPv6(b).Payload()) 496 iss := seqnum.Value(tcp.SequenceNumber()) 497 checker.IPv6(t, b, 498 checker.TCP( 499 checker.SrcPort(context.StackPort), 500 checker.DstPort(context.TestPort), 501 checker.TCPFlags(header.TCPFlagAck|header.TCPFlagSyn), 502 checker.AckNum(uint32(irs)+1), 503 ), 504 ) 505 506 // Send ACK. 507 c.SendV6Packet(nil, &context.Headers{ 508 SrcPort: context.TestPort, 509 DstPort: context.StackPort, 510 Flags: header.TCPFlagAck, 511 SeqNum: irs + 1, 512 AckNum: iss + 1, 513 RcvWnd: 30000, 514 }) 515 516 // Try to accept the connection. 517 we, ch := waiter.NewChannelEntry(nil) 518 c.WQ.EventRegister(&we, waiter.EventIn) 519 defer c.WQ.EventUnregister(&we) 520 521 nep, _, err := c.EP.Accept() 522 if err == tcpip.ErrWouldBlock { 523 // Wait for connection to be established. 524 select { 525 case <-ch: 526 nep, _, err = c.EP.Accept() 527 if err != nil { 528 t.Fatalf("Accept failed: %v", err) 529 } 530 531 case <-time.After(1 * time.Second): 532 t.Fatalf("Timed out waiting for accept") 533 } 534 } 535 536 // Make sure we can still query the v6 only status of the new endpoint, 537 // that is, that it is in fact a v6 socket. 538 var v tcpip.V6OnlyOption 539 if err := nep.GetSockOpt(&v); err != nil { 540 t.Fatalf("GetSockOpt failed failed: %v", err) 541 } 542 543 // Check the peer address. 544 addr, err := nep.GetRemoteAddress() 545 if err != nil { 546 t.Fatalf("GetRemoteAddress failed failed: %v", err) 547 } 548 549 if addr.Addr != context.TestV6Addr { 550 t.Fatalf("Unexpected remote address: got %v, want %v", addr.Addr, context.TestV6Addr) 551 } 552 } 553 554 func TestV4AcceptOnV4(t *testing.T) { 555 c := context.New(t, defaultMTU) 556 defer c.Cleanup() 557 558 // Create TCP endpoint. 559 var err *tcpip.Error 560 c.EP, err = c.Stack().NewEndpoint(tcp.ProtocolNumber, ipv4.ProtocolNumber, &c.WQ) 561 if err != nil { 562 t.Fatalf("NewEndpoint failed: %v", err) 563 } 564 565 // Bind to wildcard. 566 if err := c.EP.Bind(tcpip.FullAddress{Port: context.StackPort}); err != nil { 567 t.Fatalf("Bind failed: %v", err) 568 } 569 570 // Test acceptance. 571 testV4Accept(t, c) 572 } 573 574 func testV4ListenClose(t *testing.T, c *context.Context) { 575 // Set the SynRcvd threshold to zero to force a syn cookie based accept 576 // to happen. 577 saved := tcp.SynRcvdCountThreshold 578 defer func() { 579 tcp.SynRcvdCountThreshold = saved 580 }() 581 tcp.SynRcvdCountThreshold = 0 582 const n = uint16(32) 583 584 // Start listening. 585 if err := c.EP.Listen(int(tcp.SynRcvdCountThreshold + 1)); err != nil { 586 t.Fatalf("Listen failed: %v", err) 587 } 588 589 irs := seqnum.Value(789) 590 for i := uint16(0); i < n; i++ { 591 // Send a SYN request. 592 c.SendPacket(nil, &context.Headers{ 593 SrcPort: context.TestPort + i, 594 DstPort: context.StackPort, 595 Flags: header.TCPFlagSyn, 596 SeqNum: irs, 597 RcvWnd: 30000, 598 }) 599 } 600 601 // Each of these ACK's will cause a syn-cookie based connection to be 602 // accepted and delivered to the listening endpoint. 603 for i := uint16(0); i < n; i++ { 604 b := c.GetPacket() 605 tcp := header.TCP(header.IPv4(b).Payload()) 606 iss := seqnum.Value(tcp.SequenceNumber()) 607 // Send ACK. 608 c.SendPacket(nil, &context.Headers{ 609 SrcPort: tcp.DestinationPort(), 610 DstPort: context.StackPort, 611 Flags: header.TCPFlagAck, 612 SeqNum: irs + 1, 613 AckNum: iss + 1, 614 RcvWnd: 30000, 615 }) 616 } 617 618 // Try to accept the connection. 619 we, ch := waiter.NewChannelEntry(nil) 620 c.WQ.EventRegister(&we, waiter.EventIn) 621 defer c.WQ.EventUnregister(&we) 622 nep, _, err := c.EP.Accept() 623 if err == tcpip.ErrWouldBlock { 624 // Wait for connection to be established. 625 select { 626 case <-ch: 627 nep, _, err = c.EP.Accept() 628 if err != nil { 629 t.Fatalf("Accept failed: %v", err) 630 } 631 632 case <-time.After(10 * time.Second): 633 t.Fatalf("Timed out waiting for accept") 634 } 635 } 636 nep.Close() 637 c.EP.Close() 638 } 639 640 func TestV4ListenCloseOnV4(t *testing.T) { 641 c := context.New(t, defaultMTU) 642 defer c.Cleanup() 643 644 // Create TCP endpoint. 645 var err *tcpip.Error 646 c.EP, err = c.Stack().NewEndpoint(tcp.ProtocolNumber, ipv4.ProtocolNumber, &c.WQ) 647 if err != nil { 648 t.Fatalf("NewEndpoint failed: %v", err) 649 } 650 651 // Bind to wildcard. 652 if err := c.EP.Bind(tcpip.FullAddress{Port: context.StackPort}); err != nil { 653 t.Fatalf("Bind failed: %v", err) 654 } 655 656 // Test acceptance. 657 testV4ListenClose(t, c) 658 }