diff options
Diffstat (limited to 'test/syscalls/linux/raw_socket_icmp.cc')
-rw-r--r-- | test/syscalls/linux/raw_socket_icmp.cc | 115 |
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. |