diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/syscalls/linux/packet_socket_raw.cc | 52 | ||||
-rw-r--r-- | test/syscalls/linux/socket_test_util.cc | 13 | ||||
-rw-r--r-- | test/syscalls/linux/socket_test_util.h | 7 |
3 files changed, 71 insertions, 1 deletions
diff --git a/test/syscalls/linux/packet_socket_raw.cc b/test/syscalls/linux/packet_socket_raw.cc index a7c46adbf..2ed4f6f9c 100644 --- a/test/syscalls/linux/packet_socket_raw.cc +++ b/test/syscalls/linux/packet_socket_raw.cc @@ -678,6 +678,58 @@ TEST_P(RawPacketTest, GetSocketAcceptConn) { INSTANTIATE_TEST_SUITE_P(AllInetTests, RawPacketTest, ::testing::Values(ETH_P_IP, ETH_P_ALL)); +class RawPacketMsgSizeTest : public ::testing::TestWithParam<TestAddress> {}; + +TEST_P(RawPacketMsgSizeTest, SendTooLong) { + SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW))); + + TestAddress addr = GetParam().WithPort(kPort); + + FileDescriptor udp_sock = + ASSERT_NO_ERRNO_AND_VALUE(Socket(addr.family(), SOCK_RAW, IPPROTO_UDP)); + + ASSERT_THAT( + connect(udp_sock.get(), reinterpret_cast<struct sockaddr*>(&addr.addr), + addr.addr_len), + SyscallSucceeds()); + + const char buf[65536] = {}; + ASSERT_THAT(send(udp_sock.get(), buf, sizeof(buf), 0), + SyscallFailsWithErrno(EMSGSIZE)); +} + +TEST_P(RawPacketMsgSizeTest, SpliceTooLong) { + SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW))); + + const char buf[65536] = {}; + int fds[2]; + ASSERT_THAT(pipe(fds), SyscallSucceeds()); + ASSERT_THAT(write(fds[1], buf, sizeof(buf)), + SyscallSucceedsWithValue(sizeof(buf))); + + TestAddress addr = GetParam().WithPort(kPort); + + FileDescriptor udp_sock = + ASSERT_NO_ERRNO_AND_VALUE(Socket(addr.family(), SOCK_RAW, IPPROTO_UDP)); + + ASSERT_THAT( + connect(udp_sock.get(), reinterpret_cast<struct sockaddr*>(&addr.addr), + addr.addr_len), + SyscallSucceeds()); + + ssize_t n = splice(fds[0], nullptr, udp_sock.get(), nullptr, sizeof(buf), 0); + if (IsRunningOnGvisor()) { + EXPECT_THAT(n, SyscallFailsWithErrno(EMSGSIZE)); + } else { + // TODO(gvisor.dev/issue/138): Linux sends out multiple UDP datagrams, each + // of the size of a page. + EXPECT_THAT(n, SyscallSucceedsWithValue(sizeof(buf))); + } +} + +INSTANTIATE_TEST_SUITE_P(AllRawPacketMsgSizeTest, RawPacketMsgSizeTest, + ::testing::Values(V4Loopback(), V6Loopback())); + } // namespace } // namespace testing diff --git a/test/syscalls/linux/socket_test_util.cc b/test/syscalls/linux/socket_test_util.cc index 26dacc95e..b2a96086c 100644 --- a/test/syscalls/linux/socket_test_util.cc +++ b/test/syscalls/linux/socket_test_util.cc @@ -791,6 +791,19 @@ void RecvNoData(int sock) { SyscallFailsWithErrno(EAGAIN)); } +TestAddress TestAddress::WithPort(uint16_t port) const { + TestAddress addr = *this; + switch (addr.family()) { + case AF_INET: + reinterpret_cast<sockaddr_in*>(&addr.addr)->sin_port = htons(port); + break; + case AF_INET6: + reinterpret_cast<sockaddr_in6*>(&addr.addr)->sin6_port = htons(port); + break; + } + return addr; +} + TestAddress V4Any() { TestAddress t("V4Any"); t.addr.ss_family = AF_INET; diff --git a/test/syscalls/linux/socket_test_util.h b/test/syscalls/linux/socket_test_util.h index 75c0d4735..b3ab286b8 100644 --- a/test/syscalls/linux/socket_test_util.h +++ b/test/syscalls/linux/socket_test_util.h @@ -486,9 +486,14 @@ struct TestAddress { sockaddr_storage addr; socklen_t addr_len; - int family() const { return addr.ss_family; } explicit TestAddress(std::string description = "") : description(std::move(description)), addr(), addr_len() {} + + int family() const { return addr.ss_family; } + + // Returns a new TestAddress with specified port. If port is not supported, + // the same TestAddress is returned. + TestAddress WithPort(uint16_t port) const; }; constexpr char kMulticastAddress[] = "224.0.2.1"; |