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