github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/syscalls/linux/socket_ipv6_udp_unbound_external_networking.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_external_networking.h"
    16  
    17  namespace gvisor {
    18  namespace testing {
    19  
    20  TEST_P(IPv6UDPUnboundExternalNetworkingSocketTest, TestJoinLeaveMulticast) {
    21    SKIP_IF(!found_net_interfaces_);
    22  
    23    auto sender = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
    24    auto receiver = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
    25  
    26    auto receiver_addr = V6Any();
    27    ASSERT_THAT(bind(receiver->get(), AsSockAddr(&receiver_addr.addr),
    28                     receiver_addr.addr_len),
    29                SyscallSucceeds());
    30    socklen_t receiver_addr_len = receiver_addr.addr_len;
    31    ASSERT_THAT(getsockname(receiver->get(), AsSockAddr(&receiver_addr.addr),
    32                            &receiver_addr_len),
    33                SyscallSucceeds());
    34    EXPECT_EQ(receiver_addr_len, receiver_addr.addr_len);
    35  
    36    // Register to receive multicast packets.
    37    auto multicast_addr = V6Multicast();
    38    ipv6_mreq group_req = {
    39        .ipv6mr_multiaddr =
    40            reinterpret_cast<sockaddr_in6*>(&multicast_addr.addr)->sin6_addr,
    41        .ipv6mr_interface = static_cast<decltype(ipv6_mreq::ipv6mr_interface)>(
    42            ASSERT_NO_ERRNO_AND_VALUE(InterfaceIndex("lo"))),
    43    };
    44    ASSERT_THAT(setsockopt(receiver->get(), IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
    45                           &group_req, sizeof(group_req)),
    46                SyscallSucceeds());
    47  
    48    // Set the sender to the loopback interface.
    49    auto sender_addr = V6Loopback();
    50    ASSERT_THAT(
    51        bind(sender->get(), AsSockAddr(&sender_addr.addr), sender_addr.addr_len),
    52        SyscallSucceeds());
    53  
    54    // Send a multicast packet.
    55    auto send_addr = multicast_addr;
    56    reinterpret_cast<sockaddr_in6*>(&send_addr.addr)->sin6_port =
    57        reinterpret_cast<sockaddr_in6*>(&receiver_addr.addr)->sin6_port;
    58    char send_buf[200];
    59    RandomizeBuffer(send_buf, sizeof(send_buf));
    60    ASSERT_THAT(
    61        RetryEINTR(sendto)(sender->get(), send_buf, sizeof(send_buf), 0,
    62                           AsSockAddr(&send_addr.addr), send_addr.addr_len),
    63        SyscallSucceedsWithValue(sizeof(send_buf)));
    64  
    65    // Check that we received the multicast packet.
    66    char recv_buf[sizeof(send_buf)] = {};
    67    ASSERT_THAT(RetryEINTR(recv)(receiver->get(), recv_buf, sizeof(recv_buf), 0),
    68                SyscallSucceedsWithValue(sizeof(recv_buf)));
    69  
    70    EXPECT_EQ(0, memcmp(send_buf, recv_buf, sizeof(send_buf)));
    71  
    72    // Leave the group and make sure we don't receive its multicast traffic.
    73    ASSERT_THAT(setsockopt(receiver->get(), IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP,
    74                           &group_req, sizeof(group_req)),
    75                SyscallSucceeds());
    76    RandomizeBuffer(send_buf, sizeof(send_buf));
    77    ASSERT_THAT(
    78        RetryEINTR(sendto)(sender->get(), send_buf, sizeof(send_buf), 0,
    79                           AsSockAddr(&send_addr.addr), send_addr.addr_len),
    80        SyscallSucceedsWithValue(sizeof(send_buf)));
    81    ASSERT_THAT(RetryEINTR(recv)(receiver->get(), recv_buf, sizeof(recv_buf),
    82                                 MSG_DONTWAIT),
    83                SyscallFailsWithErrno(EAGAIN));
    84  }
    85  
    86  }  // namespace testing
    87  }  // namespace gvisor