github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/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/syscalls/linux/socket_test_util.h"
    35  #include "test/util/posix_error.h"
    36  #include "test/util/save_util.h"
    37  #include "test/util/test_util.h"
    38  
    39  namespace gvisor {
    40  namespace testing {
    41  
    42  // Test that socket will receive IP_RECVORIGDSTADDR control message.
    43  TEST_P(IPv6UDPUnboundSocketTest, SetAndReceiveIPReceiveOrigDstAddr) {
    44    auto sender = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
    45    auto receiver = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
    46    auto receiver_addr = V6Loopback();
    47    int level = SOL_IPV6;
    48    int type = IPV6_RECVORIGDSTADDR;
    49  
    50    ASSERT_THAT(bind(receiver->get(), AsSockAddr(&receiver_addr.addr),
    51                     receiver_addr.addr_len),
    52                SyscallSucceeds());
    53  
    54    // Retrieve the port bound by the receiver.
    55    socklen_t receiver_addr_len = receiver_addr.addr_len;
    56    ASSERT_THAT(getsockname(receiver->get(), AsSockAddr(&receiver_addr.addr),
    57                            &receiver_addr_len),
    58                SyscallSucceeds());
    59    EXPECT_EQ(receiver_addr_len, receiver_addr.addr_len);
    60  
    61    ASSERT_THAT(connect(sender->get(), AsSockAddr(&receiver_addr.addr),
    62                        receiver_addr.addr_len),
    63                SyscallSucceeds());
    64  
    65    // Get address and port bound by the sender.
    66    sockaddr_storage sender_addr_storage;
    67    socklen_t sender_addr_len = sizeof(sender_addr_storage);
    68    ASSERT_THAT(getsockname(sender->get(), AsSockAddr(&sender_addr_storage),
    69                            &sender_addr_len),
    70                SyscallSucceeds());
    71    ASSERT_EQ(sender_addr_len, sizeof(struct sockaddr_in6));
    72  
    73    // Enable IP_RECVORIGDSTADDR on socket so that we get the original destination
    74    // address of the datagram as auxiliary information in the control message.
    75    ASSERT_THAT(
    76        setsockopt(receiver->get(), level, type, &kSockOptOn, sizeof(kSockOptOn)),
    77        SyscallSucceeds());
    78  
    79    // Prepare message to send.
    80    constexpr size_t kDataLength = 1024;
    81    msghdr sent_msg = {};
    82    iovec sent_iov = {};
    83    char sent_data[kDataLength];
    84    sent_iov.iov_base = sent_data;
    85    sent_iov.iov_len = kDataLength;
    86    sent_msg.msg_iov = &sent_iov;
    87    sent_msg.msg_iovlen = 1;
    88    sent_msg.msg_flags = 0;
    89  
    90    ASSERT_THAT(RetryEINTR(sendmsg)(sender->get(), &sent_msg, 0),
    91                SyscallSucceedsWithValue(kDataLength));
    92  
    93    msghdr received_msg = {};
    94    iovec received_iov = {};
    95    char received_data[kDataLength];
    96    char received_cmsg_buf[CMSG_SPACE(sizeof(sockaddr_in6))] = {};
    97    size_t cmsg_data_len = sizeof(sockaddr_in6);
    98    received_iov.iov_base = received_data;
    99    received_iov.iov_len = kDataLength;
   100    received_msg.msg_iov = &received_iov;
   101    received_msg.msg_iovlen = 1;
   102    received_msg.msg_controllen = CMSG_LEN(cmsg_data_len);
   103    received_msg.msg_control = received_cmsg_buf;
   104  
   105    ASSERT_THAT(RecvMsgTimeout(receiver->get(), &received_msg, 1 /*timeout*/),
   106                IsPosixErrorOkAndHolds(kDataLength));
   107  
   108    cmsghdr* cmsg = CMSG_FIRSTHDR(&received_msg);
   109    ASSERT_NE(cmsg, nullptr);
   110    EXPECT_EQ(cmsg->cmsg_len, CMSG_LEN(cmsg_data_len));
   111    EXPECT_EQ(cmsg->cmsg_level, level);
   112    EXPECT_EQ(cmsg->cmsg_type, type);
   113  
   114    // Check that the received address in the control message matches the expected
   115    // receiver's address.
   116    sockaddr_in6 received_addr = {};
   117    memcpy(&received_addr, CMSG_DATA(cmsg), sizeof(received_addr));
   118    auto orig_receiver_addr =
   119        reinterpret_cast<sockaddr_in6*>(&receiver_addr.addr);
   120    EXPECT_EQ(memcmp(&received_addr.sin6_addr, &orig_receiver_addr->sin6_addr,
   121                     sizeof(in6_addr)),
   122              0);
   123    EXPECT_EQ(received_addr.sin6_port, orig_receiver_addr->sin6_port);
   124  }
   125  
   126  }  // namespace testing
   127  }  // namespace gvisor