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