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