github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/syscalls/linux/raw_socket_icmp.cc (about)

     1  // Copyright 2019 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  #include <linux/capability.h>
    16  #include <netinet/in.h>
    17  #include <netinet/ip.h>
    18  #include <netinet/ip_icmp.h>
    19  #include <sys/socket.h>
    20  #include <sys/types.h>
    21  #include <unistd.h>
    22  
    23  #include <algorithm>
    24  #include <cstdint>
    25  
    26  #include "gtest/gtest.h"
    27  #include "test/syscalls/linux/socket_test_util.h"
    28  #include "test/syscalls/linux/unix_domain_socket_test_util.h"
    29  #include "test/util/capability_util.h"
    30  #include "test/util/file_descriptor.h"
    31  #include "test/util/test_util.h"
    32  
    33  namespace gvisor {
    34  namespace testing {
    35  
    36  namespace {
    37  
    38  // The size of an empty ICMP packet and IP header together.
    39  constexpr size_t kEmptyICMPSize = 28;
    40  
    41  // ICMP raw sockets get their own special tests because Linux automatically
    42  // responds to ICMP echo requests, and thus a single echo request sent via
    43  // loopback leads to 2 received ICMP packets.
    44  
    45  class RawSocketICMPTest : public ::testing::Test {
    46   protected:
    47    // Creates a socket to be used in tests.
    48    void SetUp() override;
    49  
    50    // Closes the socket created by SetUp().
    51    void TearDown() override;
    52  
    53    // Checks that both an ICMP echo request and reply are received. Calls should
    54    // be wrapped in ASSERT_NO_FATAL_FAILURE.
    55    void ExpectICMPSuccess(const struct icmphdr& icmp);
    56  
    57    // Sends icmp via s_.
    58    void SendEmptyICMP(const struct icmphdr& icmp);
    59  
    60    // Sends icmp via s_ to the given address.
    61    void SendEmptyICMPTo(int sock, const struct sockaddr_in& addr,
    62                         const struct icmphdr& icmp);
    63  
    64    // Reads from s_ into recv_buf.
    65    void ReceiveICMP(char* recv_buf, size_t recv_buf_len, size_t expected_size,
    66                     struct sockaddr_in* src);
    67  
    68    // Reads from sock into recv_buf.
    69    void ReceiveICMPFrom(char* recv_buf, size_t recv_buf_len,
    70                         size_t expected_size, struct sockaddr_in* src, int sock);
    71  
    72    // The socket used for both reading and writing.
    73    int s_;
    74  
    75    // The loopback address.
    76    struct sockaddr_in addr_;
    77  };
    78  
    79  void RawSocketICMPTest::SetUp() {
    80    if (!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW))) {
    81      ASSERT_THAT(socket(AF_INET, SOCK_RAW, IPPROTO_ICMP),
    82                  SyscallFailsWithErrno(EPERM));
    83      GTEST_SKIP();
    84    }
    85  
    86    ASSERT_THAT(s_ = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP), SyscallSucceeds());
    87  
    88    addr_ = {};
    89  
    90    // "On raw sockets sin_port is set to the IP protocol." - ip(7).
    91    addr_.sin_port = IPPROTO_IP;
    92    addr_.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    93    addr_.sin_family = AF_INET;
    94  }
    95  
    96  void RawSocketICMPTest::TearDown() {
    97    // TearDown will be run even if we skip the test.
    98    if (ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW))) {
    99      EXPECT_THAT(close(s_), SyscallSucceeds());
   100    }
   101  }
   102  
   103  // We'll only read an echo in this case, as the kernel won't respond to the
   104  // malformed ICMP checksum.
   105  TEST_F(RawSocketICMPTest, SendAndReceiveBadChecksum) {
   106    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW)));
   107  
   108    // Prepare and send an ICMP packet. Use arbitrary junk for checksum, sequence,
   109    // and ID. None of that should matter for raw sockets - the kernel should
   110    // still give us the packet.
   111    struct icmphdr icmp;
   112    icmp.type = ICMP_ECHO;
   113    icmp.code = 0;
   114    icmp.checksum = 0;
   115    icmp.un.echo.sequence = 2012;
   116    icmp.un.echo.id = 2014;
   117    ASSERT_NO_FATAL_FAILURE(SendEmptyICMP(icmp));
   118  
   119    // Veryify that we get the echo, then that there's nothing else to read.
   120    char recv_buf[kEmptyICMPSize];
   121    struct sockaddr_in src;
   122    ASSERT_NO_FATAL_FAILURE(
   123        ReceiveICMP(recv_buf, sizeof(recv_buf), sizeof(struct icmphdr), &src));
   124    EXPECT_EQ(memcmp(&src, &addr_, sizeof(src)), 0);
   125    // The packet should be identical to what we sent.
   126    EXPECT_EQ(memcmp(recv_buf + sizeof(struct iphdr), &icmp, sizeof(icmp)), 0);
   127  
   128    // And there should be nothing left to read.
   129    EXPECT_THAT(RetryEINTR(recv)(s_, recv_buf, sizeof(recv_buf), MSG_DONTWAIT),
   130                SyscallFailsWithErrno(EAGAIN));
   131  }
   132  
   133  // Send and receive an ICMP packet.
   134  TEST_F(RawSocketICMPTest, SendAndReceive) {
   135    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW)));
   136  
   137    // Prepare and send an ICMP packet. Use arbitrary junk for sequence and ID.
   138    // None of that should matter for raw sockets - the kernel should still give
   139    // us the packet.
   140    struct icmphdr icmp;
   141    icmp.type = ICMP_ECHO;
   142    icmp.code = 0;
   143    icmp.checksum = 0;
   144    icmp.un.echo.sequence = 2012;
   145    icmp.un.echo.id = 2014;
   146    icmp.checksum = ICMPChecksum(icmp, NULL, 0);
   147    ASSERT_NO_FATAL_FAILURE(SendEmptyICMP(icmp));
   148  
   149    ASSERT_NO_FATAL_FAILURE(ExpectICMPSuccess(icmp));
   150  }
   151  
   152  // We should be able to create multiple raw sockets for the same protocol and
   153  // receive the same packet on both.
   154  TEST_F(RawSocketICMPTest, MultipleSocketReceive) {
   155    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW)));
   156  
   157    FileDescriptor s2 =
   158        ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_RAW, IPPROTO_ICMP));
   159  
   160    // Prepare and send an ICMP packet. Use arbitrary junk for sequence and ID.
   161    // None of that should matter for raw sockets - the kernel should still give
   162    // us the packet.
   163    struct icmphdr icmp;
   164    icmp.type = ICMP_ECHO;
   165    icmp.code = 0;
   166    icmp.checksum = 0;
   167    icmp.un.echo.sequence = 2016;
   168    icmp.un.echo.id = 2018;
   169    icmp.checksum = ICMPChecksum(icmp, NULL, 0);
   170    ASSERT_NO_FATAL_FAILURE(SendEmptyICMP(icmp));
   171  
   172    // Both sockets will receive the echo request and reply in indeterminate
   173    // order, so we'll need to read 2 packets from each.
   174  
   175    // Receive on socket 1.
   176    constexpr int kBufSize = kEmptyICMPSize;
   177    char recv_buf1[2][kBufSize];
   178    struct sockaddr_in src;
   179    for (int i = 0; i < 2; i++) {
   180      ASSERT_NO_FATAL_FAILURE(ReceiveICMP(recv_buf1[i],
   181                                          ABSL_ARRAYSIZE(recv_buf1[i]),
   182                                          sizeof(struct icmphdr), &src));
   183      EXPECT_EQ(memcmp(&src, &addr_, sizeof(src)), 0);
   184    }
   185  
   186    // Receive on socket 2.
   187    char recv_buf2[2][kBufSize];
   188    for (int i = 0; i < 2; i++) {
   189      ASSERT_NO_FATAL_FAILURE(
   190          ReceiveICMPFrom(recv_buf2[i], ABSL_ARRAYSIZE(recv_buf2[i]),
   191                          sizeof(struct icmphdr), &src, s2.get()));
   192      EXPECT_EQ(memcmp(&src, &addr_, sizeof(src)), 0);
   193    }
   194  
   195    // Ensure both sockets receive identical packets.
   196    int types[] = {ICMP_ECHO, ICMP_ECHOREPLY};
   197    for (int type : types) {
   198      auto match_type = [=](char buf[kBufSize]) {
   199        struct icmphdr* icmp =
   200            reinterpret_cast<struct icmphdr*>(buf + sizeof(struct iphdr));
   201        return icmp->type == type;
   202      };
   203      auto icmp1_it =
   204          std::find_if(std::begin(recv_buf1), std::end(recv_buf1), match_type);
   205      auto icmp2_it =
   206          std::find_if(std::begin(recv_buf2), std::end(recv_buf2), match_type);
   207      ASSERT_NE(icmp1_it, std::end(recv_buf1));
   208      ASSERT_NE(icmp2_it, std::end(recv_buf2));
   209      EXPECT_EQ(memcmp(*icmp1_it + sizeof(struct iphdr),
   210                       *icmp2_it + sizeof(struct iphdr), sizeof(icmp)),
   211                0);
   212    }
   213  }
   214  
   215  // A raw ICMP socket and ping socket should both receive the ICMP packets
   216  // intended for the ping socket.
   217  TEST_F(RawSocketICMPTest, RawAndPingSockets) {
   218    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW)));
   219  
   220    FileDescriptor ping_sock =
   221        ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP));
   222  
   223    // Ping sockets take care of the ICMP ID and checksum.
   224    struct icmphdr icmp;
   225    icmp.type = ICMP_ECHO;
   226    icmp.code = 0;
   227    icmp.un.echo.sequence = *static_cast<unsigned short*>(&icmp.un.echo.sequence);
   228    ASSERT_THAT(RetryEINTR(sendto)(ping_sock.get(), &icmp, sizeof(icmp), 0,
   229                                   reinterpret_cast<struct sockaddr*>(&addr_),
   230                                   sizeof(addr_)),
   231                SyscallSucceedsWithValue(sizeof(icmp)));
   232  
   233    // Receive on socket 1, which receives the echo request and reply in
   234    // indeterminate order.
   235    constexpr int kBufSize = kEmptyICMPSize;
   236    char recv_buf1[2][kBufSize];
   237    struct sockaddr_in src;
   238    for (int i = 0; i < 2; i++) {
   239      ASSERT_NO_FATAL_FAILURE(
   240          ReceiveICMP(recv_buf1[i], kBufSize, sizeof(struct icmphdr), &src));
   241      EXPECT_EQ(memcmp(&src, &addr_, sizeof(src)), 0);
   242    }
   243  
   244    // Receive on socket 2. Ping sockets only get the echo reply, not the initial
   245    // echo.
   246    char ping_recv_buf[kBufSize];
   247    ASSERT_THAT(RetryEINTR(recv)(ping_sock.get(), ping_recv_buf, kBufSize, 0),
   248                SyscallSucceedsWithValue(sizeof(struct icmphdr)));
   249  
   250    // Ensure both sockets receive identical echo reply packets.
   251    auto match_type_raw = [=](char buf[kBufSize]) {
   252      struct icmphdr* icmp =
   253          reinterpret_cast<struct icmphdr*>(buf + sizeof(struct iphdr));
   254      return icmp->type == ICMP_ECHOREPLY;
   255    };
   256    auto raw_reply_it =
   257        std::find_if(std::begin(recv_buf1), std::end(recv_buf1), match_type_raw);
   258    ASSERT_NE(raw_reply_it, std::end(recv_buf1));
   259    EXPECT_EQ(
   260        memcmp(*raw_reply_it + sizeof(struct iphdr), ping_recv_buf, sizeof(icmp)),
   261        0);
   262  }
   263  
   264  // A raw ICMP socket should be able to send a malformed short ICMP Echo Request,
   265  // while a ping socket should not. Neither should be able to receieve a short
   266  // malformed packet.
   267  TEST_F(RawSocketICMPTest, ShortEchoRawAndPingSockets) {
   268    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW)));
   269  
   270    FileDescriptor ping_sock =
   271        ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP));
   272  
   273    struct icmphdr icmp;
   274    icmp.type = ICMP_ECHO;
   275    icmp.code = 0;
   276    icmp.un.echo.sequence = 0;
   277    icmp.un.echo.id = 6789;
   278    icmp.checksum = 0;
   279    icmp.checksum = ICMPChecksum(icmp, NULL, 0);
   280  
   281    // Omit 2 bytes from ICMP packet.
   282    constexpr int kShortICMPSize = sizeof(icmp) - 2;
   283  
   284    // Sending a malformed short ICMP message to a ping socket should fail.
   285    ASSERT_THAT(RetryEINTR(sendto)(ping_sock.get(), &icmp, kShortICMPSize, 0,
   286                                   reinterpret_cast<struct sockaddr*>(&addr_),
   287                                   sizeof(addr_)),
   288                SyscallFailsWithErrno(EINVAL));
   289  
   290    // Sending a malformed short ICMP message to a raw socket should not fail.
   291    ASSERT_THAT(RetryEINTR(sendto)(s_, &icmp, kShortICMPSize, 0,
   292                                   reinterpret_cast<struct sockaddr*>(&addr_),
   293                                   sizeof(addr_)),
   294                SyscallSucceedsWithValue(kShortICMPSize));
   295  
   296    // Neither Ping nor Raw socket should have anything to read.
   297    char recv_buf[kEmptyICMPSize];
   298    EXPECT_THAT(RetryEINTR(recv)(ping_sock.get(), recv_buf, sizeof(recv_buf),
   299                                 MSG_DONTWAIT),
   300                SyscallFailsWithErrno(EAGAIN));
   301    EXPECT_THAT(RetryEINTR(recv)(s_, recv_buf, sizeof(recv_buf), MSG_DONTWAIT),
   302                SyscallFailsWithErrno(EAGAIN));
   303  }
   304  
   305  // A raw ICMP socket should be able to send a malformed short ICMP Echo Reply,
   306  // while ping socket should not.
   307  // Neither should be able to receieve a short malformed packet.
   308  TEST_F(RawSocketICMPTest, ShortEchoReplyRawAndPingSockets) {
   309    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW)));
   310  
   311    FileDescriptor ping_sock =
   312        ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP));
   313  
   314    struct icmphdr icmp;
   315    icmp.type = ICMP_ECHOREPLY;
   316    icmp.code = 0;
   317    icmp.un.echo.sequence = 0;
   318    icmp.un.echo.id = 6789;
   319    icmp.checksum = 0;
   320    icmp.checksum = ICMPChecksum(icmp, NULL, 0);
   321  
   322    // Omit 2 bytes from ICMP packet.
   323    constexpr int kShortICMPSize = sizeof(icmp) - 2;
   324  
   325    // Sending a malformed short ICMP message to a ping socket should fail.
   326    ASSERT_THAT(RetryEINTR(sendto)(ping_sock.get(), &icmp, kShortICMPSize, 0,
   327                                   reinterpret_cast<struct sockaddr*>(&addr_),
   328                                   sizeof(addr_)),
   329                SyscallFailsWithErrno(EINVAL));
   330  
   331    // Sending a malformed short ICMP message to a raw socket should not fail.
   332    ASSERT_THAT(RetryEINTR(sendto)(s_, &icmp, kShortICMPSize, 0,
   333                                   reinterpret_cast<struct sockaddr*>(&addr_),
   334                                   sizeof(addr_)),
   335                SyscallSucceedsWithValue(kShortICMPSize));
   336  
   337    // Neither Ping nor Raw socket should have anything to read.
   338    char recv_buf[kEmptyICMPSize];
   339    EXPECT_THAT(RetryEINTR(recv)(ping_sock.get(), recv_buf, sizeof(recv_buf),
   340                                 MSG_DONTWAIT),
   341                SyscallFailsWithErrno(EAGAIN));
   342    EXPECT_THAT(RetryEINTR(recv)(s_, recv_buf, sizeof(recv_buf), MSG_DONTWAIT),
   343                SyscallFailsWithErrno(EAGAIN));
   344  }
   345  
   346  // Test that connect() sends packets to the right place.
   347  TEST_F(RawSocketICMPTest, SendAndReceiveViaConnect) {
   348    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW)));
   349  
   350    ASSERT_THAT(
   351        connect(s_, reinterpret_cast<struct sockaddr*>(&addr_), sizeof(addr_)),
   352        SyscallSucceeds());
   353  
   354    // Prepare and send an ICMP packet. Use arbitrary junk for sequence and ID.
   355    // None of that should matter for raw sockets - the kernel should still give
   356    // us the packet.
   357    struct icmphdr icmp;
   358    icmp.type = ICMP_ECHO;
   359    icmp.code = 0;
   360    icmp.checksum = 0;
   361    icmp.un.echo.sequence = 2003;
   362    icmp.un.echo.id = 2004;
   363    icmp.checksum = ICMPChecksum(icmp, NULL, 0);
   364    ASSERT_THAT(send(s_, &icmp, sizeof(icmp), 0),
   365                SyscallSucceedsWithValue(sizeof(icmp)));
   366  
   367    ASSERT_NO_FATAL_FAILURE(ExpectICMPSuccess(icmp));
   368  }
   369  
   370  // Bind to localhost, then send and receive packets.
   371  TEST_F(RawSocketICMPTest, BindSendAndReceive) {
   372    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW)));
   373  
   374    ASSERT_THAT(
   375        bind(s_, reinterpret_cast<struct sockaddr*>(&addr_), sizeof(addr_)),
   376        SyscallSucceeds());
   377  
   378    // Prepare and send an ICMP packet. Use arbitrary junk for checksum, sequence,
   379    // and ID. None of that should matter for raw sockets - the kernel should
   380    // still give us the packet.
   381    struct icmphdr icmp;
   382    icmp.type = ICMP_ECHO;
   383    icmp.code = 0;
   384    icmp.checksum = 0;
   385    icmp.un.echo.sequence = 2004;
   386    icmp.un.echo.id = 2007;
   387    icmp.checksum = ICMPChecksum(icmp, NULL, 0);
   388    ASSERT_NO_FATAL_FAILURE(SendEmptyICMP(icmp));
   389  
   390    ASSERT_NO_FATAL_FAILURE(ExpectICMPSuccess(icmp));
   391  }
   392  
   393  // Bind and connect to localhost and send/receive packets.
   394  TEST_F(RawSocketICMPTest, BindConnectSendAndReceive) {
   395    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW)));
   396  
   397    ASSERT_THAT(
   398        bind(s_, reinterpret_cast<struct sockaddr*>(&addr_), sizeof(addr_)),
   399        SyscallSucceeds());
   400    ASSERT_THAT(
   401        connect(s_, reinterpret_cast<struct sockaddr*>(&addr_), sizeof(addr_)),
   402        SyscallSucceeds());
   403  
   404    // Prepare and send an ICMP packet. Use arbitrary junk for checksum, sequence,
   405    // and ID. None of that should matter for raw sockets - the kernel should
   406    // still give us the packet.
   407    struct icmphdr icmp;
   408    icmp.type = ICMP_ECHO;
   409    icmp.code = 0;
   410    icmp.checksum = 0;
   411    icmp.un.echo.sequence = 2010;
   412    icmp.un.echo.id = 7;
   413    icmp.checksum = ICMPChecksum(icmp, NULL, 0);
   414    ASSERT_NO_FATAL_FAILURE(SendEmptyICMP(icmp));
   415  
   416    ASSERT_NO_FATAL_FAILURE(ExpectICMPSuccess(icmp));
   417  }
   418  
   419  // Set and get SO_LINGER.
   420  TEST_F(RawSocketICMPTest, SetAndGetSocketLinger) {
   421    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW)));
   422  
   423    int level = SOL_SOCKET;
   424    int type = SO_LINGER;
   425  
   426    struct linger sl;
   427    sl.l_onoff = 1;
   428    sl.l_linger = 5;
   429    ASSERT_THAT(setsockopt(s_, level, type, &sl, sizeof(sl)),
   430                SyscallSucceedsWithValue(0));
   431  
   432    struct linger got_linger = {};
   433    socklen_t length = sizeof(sl);
   434    ASSERT_THAT(getsockopt(s_, level, type, &got_linger, &length),
   435                SyscallSucceedsWithValue(0));
   436  
   437    ASSERT_EQ(length, sizeof(got_linger));
   438    EXPECT_EQ(0, memcmp(&sl, &got_linger, length));
   439  }
   440  
   441  // Test getsockopt for SO_ACCEPTCONN.
   442  TEST_F(RawSocketICMPTest, GetSocketAcceptConn) {
   443    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW)));
   444  
   445    int got = -1;
   446    socklen_t length = sizeof(got);
   447    ASSERT_THAT(getsockopt(s_, SOL_SOCKET, SO_ACCEPTCONN, &got, &length),
   448                SyscallSucceedsWithValue(0));
   449  
   450    ASSERT_EQ(length, sizeof(got));
   451    EXPECT_EQ(got, 0);
   452  }
   453  
   454  void RawSocketICMPTest::ExpectICMPSuccess(const struct icmphdr& icmp) {
   455    // We're going to receive both the echo request and reply, but the order is
   456    // indeterminate.
   457    char recv_buf[kEmptyICMPSize];
   458    struct sockaddr_in src;
   459    bool received_request = false;
   460    bool received_reply = false;
   461  
   462    for (int i = 0; i < 2; i++) {
   463      // Receive the packet.
   464      ASSERT_NO_FATAL_FAILURE(ReceiveICMP(recv_buf, ABSL_ARRAYSIZE(recv_buf),
   465                                          sizeof(struct icmphdr), &src));
   466      EXPECT_EQ(memcmp(&src, &addr_, sizeof(src)), 0);
   467      struct icmphdr* recvd_icmp =
   468          reinterpret_cast<struct icmphdr*>(recv_buf + sizeof(struct iphdr));
   469      switch (recvd_icmp->type) {
   470        case ICMP_ECHO:
   471          EXPECT_FALSE(received_request);
   472          received_request = true;
   473          // The packet should be identical to what we sent.
   474          EXPECT_EQ(memcmp(recv_buf + sizeof(struct iphdr), &icmp, sizeof(icmp)),
   475                    0);
   476          break;
   477  
   478        case ICMP_ECHOREPLY:
   479          EXPECT_FALSE(received_reply);
   480          received_reply = true;
   481          // Most fields should be the same.
   482          EXPECT_EQ(recvd_icmp->code, icmp.code);
   483          EXPECT_EQ(recvd_icmp->un.echo.sequence, icmp.un.echo.sequence);
   484          EXPECT_EQ(recvd_icmp->un.echo.id, icmp.un.echo.id);
   485          // A couple are different.
   486          EXPECT_EQ(recvd_icmp->type, ICMP_ECHOREPLY);
   487          // The checksum computed over the reply should still be valid.
   488          EXPECT_EQ(ICMPChecksum(*recvd_icmp, NULL, 0), 0);
   489          break;
   490      }
   491    }
   492  
   493    ASSERT_TRUE(received_request);
   494    ASSERT_TRUE(received_reply);
   495  }
   496  
   497  void RawSocketICMPTest::SendEmptyICMP(const struct icmphdr& icmp) {
   498    ASSERT_NO_FATAL_FAILURE(SendEmptyICMPTo(s_, addr_, icmp));
   499  }
   500  
   501  void RawSocketICMPTest::SendEmptyICMPTo(int sock,
   502                                          const struct sockaddr_in& addr,
   503                                          const struct icmphdr& icmp) {
   504    // It's safe to use const_cast here because sendmsg won't modify the iovec or
   505    // address.
   506    struct iovec iov = {};
   507    iov.iov_base = static_cast<void*>(const_cast<struct icmphdr*>(&icmp));
   508    iov.iov_len = sizeof(icmp);
   509    struct msghdr msg = {};
   510    msg.msg_name = static_cast<void*>(const_cast<struct sockaddr_in*>(&addr));
   511    msg.msg_namelen = sizeof(addr);
   512    msg.msg_iov = &iov;
   513    msg.msg_iovlen = 1;
   514    msg.msg_control = NULL;
   515    msg.msg_controllen = 0;
   516    msg.msg_flags = 0;
   517    ASSERT_THAT(sendmsg(sock, &msg, 0), SyscallSucceedsWithValue(sizeof(icmp)));
   518  }
   519  
   520  void RawSocketICMPTest::ReceiveICMP(char* recv_buf, size_t recv_buf_len,
   521                                      size_t expected_size,
   522                                      struct sockaddr_in* src) {
   523    ASSERT_NO_FATAL_FAILURE(
   524        ReceiveICMPFrom(recv_buf, recv_buf_len, expected_size, src, s_));
   525  }
   526  
   527  void RawSocketICMPTest::ReceiveICMPFrom(char* recv_buf, size_t recv_buf_len,
   528                                          size_t expected_size,
   529                                          struct sockaddr_in* src, int sock) {
   530    struct iovec iov = {};
   531    iov.iov_base = recv_buf;
   532    iov.iov_len = recv_buf_len;
   533    struct msghdr msg = {};
   534    msg.msg_name = src;
   535    msg.msg_namelen = sizeof(*src);
   536    msg.msg_iov = &iov;
   537    msg.msg_iovlen = 1;
   538    msg.msg_control = NULL;
   539    msg.msg_controllen = 0;
   540    msg.msg_flags = 0;
   541    // We should receive the ICMP packet plus 20 bytes of IP header.
   542    ASSERT_THAT(recvmsg(sock, &msg, 0),
   543                SyscallSucceedsWithValue(expected_size + sizeof(struct iphdr)));
   544  }
   545  
   546  }  // namespace
   547  
   548  }  // namespace testing
   549  }  // namespace gvisor