gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/udp_raw_socket.cc (about)

     1  // Copyright 2023 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 <arpa/inet.h>
    16  #include <fcntl.h>
    17  #include <net/ethernet.h>
    18  #include <netinet/icmp6.h>
    19  #include <netinet/ip.h>
    20  #include <netinet/ip6.h>
    21  #include <netinet/ip_icmp.h>
    22  #include <netinet/udp.h>
    23  #include <netpacket/packet.h>
    24  
    25  #ifdef __linux__
    26  #include <linux/errqueue.h>
    27  #include <linux/filter.h>
    28  #endif  // __linux__
    29  #include <netinet/in.h>
    30  #include <poll.h>
    31  #include <sys/ioctl.h>
    32  #include <sys/socket.h>
    33  #include <sys/types.h>
    34  
    35  #ifndef SIOCGSTAMP
    36  #include <linux/sockios.h>
    37  #endif
    38  
    39  #include "gtest/gtest.h"
    40  #include "test/util/capability_util.h"
    41  #include "test/util/file_descriptor.h"
    42  #include "test/util/posix_error.h"
    43  #include "test/util/socket_util.h"
    44  #include "test/util/test_util.h"
    45  
    46  namespace gvisor {
    47  namespace testing {
    48  
    49  namespace {
    50  
    51  // Tests for UDP that require raw socket access.
    52  class UdpSocketRawTest : public ::testing::TestWithParam<int> {};
    53  
    54  TEST_P(UdpSocketRawTest, ReceiveWithZeroSourcePort) {
    55    // UDP sockets can't bind to port 0, so send a UDP packet via a raw IP
    56    // socket instead. If those aren't available, skip the test.
    57    if (!ASSERT_NO_ERRNO_AND_VALUE(HaveRawIPSocketCapability())) {
    58      GTEST_SKIP();
    59    }
    60  
    61    FileDescriptor udp_socket =
    62        ASSERT_NO_ERRNO_AND_VALUE(Socket(GetParam(), SOCK_DGRAM, 0));
    63    sockaddr_storage bind_addr = InetLoopbackAddr(GetParam());
    64    ASSERT_THAT(bind(udp_socket.get(), AsSockAddr(&bind_addr), sizeof(bind_addr)),
    65                SyscallSucceeds());
    66    socklen_t bind_addr_len = sizeof(bind_addr);
    67    ASSERT_THAT(
    68        getsockname(udp_socket.get(), AsSockAddr(&bind_addr), &bind_addr_len),
    69        SyscallSucceeds());
    70    uint16_t udp_port =
    71        ASSERT_NO_ERRNO_AND_VALUE(AddrPort(GetParam(), bind_addr));
    72  
    73    constexpr absl::string_view kMessage = "hi";
    74  
    75    // Set up the UDP body.
    76    struct udphdr udphdr = {
    77        .source = 0,
    78        .dest = udp_port,
    79        .len = htons(sizeof(udphdr) + kMessage.size()),
    80        .check = 0,
    81    };
    82  
    83    if (GetParam() == AF_INET) {
    84      udphdr.check = UDPChecksum(
    85          iphdr{
    86              .saddr = htonl(INADDR_LOOPBACK),
    87              .daddr = htonl(INADDR_LOOPBACK),
    88          },
    89          udphdr, kMessage.data(), kMessage.size());
    90    } else {
    91      udphdr.check = UDPChecksum(
    92          ip6_hdr{
    93              .ip6_src = in6addr_loopback,
    94              .ip6_dst = in6addr_loopback,
    95          },
    96          udphdr, kMessage.data(), kMessage.size());
    97    }
    98    // Copy the header and the payload into our packet buffer.
    99    char send_buf[sizeof(udphdr) + kMessage.size()];
   100    memcpy(send_buf, &udphdr, sizeof(udphdr));
   101    memcpy(send_buf + sizeof(udphdr), kMessage.data(), kMessage.size());
   102  
   103    {
   104      // Send the packet out a raw socket.
   105      struct sockaddr_storage raw_socket_addr = InetLoopbackAddr(GetParam());
   106      FileDescriptor raw_socket =
   107          ASSERT_NO_ERRNO_AND_VALUE(Socket(GetParam(), SOCK_RAW, IPPROTO_UDP));
   108      ASSERT_THAT(sendto(raw_socket.get(), send_buf, sizeof(send_buf), 0,
   109                         reinterpret_cast<struct sockaddr*>(&raw_socket_addr),
   110                         sizeof(raw_socket_addr)),
   111                  SyscallSucceedsWithValue(sizeof(send_buf)));
   112    }
   113  
   114    // Receive and validate the data.
   115    char received[kMessage.size() + 1];
   116    struct sockaddr_storage src;
   117    socklen_t addr2len = sizeof(src);
   118    EXPECT_THAT(recvfrom(udp_socket.get(), received, sizeof(received), 0,
   119                         AsSockAddr(&src), &addr2len),
   120                SyscallSucceedsWithValue(kMessage.size()));
   121    ASSERT_EQ(src.ss_family, GetParam());
   122    ASSERT_EQ(ASSERT_NO_ERRNO_AND_VALUE(AddrPort(GetParam(), src)), 0);
   123    ASSERT_EQ(absl::string_view(received, kMessage.size()), kMessage);
   124  }
   125  
   126  INSTANTIATE_TEST_SUITE_P(AllInetTests, UdpSocketRawTest,
   127                           ::testing::Values(AF_INET, AF_INET6));
   128  
   129  }  // namespace
   130  }  // namespace testing
   131  }  // namespace gvisor