gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/socket_ipv6_unbound.cc (about) 1 // Copyright 2021 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 <netinet/in.h> 16 #ifdef __linux__ 17 #include <linux/in6.h> 18 #endif // __linux__ 19 #include <sys/socket.h> 20 #include <sys/types.h> 21 22 #include "gtest/gtest.h" 23 #include "test/syscalls/linux/ip_socket_test_util.h" 24 #include "test/util/socket_util.h" 25 #include "test/util/test_util.h" 26 27 namespace gvisor { 28 namespace testing { 29 namespace { 30 31 constexpr int kDefaultHopLimit = 64; 32 constexpr int kDefaultTtl = 64; 33 34 using ::testing::ValuesIn; 35 using IPv6UnboundSocketTest = SimpleSocketTest; 36 37 TEST_P(IPv6UnboundSocketTest, HopLimitDefault) { 38 std::unique_ptr<FileDescriptor> socket = 39 ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 40 41 const int set = -1; 42 ASSERT_THAT(setsockopt(socket->get(), IPPROTO_IPV6, IPV6_UNICAST_HOPS, &set, 43 sizeof(set)), 44 SyscallSucceedsWithValue(0)); 45 46 int get = -1; 47 socklen_t get_sz = sizeof(get); 48 ASSERT_THAT( 49 getsockopt(socket->get(), IPPROTO_IPV6, IPV6_UNICAST_HOPS, &get, &get_sz), 50 SyscallSucceedsWithValue(0)); 51 ASSERT_EQ(get_sz, sizeof(get)); 52 EXPECT_EQ(get, kDefaultTtl); 53 } 54 55 TEST_P(IPv6UnboundSocketTest, SetHopLimit) { 56 std::unique_ptr<FileDescriptor> socket = 57 ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 58 59 int get1 = -1; 60 socklen_t get1_sz = sizeof(get1); 61 ASSERT_THAT(getsockopt(socket->get(), IPPROTO_IPV6, IPV6_UNICAST_HOPS, &get1, 62 &get1_sz), 63 SyscallSucceedsWithValue(0)); 64 ASSERT_EQ(get1_sz, sizeof(get1)); 65 EXPECT_EQ(get1, kDefaultHopLimit); 66 67 const int set = (get1 % 255) + 1; 68 ASSERT_THAT(setsockopt(socket->get(), IPPROTO_IPV6, IPV6_UNICAST_HOPS, &set, 69 sizeof(set)), 70 SyscallSucceedsWithValue(0)); 71 72 int get2 = -1; 73 socklen_t get2_sz = sizeof(get2); 74 ASSERT_THAT(getsockopt(socket->get(), IPPROTO_IPV6, IPV6_UNICAST_HOPS, &get2, 75 &get2_sz), 76 SyscallSucceedsWithValue(0)); 77 ASSERT_EQ(get2_sz, sizeof(get2)); 78 EXPECT_EQ(get2, set); 79 } 80 81 TEST_P(IPv6UnboundSocketTest, ResetHopLimitToDefault) { 82 std::unique_ptr<FileDescriptor> socket = 83 ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 84 85 int get1 = -1; 86 socklen_t get1_sz = sizeof(get1); 87 ASSERT_THAT(getsockopt(socket->get(), IPPROTO_IPV6, IPV6_UNICAST_HOPS, &get1, 88 &get1_sz), 89 SyscallSucceedsWithValue(0)); 90 ASSERT_EQ(get1_sz, sizeof(get1)); 91 EXPECT_EQ(get1, kDefaultHopLimit); 92 93 const int set = (get1 % 255) + 1; 94 ASSERT_THAT(setsockopt(socket->get(), IPPROTO_IPV6, IPV6_UNICAST_HOPS, &set, 95 sizeof(set)), 96 SyscallSucceedsWithValue(0)); 97 98 constexpr int kUseDefaultHopLimit = -1; 99 ASSERT_THAT(setsockopt(socket->get(), IPPROTO_IPV6, IPV6_UNICAST_HOPS, 100 &kUseDefaultHopLimit, sizeof(kUseDefaultHopLimit)), 101 SyscallSucceedsWithValue(0)); 102 103 int get2 = -1; 104 socklen_t get2_sz = sizeof(get2); 105 ASSERT_THAT(getsockopt(socket->get(), IPPROTO_IPV6, IPV6_UNICAST_HOPS, &get2, 106 &get2_sz), 107 SyscallSucceedsWithValue(0)); 108 ASSERT_EQ(get2_sz, sizeof(get2)); 109 EXPECT_EQ(get2, get1); 110 } 111 112 TEST_P(IPv6UnboundSocketTest, ZeroHopLimit) { 113 std::unique_ptr<FileDescriptor> socket = 114 ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 115 116 constexpr int kZero = 0; 117 ASSERT_THAT(setsockopt(socket->get(), IPPROTO_IPV6, IPV6_UNICAST_HOPS, &kZero, 118 sizeof(kZero)), 119 SyscallSucceedsWithValue(0)); 120 121 int get = -1; 122 socklen_t get_sz = sizeof(get); 123 ASSERT_THAT( 124 getsockopt(socket->get(), IPPROTO_IPV6, IPV6_UNICAST_HOPS, &get, &get_sz), 125 SyscallSucceedsWithValue(0)); 126 ASSERT_EQ(get, kZero); 127 EXPECT_EQ(get_sz, sizeof(get)); 128 } 129 130 TEST_P(IPv6UnboundSocketTest, InvalidLargeHopLimit) { 131 std::unique_ptr<FileDescriptor> socket = 132 ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 133 134 constexpr int kInvalidLarge = 256; 135 EXPECT_THAT(setsockopt(socket->get(), IPPROTO_IPV6, IPV6_UNICAST_HOPS, 136 &kInvalidLarge, sizeof(kInvalidLarge)), 137 SyscallFailsWithErrno(EINVAL)); 138 } 139 140 TEST_P(IPv6UnboundSocketTest, InvalidNegativeHopLimit) { 141 std::unique_ptr<FileDescriptor> socket = 142 ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 143 144 constexpr int kInvalidNegative = -2; 145 EXPECT_THAT(setsockopt(socket->get(), IPPROTO_IPV6, IPV6_UNICAST_HOPS, 146 &kInvalidNegative, sizeof(kInvalidNegative)), 147 SyscallFailsWithErrno(EINVAL)); 148 } 149 150 TEST_P(IPv6UnboundSocketTest, SetTtlDoesNotAffectHopLimit) { 151 std::unique_ptr<FileDescriptor> socket = 152 ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 153 154 int get = -1; 155 socklen_t get_sz = sizeof(get); 156 ASSERT_THAT( 157 getsockopt(socket->get(), IPPROTO_IPV6, IPV6_UNICAST_HOPS, &get, &get_sz), 158 SyscallSucceedsWithValue(0)); 159 ASSERT_EQ(get_sz, sizeof(get)); 160 161 const int set = (get % 255) + 1; 162 ASSERT_THAT(setsockopt(socket->get(), IPPROTO_IP, IP_TTL, &set, sizeof(set)), 163 SyscallSucceedsWithValue(0)); 164 165 int get2 = -1; 166 socklen_t get2_sz = sizeof(get2); 167 ASSERT_THAT(getsockopt(socket->get(), IPPROTO_IPV6, IPV6_UNICAST_HOPS, &get2, 168 &get2_sz), 169 SyscallSucceedsWithValue(0)); 170 ASSERT_EQ(get2_sz, sizeof(get2)); 171 EXPECT_EQ(get2, get); 172 } 173 174 TEST_P(IPv6UnboundSocketTest, SetHopLimitDoesNotAffectTtl) { 175 std::unique_ptr<FileDescriptor> socket = 176 ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 177 178 int get = -1; 179 socklen_t get_sz = sizeof(get); 180 ASSERT_THAT(getsockopt(socket->get(), IPPROTO_IP, IP_TTL, &get, &get_sz), 181 SyscallSucceedsWithValue(0)); 182 ASSERT_EQ(get_sz, sizeof(get)); 183 184 const int set = (get % 255) + 1; 185 ASSERT_THAT(setsockopt(socket->get(), IPPROTO_IPV6, IPV6_UNICAST_HOPS, &set, 186 sizeof(set)), 187 SyscallSucceedsWithValue(0)); 188 189 int get2 = -1; 190 socklen_t get2_sz = sizeof(get2); 191 ASSERT_THAT(getsockopt(socket->get(), IPPROTO_IP, IP_TTL, &get2, &get2_sz), 192 SyscallSucceedsWithValue(0)); 193 ASSERT_EQ(get2_sz, sizeof(get2)); 194 EXPECT_EQ(get2, get); 195 } 196 197 INSTANTIATE_TEST_SUITE_P( 198 IPv6UnboundSockets, IPv6UnboundSocketTest, 199 ValuesIn(VecCat<SocketKind>( 200 ApplyVec<SocketKind>(IPv6UDPUnboundSocket, 201 std::vector<int>{0, SOCK_NONBLOCK}), 202 ApplyVec<SocketKind>(IPv6TCPUnboundSocket, 203 std::vector{0, SOCK_NONBLOCK})))); 204 205 } // namespace 206 } // namespace testing 207 } // namespace gvisor