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