gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/socket_inet_loopback_isolated.cc (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 #include <netinet/tcp.h> 16 #include <sys/socket.h> 17 18 #include "gmock/gmock.h" 19 #include "gtest/gtest.h" 20 #include "absl/time/clock.h" 21 #include "absl/time/time.h" 22 #include "test/syscalls/linux/socket_inet_loopback_test_params.h" 23 #include "test/util/capability_util.h" 24 #include "test/util/save_util.h" 25 #include "test/util/socket_util.h" 26 #include "test/util/test_util.h" 27 28 // Unit tests in this file will run in their own network namespace. 29 30 namespace gvisor { 31 namespace testing { 32 33 namespace { 34 35 using SocketInetLoopbackIsolatedTest = 36 ::testing::TestWithParam<SocketInetTestParam>; 37 38 TEST_P(SocketInetLoopbackIsolatedTest, TCPActiveCloseTimeWaitTest) { 39 SocketInetTestParam const& param = GetParam(); 40 sockaddr_storage listen_addr, conn_bound_addr; 41 listen_addr = param.listener.addr; 42 SetupTimeWaitClose(¶m.listener, ¶m.connector, false /*reuse*/, 43 false /*accept_close*/, &listen_addr, &conn_bound_addr); 44 FileDescriptor conn_fd = ASSERT_NO_ERRNO_AND_VALUE( 45 Socket(param.connector.family(), SOCK_STREAM, IPPROTO_TCP)); 46 47 ASSERT_THAT(bind(conn_fd.get(), AsSockAddr(&conn_bound_addr), 48 param.connector.addr_len), 49 SyscallFailsWithErrno(EADDRINUSE)); 50 } 51 52 TEST_P(SocketInetLoopbackIsolatedTest, TCPActiveCloseTimeWaitReuseTest) { 53 SocketInetTestParam const& param = GetParam(); 54 sockaddr_storage listen_addr, conn_bound_addr; 55 listen_addr = param.listener.addr; 56 SetupTimeWaitClose(¶m.listener, ¶m.connector, true /*reuse*/, 57 false /*accept_close*/, &listen_addr, &conn_bound_addr); 58 FileDescriptor conn_fd = ASSERT_NO_ERRNO_AND_VALUE( 59 Socket(param.connector.family(), SOCK_STREAM, IPPROTO_TCP)); 60 ASSERT_THAT(setsockopt(conn_fd.get(), SOL_SOCKET, SO_REUSEADDR, &kSockOptOn, 61 sizeof(kSockOptOn)), 62 SyscallSucceeds()); 63 ASSERT_THAT(bind(conn_fd.get(), AsSockAddr(&conn_bound_addr), 64 param.connector.addr_len), 65 SyscallFailsWithErrno(EADDRINUSE)); 66 } 67 68 // These tests are disabled under random save as the restore run 69 // results in the stack.Seed() being different which can cause 70 // sequence number of final connect to be one that is considered 71 // old and can cause the test to be flaky. 72 // 73 // Test re-binding of client and server bound addresses when the older 74 // connection is in TIME_WAIT. 75 TEST_P(SocketInetLoopbackIsolatedTest, TCPPassiveCloseNoTimeWaitTest) { 76 SocketInetTestParam const& param = GetParam(); 77 sockaddr_storage listen_addr, conn_bound_addr; 78 listen_addr = param.listener.addr; 79 SetupTimeWaitClose(¶m.listener, ¶m.connector, false /*reuse*/, 80 true /*accept_close*/, &listen_addr, &conn_bound_addr); 81 82 // Now bind a new socket and verify that we can immediately rebind the address 83 // bound by the conn_fd as it never entered TIME_WAIT. 84 const FileDescriptor conn_fd = ASSERT_NO_ERRNO_AND_VALUE( 85 Socket(param.connector.family(), SOCK_STREAM, IPPROTO_TCP)); 86 ASSERT_THAT(bind(conn_fd.get(), AsSockAddr(&conn_bound_addr), 87 param.connector.addr_len), 88 SyscallSucceeds()); 89 90 FileDescriptor listen_fd = ASSERT_NO_ERRNO_AND_VALUE( 91 Socket(param.listener.family(), SOCK_STREAM, IPPROTO_TCP)); 92 ASSERT_THAT( 93 bind(listen_fd.get(), AsSockAddr(&listen_addr), param.listener.addr_len), 94 SyscallFailsWithErrno(EADDRINUSE)); 95 } 96 97 TEST_P(SocketInetLoopbackIsolatedTest, TCPPassiveCloseNoTimeWaitReuseTest) { 98 SocketInetTestParam const& param = GetParam(); 99 sockaddr_storage listen_addr, conn_bound_addr; 100 listen_addr = param.listener.addr; 101 SetupTimeWaitClose(¶m.listener, ¶m.connector, true /*reuse*/, 102 true /*accept_close*/, &listen_addr, &conn_bound_addr); 103 104 FileDescriptor listen_fd = ASSERT_NO_ERRNO_AND_VALUE( 105 Socket(param.listener.family(), SOCK_STREAM, IPPROTO_TCP)); 106 ASSERT_THAT(setsockopt(listen_fd.get(), SOL_SOCKET, SO_REUSEADDR, &kSockOptOn, 107 sizeof(kSockOptOn)), 108 SyscallSucceeds()); 109 ASSERT_THAT( 110 bind(listen_fd.get(), AsSockAddr(&listen_addr), param.listener.addr_len), 111 SyscallSucceeds()); 112 ASSERT_THAT(listen(listen_fd.get(), SOMAXCONN), SyscallSucceeds()); 113 114 // Now bind and connect new socket and verify that we can immediately rebind 115 // the address bound by the conn_fd as it never entered TIME_WAIT. 116 const FileDescriptor conn_fd = ASSERT_NO_ERRNO_AND_VALUE( 117 Socket(param.connector.family(), SOCK_STREAM, IPPROTO_TCP)); 118 ASSERT_THAT(setsockopt(conn_fd.get(), SOL_SOCKET, SO_REUSEADDR, &kSockOptOn, 119 sizeof(kSockOptOn)), 120 SyscallSucceeds()); 121 ASSERT_THAT(bind(conn_fd.get(), AsSockAddr(&conn_bound_addr), 122 param.connector.addr_len), 123 SyscallSucceeds()); 124 125 uint16_t const port = 126 ASSERT_NO_ERRNO_AND_VALUE(AddrPort(param.listener.family(), listen_addr)); 127 sockaddr_storage conn_addr = param.connector.addr; 128 ASSERT_NO_ERRNO(SetAddrPort(param.connector.family(), &conn_addr, port)); 129 ASSERT_THAT(RetryEINTR(connect)(conn_fd.get(), AsSockAddr(&conn_addr), 130 param.connector.addr_len), 131 SyscallSucceeds()); 132 } 133 134 // TCPFinWait2Test creates a pair of connected sockets then closes one end to 135 // trigger FIN_WAIT2 state for the closed endpoint. Then it binds the same local 136 // IP/port on a new socket and tries to connect. The connect should fail w/ 137 // an EADDRINUSE. Then we wait till the FIN_WAIT2 timeout is over and try the 138 // bind/connect again with a new socket and this time it should succeed. 139 // 140 // TCP timers are not S/R today, this can cause this test to be flaky when run 141 // under random S/R due to timer being reset on a restore. 142 TEST_P(SocketInetLoopbackIsolatedTest, TCPFinWait2Test) { 143 SocketInetTestParam const& param = GetParam(); 144 TestAddress const& listener = param.listener; 145 TestAddress const& connector = param.connector; 146 147 // Disable cooperative saves after this point. As a save between the first 148 // bind/connect and the second one can cause the linger timeout timer to 149 // be restarted causing the final bind/connect to fail. 150 DisableSave ds; 151 152 // Create the listening socket. 153 const FileDescriptor listen_fd = ASSERT_NO_ERRNO_AND_VALUE( 154 Socket(listener.family(), SOCK_STREAM, IPPROTO_TCP)); 155 sockaddr_storage listen_addr = listener.addr; 156 ASSERT_THAT( 157 bind(listen_fd.get(), AsSockAddr(&listen_addr), listener.addr_len), 158 SyscallSucceeds()); 159 ASSERT_THAT(listen(listen_fd.get(), SOMAXCONN), SyscallSucceeds()); 160 161 // Get the port bound by the listening socket. 162 socklen_t addrlen = listener.addr_len; 163 ASSERT_THAT(getsockname(listen_fd.get(), AsSockAddr(&listen_addr), &addrlen), 164 SyscallSucceeds()); 165 166 uint16_t const port = 167 ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener.family(), listen_addr)); 168 169 // Connect to the listening socket. 170 FileDescriptor conn_fd = ASSERT_NO_ERRNO_AND_VALUE( 171 Socket(connector.family(), SOCK_STREAM, IPPROTO_TCP)); 172 173 // Lower FIN_WAIT2 state to 5 seconds for test. 174 constexpr int kTCPLingerTimeout = 5; 175 EXPECT_THAT(setsockopt(conn_fd.get(), IPPROTO_TCP, TCP_LINGER2, 176 &kTCPLingerTimeout, sizeof(kTCPLingerTimeout)), 177 SyscallSucceedsWithValue(0)); 178 179 sockaddr_storage conn_addr = connector.addr; 180 ASSERT_NO_ERRNO(SetAddrPort(connector.family(), &conn_addr, port)); 181 ASSERT_THAT(RetryEINTR(connect)(conn_fd.get(), AsSockAddr(&conn_addr), 182 connector.addr_len), 183 SyscallSucceeds()); 184 185 // Accept the connection. 186 auto accepted = 187 ASSERT_NO_ERRNO_AND_VALUE(Accept(listen_fd.get(), nullptr, nullptr)); 188 189 // Get the address/port bound by the connecting socket. 190 sockaddr_storage conn_bound_addr; 191 socklen_t conn_addrlen = connector.addr_len; 192 ASSERT_THAT( 193 getsockname(conn_fd.get(), AsSockAddr(&conn_bound_addr), &conn_addrlen), 194 SyscallSucceeds()); 195 196 // close the connecting FD to trigger FIN_WAIT2 on the connected fd. 197 conn_fd.reset(); 198 199 // Now bind and connect a new socket. 200 const FileDescriptor conn_fd2 = ASSERT_NO_ERRNO_AND_VALUE( 201 Socket(connector.family(), SOCK_STREAM, IPPROTO_TCP)); 202 203 ASSERT_THAT(bind(conn_fd2.get(), AsSockAddr(&conn_bound_addr), conn_addrlen), 204 SyscallFailsWithErrno(EADDRINUSE)); 205 206 // Sleep for a little over the linger timeout to reduce flakiness in 207 // save/restore tests. 208 absl::SleepFor(absl::Seconds(kTCPLingerTimeout + 2)); 209 210 ASSERT_THAT(bind(conn_fd2.get(), AsSockAddr(&conn_bound_addr), conn_addrlen), 211 SyscallSucceeds()); 212 213 ASSERT_THAT( 214 RetryEINTR(connect)(conn_fd2.get(), AsSockAddr(&conn_addr), conn_addrlen), 215 SyscallSucceeds()); 216 } 217 218 // TCPLinger2TimeoutAfterClose creates a pair of connected sockets 219 // then closes one end to trigger FIN_WAIT2 state for the closed endpoint. 220 // It then sleeps for the TCP_LINGER2 timeout and verifies that bind/ 221 // connecting the same address succeeds. 222 // 223 // TCP timers are not S/R today, this can cause this test to be flaky when run 224 // under random S/R due to timer being reset on a restore. 225 TEST_P(SocketInetLoopbackIsolatedTest, TCPLinger2TimeoutAfterClose) { 226 SocketInetTestParam const& param = GetParam(); 227 TestAddress const& listener = param.listener; 228 TestAddress const& connector = param.connector; 229 230 // Create the listening socket. 231 const FileDescriptor listen_fd = ASSERT_NO_ERRNO_AND_VALUE( 232 Socket(listener.family(), SOCK_STREAM, IPPROTO_TCP)); 233 sockaddr_storage listen_addr = listener.addr; 234 ASSERT_THAT( 235 bind(listen_fd.get(), AsSockAddr(&listen_addr), listener.addr_len), 236 SyscallSucceeds()); 237 ASSERT_THAT(listen(listen_fd.get(), SOMAXCONN), SyscallSucceeds()); 238 239 // Get the port bound by the listening socket. 240 socklen_t addrlen = listener.addr_len; 241 ASSERT_THAT(getsockname(listen_fd.get(), AsSockAddr(&listen_addr), &addrlen), 242 SyscallSucceeds()); 243 244 uint16_t const port = 245 ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener.family(), listen_addr)); 246 247 // Connect to the listening socket. 248 FileDescriptor conn_fd = ASSERT_NO_ERRNO_AND_VALUE( 249 Socket(connector.family(), SOCK_STREAM, IPPROTO_TCP)); 250 251 sockaddr_storage conn_addr = connector.addr; 252 ASSERT_NO_ERRNO(SetAddrPort(connector.family(), &conn_addr, port)); 253 ASSERT_THAT(RetryEINTR(connect)(conn_fd.get(), AsSockAddr(&conn_addr), 254 connector.addr_len), 255 SyscallSucceeds()); 256 257 // Accept the connection. 258 auto accepted = 259 ASSERT_NO_ERRNO_AND_VALUE(Accept(listen_fd.get(), nullptr, nullptr)); 260 261 // Get the address/port bound by the connecting socket. 262 sockaddr_storage conn_bound_addr; 263 socklen_t conn_addrlen = connector.addr_len; 264 ASSERT_THAT( 265 getsockname(conn_fd.get(), AsSockAddr(&conn_bound_addr), &conn_addrlen), 266 SyscallSucceeds()); 267 268 // Disable cooperative saves after this point as TCP timers are not restored 269 // across a S/R. 270 { 271 DisableSave ds; 272 constexpr int kTCPLingerTimeout = 4; 273 EXPECT_THAT(setsockopt(conn_fd.get(), IPPROTO_TCP, TCP_LINGER2, 274 &kTCPLingerTimeout, sizeof(kTCPLingerTimeout)), 275 SyscallSucceedsWithValue(0)); 276 277 // close the connecting FD to trigger FIN_WAIT2 on the connected fd. 278 conn_fd.reset(); 279 280 absl::SleepFor(absl::Seconds(kTCPLingerTimeout + 2)); 281 282 // ds going out of scope will Re-enable S/R's since at this point the timer 283 // must have fired and cleaned up the endpoint. 284 } 285 286 // Now bind and connect a new socket and verify that we can immediately 287 // rebind the address bound by the conn_fd as it never entered TIME_WAIT. 288 const FileDescriptor conn_fd2 = ASSERT_NO_ERRNO_AND_VALUE( 289 Socket(connector.family(), SOCK_STREAM, IPPROTO_TCP)); 290 291 ASSERT_THAT(bind(conn_fd2.get(), AsSockAddr(&conn_bound_addr), conn_addrlen), 292 SyscallSucceeds()); 293 ASSERT_THAT( 294 RetryEINTR(connect)(conn_fd2.get(), AsSockAddr(&conn_addr), conn_addrlen), 295 SyscallSucceeds()); 296 } 297 298 TEST_P(SocketInetLoopbackIsolatedTest, TCPConnectionReuseAddrConflicts) { 299 SocketInetTestParam const& param = GetParam(); 300 TestAddress const& listener = param.listener; 301 TestAddress const& connector = param.connector; 302 303 const FileDescriptor listen_fd = 304 ASSERT_NO_ERRNO_AND_VALUE(Socket(listener.family(), SOCK_STREAM, 0)); 305 306 sockaddr_storage listen_addr = listener.addr; 307 ASSERT_THAT( 308 bind(listen_fd.get(), AsSockAddr(&listen_addr), listener.addr_len), 309 SyscallSucceeds()); 310 ASSERT_THAT(listen(listen_fd.get(), SOMAXCONN), SyscallSucceeds()); 311 312 // Get the port bound by the listening socket. 313 socklen_t addrlen = listener.addr_len; 314 ASSERT_THAT(getsockname(listen_fd.get(), AsSockAddr(&listen_addr), &addrlen), 315 SyscallSucceeds()); 316 317 const uint16_t port = 318 ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener.family(), listen_addr)); 319 320 // Create a first connection. 321 FileDescriptor conn_fd1 = ASSERT_NO_ERRNO_AND_VALUE( 322 Socket(connector.family(), SOCK_STREAM, IPPROTO_TCP)); 323 ASSERT_THAT(setsockopt(conn_fd1.get(), SOL_SOCKET, SO_REUSEADDR, &kSockOptOn, 324 sizeof(kSockOptOn)), 325 SyscallSucceeds()); 326 327 sockaddr_storage conn_addr = connector.addr; 328 ASSERT_NO_ERRNO(SetAddrPort(connector.family(), &conn_addr, port)); 329 ASSERT_THAT(RetryEINTR(connect)(conn_fd1.get(), AsSockAddr(&conn_addr), 330 connector.addr_len), 331 SyscallSucceeds()); 332 sockaddr_storage conn_bound_addr; 333 addrlen = sizeof(conn_bound_addr); 334 ASSERT_THAT( 335 getsockname(conn_fd1.get(), AsSockAddr(&conn_bound_addr), &addrlen), 336 SyscallSucceeds()); 337 ASSERT_EQ(addrlen, connector.addr_len); 338 339 // Create the second connection that is bind to the same local address as the 340 // first. 341 FileDescriptor conn_fd2 = ASSERT_NO_ERRNO_AND_VALUE( 342 Socket(connector.family(), SOCK_STREAM, IPPROTO_TCP)); 343 ASSERT_THAT(setsockopt(conn_fd2.get(), SOL_SOCKET, SO_REUSEADDR, &kSockOptOn, 344 sizeof(kSockOptOn)), 345 SyscallSucceeds()); 346 // Bind should succeed. 347 ASSERT_THAT(bind(conn_fd2.get(), AsSockAddr(&conn_bound_addr), addrlen), 348 SyscallSucceeds()); 349 350 // Connect should fail. 351 ASSERT_NO_ERRNO(SetAddrPort(connector.family(), &conn_addr, port)); 352 ASSERT_THAT(RetryEINTR(connect)(conn_fd2.get(), AsSockAddr(&conn_addr), 353 connector.addr_len), 354 SyscallFailsWithErrno(EADDRNOTAVAIL)); 355 } 356 357 INSTANTIATE_TEST_SUITE_P(All, SocketInetLoopbackIsolatedTest, 358 SocketInetLoopbackTestValues(), 359 DescribeSocketInetTestParam); 360 361 using SocketMultiProtocolInetLoopbackIsolatedTest = 362 ::testing::TestWithParam<ProtocolTestParam>; 363 364 TEST_P(SocketMultiProtocolInetLoopbackIsolatedTest, BindToDeviceReusePort) { 365 // setsockopt(SO_BINDTODEVICE) requires CAP_NET_RAW. 366 SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveRawIPSocketCapability())); 367 368 ProtocolTestParam const& param = GetParam(); 369 TestAddress const& test_addr = V4Loopback(); 370 371 auto socket1 = 372 ASSERT_NO_ERRNO_AND_VALUE(Socket(test_addr.family(), param.type, 0)); 373 auto socket2 = 374 ASSERT_NO_ERRNO_AND_VALUE(Socket(test_addr.family(), param.type, 0)); 375 376 const char kLoopbackDeviceName[] = "lo"; 377 378 // Bind socket1 with REUSEPORT and BINDTODEVICE. 379 ASSERT_THAT(setsockopt(socket1.get(), SOL_SOCKET, SO_REUSEPORT, &kSockOptOn, 380 sizeof(kSockOptOn)), 381 SyscallSucceeds()); 382 ASSERT_THAT(setsockopt(socket1.get(), SOL_SOCKET, SO_BINDTODEVICE, 383 kLoopbackDeviceName, strlen(kLoopbackDeviceName)), 384 SyscallSucceeds()); 385 386 // Bind the first socket to the loopback and take note of the selected port. 387 auto addr = V4Loopback(); 388 ASSERT_THAT(bind(socket1.get(), AsSockAddr(&addr.addr), addr.addr_len), 389 SyscallSucceeds()); 390 socklen_t addr_len = addr.addr_len; 391 ASSERT_THAT(getsockname(socket1.get(), AsSockAddr(&addr.addr), &addr_len), 392 SyscallSucceeds()); 393 EXPECT_EQ(addr_len, addr.addr_len); 394 395 // Bind socket2 to the same device and address as socket1. 396 ASSERT_THAT(setsockopt(socket2.get(), SOL_SOCKET, SO_BINDTODEVICE, 397 kLoopbackDeviceName, strlen(kLoopbackDeviceName)), 398 SyscallSucceeds()); 399 ASSERT_THAT(setsockopt(socket2.get(), SOL_SOCKET, SO_REUSEPORT, &kSockOptOn, 400 sizeof(kSockOptOn)), 401 SyscallSucceeds()); 402 ASSERT_THAT(bind(socket2.get(), AsSockAddr(&addr.addr), addr.addr_len), 403 SyscallSucceeds()); 404 } 405 406 TEST_P(SocketMultiProtocolInetLoopbackIsolatedTest, 407 V4EphemeralPortReservedReuseAddr) { 408 ProtocolTestParam const& param = GetParam(); 409 410 // Bind the v4 loopback on a v4 socket. 411 TestAddress const& test_addr = V4Loopback(); 412 sockaddr_storage bound_addr = test_addr.addr; 413 const FileDescriptor bound_fd = 414 ASSERT_NO_ERRNO_AND_VALUE(Socket(test_addr.family(), param.type, 0)); 415 416 ASSERT_THAT(setsockopt(bound_fd.get(), SOL_SOCKET, SO_REUSEADDR, &kSockOptOn, 417 sizeof(kSockOptOn)), 418 SyscallSucceeds()); 419 420 ASSERT_THAT(bind(bound_fd.get(), AsSockAddr(&bound_addr), test_addr.addr_len), 421 SyscallSucceeds()); 422 423 // Listen iff TCP. 424 if (param.type == SOCK_STREAM) { 425 ASSERT_THAT(listen(bound_fd.get(), SOMAXCONN), SyscallSucceeds()); 426 } 427 428 // Get the port that we bound. 429 socklen_t bound_addr_len = test_addr.addr_len; 430 ASSERT_THAT( 431 getsockname(bound_fd.get(), AsSockAddr(&bound_addr), &bound_addr_len), 432 SyscallSucceeds()); 433 434 // Connect to bind an ephemeral port. 435 const FileDescriptor connected_fd = 436 ASSERT_NO_ERRNO_AND_VALUE(Socket(test_addr.family(), param.type, 0)); 437 438 ASSERT_THAT(setsockopt(connected_fd.get(), SOL_SOCKET, SO_REUSEADDR, 439 &kSockOptOn, sizeof(kSockOptOn)), 440 SyscallSucceeds()); 441 442 ASSERT_THAT(RetryEINTR(connect)(connected_fd.get(), AsSockAddr(&bound_addr), 443 bound_addr_len), 444 SyscallSucceeds()); 445 446 // Get the ephemeral port. 447 sockaddr_storage connected_addr = {}; 448 socklen_t connected_addr_len = sizeof(connected_addr); 449 ASSERT_THAT(getsockname(connected_fd.get(), AsSockAddr(&connected_addr), 450 &connected_addr_len), 451 SyscallSucceeds()); 452 uint16_t const ephemeral_port = 453 ASSERT_NO_ERRNO_AND_VALUE(AddrPort(test_addr.family(), connected_addr)); 454 455 // Verify that we actually got an ephemeral port. 456 ASSERT_NE(ephemeral_port, 0); 457 458 // Verify that the ephemeral port is not reserved. 459 const FileDescriptor checking_fd = 460 ASSERT_NO_ERRNO_AND_VALUE(Socket(test_addr.family(), param.type, 0)); 461 ASSERT_THAT(setsockopt(checking_fd.get(), SOL_SOCKET, SO_REUSEADDR, 462 &kSockOptOn, sizeof(kSockOptOn)), 463 SyscallSucceeds()); 464 EXPECT_THAT( 465 bind(checking_fd.get(), AsSockAddr(&connected_addr), connected_addr_len), 466 SyscallSucceeds()); 467 } 468 469 TEST_P(SocketMultiProtocolInetLoopbackIsolatedTest, 470 V4MappedEphemeralPortReservedReuseAddr) { 471 ProtocolTestParam const& param = GetParam(); 472 473 // Bind the v4 loopback on a dual stack socket. 474 TestAddress const& test_addr = V4MappedLoopback(); 475 sockaddr_storage bound_addr = test_addr.addr; 476 const FileDescriptor bound_fd = 477 ASSERT_NO_ERRNO_AND_VALUE(Socket(test_addr.family(), param.type, 0)); 478 ASSERT_THAT(bind(bound_fd.get(), AsSockAddr(&bound_addr), test_addr.addr_len), 479 SyscallSucceeds()); 480 481 ASSERT_THAT(setsockopt(bound_fd.get(), SOL_SOCKET, SO_REUSEADDR, &kSockOptOn, 482 sizeof(kSockOptOn)), 483 SyscallSucceeds()); 484 485 // Listen iff TCP. 486 if (param.type == SOCK_STREAM) { 487 ASSERT_THAT(listen(bound_fd.get(), SOMAXCONN), SyscallSucceeds()); 488 } 489 490 // Get the port that we bound. 491 socklen_t bound_addr_len = test_addr.addr_len; 492 ASSERT_THAT( 493 getsockname(bound_fd.get(), AsSockAddr(&bound_addr), &bound_addr_len), 494 SyscallSucceeds()); 495 496 // Connect to bind an ephemeral port. 497 const FileDescriptor connected_fd = 498 ASSERT_NO_ERRNO_AND_VALUE(Socket(test_addr.family(), param.type, 0)); 499 ASSERT_THAT(setsockopt(connected_fd.get(), SOL_SOCKET, SO_REUSEADDR, 500 &kSockOptOn, sizeof(kSockOptOn)), 501 SyscallSucceeds()); 502 ASSERT_THAT(RetryEINTR(connect)(connected_fd.get(), AsSockAddr(&bound_addr), 503 bound_addr_len), 504 SyscallSucceeds()); 505 506 // Get the ephemeral port. 507 sockaddr_storage connected_addr = {}; 508 socklen_t connected_addr_len = sizeof(connected_addr); 509 ASSERT_THAT(getsockname(connected_fd.get(), AsSockAddr(&connected_addr), 510 &connected_addr_len), 511 SyscallSucceeds()); 512 uint16_t const ephemeral_port = 513 ASSERT_NO_ERRNO_AND_VALUE(AddrPort(test_addr.family(), connected_addr)); 514 515 // Verify that we actually got an ephemeral port. 516 ASSERT_NE(ephemeral_port, 0); 517 518 // Verify that the ephemeral port is not reserved. 519 const FileDescriptor checking_fd = 520 ASSERT_NO_ERRNO_AND_VALUE(Socket(test_addr.family(), param.type, 0)); 521 ASSERT_THAT(setsockopt(checking_fd.get(), SOL_SOCKET, SO_REUSEADDR, 522 &kSockOptOn, sizeof(kSockOptOn)), 523 SyscallSucceeds()); 524 EXPECT_THAT( 525 bind(checking_fd.get(), AsSockAddr(&connected_addr), connected_addr_len), 526 SyscallSucceeds()); 527 } 528 529 TEST_P(SocketMultiProtocolInetLoopbackIsolatedTest, 530 V6EphemeralPortReservedReuseAddr) { 531 ProtocolTestParam const& param = GetParam(); 532 533 // Bind the v6 loopback on a dual stack socket. 534 TestAddress const& test_addr = V6Loopback(); 535 sockaddr_storage bound_addr = test_addr.addr; 536 const FileDescriptor bound_fd = 537 ASSERT_NO_ERRNO_AND_VALUE(Socket(test_addr.family(), param.type, 0)); 538 ASSERT_THAT(bind(bound_fd.get(), AsSockAddr(&bound_addr), test_addr.addr_len), 539 SyscallSucceeds()); 540 ASSERT_THAT(setsockopt(bound_fd.get(), SOL_SOCKET, SO_REUSEADDR, &kSockOptOn, 541 sizeof(kSockOptOn)), 542 SyscallSucceeds()); 543 544 // Listen iff TCP. 545 if (param.type == SOCK_STREAM) { 546 ASSERT_THAT(listen(bound_fd.get(), SOMAXCONN), SyscallSucceeds()); 547 } 548 549 // Get the port that we bound. 550 socklen_t bound_addr_len = test_addr.addr_len; 551 ASSERT_THAT( 552 getsockname(bound_fd.get(), AsSockAddr(&bound_addr), &bound_addr_len), 553 SyscallSucceeds()); 554 555 // Connect to bind an ephemeral port. 556 const FileDescriptor connected_fd = 557 ASSERT_NO_ERRNO_AND_VALUE(Socket(test_addr.family(), param.type, 0)); 558 ASSERT_THAT(setsockopt(connected_fd.get(), SOL_SOCKET, SO_REUSEADDR, 559 &kSockOptOn, sizeof(kSockOptOn)), 560 SyscallSucceeds()); 561 ASSERT_THAT(RetryEINTR(connect)(connected_fd.get(), AsSockAddr(&bound_addr), 562 bound_addr_len), 563 SyscallSucceeds()); 564 565 // Get the ephemeral port. 566 sockaddr_storage connected_addr = {}; 567 socklen_t connected_addr_len = sizeof(connected_addr); 568 ASSERT_THAT(getsockname(connected_fd.get(), AsSockAddr(&connected_addr), 569 &connected_addr_len), 570 SyscallSucceeds()); 571 uint16_t const ephemeral_port = 572 ASSERT_NO_ERRNO_AND_VALUE(AddrPort(test_addr.family(), connected_addr)); 573 574 // Verify that we actually got an ephemeral port. 575 ASSERT_NE(ephemeral_port, 0); 576 577 // Verify that the ephemeral port is not reserved. 578 const FileDescriptor checking_fd = 579 ASSERT_NO_ERRNO_AND_VALUE(Socket(test_addr.family(), param.type, 0)); 580 ASSERT_THAT(setsockopt(checking_fd.get(), SOL_SOCKET, SO_REUSEADDR, 581 &kSockOptOn, sizeof(kSockOptOn)), 582 SyscallSucceeds()); 583 EXPECT_THAT( 584 bind(checking_fd.get(), AsSockAddr(&connected_addr), connected_addr_len), 585 SyscallSucceeds()); 586 } 587 588 INSTANTIATE_TEST_SUITE_P(AllFamilies, 589 SocketMultiProtocolInetLoopbackIsolatedTest, 590 ProtocolTestValues(), DescribeProtocolTestParam); 591 592 } // namespace 593 594 } // namespace testing 595 } // namespace gvisor