gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/socket_bind_to_device_sequence.cc (about) 1 // Copyright 2019 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 <arpa/inet.h> 16 #include <linux/capability.h> 17 #include <linux/if_tun.h> 18 #include <net/if.h> 19 #include <netinet/in.h> 20 #include <sys/ioctl.h> 21 #include <sys/socket.h> 22 #include <sys/types.h> 23 #include <sys/un.h> 24 25 #include <cstdio> 26 #include <cstring> 27 #include <map> 28 #include <memory> 29 #include <unordered_map> 30 #include <unordered_set> 31 #include <utility> 32 #include <vector> 33 34 #include "gmock/gmock.h" 35 #include "gtest/gtest.h" 36 #include "absl/container/node_hash_map.h" 37 #include "test/syscalls/linux/ip_socket_test_util.h" 38 #include "test/syscalls/linux/socket_bind_to_device_util.h" 39 #include "test/util/capability_util.h" 40 #include "test/util/socket_util.h" 41 #include "test/util/test_util.h" 42 #include "test/util/thread_util.h" 43 44 namespace gvisor { 45 namespace testing { 46 47 using std::string; 48 using std::vector; 49 50 // Test fixture for SO_BINDTODEVICE tests the results of sequences of socket 51 // binding. 52 class BindToDeviceSequenceTest : public ::testing::TestWithParam<SocketKind> { 53 protected: 54 void SetUp() override { 55 printf("Testing case: %s\n", GetParam().description.c_str()); 56 ASSERT_TRUE(ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW))) 57 << "CAP_NET_RAW is required to use SO_BINDTODEVICE"; 58 socket_factory_ = GetParam(); 59 60 interface_names_ = GetInterfaceNames(); 61 } 62 63 PosixErrorOr<std::unique_ptr<FileDescriptor>> NewSocket() const { 64 return socket_factory_.Create(); 65 } 66 67 // Gets a device by device_id. If the device_id has been seen before, returns 68 // the previously returned device. If not, finds or creates a new device. 69 // Returns an empty string on failure. 70 void GetDevice(int device_id, string* device_name) { 71 auto device = devices_.find(device_id); 72 if (device != devices_.end()) { 73 *device_name = device->second; 74 return; 75 } 76 77 // Need to pick a new device. Try ethernet first. 78 *device_name = absl::StrCat("eth", next_unused_eth_); 79 if (interface_names_.find(*device_name) != interface_names_.end()) { 80 devices_[device_id] = *device_name; 81 next_unused_eth_++; 82 return; 83 } 84 85 // Need to make a new tunnel device. gVisor tests should have enough 86 // ethernet devices to never reach here. 87 ASSERT_FALSE(IsRunningOnGvisor()); 88 // Need a tunnel. 89 tunnels_.push_back(ASSERT_NO_ERRNO_AND_VALUE(Tunnel::New())); 90 devices_[device_id] = tunnels_.back()->GetName(); 91 *device_name = devices_[device_id]; 92 } 93 94 // Release the socket 95 void ReleaseSocket(int socket_id) { 96 // Close the socket that was made in a previous action. The socket_id 97 // indicates which socket to close based on index into the list of actions. 98 sockets_to_close_.erase(socket_id); 99 } 100 101 // SetDevice changes the bind_to_device option. It does not bind or re-bind. 102 void SetDevice(int socket_id, int device_id) { 103 auto socket_fd = sockets_to_close_[socket_id]->get(); 104 string device_name; 105 ASSERT_NO_FATAL_FAILURE(GetDevice(device_id, &device_name)); 106 EXPECT_THAT(setsockopt(socket_fd, SOL_SOCKET, SO_BINDTODEVICE, 107 device_name.c_str(), device_name.size() + 1), 108 SyscallSucceedsWithValue(0)); 109 } 110 111 // Bind a socket with the reuse options and bind_to_device options. Checks 112 // that all steps succeed and that the bind command's error matches want. 113 // Sets the socket_id to uniquely identify the socket bound if it is not 114 // nullptr. 115 void BindSocket(bool reuse_port, bool reuse_addr, int device_id = 0, 116 int want = 0, int* socket_id = nullptr) { 117 next_socket_id_++; 118 sockets_to_close_[next_socket_id_] = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 119 auto socket_fd = sockets_to_close_[next_socket_id_]->get(); 120 if (socket_id != nullptr) { 121 *socket_id = next_socket_id_; 122 } 123 124 // If reuse_port is indicated, do that. 125 if (reuse_port) { 126 EXPECT_THAT(setsockopt(socket_fd, SOL_SOCKET, SO_REUSEPORT, &kSockOptOn, 127 sizeof(kSockOptOn)), 128 SyscallSucceedsWithValue(0)); 129 } 130 131 // If reuse_addr is indicated, do that. 132 if (reuse_addr) { 133 EXPECT_THAT(setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &kSockOptOn, 134 sizeof(kSockOptOn)), 135 SyscallSucceedsWithValue(0)); 136 } 137 138 // If the device is non-zero, bind to that device. 139 if (device_id != 0) { 140 string device_name; 141 ASSERT_NO_FATAL_FAILURE(GetDevice(device_id, &device_name)); 142 EXPECT_THAT(setsockopt(socket_fd, SOL_SOCKET, SO_BINDTODEVICE, 143 device_name.c_str(), device_name.size() + 1), 144 SyscallSucceedsWithValue(0)); 145 char get_device[100]; 146 socklen_t get_device_size = 100; 147 EXPECT_THAT(getsockopt(socket_fd, SOL_SOCKET, SO_BINDTODEVICE, get_device, 148 &get_device_size), 149 SyscallSucceedsWithValue(0)); 150 } 151 152 struct sockaddr_in addr = {}; 153 addr.sin_family = AF_INET; 154 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 155 addr.sin_port = port_; 156 if (want == 0) { 157 ASSERT_THAT( 158 bind(socket_fd, reinterpret_cast<const struct sockaddr*>(&addr), 159 sizeof(addr)), 160 SyscallSucceeds()); 161 } else { 162 ASSERT_THAT( 163 bind(socket_fd, reinterpret_cast<const struct sockaddr*>(&addr), 164 sizeof(addr)), 165 SyscallFailsWithErrno(want)); 166 } 167 168 if (port_ == 0) { 169 // We don't yet know what port we'll be using so we need to fetch it and 170 // remember it for future commands. 171 socklen_t addr_size = sizeof(addr); 172 ASSERT_THAT( 173 getsockname(socket_fd, reinterpret_cast<struct sockaddr*>(&addr), 174 &addr_size), 175 SyscallSucceeds()); 176 port_ = addr.sin_port; 177 } 178 } 179 180 private: 181 SocketKind socket_factory_; 182 // devices maps from the device id in the test case to the name of the device. 183 absl::node_hash_map<int, string> devices_; 184 // These are the tunnels that were created for the test and will be destroyed 185 // by the destructor. 186 vector<std::unique_ptr<Tunnel>> tunnels_; 187 // A list of all interface names before the test started. 188 std::unordered_set<string> interface_names_; 189 // The next ethernet device to use when requested a device. 190 int next_unused_eth_ = 1; 191 // The port for all tests. Originally 0 (any) and later set to the port that 192 // all further commands will use. 193 in_port_t port_ = 0; 194 // sockets_to_close_ is a map from action index to the socket that was 195 // created. 196 absl::node_hash_map<int, 197 std::unique_ptr<gvisor::testing::FileDescriptor>> 198 sockets_to_close_; 199 int next_socket_id_ = 0; 200 }; 201 202 TEST_P(BindToDeviceSequenceTest, BindTwiceWithDeviceFails) { 203 ASSERT_NO_FATAL_FAILURE(BindSocket( 204 /* reuse_port */ false, /* reuse_addr */ false, /* bind_to_device */ 3)); 205 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 206 /* reuse_addr */ false, 207 /* bind_to_device */ 3, EADDRINUSE)); 208 } 209 210 TEST_P(BindToDeviceSequenceTest, BindToDevice) { 211 ASSERT_NO_FATAL_FAILURE(BindSocket( 212 /* reuse_port */ false, /* reuse_addr */ false, /* bind_to_device */ 1)); 213 ASSERT_NO_FATAL_FAILURE(BindSocket( 214 /* reuse_port */ false, /* reuse_addr */ false, /* bind_to_device */ 2)); 215 } 216 217 TEST_P(BindToDeviceSequenceTest, BindToDeviceAndThenWithoutDevice) { 218 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 219 /* reuse_addr */ false, 220 /* bind_to_device */ 123)); 221 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 222 /* reuse_addr */ false, 223 /* bind_to_device */ 0, EADDRINUSE)); 224 } 225 226 TEST_P(BindToDeviceSequenceTest, BindWithoutDevice) { 227 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 228 /* reuse_addr */ false)); 229 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 230 /* reuse_addr */ false, 231 /* bind_to_device */ 123, EADDRINUSE)); 232 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 233 /* reuse_addr */ false, 234 /* bind_to_device */ 123, EADDRINUSE)); 235 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 236 /* reuse_addr */ false, 237 /* bind_to_device */ 0, EADDRINUSE)); 238 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 239 /* reuse_addr */ false, 240 /* bind_to_device */ 0, EADDRINUSE)); 241 } 242 243 TEST_P(BindToDeviceSequenceTest, BindWithDevice) { 244 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 245 /* reuse_addr */ false, 246 /* bind_to_device */ 123, 0)); 247 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 248 /* reuse_addr */ false, 249 /* bind_to_device */ 123, EADDRINUSE)); 250 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 251 /* reuse_addr */ false, 252 /* bind_to_device */ 123, EADDRINUSE)); 253 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 254 /* reuse_addr */ false, 255 /* bind_to_device */ 0, EADDRINUSE)); 256 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 257 /* reuse_addr */ false, 258 /* bind_to_device */ 0, EADDRINUSE)); 259 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 260 /* reuse_addr */ false, 261 /* bind_to_device */ 456, 0)); 262 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 263 /* reuse_addr */ false, 264 /* bind_to_device */ 789, 0)); 265 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 266 /* reuse_addr */ false, 267 /* bind_to_device */ 0, EADDRINUSE)); 268 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 269 /* reuse_addr */ false, 270 /* bind_to_device */ 0, EADDRINUSE)); 271 } 272 273 TEST_P(BindToDeviceSequenceTest, BindWithReuse) { 274 ASSERT_NO_FATAL_FAILURE( 275 BindSocket(/* reusePort */ true, /* reuse_addr */ false)); 276 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 277 /* reuse_addr */ false, 278 /* bind_to_device */ 123, EADDRINUSE)); 279 ASSERT_NO_FATAL_FAILURE(BindSocket( 280 /* reuse_port */ true, /* reuse_addr */ false, 281 /* bind_to_device */ 123)); 282 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 283 /* reuse_addr */ false, 284 /* bind_to_device */ 0, EADDRINUSE)); 285 ASSERT_NO_FATAL_FAILURE(BindSocket( 286 /* reuse_port */ true, /* reuse_addr */ false, /* bind_to_device */ 0)); 287 } 288 289 TEST_P(BindToDeviceSequenceTest, BindingWithReuseAndDevice) { 290 ASSERT_NO_FATAL_FAILURE(BindSocket( 291 /* reuse_port */ true, /* reuse_addr */ false, /* bind_to_device */ 123)); 292 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 293 /* reuse_addr */ false, 294 /* bind_to_device */ 123, EADDRINUSE)); 295 ASSERT_NO_FATAL_FAILURE(BindSocket( 296 /* reuse_port */ true, /* reuse_addr */ false, /* bind_to_device */ 123)); 297 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 298 /* reuse_addr */ false, 299 /* bind_to_device */ 0, EADDRINUSE)); 300 ASSERT_NO_FATAL_FAILURE(BindSocket( 301 /* reuse_port */ true, /* reuse_addr */ false, /* bind_to_device */ 456)); 302 ASSERT_NO_FATAL_FAILURE( 303 BindSocket(/* reuse_port */ true, /* reuse_addr */ false)); 304 ASSERT_NO_FATAL_FAILURE(BindSocket( 305 /* reuse_port */ true, /* reuse_addr */ false, /* bind_to_device */ 789)); 306 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 307 /* reuse_addr */ false, 308 /* bind_to_device */ 999, EADDRINUSE)); 309 } 310 311 TEST_P(BindToDeviceSequenceTest, MixingReuseAndNotReuseByBindingToDevice) { 312 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 313 /* reuse_addr */ false, 314 /* bind_to_device */ 123, 0)); 315 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 316 /* reuse_addr */ false, 317 /* bind_to_device */ 456, 0)); 318 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 319 /* reuse_addr */ false, 320 /* bind_to_device */ 789, 0)); 321 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 322 /* reuse_addr */ false, 323 /* bind_to_device */ 999, 0)); 324 } 325 326 TEST_P(BindToDeviceSequenceTest, CannotBindTo0AfterMixingReuseAndNotReuse) { 327 ASSERT_NO_FATAL_FAILURE(BindSocket( 328 /* reuse_port */ true, /* reuse_addr */ false, /* bind_to_device */ 123)); 329 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 330 /* reuse_addr */ false, 331 /* bind_to_device */ 456)); 332 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 333 /* reuse_addr */ false, 334 /* bind_to_device */ 0, EADDRINUSE)); 335 } 336 337 TEST_P(BindToDeviceSequenceTest, BindAndRelease) { 338 ASSERT_NO_FATAL_FAILURE(BindSocket( 339 /* reuse_port */ true, /* reuse_addr */ false, /* bind_to_device */ 123)); 340 int to_release; 341 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 342 /* reuse_addr */ false, 343 /* bind_to_device */ 0, 0, &to_release)); 344 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 345 /* reuse_addr */ false, 346 /* bind_to_device */ 345, EADDRINUSE)); 347 ASSERT_NO_FATAL_FAILURE(BindSocket( 348 /* reuse_port */ true, /* reuse_addr */ false, /* bind_to_device */ 789)); 349 // Release the bind to device 0 and try again. 350 ASSERT_NO_FATAL_FAILURE(ReleaseSocket(to_release)); 351 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 352 /* reuse_addr */ false, 353 /* bind_to_device */ 345)); 354 } 355 356 TEST_P(BindToDeviceSequenceTest, BindTwiceWithReuseOnce) { 357 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 358 /* reuse_addr */ false, 359 /* bind_to_device */ 123)); 360 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 361 /* reuse_addr */ false, 362 /* bind_to_device */ 0, EADDRINUSE)); 363 } 364 365 TEST_P(BindToDeviceSequenceTest, BindWithReuseAddr) { 366 ASSERT_NO_FATAL_FAILURE( 367 BindSocket(/* reusePort */ false, /* reuse_addr */ true)); 368 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 369 /* reuse_addr */ false, 370 /* bind_to_device */ 123, EADDRINUSE)); 371 ASSERT_NO_FATAL_FAILURE(BindSocket( 372 /* reuse_port */ false, /* reuse_addr */ true, /* bind_to_device */ 123)); 373 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 374 /* reuse_addr */ false, 375 /* bind_to_device */ 0, EADDRINUSE)); 376 ASSERT_NO_FATAL_FAILURE(BindSocket( 377 /* reuse_port */ false, /* reuse_addr */ true, /* bind_to_device */ 0)); 378 } 379 380 TEST_P(BindToDeviceSequenceTest, 381 CannotBindTo0AfterMixingReuseAddrAndNotReuseAddr) { 382 ASSERT_NO_FATAL_FAILURE(BindSocket( 383 /* reuse_port */ true, /* reuse_addr */ false, /* bind_to_device */ 123)); 384 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 385 /* reuse_addr */ false, 386 /* bind_to_device */ 456)); 387 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 388 /* reuse_addr */ true, 389 /* bind_to_device */ 0, EADDRINUSE)); 390 } 391 392 TEST_P(BindToDeviceSequenceTest, BindReuseAddrReusePortThenReusePort) { 393 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 394 /* reuse_addr */ true, 395 /* bind_to_device */ 0)); 396 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 397 /* reuse_addr */ false, 398 /* bind_to_device */ 0)); 399 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 400 /* reuse_addr */ true, 401 /* bind_to_device */ 0, EADDRINUSE)); 402 } 403 404 TEST_P(BindToDeviceSequenceTest, BindReuseAddrReusePortThenReuseAddr) { 405 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 406 /* reuse_addr */ true, 407 /* bind_to_device */ 0)); 408 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 409 /* reuse_addr */ true, 410 /* bind_to_device */ 0)); 411 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 412 /* reuse_addr */ false, 413 /* bind_to_device */ 0, EADDRINUSE)); 414 } 415 416 TEST_P(BindToDeviceSequenceTest, BindDoubleReuseAddrReusePortThenReusePort) { 417 ASSERT_NO_FATAL_FAILURE(BindSocket( 418 /* reuse_port */ true, /* reuse_addr */ true, /* bind_to_device */ 0)); 419 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 420 /* reuse_addr */ true, 421 /* bind_to_device */ 0)); 422 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 423 /* reuse_addr */ false, 424 /* bind_to_device */ 0)); 425 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 426 /* reuse_addr */ true, 427 /* bind_to_device */ 0, EADDRINUSE)); 428 } 429 430 TEST_P(BindToDeviceSequenceTest, BindDoubleReuseAddrReusePortThenReuseAddr) { 431 ASSERT_NO_FATAL_FAILURE(BindSocket( 432 /* reuse_port */ true, /* reuse_addr */ true, /* bind_to_device */ 0)); 433 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 434 /* reuse_addr */ true, 435 /* bind_to_device */ 0)); 436 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 437 /* reuse_addr */ true, 438 /* bind_to_device */ 0)); 439 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 440 /* reuse_addr */ false, 441 /* bind_to_device */ 0, EADDRINUSE)); 442 } 443 444 TEST_P(BindToDeviceSequenceTest, BindReusePortThenReuseAddrReusePort) { 445 ASSERT_NO_FATAL_FAILURE(BindSocket( 446 /* reuse_port */ true, /* reuse_addr */ false, /* bind_to_device */ 0)); 447 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 448 /* reuse_addr */ true, 449 /* bind_to_device */ 0)); 450 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 451 /* reuse_addr */ true, 452 /* bind_to_device */ 0, EADDRINUSE)); 453 } 454 455 TEST_P(BindToDeviceSequenceTest, BindReuseAddrThenReuseAddr) { 456 ASSERT_NO_FATAL_FAILURE(BindSocket( 457 /* reuse_port */ false, /* reuse_addr */ true, /* bind_to_device */ 0)); 458 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 459 /* reuse_addr */ false, 460 /* bind_to_device */ 0, EADDRINUSE)); 461 } 462 463 TEST_P(BindToDeviceSequenceTest, 464 BindReuseAddrThenReuseAddrReusePortThenReuseAddr) { 465 // The behavior described in this test seems like a Linux bug. It doesn't 466 // make any sense and it is unlikely that any applications rely on it. 467 // 468 // Both SO_REUSEADDR and SO_REUSEPORT allow binding multiple UDP sockets to 469 // the same address and deliver each packet to exactly one of the bound 470 // sockets. If both are enabled, one of the strategies is selected to route 471 // packets. The strategy is selected dynamically based on the settings of the 472 // currently bound sockets. Usually, the strategy is selected based on the 473 // common setting (SO_REUSEADDR or SO_REUSEPORT) amongst the sockets, but for 474 // some reason, Linux allows binding sets of sockets with no overlapping 475 // settings in some situations. In this case, it is not obvious which strategy 476 // would be selected as the configured setting is a contradiction. 477 SKIP_IF(IsRunningOnGvisor()); 478 479 ASSERT_NO_FATAL_FAILURE(BindSocket( 480 /* reuse_port */ false, /* reuse_addr */ true, /* bind_to_device */ 0)); 481 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 482 /* reuse_addr */ true, 483 /* bind_to_device */ 0)); 484 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ true, 485 /* reuse_addr */ false, 486 /* bind_to_device */ 0)); 487 } 488 489 // Repro test for gvisor.dev/issue/1217. Not replicated in ports_test.go as this 490 // test is different from the others and wouldn't fit well there. 491 TEST_P(BindToDeviceSequenceTest, BindAndReleaseDifferentDevice) { 492 int to_release; 493 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 494 /* reuse_addr */ false, 495 /* bind_to_device */ 3, 0, &to_release)); 496 ASSERT_NO_FATAL_FAILURE(BindSocket(/* reuse_port */ false, 497 /* reuse_addr */ false, 498 /* bind_to_device */ 3, EADDRINUSE)); 499 // Change the device. Since the socket was already bound, this should have no 500 // effect. 501 SetDevice(to_release, 2); 502 // Release the bind to device 3 and try again. 503 ASSERT_NO_FATAL_FAILURE(ReleaseSocket(to_release)); 504 ASSERT_NO_FATAL_FAILURE(BindSocket( 505 /* reuse_port */ false, /* reuse_addr */ false, /* bind_to_device */ 3)); 506 } 507 508 INSTANTIATE_TEST_SUITE_P(BindToDeviceTest, BindToDeviceSequenceTest, 509 ::testing::Values(IPv4UDPUnboundSocket(0), 510 IPv4TCPUnboundSocket(0))); 511 512 } // namespace testing 513 } // namespace gvisor