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