summaryrefslogtreecommitdiffhomepage
path: root/test/syscalls
diff options
context:
space:
mode:
authorGhanan Gowripalan <ghanan@google.com>2021-09-14 18:35:55 -0700
committergVisor bot <gvisor-bot@google.com>2021-09-14 18:38:46 -0700
commit0bec34a8e29e1099827a025009e08aa190ff4441 (patch)
tree6e87a5813e8e55b6d171914f65c9931e2ed43104 /test/syscalls
parent39470428dd3c5fef966cee138ae00ab8b9059983 (diff)
Compose raw IP with datagram-based endpoint
A raw IP endpoint's write and socket option get/set path can use the datagram-based endpoint. This change extracts tests from UDP that may also run on Raw IP sockets. Updates #6565. Test: Raw IP + datagram-based socket syscall tests. PiperOrigin-RevId: 396729727
Diffstat (limited to 'test/syscalls')
-rw-r--r--test/syscalls/BUILD5
-rw-r--r--test/syscalls/linux/BUILD38
-rw-r--r--test/syscalls/linux/ip_socket_test_util.cc8
-rw-r--r--test/syscalls/linux/ip_socket_test_util.h4
-rw-r--r--test/syscalls/linux/socket_ipv4_datagram_based_socket_unbound.cc299
-rw-r--r--test/syscalls/linux/socket_ipv4_datagram_based_socket_unbound.h31
-rw-r--r--test/syscalls/linux/socket_ipv4_datagram_based_socket_unbound_loopback.cc28
-rw-r--r--test/syscalls/linux/socket_ipv4_udp_unbound.cc272
-rw-r--r--test/syscalls/linux/socket_ipv4_udp_unbound_loopback.cc4
9 files changed, 408 insertions, 281 deletions
diff --git a/test/syscalls/BUILD b/test/syscalls/BUILD
index 16c451786..3b55112e6 100644
--- a/test/syscalls/BUILD
+++ b/test/syscalls/BUILD
@@ -707,6 +707,11 @@ syscall_test(
syscall_test(
size = "medium",
+ test = "//test/syscalls/linux:socket_ipv4_datagram_based_socket_unbound_loopback_test",
+)
+
+syscall_test(
+ size = "medium",
test = "//test/syscalls/linux:socket_ipv4_udp_unbound_loopback_test",
)
diff --git a/test/syscalls/linux/BUILD b/test/syscalls/linux/BUILD
index 190135d6c..a4efd9486 100644
--- a/test/syscalls/linux/BUILD
+++ b/test/syscalls/linux/BUILD
@@ -26,6 +26,7 @@ exports_files(
"socket_ip_udp_loopback_blocking.cc",
"socket_ip_udp_loopback_nonblock.cc",
"socket_ip_unbound.cc",
+ "socket_ipv4_datagram_based_socket_unbound_loopback.cc",
"socket_ipv4_udp_unbound_external_networking_test.cc",
"socket_ipv6_udp_unbound_external_networking_test.cc",
"socket_ipv4_udp_unbound_loopback.cc",
@@ -2534,6 +2535,24 @@ cc_library(
)
cc_library(
+ name = "socket_ipv4_datagram_based_socket_unbound_test_cases",
+ testonly = 1,
+ srcs = [
+ "socket_ipv4_datagram_based_socket_unbound.cc",
+ ],
+ hdrs = [
+ "socket_ipv4_datagram_based_socket_unbound.h",
+ ],
+ deps = [
+ ":ip_socket_test_util",
+ "//test/util:capability_util",
+ "//test/util:socket_util",
+ gtest,
+ ],
+ alwayslink = 1,
+)
+
+cc_library(
name = "socket_ipv4_udp_unbound_test_cases",
testonly = 1,
srcs = [
@@ -2547,9 +2566,6 @@ cc_library(
"//test/util:socket_util",
"@com_google_absl//absl/memory",
gtest,
- "//test/util:posix_error",
- "//test/util:save_util",
- "//test/util:test_util",
],
alwayslink = 1,
)
@@ -2956,9 +2972,21 @@ cc_binary(
deps = [
":ip_socket_test_util",
":socket_ipv4_udp_unbound_test_cases",
- "//test/util:socket_util",
"//test/util:test_main",
- "//test/util:test_util",
+ ],
+)
+
+cc_binary(
+ name = "socket_ipv4_datagram_based_socket_unbound_loopback_test",
+ testonly = 1,
+ srcs = [
+ "socket_ipv4_datagram_based_socket_unbound_loopback.cc",
+ ],
+ linkstatic = 1,
+ deps = [
+ ":ip_socket_test_util",
+ ":socket_ipv4_datagram_based_socket_unbound_test_cases",
+ "//test/util:test_main",
],
)
diff --git a/test/syscalls/linux/ip_socket_test_util.cc b/test/syscalls/linux/ip_socket_test_util.cc
index e90a7e411..a1216d23f 100644
--- a/test/syscalls/linux/ip_socket_test_util.cc
+++ b/test/syscalls/linux/ip_socket_test_util.cc
@@ -156,6 +156,14 @@ SocketKind ICMPv6UnboundSocket(int type) {
UnboundSocketCreator(AF_INET6, type | SOCK_DGRAM, IPPROTO_ICMPV6)};
}
+SocketKind IPv4RawUDPUnboundSocket(int type) {
+ std::string description =
+ absl::StrCat(DescribeSocketType(type), "IPv4 Raw UDP socket");
+ return SocketKind{
+ description, AF_INET, type | SOCK_RAW, IPPROTO_UDP,
+ UnboundSocketCreator(AF_INET, type | SOCK_RAW, IPPROTO_UDP)};
+}
+
SocketKind IPv4UDPUnboundSocket(int type) {
std::string description =
absl::StrCat(DescribeSocketType(type), "IPv4 UDP socket");
diff --git a/test/syscalls/linux/ip_socket_test_util.h b/test/syscalls/linux/ip_socket_test_util.h
index 930e26ca5..556838356 100644
--- a/test/syscalls/linux/ip_socket_test_util.h
+++ b/test/syscalls/linux/ip_socket_test_util.h
@@ -95,6 +95,10 @@ SocketKind ICMPUnboundSocket(int type);
// created with AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6, and the given type.
SocketKind ICMPv6UnboundSocket(int type);
+// IPv4RawUDPUnboundSocket returns a SocketKind that represents a SimpleSocket
+// created with AF_INET, SOCK_RAW, IPPROTO_UDP, and the given type.
+SocketKind IPv4RawUDPUnboundSocket(int type);
+
// IPv4UDPUnboundSocket returns a SocketKind that represents a SimpleSocket
// created with AF_INET, SOCK_DGRAM, IPPROTO_UDP, and the given type.
SocketKind IPv4UDPUnboundSocket(int type);
diff --git a/test/syscalls/linux/socket_ipv4_datagram_based_socket_unbound.cc b/test/syscalls/linux/socket_ipv4_datagram_based_socket_unbound.cc
new file mode 100644
index 000000000..0e3e7057b
--- /dev/null
+++ b/test/syscalls/linux/socket_ipv4_datagram_based_socket_unbound.cc
@@ -0,0 +1,299 @@
+// Copyright 2019 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "test/syscalls/linux/socket_ipv4_datagram_based_socket_unbound.h"
+
+#include "gtest/gtest.h"
+#include "test/syscalls/linux/ip_socket_test_util.h"
+#include "test/util/capability_util.h"
+
+namespace gvisor {
+namespace testing {
+
+void IPv4DatagramBasedUnboundSocketTest::SetUp() {
+ if (GetParam().type & SOCK_RAW) {
+ SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveRawIPSocketCapability()));
+ }
+}
+
+// Check that dropping a group membership that does not exist fails.
+TEST_P(IPv4DatagramBasedUnboundSocketTest, IpMulticastInvalidDrop) {
+ auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+ auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+
+ // Unregister from a membership that we didn't have.
+ ip_mreq group = {};
+ group.imr_multiaddr.s_addr = inet_addr(kMulticastAddress);
+ group.imr_interface.s_addr = htonl(INADDR_LOOPBACK);
+ EXPECT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_DROP_MEMBERSHIP, &group,
+ sizeof(group)),
+ SyscallFailsWithErrno(EADDRNOTAVAIL));
+}
+
+TEST_P(IPv4DatagramBasedUnboundSocketTest, IpMulticastIfZero) {
+ auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+ auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+
+ ip_mreqn iface = {};
+ EXPECT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &iface,
+ sizeof(iface)),
+ SyscallSucceeds());
+}
+
+TEST_P(IPv4DatagramBasedUnboundSocketTest, IpMulticastIfInvalidNic) {
+ auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+ auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+
+ ip_mreqn iface = {};
+ iface.imr_ifindex = -1;
+ EXPECT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &iface,
+ sizeof(iface)),
+ SyscallFailsWithErrno(EADDRNOTAVAIL));
+}
+
+TEST_P(IPv4DatagramBasedUnboundSocketTest, IpMulticastIfInvalidAddr) {
+ auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+ auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+
+ ip_mreq iface = {};
+ iface.imr_interface.s_addr = inet_addr("255.255.255");
+ EXPECT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &iface,
+ sizeof(iface)),
+ SyscallFailsWithErrno(EADDRNOTAVAIL));
+}
+
+TEST_P(IPv4DatagramBasedUnboundSocketTest, IpMulticastIfSetShort) {
+ auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+ auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+
+ // Create a valid full-sized request.
+ ip_mreqn iface = {};
+ iface.imr_ifindex = ASSERT_NO_ERRNO_AND_VALUE(GetLoopbackIndex());
+
+ // Send an optlen of 1 to check that optlen is enforced.
+ EXPECT_THAT(
+ setsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &iface, 1),
+ SyscallFailsWithErrno(EINVAL));
+}
+
+TEST_P(IPv4DatagramBasedUnboundSocketTest, IpMulticastIfDefault) {
+ auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+ auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+
+ in_addr get = {};
+ socklen_t size = sizeof(get);
+ ASSERT_THAT(
+ getsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &get, &size),
+ SyscallSucceeds());
+ EXPECT_EQ(size, sizeof(get));
+ EXPECT_EQ(get.s_addr, 0);
+}
+
+TEST_P(IPv4DatagramBasedUnboundSocketTest, IpMulticastIfDefaultReqn) {
+ auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+ auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+
+ ip_mreqn get = {};
+ socklen_t size = sizeof(get);
+ ASSERT_THAT(
+ getsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &get, &size),
+ SyscallSucceeds());
+
+ // getsockopt(IP_MULTICAST_IF) can only return an in_addr, so it treats the
+ // first sizeof(struct in_addr) bytes of struct ip_mreqn as a struct in_addr.
+ // Conveniently, this corresponds to the field ip_mreqn::imr_multiaddr.
+ EXPECT_EQ(size, sizeof(in_addr));
+
+ // getsockopt(IP_MULTICAST_IF) will only return the interface address which
+ // hasn't been set.
+ EXPECT_EQ(get.imr_multiaddr.s_addr, 0);
+ EXPECT_EQ(get.imr_address.s_addr, 0);
+ EXPECT_EQ(get.imr_ifindex, 0);
+}
+
+TEST_P(IPv4DatagramBasedUnboundSocketTest, IpMulticastIfSetAddrGetReqn) {
+ auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+ auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+
+ in_addr set = {};
+ set.s_addr = htonl(INADDR_LOOPBACK);
+ ASSERT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &set,
+ sizeof(set)),
+ SyscallSucceeds());
+
+ ip_mreqn get = {};
+ socklen_t size = sizeof(get);
+ ASSERT_THAT(
+ getsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &get, &size),
+ SyscallSucceeds());
+
+ // getsockopt(IP_MULTICAST_IF) can only return an in_addr, so it treats the
+ // first sizeof(struct in_addr) bytes of struct ip_mreqn as a struct in_addr.
+ // Conveniently, this corresponds to the field ip_mreqn::imr_multiaddr.
+ EXPECT_EQ(size, sizeof(in_addr));
+ EXPECT_EQ(get.imr_multiaddr.s_addr, set.s_addr);
+ EXPECT_EQ(get.imr_address.s_addr, 0);
+ EXPECT_EQ(get.imr_ifindex, 0);
+}
+
+TEST_P(IPv4DatagramBasedUnboundSocketTest, IpMulticastIfSetReqAddrGetReqn) {
+ auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+ auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+
+ ip_mreq set = {};
+ set.imr_interface.s_addr = htonl(INADDR_LOOPBACK);
+ ASSERT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &set,
+ sizeof(set)),
+ SyscallSucceeds());
+
+ ip_mreqn get = {};
+ socklen_t size = sizeof(get);
+ ASSERT_THAT(
+ getsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &get, &size),
+ SyscallSucceeds());
+
+ // getsockopt(IP_MULTICAST_IF) can only return an in_addr, so it treats the
+ // first sizeof(struct in_addr) bytes of struct ip_mreqn as a struct in_addr.
+ // Conveniently, this corresponds to the field ip_mreqn::imr_multiaddr.
+ EXPECT_EQ(size, sizeof(in_addr));
+ EXPECT_EQ(get.imr_multiaddr.s_addr, set.imr_interface.s_addr);
+ EXPECT_EQ(get.imr_address.s_addr, 0);
+ EXPECT_EQ(get.imr_ifindex, 0);
+}
+
+TEST_P(IPv4DatagramBasedUnboundSocketTest, IpMulticastIfSetNicGetReqn) {
+ auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+ auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+
+ ip_mreqn set = {};
+ set.imr_ifindex = ASSERT_NO_ERRNO_AND_VALUE(GetLoopbackIndex());
+ ASSERT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &set,
+ sizeof(set)),
+ SyscallSucceeds());
+
+ ip_mreqn get = {};
+ socklen_t size = sizeof(get);
+ ASSERT_THAT(
+ getsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &get, &size),
+ SyscallSucceeds());
+ EXPECT_EQ(size, sizeof(in_addr));
+ EXPECT_EQ(get.imr_multiaddr.s_addr, 0);
+ EXPECT_EQ(get.imr_address.s_addr, 0);
+ EXPECT_EQ(get.imr_ifindex, 0);
+}
+
+TEST_P(IPv4DatagramBasedUnboundSocketTest, IpMulticastIfSetAddr) {
+ auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+ auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+
+ in_addr set = {};
+ set.s_addr = htonl(INADDR_LOOPBACK);
+ ASSERT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &set,
+ sizeof(set)),
+ SyscallSucceeds());
+
+ in_addr get = {};
+ socklen_t size = sizeof(get);
+ ASSERT_THAT(
+ getsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &get, &size),
+ SyscallSucceeds());
+
+ EXPECT_EQ(size, sizeof(get));
+ EXPECT_EQ(get.s_addr, set.s_addr);
+}
+
+TEST_P(IPv4DatagramBasedUnboundSocketTest, IpMulticastIfSetReqAddr) {
+ auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+ auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+
+ ip_mreq set = {};
+ set.imr_interface.s_addr = htonl(INADDR_LOOPBACK);
+ ASSERT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &set,
+ sizeof(set)),
+ SyscallSucceeds());
+
+ in_addr get = {};
+ socklen_t size = sizeof(get);
+ ASSERT_THAT(
+ getsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &get, &size),
+ SyscallSucceeds());
+
+ EXPECT_EQ(size, sizeof(get));
+ EXPECT_EQ(get.s_addr, set.imr_interface.s_addr);
+}
+
+TEST_P(IPv4DatagramBasedUnboundSocketTest, IpMulticastIfSetNic) {
+ auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+ auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+
+ ip_mreqn set = {};
+ set.imr_ifindex = ASSERT_NO_ERRNO_AND_VALUE(GetLoopbackIndex());
+ ASSERT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &set,
+ sizeof(set)),
+ SyscallSucceeds());
+
+ in_addr get = {};
+ socklen_t size = sizeof(get);
+ ASSERT_THAT(
+ getsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &get, &size),
+ SyscallSucceeds());
+ EXPECT_EQ(size, sizeof(get));
+ EXPECT_EQ(get.s_addr, 0);
+}
+
+TEST_P(IPv4DatagramBasedUnboundSocketTest, TestJoinGroupNoIf) {
+ // TODO(b/185517803): Fix for native test.
+ SKIP_IF(!IsRunningOnGvisor());
+ auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+ auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+
+ ip_mreqn group = {};
+ group.imr_multiaddr.s_addr = inet_addr(kMulticastAddress);
+ EXPECT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_ADD_MEMBERSHIP, &group,
+ sizeof(group)),
+ SyscallFailsWithErrno(ENODEV));
+}
+
+TEST_P(IPv4DatagramBasedUnboundSocketTest, TestJoinGroupInvalidIf) {
+ auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+ auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+
+ ip_mreqn group = {};
+ group.imr_address.s_addr = inet_addr("255.255.255");
+ group.imr_multiaddr.s_addr = inet_addr(kMulticastAddress);
+ EXPECT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_ADD_MEMBERSHIP, &group,
+ sizeof(group)),
+ SyscallFailsWithErrno(ENODEV));
+}
+
+// Check that multiple memberships are not allowed on the same socket.
+TEST_P(IPv4DatagramBasedUnboundSocketTest, TestMultipleJoinsOnSingleSocket) {
+ auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+ auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
+ auto fd = socket1->get();
+ ip_mreqn group = {};
+ group.imr_multiaddr.s_addr = inet_addr(kMulticastAddress);
+ group.imr_ifindex = ASSERT_NO_ERRNO_AND_VALUE(GetLoopbackIndex());
+
+ EXPECT_THAT(
+ setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &group, sizeof(group)),
+ SyscallSucceeds());
+
+ EXPECT_THAT(
+ setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &group, sizeof(group)),
+ SyscallFailsWithErrno(EADDRINUSE));
+}
+
+} // namespace testing
+} // namespace gvisor
diff --git a/test/syscalls/linux/socket_ipv4_datagram_based_socket_unbound.h b/test/syscalls/linux/socket_ipv4_datagram_based_socket_unbound.h
new file mode 100644
index 000000000..7ab235cad
--- /dev/null
+++ b/test/syscalls/linux/socket_ipv4_datagram_based_socket_unbound.h
@@ -0,0 +1,31 @@
+// Copyright 2019 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef GVISOR_TEST_SYSCALLS_LINUX_SOCKET_IPV4_DATAGRAM_BASED_SOCKET_UNBOUND_H_
+#define GVISOR_TEST_SYSCALLS_LINUX_SOCKET_IPV4_DATAGRAM_BASED_SOCKET_UNBOUND_H_
+
+#include "test/util/socket_util.h"
+
+namespace gvisor {
+namespace testing {
+
+// Test fixture for tests that apply to IPv4 datagram-based sockets.
+class IPv4DatagramBasedUnboundSocketTest : public SimpleSocketTest {
+ void SetUp() override;
+};
+
+} // namespace testing
+} // namespace gvisor
+
+#endif // GVISOR_TEST_SYSCALLS_LINUX_SOCKET_IPV4_DATAGRAM_BASED_SOCKET_UNBOUND_H_
diff --git a/test/syscalls/linux/socket_ipv4_datagram_based_socket_unbound_loopback.cc b/test/syscalls/linux/socket_ipv4_datagram_based_socket_unbound_loopback.cc
new file mode 100644
index 000000000..9ae68e015
--- /dev/null
+++ b/test/syscalls/linux/socket_ipv4_datagram_based_socket_unbound_loopback.cc
@@ -0,0 +1,28 @@
+// Copyright 2018 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "test/syscalls/linux/ip_socket_test_util.h"
+#include "test/syscalls/linux/socket_ipv4_datagram_based_socket_unbound.h"
+
+namespace gvisor {
+namespace testing {
+
+INSTANTIATE_TEST_SUITE_P(IPv4Sockets, IPv4DatagramBasedUnboundSocketTest,
+ ::testing::ValuesIn(ApplyVecToVec<SocketKind>(
+ {IPv4UDPUnboundSocket, IPv4RawUDPUnboundSocket},
+ AllBitwiseCombinations(List<int>{
+ 0, SOCK_NONBLOCK}))));
+
+} // namespace testing
+} // namespace gvisor
diff --git a/test/syscalls/linux/socket_ipv4_udp_unbound.cc b/test/syscalls/linux/socket_ipv4_udp_unbound.cc
index a4a793c86..05773a29c 100644
--- a/test/syscalls/linux/socket_ipv4_udp_unbound.cc
+++ b/test/syscalls/linux/socket_ipv4_udp_unbound.cc
@@ -24,10 +24,6 @@
#include "gtest/gtest.h"
#include "absl/memory/memory.h"
#include "test/syscalls/linux/ip_socket_test_util.h"
-#include "test/util/posix_error.h"
-#include "test/util/save_util.h"
-#include "test/util/socket_util.h"
-#include "test/util/test_util.h"
namespace gvisor {
namespace testing {
@@ -817,20 +813,6 @@ TEST_P(IPv4UDPUnboundSocketTest, IpMulticastLoopbackIfNicSelfNoLoop) {
EXPECT_EQ(0, memcmp(send_buf, recv_buf, sizeof(send_buf)));
}
-// Check that dropping a group membership that does not exist fails.
-TEST_P(IPv4UDPUnboundSocketTest, IpMulticastInvalidDrop) {
- auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
- auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
-
- // Unregister from a membership that we didn't have.
- ip_mreq group = {};
- group.imr_multiaddr.s_addr = inet_addr(kMulticastAddress);
- group.imr_interface.s_addr = htonl(INADDR_LOOPBACK);
- EXPECT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_DROP_MEMBERSHIP, &group,
- sizeof(group)),
- SyscallFailsWithErrno(EADDRNOTAVAIL));
-}
-
// Check that dropping a group membership prevents multicast packets from being
// delivered. Default send address configured by bind and group membership
// interface configured by address.
@@ -941,260 +923,6 @@ TEST_P(IPv4UDPUnboundSocketTest, IpMulticastDropNic) {
PosixErrorIs(EAGAIN, ::testing::_));
}
-TEST_P(IPv4UDPUnboundSocketTest, IpMulticastIfZero) {
- auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
- auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
-
- ip_mreqn iface = {};
- EXPECT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &iface,
- sizeof(iface)),
- SyscallSucceeds());
-}
-
-TEST_P(IPv4UDPUnboundSocketTest, IpMulticastIfInvalidNic) {
- auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
- auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
-
- ip_mreqn iface = {};
- iface.imr_ifindex = -1;
- EXPECT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &iface,
- sizeof(iface)),
- SyscallFailsWithErrno(EADDRNOTAVAIL));
-}
-
-TEST_P(IPv4UDPUnboundSocketTest, IpMulticastIfInvalidAddr) {
- auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
- auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
-
- ip_mreq iface = {};
- iface.imr_interface.s_addr = inet_addr("255.255.255");
- EXPECT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &iface,
- sizeof(iface)),
- SyscallFailsWithErrno(EADDRNOTAVAIL));
-}
-
-TEST_P(IPv4UDPUnboundSocketTest, IpMulticastIfSetShort) {
- auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
- auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
-
- // Create a valid full-sized request.
- ip_mreqn iface = {};
- iface.imr_ifindex = ASSERT_NO_ERRNO_AND_VALUE(GetLoopbackIndex());
-
- // Send an optlen of 1 to check that optlen is enforced.
- EXPECT_THAT(
- setsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &iface, 1),
- SyscallFailsWithErrno(EINVAL));
-}
-
-TEST_P(IPv4UDPUnboundSocketTest, IpMulticastIfDefault) {
- auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
- auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
-
- in_addr get = {};
- socklen_t size = sizeof(get);
- ASSERT_THAT(
- getsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &get, &size),
- SyscallSucceeds());
- EXPECT_EQ(size, sizeof(get));
- EXPECT_EQ(get.s_addr, 0);
-}
-
-TEST_P(IPv4UDPUnboundSocketTest, IpMulticastIfDefaultReqn) {
- auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
- auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
-
- ip_mreqn get = {};
- socklen_t size = sizeof(get);
- ASSERT_THAT(
- getsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &get, &size),
- SyscallSucceeds());
-
- // getsockopt(IP_MULTICAST_IF) can only return an in_addr, so it treats the
- // first sizeof(struct in_addr) bytes of struct ip_mreqn as a struct in_addr.
- // Conveniently, this corresponds to the field ip_mreqn::imr_multiaddr.
- EXPECT_EQ(size, sizeof(in_addr));
-
- // getsockopt(IP_MULTICAST_IF) will only return the interface address which
- // hasn't been set.
- EXPECT_EQ(get.imr_multiaddr.s_addr, 0);
- EXPECT_EQ(get.imr_address.s_addr, 0);
- EXPECT_EQ(get.imr_ifindex, 0);
-}
-
-TEST_P(IPv4UDPUnboundSocketTest, IpMulticastIfSetAddrGetReqn) {
- auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
- auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
-
- in_addr set = {};
- set.s_addr = htonl(INADDR_LOOPBACK);
- ASSERT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &set,
- sizeof(set)),
- SyscallSucceeds());
-
- ip_mreqn get = {};
- socklen_t size = sizeof(get);
- ASSERT_THAT(
- getsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &get, &size),
- SyscallSucceeds());
-
- // getsockopt(IP_MULTICAST_IF) can only return an in_addr, so it treats the
- // first sizeof(struct in_addr) bytes of struct ip_mreqn as a struct in_addr.
- // Conveniently, this corresponds to the field ip_mreqn::imr_multiaddr.
- EXPECT_EQ(size, sizeof(in_addr));
- EXPECT_EQ(get.imr_multiaddr.s_addr, set.s_addr);
- EXPECT_EQ(get.imr_address.s_addr, 0);
- EXPECT_EQ(get.imr_ifindex, 0);
-}
-
-TEST_P(IPv4UDPUnboundSocketTest, IpMulticastIfSetReqAddrGetReqn) {
- auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
- auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
-
- ip_mreq set = {};
- set.imr_interface.s_addr = htonl(INADDR_LOOPBACK);
- ASSERT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &set,
- sizeof(set)),
- SyscallSucceeds());
-
- ip_mreqn get = {};
- socklen_t size = sizeof(get);
- ASSERT_THAT(
- getsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &get, &size),
- SyscallSucceeds());
-
- // getsockopt(IP_MULTICAST_IF) can only return an in_addr, so it treats the
- // first sizeof(struct in_addr) bytes of struct ip_mreqn as a struct in_addr.
- // Conveniently, this corresponds to the field ip_mreqn::imr_multiaddr.
- EXPECT_EQ(size, sizeof(in_addr));
- EXPECT_EQ(get.imr_multiaddr.s_addr, set.imr_interface.s_addr);
- EXPECT_EQ(get.imr_address.s_addr, 0);
- EXPECT_EQ(get.imr_ifindex, 0);
-}
-
-TEST_P(IPv4UDPUnboundSocketTest, IpMulticastIfSetNicGetReqn) {
- auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
- auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
-
- ip_mreqn set = {};
- set.imr_ifindex = ASSERT_NO_ERRNO_AND_VALUE(GetLoopbackIndex());
- ASSERT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &set,
- sizeof(set)),
- SyscallSucceeds());
-
- ip_mreqn get = {};
- socklen_t size = sizeof(get);
- ASSERT_THAT(
- getsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &get, &size),
- SyscallSucceeds());
- EXPECT_EQ(size, sizeof(in_addr));
- EXPECT_EQ(get.imr_multiaddr.s_addr, 0);
- EXPECT_EQ(get.imr_address.s_addr, 0);
- EXPECT_EQ(get.imr_ifindex, 0);
-}
-
-TEST_P(IPv4UDPUnboundSocketTest, IpMulticastIfSetAddr) {
- auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
- auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
-
- in_addr set = {};
- set.s_addr = htonl(INADDR_LOOPBACK);
- ASSERT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &set,
- sizeof(set)),
- SyscallSucceeds());
-
- in_addr get = {};
- socklen_t size = sizeof(get);
- ASSERT_THAT(
- getsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &get, &size),
- SyscallSucceeds());
-
- EXPECT_EQ(size, sizeof(get));
- EXPECT_EQ(get.s_addr, set.s_addr);
-}
-
-TEST_P(IPv4UDPUnboundSocketTest, IpMulticastIfSetReqAddr) {
- auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
- auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
-
- ip_mreq set = {};
- set.imr_interface.s_addr = htonl(INADDR_LOOPBACK);
- ASSERT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &set,
- sizeof(set)),
- SyscallSucceeds());
-
- in_addr get = {};
- socklen_t size = sizeof(get);
- ASSERT_THAT(
- getsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &get, &size),
- SyscallSucceeds());
-
- EXPECT_EQ(size, sizeof(get));
- EXPECT_EQ(get.s_addr, set.imr_interface.s_addr);
-}
-
-TEST_P(IPv4UDPUnboundSocketTest, IpMulticastIfSetNic) {
- auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
- auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
-
- ip_mreqn set = {};
- set.imr_ifindex = ASSERT_NO_ERRNO_AND_VALUE(GetLoopbackIndex());
- ASSERT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &set,
- sizeof(set)),
- SyscallSucceeds());
-
- in_addr get = {};
- socklen_t size = sizeof(get);
- ASSERT_THAT(
- getsockopt(socket1->get(), IPPROTO_IP, IP_MULTICAST_IF, &get, &size),
- SyscallSucceeds());
- EXPECT_EQ(size, sizeof(get));
- EXPECT_EQ(get.s_addr, 0);
-}
-
-TEST_P(IPv4UDPUnboundSocketTest, TestJoinGroupNoIf) {
- // TODO(b/185517803): Fix for native test.
- SKIP_IF(!IsRunningOnGvisor());
- auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
- auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
-
- ip_mreqn group = {};
- group.imr_multiaddr.s_addr = inet_addr(kMulticastAddress);
- EXPECT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_ADD_MEMBERSHIP, &group,
- sizeof(group)),
- SyscallFailsWithErrno(ENODEV));
-}
-
-TEST_P(IPv4UDPUnboundSocketTest, TestJoinGroupInvalidIf) {
- auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
- auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
-
- ip_mreqn group = {};
- group.imr_address.s_addr = inet_addr("255.255.255");
- group.imr_multiaddr.s_addr = inet_addr(kMulticastAddress);
- EXPECT_THAT(setsockopt(socket1->get(), IPPROTO_IP, IP_ADD_MEMBERSHIP, &group,
- sizeof(group)),
- SyscallFailsWithErrno(ENODEV));
-}
-
-// Check that multiple memberships are not allowed on the same socket.
-TEST_P(IPv4UDPUnboundSocketTest, TestMultipleJoinsOnSingleSocket) {
- auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
- auto socket2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
- auto fd = socket1->get();
- ip_mreqn group = {};
- group.imr_multiaddr.s_addr = inet_addr(kMulticastAddress);
- group.imr_ifindex = ASSERT_NO_ERRNO_AND_VALUE(GetLoopbackIndex());
-
- EXPECT_THAT(
- setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &group, sizeof(group)),
- SyscallSucceeds());
-
- EXPECT_THAT(
- setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &group, sizeof(group)),
- SyscallFailsWithErrno(EADDRINUSE));
-}
-
// Check that two sockets can join the same multicast group at the same time.
TEST_P(IPv4UDPUnboundSocketTest, TestTwoSocketsJoinSameMulticastGroup) {
auto socket1 = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
diff --git a/test/syscalls/linux/socket_ipv4_udp_unbound_loopback.cc b/test/syscalls/linux/socket_ipv4_udp_unbound_loopback.cc
index 00930c544..bef284530 100644
--- a/test/syscalls/linux/socket_ipv4_udp_unbound_loopback.cc
+++ b/test/syscalls/linux/socket_ipv4_udp_unbound_loopback.cc
@@ -12,12 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include <vector>
-
#include "test/syscalls/linux/ip_socket_test_util.h"
#include "test/syscalls/linux/socket_ipv4_udp_unbound.h"
-#include "test/util/socket_util.h"
-#include "test/util/test_util.h"
namespace gvisor {
namespace testing {