diff options
author | Rahat Mahmood <rahat@google.com> | 2019-06-13 17:23:35 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2019-06-13 17:24:51 -0700 |
commit | 05ff1ffaadaa0ac370365eb14febc761506735ce (patch) | |
tree | e6505afe1536c60c7a2e362aa8355e01ec34f91a /test/syscalls/linux | |
parent | 7b0f068258146b4081060ae793ba6b73399f1452 (diff) |
Implement getsockopt() SO_DOMAIN, SO_PROTOCOL and SO_TYPE.
SO_TYPE was already implemented for everything but netlink sockets.
PiperOrigin-RevId: 253138157
Diffstat (limited to 'test/syscalls/linux')
-rw-r--r-- | test/syscalls/linux/BUILD | 2 | ||||
-rw-r--r-- | test/syscalls/linux/ip_socket_test_util.cc | 51 | ||||
-rw-r--r-- | test/syscalls/linux/socket_generic.cc | 50 | ||||
-rw-r--r-- | test/syscalls/linux/socket_netlink_route.cc | 45 | ||||
-rw-r--r-- | test/syscalls/linux/socket_test_util.cc | 7 | ||||
-rw-r--r-- | test/syscalls/linux/socket_test_util.h | 7 | ||||
-rw-r--r-- | test/syscalls/linux/unix_domain_socket_test_util.cc | 19 |
7 files changed, 143 insertions, 38 deletions
diff --git a/test/syscalls/linux/BUILD b/test/syscalls/linux/BUILD index 9bafc6e4f..2f6704842 100644 --- a/test/syscalls/linux/BUILD +++ b/test/syscalls/linux/BUILD @@ -1909,6 +1909,7 @@ cc_library( ":unix_domain_socket_test_util", "//test/util:test_util", "@com_google_absl//absl/strings", + "@com_google_absl//absl/strings:str_format", "@com_google_googletest//:gtest", ], alwayslink = 1, @@ -2427,6 +2428,7 @@ cc_binary( "//test/util:file_descriptor", "//test/util:test_main", "//test/util:test_util", + "@com_google_absl//absl/strings:str_format", "@com_google_googletest//:gtest", ], ) diff --git a/test/syscalls/linux/ip_socket_test_util.cc b/test/syscalls/linux/ip_socket_test_util.cc index 7612919d4..5fc4e9115 100644 --- a/test/syscalls/linux/ip_socket_test_util.cc +++ b/test/syscalls/linux/ip_socket_test_util.cc @@ -45,70 +45,79 @@ SocketPairKind IPv6TCPAcceptBindSocketPair(int type) { std::string description = absl::StrCat(DescribeSocketType(type), "connected IPv6 TCP socket"); return SocketPairKind{ - description, TCPAcceptBindSocketPairCreator(AF_INET6, type | SOCK_STREAM, - 0, /* dual_stack = */ false)}; + description, AF_INET6, type | SOCK_STREAM, IPPROTO_TCP, + TCPAcceptBindSocketPairCreator(AF_INET6, type | SOCK_STREAM, 0, + /* dual_stack = */ false)}; } SocketPairKind IPv4TCPAcceptBindSocketPair(int type) { std::string description = absl::StrCat(DescribeSocketType(type), "connected IPv4 TCP socket"); return SocketPairKind{ - description, TCPAcceptBindSocketPairCreator(AF_INET, type | SOCK_STREAM, - 0, /* dual_stack = */ false)}; + description, AF_INET, type | SOCK_STREAM, IPPROTO_TCP, + TCPAcceptBindSocketPairCreator(AF_INET, type | SOCK_STREAM, 0, + /* dual_stack = */ false)}; } SocketPairKind DualStackTCPAcceptBindSocketPair(int type) { std::string description = absl::StrCat(DescribeSocketType(type), "connected dual stack TCP socket"); return SocketPairKind{ - description, TCPAcceptBindSocketPairCreator(AF_INET6, type | SOCK_STREAM, - 0, /* dual_stack = */ true)}; + description, AF_INET6, type | SOCK_STREAM, IPPROTO_TCP, + TCPAcceptBindSocketPairCreator(AF_INET6, type | SOCK_STREAM, 0, + /* dual_stack = */ true)}; } SocketPairKind IPv6UDPBidirectionalBindSocketPair(int type) { std::string description = absl::StrCat(DescribeSocketType(type), "connected IPv6 UDP socket"); - return SocketPairKind{description, UDPBidirectionalBindSocketPairCreator( - AF_INET6, type | SOCK_DGRAM, 0, - /* dual_stack = */ false)}; + return SocketPairKind{ + description, AF_INET6, type | SOCK_DGRAM, IPPROTO_UDP, + UDPBidirectionalBindSocketPairCreator(AF_INET6, type | SOCK_DGRAM, 0, + /* dual_stack = */ false)}; } SocketPairKind IPv4UDPBidirectionalBindSocketPair(int type) { std::string description = absl::StrCat(DescribeSocketType(type), "connected IPv4 UDP socket"); - return SocketPairKind{description, UDPBidirectionalBindSocketPairCreator( - AF_INET, type | SOCK_DGRAM, 0, - /* dual_stack = */ false)}; + return SocketPairKind{ + description, AF_INET, type | SOCK_DGRAM, IPPROTO_UDP, + UDPBidirectionalBindSocketPairCreator(AF_INET, type | SOCK_DGRAM, 0, + /* dual_stack = */ false)}; } SocketPairKind DualStackUDPBidirectionalBindSocketPair(int type) { std::string description = absl::StrCat(DescribeSocketType(type), "connected dual stack UDP socket"); - return SocketPairKind{description, UDPBidirectionalBindSocketPairCreator( - AF_INET6, type | SOCK_DGRAM, 0, - /* dual_stack = */ true)}; + return SocketPairKind{ + description, AF_INET6, type | SOCK_DGRAM, IPPROTO_UDP, + UDPBidirectionalBindSocketPairCreator(AF_INET6, type | SOCK_DGRAM, 0, + /* dual_stack = */ true)}; } SocketPairKind IPv4UDPUnboundSocketPair(int type) { std::string description = absl::StrCat(DescribeSocketType(type), "IPv4 UDP socket"); return SocketPairKind{ - description, UDPUnboundSocketPairCreator(AF_INET, type | SOCK_DGRAM, 0, - /* dual_stack = */ false)}; + description, AF_INET, type | SOCK_DGRAM, IPPROTO_UDP, + UDPUnboundSocketPairCreator(AF_INET, type | SOCK_DGRAM, 0, + /* dual_stack = */ false)}; } SocketKind IPv4UDPUnboundSocket(int type) { std::string description = absl::StrCat(DescribeSocketType(type), "IPv4 UDP socket"); - return SocketKind{description, UnboundSocketCreator( - AF_INET, type | SOCK_DGRAM, IPPROTO_UDP)}; + return SocketKind{ + description, AF_INET, type | SOCK_DGRAM, IPPROTO_UDP, + UnboundSocketCreator(AF_INET, type | SOCK_DGRAM, IPPROTO_UDP)}; } SocketKind IPv4TCPUnboundSocket(int type) { std::string description = absl::StrCat(DescribeSocketType(type), "IPv4 TCP socket"); - return SocketKind{description, UnboundSocketCreator( - AF_INET, type | SOCK_STREAM, IPPROTO_TCP)}; + return SocketKind{ + description, AF_INET, type | SOCK_STREAM, IPPROTO_TCP, + UnboundSocketCreator(AF_INET, type | SOCK_STREAM, IPPROTO_TCP)}; } } // namespace testing diff --git a/test/syscalls/linux/socket_generic.cc b/test/syscalls/linux/socket_generic.cc index f99f3fe62..51d614639 100644 --- a/test/syscalls/linux/socket_generic.cc +++ b/test/syscalls/linux/socket_generic.cc @@ -21,6 +21,7 @@ #include "gtest/gtest.h" #include "gtest/gtest.h" +#include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/syscalls/linux/unix_domain_socket_test_util.h" @@ -687,5 +688,54 @@ TEST_P(AllSocketPairTest, RecvTimeoutWaitAll) { EXPECT_EQ(0, memcmp(sent_data, received_data, sizeof(sent_data))); } +TEST_P(AllSocketPairTest, GetSockoptType) { + int type = GetParam().type; + auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); + for (const int fd : {sockets->first_fd(), sockets->second_fd()}) { + int opt; + socklen_t optlen = sizeof(opt); + EXPECT_THAT(getsockopt(fd, SOL_SOCKET, SO_TYPE, &opt, &optlen), + SyscallSucceeds()); + + // Type may have SOCK_NONBLOCK and SOCK_CLOEXEC ORed into it. Remove these + // before comparison. + type &= ~(SOCK_NONBLOCK | SOCK_CLOEXEC); + EXPECT_EQ(opt, type) << absl::StrFormat( + "getsockopt(%d, SOL_SOCKET, SO_TYPE, &opt, &optlen) => opt=%d was " + "unexpected", + fd, opt); + } +} + +TEST_P(AllSocketPairTest, GetSockoptDomain) { + const int domain = GetParam().domain; + auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); + for (const int fd : {sockets->first_fd(), sockets->second_fd()}) { + int opt; + socklen_t optlen = sizeof(opt); + EXPECT_THAT(getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &opt, &optlen), + SyscallSucceeds()); + EXPECT_EQ(opt, domain) << absl::StrFormat( + "getsockopt(%d, SOL_SOCKET, SO_DOMAIN, &opt, &optlen) => opt=%d was " + "unexpected", + fd, opt); + } +} + +TEST_P(AllSocketPairTest, GetSockoptProtocol) { + const int protocol = GetParam().protocol; + auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); + for (const int fd : {sockets->first_fd(), sockets->second_fd()}) { + int opt; + socklen_t optlen = sizeof(opt); + EXPECT_THAT(getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &opt, &optlen), + SyscallSucceeds()); + EXPECT_EQ(opt, protocol) << absl::StrFormat( + "getsockopt(%d, SOL_SOCKET, SO_PROTOCOL, &opt, &optlen) => opt=%d was " + "unexpected", + fd, opt); + } +} + } // namespace testing } // namespace gvisor diff --git a/test/syscalls/linux/socket_netlink_route.cc b/test/syscalls/linux/socket_netlink_route.cc index c8693225f..53dd1ca78 100644 --- a/test/syscalls/linux/socket_netlink_route.cc +++ b/test/syscalls/linux/socket_netlink_route.cc @@ -23,6 +23,7 @@ #include <vector> #include "gtest/gtest.h" +#include "absl/strings/str_format.h" #include "test/syscalls/linux/socket_netlink_util.h" #include "test/syscalls/linux/socket_test_util.h" #include "test/util/cleanup.h" @@ -144,24 +145,56 @@ TEST(NetlinkRouteTest, GetPeerName) { EXPECT_EQ(addr.nl_pid, 0); } -using IntSockOptTest = ::testing::TestWithParam<int>; +// Parameters for GetSockOpt test. They are: +// 0: Socket option to query. +// 1: A predicate to run on the returned sockopt value. Should return true if +// the value is considered ok. +// 2: A description of what the sockopt value is expected to be. Should complete +// the sentence "<value> was unexpected, expected <description>" +using SockOptTest = + ::testing::TestWithParam<std::tuple<int, std::function<bool(int)>, std::string>>; + +TEST_P(SockOptTest, GetSockOpt) { + int sockopt = std::get<0>(GetParam()); + auto verifier = std::get<1>(GetParam()); + std::string verifier_description = std::get<2>(GetParam()); -TEST_P(IntSockOptTest, GetSockOpt) { FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)); int res; socklen_t len = sizeof(res); - EXPECT_THAT(getsockopt(fd.get(), SOL_SOCKET, GetParam(), &res, &len), + EXPECT_THAT(getsockopt(fd.get(), SOL_SOCKET, sockopt, &res, &len), SyscallSucceeds()); EXPECT_EQ(len, sizeof(res)); - EXPECT_GT(res, 0); + EXPECT_TRUE(verifier(res)) << absl::StrFormat( + "getsockopt(%d, SOL_SOCKET, %d, &res, &len) => res=%d was unexpected, " + "expected %s", + fd.get(), sockopt, res, verifier_description); +} + +std::function<bool(int)> IsPositive() { + return [](int val) { return val > 0; }; +} + +std::function<bool(int)> IsEqual(int target) { + return [target](int val) { return val == target; }; } -INSTANTIATE_TEST_SUITE_P(NetlinkRouteTest, IntSockOptTest, - ::testing::Values(SO_SNDBUF, SO_RCVBUF)); +INSTANTIATE_TEST_SUITE_P( + NetlinkRouteTest, SockOptTest, + ::testing::Values( + std::make_tuple(SO_SNDBUF, IsPositive(), "positive send buffer size"), + std::make_tuple(SO_RCVBUF, IsPositive(), + "positive receive buffer size"), + std::make_tuple(SO_TYPE, IsEqual(SOCK_RAW), + absl::StrFormat("SOCK_RAW (%d)", SOCK_RAW)), + std::make_tuple(SO_DOMAIN, IsEqual(AF_NETLINK), + absl::StrFormat("AF_NETLINK (%d)", AF_NETLINK)), + std::make_tuple(SO_PROTOCOL, IsEqual(NETLINK_ROUTE), + absl::StrFormat("NETLINK_ROUTE (%d)", NETLINK_ROUTE)))); // Validates the reponses to RTM_GETLINK + NLM_F_DUMP. void CheckGetLinkResponse(const struct nlmsghdr* hdr, int seq, int port) { diff --git a/test/syscalls/linux/socket_test_util.cc b/test/syscalls/linux/socket_test_util.cc index da69de37c..4f65cf5ae 100644 --- a/test/syscalls/linux/socket_test_util.cc +++ b/test/syscalls/linux/socket_test_util.cc @@ -457,7 +457,8 @@ Creator<SocketPair> UDPUnboundSocketPairCreator(int domain, int type, SocketPairKind Reversed(SocketPairKind const& base) { auto const& creator = base.creator; return SocketPairKind{ - absl::StrCat("reversed ", base.description), + absl::StrCat("reversed ", base.description), base.domain, base.type, + base.protocol, [creator]() -> PosixErrorOr<std::unique_ptr<ReversedSocketPair>> { ASSIGN_OR_RETURN_ERRNO(auto creator_value, creator()); return absl::make_unique<ReversedSocketPair>(std::move(creator_value)); @@ -542,8 +543,8 @@ struct sockaddr_storage AddrFDSocketPair::to_storage(const sockaddr_in6& addr) { SocketKind SimpleSocket(int fam, int type, int proto) { return SocketKind{ - absl::StrCat("Family ", fam, ", type ", type, ", proto ", proto), - SyscallSocketCreator(fam, type, proto)}; + absl::StrCat("Family ", fam, ", type ", type, ", proto ", proto), fam, + type, proto, SyscallSocketCreator(fam, type, proto)}; } ssize_t SendLargeSendMsg(const std::unique_ptr<SocketPair>& sockets, diff --git a/test/syscalls/linux/socket_test_util.h b/test/syscalls/linux/socket_test_util.h index 058313986..4fd59767a 100644 --- a/test/syscalls/linux/socket_test_util.h +++ b/test/syscalls/linux/socket_test_util.h @@ -287,6 +287,9 @@ Creator<FileDescriptor> UnboundSocketCreator(int domain, int type, // a function that creates such a socket pair. struct SocketPairKind { std::string description; + int domain; + int type; + int protocol; Creator<SocketPair> creator; // Create creates a socket pair of this kind. @@ -297,6 +300,9 @@ struct SocketPairKind { // a function that creates such a socket. struct SocketKind { std::string description; + int domain; + int type; + int protocol; Creator<FileDescriptor> creator; // Create creates a socket pair of this kind. @@ -353,6 +359,7 @@ Middleware SetSockOpt(int level, int optname, T* value) { return SocketPairKind{ absl::StrCat("setsockopt(", level, ", ", optname, ", ", *value, ") ", base.description), + base.domain, base.type, base.protocol, [creator, level, optname, value]() -> PosixErrorOr<std::unique_ptr<SocketPair>> { ASSIGN_OR_RETURN_ERRNO(auto creator_value, creator()); diff --git a/test/syscalls/linux/unix_domain_socket_test_util.cc b/test/syscalls/linux/unix_domain_socket_test_util.cc index 6f49e3660..ff28850b2 100644 --- a/test/syscalls/linux/unix_domain_socket_test_util.cc +++ b/test/syscalls/linux/unix_domain_socket_test_util.cc @@ -47,7 +47,7 @@ std::string DescribeUnixDomainSocketType(int type) { } SocketPairKind UnixDomainSocketPair(int type) { - return SocketPairKind{DescribeUnixDomainSocketType(type), + return SocketPairKind{DescribeUnixDomainSocketType(type), AF_UNIX, type, 0, SyscallSocketPairCreator(AF_UNIX, type, 0)}; } @@ -56,11 +56,12 @@ SocketPairKind FilesystemBoundUnixDomainSocketPair(int type) { " created with filesystem binding"); if ((type & SOCK_DGRAM) == SOCK_DGRAM) { return SocketPairKind{ - description, + description, AF_UNIX, type, 0, FilesystemBidirectionalBindSocketPairCreator(AF_UNIX, type, 0)}; } return SocketPairKind{ - description, FilesystemAcceptBindSocketPairCreator(AF_UNIX, type, 0)}; + description, AF_UNIX, type, 0, + FilesystemAcceptBindSocketPairCreator(AF_UNIX, type, 0)}; } SocketPairKind AbstractBoundUnixDomainSocketPair(int type) { @@ -68,17 +69,17 @@ SocketPairKind AbstractBoundUnixDomainSocketPair(int type) { " created with abstract namespace binding"); if ((type & SOCK_DGRAM) == SOCK_DGRAM) { return SocketPairKind{ - description, + description, AF_UNIX, type, 0, AbstractBidirectionalBindSocketPairCreator(AF_UNIX, type, 0)}; } - return SocketPairKind{description, + return SocketPairKind{description, AF_UNIX, type, 0, AbstractAcceptBindSocketPairCreator(AF_UNIX, type, 0)}; } SocketPairKind SocketpairGoferUnixDomainSocketPair(int type) { std::string description = absl::StrCat(DescribeUnixDomainSocketType(type), " created with the socketpair gofer"); - return SocketPairKind{description, + return SocketPairKind{description, AF_UNIX, type, 0, SocketpairGoferSocketPairCreator(AF_UNIX, type, 0)}; } @@ -87,13 +88,15 @@ SocketPairKind SocketpairGoferFileSocketPair(int type) { absl::StrCat(((type & O_NONBLOCK) != 0) ? "non-blocking " : "", ((type & O_CLOEXEC) != 0) ? "close-on-exec " : "", "file socket created with the socketpair gofer"); - return SocketPairKind{description, + // The socketpair gofer always creates SOCK_STREAM sockets on open(2). + return SocketPairKind{description, AF_UNIX, SOCK_STREAM, 0, SocketpairGoferFileSocketPairCreator(type)}; } SocketPairKind FilesystemUnboundUnixDomainSocketPair(int type) { return SocketPairKind{absl::StrCat(DescribeUnixDomainSocketType(type), " unbound with a filesystem address"), + AF_UNIX, type, 0, FilesystemUnboundSocketPairCreator(AF_UNIX, type, 0)}; } @@ -101,7 +104,7 @@ SocketPairKind AbstractUnboundUnixDomainSocketPair(int type) { return SocketPairKind{ absl::StrCat(DescribeUnixDomainSocketType(type), " unbound with an abstract namespace address"), - AbstractUnboundSocketPairCreator(AF_UNIX, type, 0)}; + AF_UNIX, type, 0, AbstractUnboundSocketPairCreator(AF_UNIX, type, 0)}; } void SendSingleFD(int sock, int fd, char buf[], int buf_size) { |