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

     1  // Copyright 2020 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 "test/syscalls/linux/socket_ipv6_udp_unbound.h"
    16  
    17  #include <arpa/inet.h>
    18  #include <netinet/in.h>
    19  #ifdef __linux__
    20  #include <linux/in6.h>
    21  #endif  //  __linux__
    22  #include <net/if.h>
    23  #include <sys/ioctl.h>
    24  #include <sys/socket.h>
    25  #include <sys/types.h>
    26  #include <sys/un.h>
    27  
    28  #include <cstdio>
    29  #include <cstring>
    30  
    31  #include "gtest/gtest.h"
    32  #include "absl/memory/memory.h"
    33  #include "test/syscalls/linux/ip_socket_test_util.h"
    34  #include "test/util/posix_error.h"
    35  #include "test/util/save_util.h"
    36  #include "test/util/socket_util.h"
    37  #include "test/util/test_util.h"
    38  
    39  namespace gvisor {
    40  namespace testing {
    41  
    42  using ::testing::IsNull;
    43  using ::testing::NotNull;
    44  
    45  TEST_P(IPv6UDPUnboundSocketTest, IPv6PacketInfo) {
    46    auto sender_socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
    47    auto receiver_socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
    48  
    49    auto sender_addr = V6Loopback();
    50    ASSERT_THAT(bind(sender_socket->get(), AsSockAddr(&sender_addr.addr),
    51                     sender_addr.addr_len),
    52                SyscallSucceeds());
    53  
    54    auto receiver_addr = V6Loopback();
    55    ASSERT_THAT(bind(receiver_socket->get(), AsSockAddr(&receiver_addr.addr),
    56                     receiver_addr.addr_len),
    57                SyscallSucceeds());
    58    socklen_t receiver_addr_len = receiver_addr.addr_len;
    59    ASSERT_THAT(getsockname(receiver_socket->get(),
    60                            AsSockAddr(&receiver_addr.addr), &receiver_addr_len),
    61                SyscallSucceeds());
    62    ASSERT_EQ(receiver_addr_len, receiver_addr.addr_len);
    63  
    64    // Make sure we get IPv6 packet information as control messages.
    65    constexpr int one = 1;
    66    ASSERT_THAT(setsockopt(receiver_socket->get(), IPPROTO_IPV6, IPV6_RECVPKTINFO,
    67                           &one, sizeof(one)),
    68                SyscallSucceeds());
    69  
    70    // Send a packet - we don't care about the packet itself, only the returned
    71    // IPV6_PKTINFO control message.
    72    char send_buf[200];
    73    RandomizeBuffer(send_buf, sizeof(send_buf));
    74    ASSERT_THAT(RetryEINTR(sendto)(
    75                    sender_socket->get(), send_buf, sizeof(send_buf), 0,
    76                    AsSockAddr(&receiver_addr.addr), receiver_addr.addr_len),
    77                SyscallSucceedsWithValue(sizeof(send_buf)));
    78  
    79    // Check that we received the packet with the packet information control
    80    // message.
    81    char recv_buf[sizeof(send_buf) + 1];
    82    in6_pktinfo received_pktinfo;
    83    char recv_cmsg_buf[CMSG_SPACE(sizeof(received_pktinfo))];
    84    iovec recv_iov = {
    85        .iov_base = recv_buf,
    86        .iov_len = sizeof(recv_buf),
    87    };
    88    msghdr recv_msg = {
    89        .msg_iov = &recv_iov,
    90        .msg_iovlen = 1,
    91        .msg_control = recv_cmsg_buf,
    92        .msg_controllen = sizeof(recv_cmsg_buf),
    93    };
    94    ASSERT_THAT(RecvMsgTimeout(receiver_socket->get(), &recv_msg, 1 /*timeout*/),
    95                IsPosixErrorOkAndHolds(sizeof(send_buf)));
    96    EXPECT_EQ(memcmp(send_buf, recv_buf, sizeof(send_buf)), 0);
    97  
    98    cmsghdr* cmsg = CMSG_FIRSTHDR(&recv_msg);
    99    ASSERT_THAT(cmsg, NotNull());
   100    EXPECT_EQ(cmsg->cmsg_len, CMSG_LEN(sizeof(in6_pktinfo)));
   101    EXPECT_EQ(cmsg->cmsg_level, IPPROTO_IPV6);
   102    EXPECT_EQ(cmsg->cmsg_type, IPV6_PKTINFO);
   103    // As per cmsg(3) (https://www.man7.org/linux/man-pages/man3/cmsg.3.html),
   104    //
   105    //   CMSG_DATA() returns a pointer to the data portion of a cmsghdr. The
   106    //   pointer returned cannot be assumed to be suitably aligned for accessing
   107    //   arbitrary payload data types. Applications should not cast it to a
   108    //   pointer type matching the payload, but should instead use memcpy(3) to
   109    //   copy data to or from a suitably declared object.
   110    memcpy(&received_pktinfo, CMSG_DATA(cmsg), sizeof(received_pktinfo));
   111    EXPECT_EQ(
   112        memcmp(&received_pktinfo.ipi6_addr,
   113               &(reinterpret_cast<sockaddr_in6*>(&sender_addr.addr)->sin6_addr),
   114               sizeof(received_pktinfo.ipi6_addr)),
   115        0);
   116    EXPECT_EQ(received_pktinfo.ipi6_ifindex,
   117              ASSERT_NO_ERRNO_AND_VALUE(GetLoopbackIndex()));
   118    EXPECT_THAT(CMSG_NXTHDR(&recv_msg, cmsg), IsNull());
   119  }
   120  
   121  // Test that socket will receive IP_RECVORIGDSTADDR control message.
   122  TEST_P(IPv6UDPUnboundSocketTest, SetAndReceiveIPReceiveOrigDstAddr) {
   123    auto sender = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
   124    auto receiver = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
   125    auto receiver_addr = V6Loopback();
   126    int level = SOL_IPV6;
   127    int type = IPV6_RECVORIGDSTADDR;
   128  
   129    ASSERT_THAT(bind(receiver->get(), AsSockAddr(&receiver_addr.addr),
   130                     receiver_addr.addr_len),
   131                SyscallSucceeds());
   132  
   133    // Retrieve the port bound by the receiver.
   134    socklen_t receiver_addr_len = receiver_addr.addr_len;
   135    ASSERT_THAT(getsockname(receiver->get(), AsSockAddr(&receiver_addr.addr),
   136                            &receiver_addr_len),
   137                SyscallSucceeds());
   138    EXPECT_EQ(receiver_addr_len, receiver_addr.addr_len);
   139  
   140    ASSERT_THAT(connect(sender->get(), AsSockAddr(&receiver_addr.addr),
   141                        receiver_addr.addr_len),
   142                SyscallSucceeds());
   143  
   144    // Get address and port bound by the sender.
   145    sockaddr_storage sender_addr_storage;
   146    socklen_t sender_addr_len = sizeof(sender_addr_storage);
   147    ASSERT_THAT(getsockname(sender->get(), AsSockAddr(&sender_addr_storage),
   148                            &sender_addr_len),
   149                SyscallSucceeds());
   150    ASSERT_EQ(sender_addr_len, sizeof(struct sockaddr_in6));
   151  
   152    // Enable IP_RECVORIGDSTADDR on socket so that we get the original destination
   153    // address of the datagram as auxiliary information in the control message.
   154    ASSERT_THAT(
   155        setsockopt(receiver->get(), level, type, &kSockOptOn, sizeof(kSockOptOn)),
   156        SyscallSucceeds());
   157  
   158    // Prepare message to send.
   159    constexpr size_t kDataLength = 1024;
   160    msghdr sent_msg = {};
   161    iovec sent_iov = {};
   162    char sent_data[kDataLength];
   163    sent_iov.iov_base = sent_data;
   164    sent_iov.iov_len = kDataLength;
   165    sent_msg.msg_iov = &sent_iov;
   166    sent_msg.msg_iovlen = 1;
   167    sent_msg.msg_flags = 0;
   168  
   169    ASSERT_THAT(RetryEINTR(sendmsg)(sender->get(), &sent_msg, 0),
   170                SyscallSucceedsWithValue(kDataLength));
   171  
   172    msghdr received_msg = {};
   173    iovec received_iov = {};
   174    char received_data[kDataLength];
   175    char received_cmsg_buf[CMSG_SPACE(sizeof(sockaddr_in6))] = {};
   176    size_t cmsg_data_len = sizeof(sockaddr_in6);
   177    received_iov.iov_base = received_data;
   178    received_iov.iov_len = kDataLength;
   179    received_msg.msg_iov = &received_iov;
   180    received_msg.msg_iovlen = 1;
   181    received_msg.msg_controllen = CMSG_LEN(cmsg_data_len);
   182    received_msg.msg_control = received_cmsg_buf;
   183  
   184    ASSERT_THAT(RecvMsgTimeout(receiver->get(), &received_msg, 1 /*timeout*/),
   185                IsPosixErrorOkAndHolds(kDataLength));
   186  
   187    cmsghdr* cmsg = CMSG_FIRSTHDR(&received_msg);
   188    ASSERT_NE(cmsg, nullptr);
   189    EXPECT_EQ(cmsg->cmsg_len, CMSG_LEN(cmsg_data_len));
   190    EXPECT_EQ(cmsg->cmsg_level, level);
   191    EXPECT_EQ(cmsg->cmsg_type, type);
   192  
   193    // Check that the received address in the control message matches the expected
   194    // receiver's address.
   195    sockaddr_in6 received_addr = {};
   196    memcpy(&received_addr, CMSG_DATA(cmsg), sizeof(received_addr));
   197    auto orig_receiver_addr =
   198        reinterpret_cast<sockaddr_in6*>(&receiver_addr.addr);
   199    EXPECT_EQ(memcmp(&received_addr.sin6_addr, &orig_receiver_addr->sin6_addr,
   200                     sizeof(in6_addr)),
   201              0);
   202    EXPECT_EQ(received_addr.sin6_port, orig_receiver_addr->sin6_port);
   203  }
   204  
   205  }  // namespace testing
   206  }  // namespace gvisor