summaryrefslogtreecommitdiffhomepage
path: root/test/syscalls/linux/raw_socket_icmp.cc
diff options
context:
space:
mode:
Diffstat (limited to 'test/syscalls/linux/raw_socket_icmp.cc')
-rw-r--r--test/syscalls/linux/raw_socket_icmp.cc115
1 files changed, 99 insertions, 16 deletions
diff --git a/test/syscalls/linux/raw_socket_icmp.cc b/test/syscalls/linux/raw_socket_icmp.cc
index 24d9dc79a..ad19120d5 100644
--- a/test/syscalls/linux/raw_socket_icmp.cc
+++ b/test/syscalls/linux/raw_socket_icmp.cc
@@ -195,7 +195,7 @@ TEST_F(RawSocketICMPTest, MultipleSocketReceive) {
// Receive on socket 1.
constexpr int kBufSize = kEmptyICMPSize;
- std::vector<char[kBufSize]> recv_buf1(2);
+ char recv_buf1[2][kBufSize];
struct sockaddr_in src;
for (int i = 0; i < 2; i++) {
ASSERT_NO_FATAL_FAILURE(ReceiveICMP(recv_buf1[i],
@@ -205,7 +205,7 @@ TEST_F(RawSocketICMPTest, MultipleSocketReceive) {
}
// Receive on socket 2.
- std::vector<char[kBufSize]> recv_buf2(2);
+ char recv_buf2[2][kBufSize];
for (int i = 0; i < 2; i++) {
ASSERT_NO_FATAL_FAILURE(
ReceiveICMPFrom(recv_buf2[i], ABSL_ARRAYSIZE(recv_buf2[i]),
@@ -221,20 +221,20 @@ TEST_F(RawSocketICMPTest, MultipleSocketReceive) {
reinterpret_cast<struct icmphdr*>(buf + sizeof(struct iphdr));
return icmp->type == type;
};
- const char* icmp1 =
- *std::find_if(recv_buf1.begin(), recv_buf1.end(), match_type);
- const char* icmp2 =
- *std::find_if(recv_buf2.begin(), recv_buf2.end(), match_type);
- ASSERT_NE(icmp1, *recv_buf1.end());
- ASSERT_NE(icmp2, *recv_buf2.end());
- EXPECT_EQ(memcmp(icmp1 + sizeof(struct iphdr), icmp2 + sizeof(struct iphdr),
- sizeof(icmp)),
+ auto icmp1_it =
+ std::find_if(std::begin(recv_buf1), std::end(recv_buf1), match_type);
+ auto icmp2_it =
+ std::find_if(std::begin(recv_buf2), std::end(recv_buf2), match_type);
+ ASSERT_NE(icmp1_it, std::end(recv_buf1));
+ ASSERT_NE(icmp2_it, std::end(recv_buf2));
+ EXPECT_EQ(memcmp(*icmp1_it + sizeof(struct iphdr),
+ *icmp2_it + sizeof(struct iphdr), sizeof(icmp)),
0);
}
}
// A raw ICMP socket and ping socket should both receive the ICMP packets
-// indended for the ping socket.
+// intended for the ping socket.
TEST_F(RawSocketICMPTest, RawAndPingSockets) {
SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW)));
@@ -254,7 +254,7 @@ TEST_F(RawSocketICMPTest, RawAndPingSockets) {
// Receive on socket 1, which receives the echo request and reply in
// indeterminate order.
constexpr int kBufSize = kEmptyICMPSize;
- std::vector<char[kBufSize]> recv_buf1(2);
+ char recv_buf1[2][kBufSize];
struct sockaddr_in src;
for (int i = 0; i < 2; i++) {
ASSERT_NO_FATAL_FAILURE(
@@ -274,11 +274,94 @@ TEST_F(RawSocketICMPTest, RawAndPingSockets) {
reinterpret_cast<struct icmphdr*>(buf + sizeof(struct iphdr));
return icmp->type == ICMP_ECHOREPLY;
};
- char* raw_reply =
- *std::find_if(recv_buf1.begin(), recv_buf1.end(), match_type_raw);
- ASSERT_NE(raw_reply, *recv_buf1.end());
+ auto raw_reply_it =
+ std::find_if(std::begin(recv_buf1), std::end(recv_buf1), match_type_raw);
+ ASSERT_NE(raw_reply_it, std::end(recv_buf1));
EXPECT_EQ(
- memcmp(raw_reply + sizeof(struct iphdr), ping_recv_buf, sizeof(icmp)), 0);
+ memcmp(*raw_reply_it + sizeof(struct iphdr), ping_recv_buf, sizeof(icmp)),
+ 0);
+}
+
+// A raw ICMP socket should be able to send a malformed short ICMP Echo Request,
+// while ping socket should not.
+// Neither should be able to receieve a short malformed packet.
+TEST_F(RawSocketICMPTest, ShortEchoRawAndPingSockets) {
+ SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW)));
+
+ FileDescriptor ping_sock =
+ ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP));
+
+ struct icmphdr icmp;
+ icmp.type = ICMP_ECHO;
+ icmp.code = 0;
+ icmp.un.echo.sequence = 0;
+ icmp.un.echo.id = 6789;
+ icmp.checksum = 0;
+ icmp.checksum = Checksum(&icmp);
+
+ // Omit 2 bytes from ICMP packet.
+ constexpr int kShortICMPSize = sizeof(icmp) - 2;
+
+ // Sending a malformed short ICMP message to a ping socket should fail.
+ ASSERT_THAT(RetryEINTR(sendto)(ping_sock.get(), &icmp, kShortICMPSize, 0,
+ reinterpret_cast<struct sockaddr*>(&addr_),
+ sizeof(addr_)),
+ SyscallFailsWithErrno(EINVAL));
+
+ // Sending a malformed short ICMP message to a raw socket should not fail.
+ ASSERT_THAT(RetryEINTR(sendto)(s_, &icmp, kShortICMPSize, 0,
+ reinterpret_cast<struct sockaddr*>(&addr_),
+ sizeof(addr_)),
+ SyscallSucceedsWithValue(kShortICMPSize));
+
+ // Neither Ping nor Raw socket should have anything to read.
+ char recv_buf[kEmptyICMPSize];
+ EXPECT_THAT(RetryEINTR(recv)(ping_sock.get(), recv_buf, sizeof(recv_buf),
+ MSG_DONTWAIT),
+ SyscallFailsWithErrno(EAGAIN));
+ EXPECT_THAT(RetryEINTR(recv)(s_, recv_buf, sizeof(recv_buf), MSG_DONTWAIT),
+ SyscallFailsWithErrno(EAGAIN));
+}
+
+// A raw ICMP socket should be able to send a malformed short ICMP Echo Reply,
+// while ping socket should not.
+// Neither should be able to receieve a short malformed packet.
+TEST_F(RawSocketICMPTest, ShortEchoReplyRawAndPingSockets) {
+ SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW)));
+
+ FileDescriptor ping_sock =
+ ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP));
+
+ struct icmphdr icmp;
+ icmp.type = ICMP_ECHOREPLY;
+ icmp.code = 0;
+ icmp.un.echo.sequence = 0;
+ icmp.un.echo.id = 6789;
+ icmp.checksum = 0;
+ icmp.checksum = Checksum(&icmp);
+
+ // Omit 2 bytes from ICMP packet.
+ constexpr int kShortICMPSize = sizeof(icmp) - 2;
+
+ // Sending a malformed short ICMP message to a ping socket should fail.
+ ASSERT_THAT(RetryEINTR(sendto)(ping_sock.get(), &icmp, kShortICMPSize, 0,
+ reinterpret_cast<struct sockaddr*>(&addr_),
+ sizeof(addr_)),
+ SyscallFailsWithErrno(EINVAL));
+
+ // Sending a malformed short ICMP message to a raw socket should not fail.
+ ASSERT_THAT(RetryEINTR(sendto)(s_, &icmp, kShortICMPSize, 0,
+ reinterpret_cast<struct sockaddr*>(&addr_),
+ sizeof(addr_)),
+ SyscallSucceedsWithValue(kShortICMPSize));
+
+ // Neither Ping nor Raw socket should have anything to read.
+ char recv_buf[kEmptyICMPSize];
+ EXPECT_THAT(RetryEINTR(recv)(ping_sock.get(), recv_buf, sizeof(recv_buf),
+ MSG_DONTWAIT),
+ SyscallFailsWithErrno(EAGAIN));
+ EXPECT_THAT(RetryEINTR(recv)(s_, recv_buf, sizeof(recv_buf), MSG_DONTWAIT),
+ SyscallFailsWithErrno(EAGAIN));
}
// Test that connect() sends packets to the right place.