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