github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/syscalls/linux/ip_socket_test_util.cc (about)

     1  // Copyright 2018 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/ip_socket_test_util.h"
    16  
    17  #include <net/if.h>
    18  #include <netinet/in.h>
    19  #include <sys/socket.h>
    20  
    21  #include <cstring>
    22  
    23  namespace gvisor {
    24  namespace testing {
    25  
    26  uint32_t IPFromInetSockaddr(const struct sockaddr* addr) {
    27    auto* in_addr = reinterpret_cast<const struct sockaddr_in*>(addr);
    28    return in_addr->sin_addr.s_addr;
    29  }
    30  
    31  uint16_t PortFromInetSockaddr(const struct sockaddr* addr) {
    32    auto* in_addr = reinterpret_cast<const struct sockaddr_in*>(addr);
    33    return ntohs(in_addr->sin_port);
    34  }
    35  
    36  PosixErrorOr<int> InterfaceIndex(std::string name) {
    37    int index = if_nametoindex(name.c_str());
    38    if (index) {
    39      return index;
    40    }
    41    return PosixError(errno);
    42  }
    43  
    44  namespace {
    45  
    46  std::string DescribeSocketType(int type) {
    47    return absl::StrCat(((type & SOCK_NONBLOCK) != 0) ? "non-blocking " : "",
    48                        ((type & SOCK_CLOEXEC) != 0) ? "close-on-exec " : "");
    49  }
    50  
    51  }  // namespace
    52  
    53  SocketPairKind IPv6TCPAcceptBindSocketPair(int type) {
    54    std::string description =
    55        absl::StrCat(DescribeSocketType(type), "connected IPv6 TCP socket");
    56    return SocketPairKind{
    57        description, AF_INET6, type | SOCK_STREAM, IPPROTO_TCP,
    58        TCPAcceptBindSocketPairCreator(AF_INET6, type | SOCK_STREAM, 0,
    59                                       /* dual_stack = */ false)};
    60  }
    61  
    62  SocketPairKind IPv4TCPAcceptBindSocketPair(int type) {
    63    std::string description =
    64        absl::StrCat(DescribeSocketType(type), "connected IPv4 TCP socket");
    65    return SocketPairKind{
    66        description, AF_INET, type | SOCK_STREAM, IPPROTO_TCP,
    67        TCPAcceptBindSocketPairCreator(AF_INET, type | SOCK_STREAM, 0,
    68                                       /* dual_stack = */ false)};
    69  }
    70  
    71  SocketPairKind DualStackTCPAcceptBindSocketPair(int type) {
    72    std::string description =
    73        absl::StrCat(DescribeSocketType(type), "connected dual stack TCP socket");
    74    return SocketPairKind{
    75        description, AF_INET6, type | SOCK_STREAM, IPPROTO_TCP,
    76        TCPAcceptBindSocketPairCreator(AF_INET6, type | SOCK_STREAM, 0,
    77                                       /* dual_stack = */ true)};
    78  }
    79  
    80  SocketPairKind IPv6TCPAcceptBindPersistentListenerSocketPair(int type) {
    81    std::string description =
    82        absl::StrCat(DescribeSocketType(type), "connected IPv6 TCP socket");
    83    return SocketPairKind{description, AF_INET6, type | SOCK_STREAM, IPPROTO_TCP,
    84                          TCPAcceptBindPersistentListenerSocketPairCreator(
    85                              AF_INET6, type | SOCK_STREAM, 0,
    86                              /* dual_stack = */ false)};
    87  }
    88  
    89  SocketPairKind IPv4TCPAcceptBindPersistentListenerSocketPair(int type) {
    90    std::string description =
    91        absl::StrCat(DescribeSocketType(type), "connected IPv4 TCP socket");
    92    return SocketPairKind{description, AF_INET, type | SOCK_STREAM, IPPROTO_TCP,
    93                          TCPAcceptBindPersistentListenerSocketPairCreator(
    94                              AF_INET, type | SOCK_STREAM, 0,
    95                              /* dual_stack = */ false)};
    96  }
    97  
    98  SocketPairKind DualStackTCPAcceptBindPersistentListenerSocketPair(int type) {
    99    std::string description =
   100        absl::StrCat(DescribeSocketType(type), "connected dual stack TCP socket");
   101    return SocketPairKind{description, AF_INET6, type | SOCK_STREAM, IPPROTO_TCP,
   102                          TCPAcceptBindPersistentListenerSocketPairCreator(
   103                              AF_INET6, type | SOCK_STREAM, 0,
   104                              /* dual_stack = */ true)};
   105  }
   106  
   107  SocketPairKind IPv6UDPBidirectionalBindSocketPair(int type) {
   108    std::string description =
   109        absl::StrCat(DescribeSocketType(type), "connected IPv6 UDP socket");
   110    return SocketPairKind{
   111        description, AF_INET6, type | SOCK_DGRAM, IPPROTO_UDP,
   112        UDPBidirectionalBindSocketPairCreator(AF_INET6, type | SOCK_DGRAM, 0,
   113                                              /* dual_stack = */ false)};
   114  }
   115  
   116  SocketPairKind IPv4UDPBidirectionalBindSocketPair(int type) {
   117    std::string description =
   118        absl::StrCat(DescribeSocketType(type), "connected IPv4 UDP socket");
   119    return SocketPairKind{
   120        description, AF_INET, type | SOCK_DGRAM, IPPROTO_UDP,
   121        UDPBidirectionalBindSocketPairCreator(AF_INET, type | SOCK_DGRAM, 0,
   122                                              /* dual_stack = */ false)};
   123  }
   124  
   125  SocketPairKind DualStackUDPBidirectionalBindSocketPair(int type) {
   126    std::string description =
   127        absl::StrCat(DescribeSocketType(type), "connected dual stack UDP socket");
   128    return SocketPairKind{
   129        description, AF_INET6, type | SOCK_DGRAM, IPPROTO_UDP,
   130        UDPBidirectionalBindSocketPairCreator(AF_INET6, type | SOCK_DGRAM, 0,
   131                                              /* dual_stack = */ true)};
   132  }
   133  
   134  SocketPairKind IPv4UDPUnboundSocketPair(int type) {
   135    std::string description =
   136        absl::StrCat(DescribeSocketType(type), "IPv4 UDP socket");
   137    return SocketPairKind{
   138        description, AF_INET, type | SOCK_DGRAM, IPPROTO_UDP,
   139        UDPUnboundSocketPairCreator(AF_INET, type | SOCK_DGRAM, 0,
   140                                    /* dual_stack = */ false)};
   141  }
   142  
   143  SocketKind ICMPUnboundSocket(int type) {
   144    std::string description =
   145        absl::StrCat(DescribeSocketType(type), "ICMP socket");
   146    return SocketKind{
   147        description, AF_INET, type | SOCK_DGRAM, IPPROTO_ICMP,
   148        UnboundSocketCreator(AF_INET, type | SOCK_DGRAM, IPPROTO_ICMP)};
   149  }
   150  
   151  SocketKind ICMPv6UnboundSocket(int type) {
   152    std::string description =
   153        absl::StrCat(DescribeSocketType(type), "ICMPv6 socket");
   154    return SocketKind{
   155        description, AF_INET6, type | SOCK_DGRAM, IPPROTO_ICMPV6,
   156        UnboundSocketCreator(AF_INET6, type | SOCK_DGRAM, IPPROTO_ICMPV6)};
   157  }
   158  
   159  SocketKind IPv4UDPUnboundSocket(int type) {
   160    std::string description =
   161        absl::StrCat(DescribeSocketType(type), "IPv4 UDP socket");
   162    return SocketKind{
   163        description, AF_INET, type | SOCK_DGRAM, IPPROTO_UDP,
   164        UnboundSocketCreator(AF_INET, type | SOCK_DGRAM, IPPROTO_UDP)};
   165  }
   166  
   167  SocketKind IPv6UDPUnboundSocket(int type) {
   168    std::string description =
   169        absl::StrCat(DescribeSocketType(type), "IPv6 UDP socket");
   170    return SocketKind{
   171        description, AF_INET6, type | SOCK_DGRAM, IPPROTO_UDP,
   172        UnboundSocketCreator(AF_INET6, type | SOCK_DGRAM, IPPROTO_UDP)};
   173  }
   174  
   175  SocketKind IPv4TCPUnboundSocket(int type) {
   176    std::string description =
   177        absl::StrCat(DescribeSocketType(type), "IPv4 TCP socket");
   178    return SocketKind{
   179        description, AF_INET, type | SOCK_STREAM, IPPROTO_TCP,
   180        UnboundSocketCreator(AF_INET, type | SOCK_STREAM, IPPROTO_TCP)};
   181  }
   182  
   183  SocketKind IPv6TCPUnboundSocket(int type) {
   184    std::string description =
   185        absl::StrCat(DescribeSocketType(type), "IPv6 TCP socket");
   186    return SocketKind{
   187        description, AF_INET6, type | SOCK_STREAM, IPPROTO_TCP,
   188        UnboundSocketCreator(AF_INET6, type | SOCK_STREAM, IPPROTO_TCP)};
   189  }
   190  
   191  PosixError IfAddrHelper::Load() {
   192    Release();
   193  #ifndef ANDROID
   194    RETURN_ERROR_IF_SYSCALL_FAIL(getifaddrs(&ifaddr_));
   195  #else
   196    // Android does not support getifaddrs in r22.
   197    return PosixError(ENOSYS, "getifaddrs");
   198  #endif
   199    return NoError();
   200  }
   201  
   202  void IfAddrHelper::Release() {
   203    if (ifaddr_) {
   204  #ifndef ANDROID
   205      // Android does not support freeifaddrs in r22.
   206      freeifaddrs(ifaddr_);
   207  #endif
   208      ifaddr_ = nullptr;
   209    }
   210  }
   211  
   212  std::vector<std::string> IfAddrHelper::InterfaceList(int family) const {
   213    std::vector<std::string> names;
   214    for (auto ifa = ifaddr_; ifa != NULL; ifa = ifa->ifa_next) {
   215      if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != family) {
   216        continue;
   217      }
   218      names.emplace(names.end(), ifa->ifa_name);
   219    }
   220    return names;
   221  }
   222  
   223  const sockaddr* IfAddrHelper::GetAddr(int family, std::string name) const {
   224    for (auto ifa = ifaddr_; ifa != NULL; ifa = ifa->ifa_next) {
   225      if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != family) {
   226        continue;
   227      }
   228      if (name == ifa->ifa_name) {
   229        return ifa->ifa_addr;
   230      }
   231    }
   232    return nullptr;
   233  }
   234  
   235  PosixErrorOr<int> IfAddrHelper::GetIndex(std::string name) const {
   236    return InterfaceIndex(name);
   237  }
   238  
   239  std::string GetAddr4Str(const in_addr* a) {
   240    char str[INET_ADDRSTRLEN];
   241    inet_ntop(AF_INET, a, str, sizeof(str));
   242    return std::string(str);
   243  }
   244  
   245  std::string GetAddr6Str(const in6_addr* a) {
   246    char str[INET6_ADDRSTRLEN];
   247    inet_ntop(AF_INET6, a, str, sizeof(str));
   248    return std::string(str);
   249  }
   250  
   251  std::string GetAddrStr(const sockaddr* a) {
   252    if (a->sa_family == AF_INET) {
   253      auto src = &(reinterpret_cast<const sockaddr_in*>(a)->sin_addr);
   254      return GetAddr4Str(src);
   255    } else if (a->sa_family == AF_INET6) {
   256      auto src = &(reinterpret_cast<const sockaddr_in6*>(a)->sin6_addr);
   257      return GetAddr6Str(src);
   258    }
   259    return std::string("<invalid>");
   260  }
   261  
   262  }  // namespace testing
   263  }  // namespace gvisor