summaryrefslogtreecommitdiffhomepage
path: root/test/syscalls/linux/raw_socket.cc
diff options
context:
space:
mode:
authorGhanan Gowripalan <ghanan@google.com>2021-07-20 22:47:34 -0700
committergVisor bot <gvisor-bot@google.com>2021-07-20 22:50:16 -0700
commit9e805ce937ef2f2934e72f873ea4ae8451801c82 (patch)
treeb7f664411089449a91f0b874fa725c671b97f73d /test/syscalls/linux/raw_socket.cc
parent0184f1a662b893a1634e9b2cf3adff57971b668c (diff)
Expose local address from raw sockets
PiperOrigin-RevId: 385940836
Diffstat (limited to 'test/syscalls/linux/raw_socket.cc')
-rw-r--r--test/syscalls/linux/raw_socket.cc63
1 files changed, 63 insertions, 0 deletions
diff --git a/test/syscalls/linux/raw_socket.cc b/test/syscalls/linux/raw_socket.cc
index 69616b400..f8798bc76 100644
--- a/test/syscalls/linux/raw_socket.cc
+++ b/test/syscalls/linux/raw_socket.cc
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <arpa/inet.h>
#include <linux/capability.h>
#include <linux/filter.h>
#include <netinet/in.h>
@@ -76,6 +77,20 @@ class RawSocketTest : public ::testing::TestWithParam<std::tuple<int, int>> {
return 0;
}
+ uint16_t Port(struct sockaddr* s) {
+ if (Family() == AF_INET) {
+ return ntohs(reinterpret_cast<struct sockaddr_in*>(s)->sin_port);
+ }
+ return ntohs(reinterpret_cast<struct sockaddr_in6*>(s)->sin6_port);
+ }
+
+ void* Addr(struct sockaddr* s) {
+ if (Family() == AF_INET) {
+ return &(reinterpret_cast<struct sockaddr_in*>(s)->sin_addr);
+ }
+ return &(reinterpret_cast<struct sockaddr_in6*>(s)->sin6_addr);
+ }
+
// The socket used for both reading and writing.
int s_;
@@ -181,6 +196,54 @@ TEST_P(RawSocketTest, FailAccept) {
ASSERT_THAT(accept(s_, &saddr, &addrlen), SyscallFailsWithErrno(ENOTSUP));
}
+TEST_P(RawSocketTest, BindThenGetSockName) {
+ SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW)));
+
+ struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_);
+ ASSERT_THAT(bind(s_, addr, AddrLen()), SyscallSucceeds());
+ struct sockaddr_storage saddr_storage;
+ struct sockaddr* saddr = reinterpret_cast<struct sockaddr*>(&saddr_storage);
+ socklen_t saddrlen = AddrLen();
+ ASSERT_THAT(getsockname(s_, saddr, &saddrlen), SyscallSucceeds());
+ ASSERT_EQ(saddrlen, AddrLen());
+
+ // The port is expected to hold the protocol number.
+ EXPECT_EQ(Port(saddr), Protocol());
+
+ char addrbuf[INET6_ADDRSTRLEN], saddrbuf[INET6_ADDRSTRLEN];
+ const char* addrstr =
+ inet_ntop(addr->sa_family, Addr(addr), addrbuf, sizeof(addrbuf));
+ ASSERT_NE(addrstr, nullptr);
+ const char* saddrstr =
+ inet_ntop(saddr->sa_family, Addr(saddr), saddrbuf, sizeof(saddrbuf));
+ ASSERT_NE(saddrstr, nullptr);
+ EXPECT_STREQ(saddrstr, addrstr);
+}
+
+TEST_P(RawSocketTest, ConnectThenGetSockName) {
+ SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW)));
+
+ struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_);
+ ASSERT_THAT(connect(s_, addr, AddrLen()), SyscallSucceeds());
+ struct sockaddr_storage saddr_storage;
+ struct sockaddr* saddr = reinterpret_cast<struct sockaddr*>(&saddr_storage);
+ socklen_t saddrlen = AddrLen();
+ ASSERT_THAT(getsockname(s_, saddr, &saddrlen), SyscallSucceeds());
+ ASSERT_EQ(saddrlen, AddrLen());
+
+ // The port is expected to hold the protocol number.
+ EXPECT_EQ(Port(saddr), Protocol());
+
+ char addrbuf[INET6_ADDRSTRLEN], saddrbuf[INET6_ADDRSTRLEN];
+ const char* addrstr =
+ inet_ntop(addr->sa_family, Addr(addr), addrbuf, sizeof(addrbuf));
+ ASSERT_NE(addrstr, nullptr);
+ const char* saddrstr =
+ inet_ntop(saddr->sa_family, Addr(saddr), saddrbuf, sizeof(saddrbuf));
+ ASSERT_NE(saddrstr, nullptr);
+ EXPECT_STREQ(saddrstr, addrstr);
+}
+
// Test that getpeername() returns nothing before connect().
TEST_P(RawSocketTest, FailGetPeerNameBeforeConnect) {
SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW)));