gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/util/socket_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/util/socket_util.h"
    16  
    17  #include <arpa/inet.h>
    18  #include <netinet/in.h>
    19  #include <poll.h>
    20  #include <sys/socket.h>
    21  
    22  #include <cstddef>
    23  #include <functional>
    24  #include <memory>
    25  #include <stack>
    26  
    27  #include "gtest/gtest.h"
    28  #include "absl/strings/str_cat.h"
    29  #include "absl/strings/str_split.h"
    30  #include "absl/time/clock.h"
    31  #include "absl/types/optional.h"
    32  #include "test/util/file_descriptor.h"
    33  #include "test/util/posix_error.h"
    34  #include "test/util/temp_path.h"
    35  #include "test/util/test_util.h"
    36  #include "test/util/thread_util.h"
    37  
    38  namespace gvisor {
    39  namespace testing {
    40  
    41  Creator<SocketPair> SyscallSocketPairCreator(int domain, int type,
    42                                               int protocol) {
    43    return [=]() -> PosixErrorOr<std::unique_ptr<FDSocketPair>> {
    44      int pair[2];
    45      RETURN_ERROR_IF_SYSCALL_FAIL(socketpair(domain, type, protocol, pair));
    46      MaybeSave();  // Save on successful creation.
    47      return std::make_unique<FDSocketPair>(FileDescriptor(pair[0]),
    48                                            FileDescriptor(pair[1]));
    49    };
    50  }
    51  
    52  Creator<FileDescriptor> SyscallSocketCreator(int domain, int type,
    53                                               int protocol) {
    54    return [=]() -> PosixErrorOr<std::unique_ptr<FileDescriptor>> {
    55      int fd = 0;
    56      RETURN_ERROR_IF_SYSCALL_FAIL(fd = socket(domain, type, protocol));
    57      MaybeSave();  // Save on successful creation.
    58      return std::make_unique<FileDescriptor>(fd);
    59    };
    60  }
    61  
    62  PosixErrorOr<struct sockaddr_un> UniqueUnixAddr(bool abstract, int domain) {
    63    struct sockaddr_un addr = {};
    64  
    65  #ifdef ANDROID
    66    // Using NewTempAbsPath() can cause the tmp directory path to exceed the max
    67    // length (i.e., sizeof(addr.sun_path)).
    68    //
    69    // However, existing systems that are built with the ANDROID configuration
    70    // have their temp directory in a different location, and must respect the
    71    // TEST_TMPDIR.
    72    std::string path = NewTempAbsPath();
    73  #else
    74    std::string path = NewTempAbsPathInDir("/tmp");
    75  #endif  // ANDROID
    76  
    77    if (path.size() >= sizeof(addr.sun_path)) {
    78      return PosixError(EINVAL,
    79                        "Unable to generate a temp path of appropriate length");
    80    }
    81  
    82    if (abstract) {
    83      // Indicate that the path is in the abstract namespace.
    84      path[0] = 0;
    85    }
    86    memcpy(addr.sun_path, path.c_str(), path.length());
    87    addr.sun_family = domain;
    88    return addr;
    89  }
    90  
    91  Creator<SocketPair> AcceptBindSocketPairCreator(bool abstract, int domain,
    92                                                  int type, int protocol) {
    93    return [=]() -> PosixErrorOr<std::unique_ptr<AddrFDSocketPair>> {
    94      ASSIGN_OR_RETURN_ERRNO(struct sockaddr_un bind_addr,
    95                             UniqueUnixAddr(abstract, domain));
    96      ASSIGN_OR_RETURN_ERRNO(struct sockaddr_un extra_addr,
    97                             UniqueUnixAddr(abstract, domain));
    98  
    99      ASSIGN_OR_RETURN_ERRNO(auto bound, Socket(domain, type, protocol));
   100      MaybeSave();  // Successful socket creation.
   101      RETURN_ERROR_IF_SYSCALL_FAIL(
   102          bind(bound.get(), AsSockAddr(&bind_addr), sizeof(bind_addr)));
   103      MaybeSave();  // Successful bind.
   104      RETURN_ERROR_IF_SYSCALL_FAIL(listen(
   105          bound.get(), /* backlog = */ 5));  // NOLINT(bugprone-argument-comment)
   106      MaybeSave();                           // Successful listen.
   107  
   108      ASSIGN_OR_RETURN_ERRNO(auto connected, Socket(domain, type, protocol));
   109      MaybeSave();  // Successful socket creation.
   110      RETURN_ERROR_IF_SYSCALL_FAIL(
   111          connect(connected.get(), AsSockAddr(&bind_addr), sizeof(bind_addr)));
   112      MaybeSave();  // Successful connect.
   113  
   114      ASSIGN_OR_RETURN_ERRNO(auto accepted,
   115                             Accept4(bound.get(), nullptr, nullptr,
   116                                     type & (SOCK_NONBLOCK | SOCK_CLOEXEC)));
   117      MaybeSave();  // Successful connect.
   118  
   119      // Cleanup no longer needed resources.
   120      RETURN_ERROR_IF_SYSCALL_FAIL(close(bound.release()));
   121      MaybeSave();  // Dropped original socket.
   122  
   123      // Only unlink if path is not in abstract namespace.
   124      if (bind_addr.sun_path[0] != 0) {
   125        RETURN_ERROR_IF_SYSCALL_FAIL(unlink(bind_addr.sun_path));
   126        MaybeSave();  // Unlinked path.
   127      }
   128  
   129      // accepted is before connected to destruct connected before accepted.
   130      // Destructors for nonstatic member objects are called in the reverse order
   131      // in which they appear in the class declaration.
   132      return std::make_unique<AddrFDSocketPair>(
   133          std::move(accepted), std::move(connected), bind_addr, extra_addr);
   134    };
   135  }
   136  
   137  Creator<SocketPair> FilesystemAcceptBindSocketPairCreator(int domain, int type,
   138                                                            int protocol) {
   139    return AcceptBindSocketPairCreator(/* abstract= */ false, domain, type,
   140                                       protocol);
   141  }
   142  
   143  Creator<SocketPair> AbstractAcceptBindSocketPairCreator(int domain, int type,
   144                                                          int protocol) {
   145    return AcceptBindSocketPairCreator(/* abstract= */ true, domain, type,
   146                                       protocol);
   147  }
   148  
   149  Creator<SocketPair> BidirectionalBindSocketPairCreator(bool abstract,
   150                                                         int domain, int type,
   151                                                         int protocol) {
   152    return [=]() -> PosixErrorOr<std::unique_ptr<FDSocketPair>> {
   153      ASSIGN_OR_RETURN_ERRNO(struct sockaddr_un addr1,
   154                             UniqueUnixAddr(abstract, domain));
   155      ASSIGN_OR_RETURN_ERRNO(struct sockaddr_un addr2,
   156                             UniqueUnixAddr(abstract, domain));
   157  
   158      ASSIGN_OR_RETURN_ERRNO(auto sock1, Socket(domain, type, protocol));
   159      MaybeSave();  // Successful socket creation.
   160      RETURN_ERROR_IF_SYSCALL_FAIL(
   161          bind(sock1.get(), AsSockAddr(&addr1), sizeof(addr1)));
   162      MaybeSave();  // Successful bind.
   163  
   164      ASSIGN_OR_RETURN_ERRNO(auto sock2, Socket(domain, type, protocol));
   165      MaybeSave();  // Successful socket creation.
   166      RETURN_ERROR_IF_SYSCALL_FAIL(
   167          bind(sock2.get(), AsSockAddr(&addr2), sizeof(addr2)));
   168      MaybeSave();  // Successful bind.
   169  
   170      RETURN_ERROR_IF_SYSCALL_FAIL(
   171          connect(sock1.get(), AsSockAddr(&addr2), sizeof(addr2)));
   172      MaybeSave();  // Successful connect.
   173  
   174      RETURN_ERROR_IF_SYSCALL_FAIL(
   175          connect(sock2.get(), AsSockAddr(&addr1), sizeof(addr1)));
   176      MaybeSave();  // Successful connect.
   177  
   178      // Cleanup no longer needed resources.
   179  
   180      // Only unlink if path is not in abstract namespace.
   181      if (addr1.sun_path[0] != 0) {
   182        RETURN_ERROR_IF_SYSCALL_FAIL(unlink(addr1.sun_path));
   183        MaybeSave();  // Successful unlink.
   184      }
   185  
   186      // Only unlink if path is not in abstract namespace.
   187      if (addr2.sun_path[0] != 0) {
   188        RETURN_ERROR_IF_SYSCALL_FAIL(unlink(addr2.sun_path));
   189        MaybeSave();  // Successful unlink.
   190      }
   191  
   192      return std::make_unique<FDSocketPair>(std::move(sock1), std::move(sock2));
   193    };
   194  }
   195  
   196  Creator<SocketPair> FilesystemBidirectionalBindSocketPairCreator(int domain,
   197                                                                   int type,
   198                                                                   int protocol) {
   199    return BidirectionalBindSocketPairCreator(/* abstract= */ false, domain, type,
   200                                              protocol);
   201  }
   202  
   203  Creator<SocketPair> AbstractBidirectionalBindSocketPairCreator(int domain,
   204                                                                 int type,
   205                                                                 int protocol) {
   206    return BidirectionalBindSocketPairCreator(/* abstract= */ true, domain, type,
   207                                              protocol);
   208  }
   209  
   210  Creator<SocketPair> SocketpairGoferSocketPairCreator(int domain, int type,
   211                                                       int protocol) {
   212    return [=]() -> PosixErrorOr<std::unique_ptr<FDSocketPair>> {
   213      struct sockaddr_un addr = {};
   214      constexpr char kSocketGoferPath[] = "/socket";
   215      memcpy(addr.sun_path, kSocketGoferPath, sizeof(kSocketGoferPath));
   216      addr.sun_family = domain;
   217  
   218      ASSIGN_OR_RETURN_ERRNO(auto sock1, Socket(domain, type, protocol));
   219      MaybeSave();  // Successful socket creation.
   220      RETURN_ERROR_IF_SYSCALL_FAIL(
   221          connect(sock1.get(), AsSockAddr(&addr), sizeof(addr)));
   222      MaybeSave();  // Successful connect.
   223  
   224      ASSIGN_OR_RETURN_ERRNO(auto sock2, Socket(domain, type, protocol));
   225      MaybeSave();  // Successful socket creation.
   226      RETURN_ERROR_IF_SYSCALL_FAIL(
   227          connect(sock2.get(), AsSockAddr(&addr), sizeof(addr)));
   228      MaybeSave();  // Successful connect.
   229  
   230      // Make and close another socketpair to ensure that the duped ends of the
   231      // first socketpair get closed.
   232      //
   233      // The problem is that there is no way to atomically send and close an FD.
   234      // The closest that we can do is send and then immediately close the FD,
   235      // which is what we do in the gofer. The gofer won't respond to another
   236      // request until the reply is sent and the FD is closed, so forcing the
   237      // gofer to handle another request will ensure that this has happened.
   238      for (int i = 0; i < 2; i++) {
   239        int sock;
   240        RETURN_ERROR_IF_SYSCALL_FAIL(sock = socket(domain, type, protocol));
   241        RETURN_ERROR_IF_SYSCALL_FAIL(
   242            connect(sock, AsSockAddr(&addr), sizeof(addr)));
   243        RETURN_ERROR_IF_SYSCALL_FAIL(close(sock));
   244      }
   245  
   246      return std::make_unique<FDSocketPair>(std::move(sock1), std::move(sock2));
   247    };
   248  }
   249  
   250  Creator<SocketPair> SocketpairGoferFileSocketPairCreator(int flags) {
   251    return [=]() -> PosixErrorOr<std::unique_ptr<FDSocketPair>> {
   252      constexpr char kSocketGoferPath[] = "/socket";
   253  
   254      FileDescriptor sock1;
   255      {
   256        int sock1_fd;
   257        RETURN_ERROR_IF_SYSCALL_FAIL(sock1_fd =
   258                                         open(kSocketGoferPath, O_RDWR | flags));
   259        MaybeSave();  // Successful socket creation.
   260        sock1.reset(sock1_fd);
   261      }
   262  
   263      FileDescriptor sock2;
   264      {
   265        int sock2_fd;
   266        RETURN_ERROR_IF_SYSCALL_FAIL(sock2_fd =
   267                                         open(kSocketGoferPath, O_RDWR | flags));
   268        MaybeSave();  // Successful socket creation.
   269        sock2.reset(sock2_fd);
   270      }
   271  
   272      return std::make_unique<FDSocketPair>(std::move(sock1), std::move(sock2));
   273    };
   274  }
   275  
   276  Creator<SocketPair> UnboundSocketPairCreator(bool abstract, int domain,
   277                                               int type, int protocol) {
   278    return [=]() -> PosixErrorOr<std::unique_ptr<AddrFDSocketPair>> {
   279      ASSIGN_OR_RETURN_ERRNO(struct sockaddr_un addr1,
   280                             UniqueUnixAddr(abstract, domain));
   281      ASSIGN_OR_RETURN_ERRNO(struct sockaddr_un addr2,
   282                             UniqueUnixAddr(abstract, domain));
   283  
   284      ASSIGN_OR_RETURN_ERRNO(auto sock1, Socket(domain, type, protocol));
   285      MaybeSave();  // Successful socket creation.
   286      ASSIGN_OR_RETURN_ERRNO(auto sock2, Socket(domain, type, protocol));
   287      MaybeSave();  // Successful socket creation.
   288      return std::make_unique<AddrFDSocketPair>(std::move(sock1),
   289                                                std::move(sock2), addr1, addr2);
   290    };
   291  }
   292  
   293  Creator<SocketPair> FilesystemUnboundSocketPairCreator(int domain, int type,
   294                                                         int protocol) {
   295    return UnboundSocketPairCreator(/* abstract= */ false, domain, type,
   296                                    protocol);
   297  }
   298  
   299  Creator<SocketPair> AbstractUnboundSocketPairCreator(int domain, int type,
   300                                                       int protocol) {
   301    return UnboundSocketPairCreator(/* abstract= */ true, domain, type, protocol);
   302  }
   303  
   304  void LocalhostAddr(struct sockaddr_in* addr, bool dual_stack) {
   305    addr->sin_family = AF_INET;
   306    addr->sin_port = htons(0);
   307    inet_pton(AF_INET, "127.0.0.1",
   308              reinterpret_cast<void*>(&addr->sin_addr.s_addr));
   309  }
   310  
   311  void LocalhostAddr(struct sockaddr_in6* addr, bool dual_stack) {
   312    addr->sin6_family = AF_INET6;
   313    addr->sin6_port = htons(0);
   314    if (dual_stack) {
   315      inet_pton(AF_INET6, "::ffff:127.0.0.1",
   316                reinterpret_cast<void*>(&addr->sin6_addr.s6_addr));
   317    } else {
   318      inet_pton(AF_INET6, "::1",
   319                reinterpret_cast<void*>(&addr->sin6_addr.s6_addr));
   320    }
   321    addr->sin6_scope_id = 0;
   322  }
   323  
   324  template <typename T>
   325  PosixErrorOr<T> BindIP(int fd, bool dual_stack) {
   326    T addr = {};
   327    LocalhostAddr(&addr, dual_stack);
   328    RETURN_ERROR_IF_SYSCALL_FAIL(bind(fd, AsSockAddr(&addr), sizeof(addr)));
   329    socklen_t addrlen = sizeof(addr);
   330    RETURN_ERROR_IF_SYSCALL_FAIL(getsockname(fd, AsSockAddr(&addr), &addrlen));
   331    return addr;
   332  }
   333  
   334  template <typename T>
   335  PosixErrorOr<T> TCPBindAndListen(int fd, bool dual_stack) {
   336    ASSIGN_OR_RETURN_ERRNO(T addr, BindIP<T>(fd, dual_stack));
   337    RETURN_ERROR_IF_SYSCALL_FAIL(
   338        listen(fd, /* backlog = */ 5));  // NOLINT(bugprone-argument-comment)
   339    return addr;
   340  }
   341  
   342  template <typename T>
   343  PosixErrorOr<std::unique_ptr<AddrFDSocketPair>>
   344  CreateTCPConnectAcceptSocketPair(int bound, FileDescriptor connected, int type,
   345                                   bool dual_stack, T bind_addr) {
   346    int connect_result = 0;
   347    RETURN_ERROR_IF_SYSCALL_FAIL(
   348        (connect_result = RetryEINTR(connect)(
   349             connected.get(), AsSockAddr(&bind_addr), sizeof(bind_addr))) == -1 &&
   350                errno == EINPROGRESS
   351            ? 0
   352            : connect_result);
   353    MaybeSave();  // Successful connect.
   354  
   355    if (connect_result == -1) {
   356      struct pollfd connect_poll = {connected.get(), POLLOUT | POLLERR | POLLHUP,
   357                                    0};
   358      int num_fds;
   359      RETURN_ERROR_IF_SYSCALL_FAIL(
   360          (num_fds = RetryEINTR(poll)(&connect_poll, 1, -1)));
   361      if (num_fds != 1) {
   362        return PosixError(ENOTCONN, "connect failed");
   363      }
   364      int error = 0;
   365      socklen_t errorlen = sizeof(error);
   366      RETURN_ERROR_IF_SYSCALL_FAIL(
   367          getsockopt(connected.get(), SOL_SOCKET, SO_ERROR, &error, &errorlen));
   368      errno = error;
   369      RETURN_ERROR_IF_SYSCALL_FAIL(
   370          /* connect */ error == 0 ? 0 : -1);
   371    }
   372  
   373    int accepted_fd = -1;
   374    struct pollfd accept_poll = {bound, POLLIN, 0};
   375    while (accepted_fd == -1) {
   376      RETURN_ERROR_IF_SYSCALL_FAIL(RetryEINTR(poll)(&accept_poll, 1, 0));
   377  
   378      RETURN_ERROR_IF_SYSCALL_FAIL(
   379          (accepted_fd = RetryEINTR(accept4)(
   380               bound, nullptr, nullptr, type & (SOCK_NONBLOCK | SOCK_CLOEXEC))) ==
   381                      -1 &&
   382                  errno == EAGAIN
   383              ? 0
   384              : accepted_fd);
   385    }
   386    FileDescriptor accepted(accepted_fd);
   387    MaybeSave();  // Successful accept.
   388  
   389    T extra_addr = {};
   390    LocalhostAddr(&extra_addr, dual_stack);
   391    return std::make_unique<AddrFDSocketPair>(
   392        std::move(connected), std::move(accepted), bind_addr, extra_addr);
   393  }
   394  
   395  template <typename T>
   396  PosixErrorOr<std::unique_ptr<AddrFDSocketPair>> CreateTCPAcceptBindSocketPair(
   397      FileDescriptor bound, FileDescriptor connected, int type, bool dual_stack) {
   398    ASSIGN_OR_RETURN_ERRNO(T bind_addr,
   399                           TCPBindAndListen<T>(bound.get(), dual_stack));
   400  
   401    auto result = CreateTCPConnectAcceptSocketPair(
   402        bound.get(), std::move(connected), type, dual_stack, bind_addr);
   403  
   404    // Cleanup no longer needed resources.
   405    RETURN_ERROR_IF_SYSCALL_FAIL(close(bound.release()));
   406    MaybeSave();  // Successful close.
   407  
   408    return result;
   409  }
   410  
   411  Creator<SocketPair> TCPAcceptBindSocketPairCreator(int domain, int type,
   412                                                     int protocol,
   413                                                     bool dual_stack) {
   414    return [=]() -> PosixErrorOr<std::unique_ptr<AddrFDSocketPair>> {
   415      ASSIGN_OR_RETURN_ERRNO(auto bound, Socket(domain, type, protocol));
   416      MaybeSave();  // Successful socket creation.
   417  
   418      ASSIGN_OR_RETURN_ERRNO(auto connected, Socket(domain, type, protocol));
   419      MaybeSave();  // Successful socket creation.
   420  
   421      if (domain == AF_INET) {
   422        return CreateTCPAcceptBindSocketPair<sockaddr_in>(
   423            std::move(bound), std::move(connected), type, dual_stack);
   424      }
   425      return CreateTCPAcceptBindSocketPair<sockaddr_in6>(
   426          std::move(bound), std::move(connected), type, dual_stack);
   427    };
   428  }
   429  
   430  Creator<SocketPair> TCPAcceptBindPersistentListenerSocketPairCreator(
   431      int domain, int type, int protocol, bool dual_stack) {
   432    // These are lazily initialized below, on the first call to the returned
   433    // lambda. These values are private to each returned lambda, but shared across
   434    // invocations of a specific lambda.
   435    //
   436    // The sharing allows pairs created with the same parameters to share a
   437    // listener. This prevents future connects from failing if the connecting
   438    // socket selects a port which had previously been used by a listening socket
   439    // that still has some connections in TIME-WAIT.
   440    //
   441    // The lazy initialization is to avoid creating sockets during parameter
   442    // enumeration. This is important because parameters are enumerated during the
   443    // build process where networking may not be available.
   444    auto listener = std::make_shared<absl::optional<int>>(absl::optional<int>());
   445    auto addr4 = std::make_shared<absl::optional<sockaddr_in>>(
   446        absl::optional<sockaddr_in>());
   447    auto addr6 = std::make_shared<absl::optional<sockaddr_in6>>(
   448        absl::optional<sockaddr_in6>());
   449  
   450    return [=]() -> PosixErrorOr<std::unique_ptr<AddrFDSocketPair>> {
   451      ASSIGN_OR_RETURN_ERRNO(auto connected, Socket(domain, type, protocol));
   452      MaybeSave();  // Successful socket creation.
   453  
   454      // Share the listener across invocations.
   455      if (!listener->has_value()) {
   456        int fd = socket(domain, type, protocol);
   457        if (fd < 0) {
   458          return PosixError(errno, absl::StrCat("socket(", domain, ", ", type,
   459                                                ", ", protocol, ")"));
   460        }
   461        listener->emplace(fd);
   462        MaybeSave();  // Successful socket creation.
   463      }
   464  
   465      // Bind the listener once, but create a new connect/accept pair each
   466      // time.
   467      if (domain == AF_INET) {
   468        if (!addr4->has_value()) {
   469          addr4->emplace(
   470              TCPBindAndListen<sockaddr_in>(listener->value(), dual_stack)
   471                  .ValueOrDie());
   472        }
   473        return CreateTCPConnectAcceptSocketPair(listener->value(),
   474                                                std::move(connected), type,
   475                                                dual_stack, addr4->value());
   476      }
   477      if (!addr6->has_value()) {
   478        addr6->emplace(
   479            TCPBindAndListen<sockaddr_in6>(listener->value(), dual_stack)
   480                .ValueOrDie());
   481      }
   482      return CreateTCPConnectAcceptSocketPair(listener->value(),
   483                                              std::move(connected), type,
   484                                              dual_stack, addr6->value());
   485    };
   486  }
   487  
   488  template <typename T>
   489  PosixErrorOr<std::unique_ptr<AddrFDSocketPair>> CreateUDPBoundSocketPair(
   490      FileDescriptor sock1, FileDescriptor sock2, int type, bool dual_stack) {
   491    ASSIGN_OR_RETURN_ERRNO(T addr1, BindIP<T>(sock1.get(), dual_stack));
   492    ASSIGN_OR_RETURN_ERRNO(T addr2, BindIP<T>(sock2.get(), dual_stack));
   493  
   494    return std::make_unique<AddrFDSocketPair>(std::move(sock1), std::move(sock2),
   495                                              addr1, addr2);
   496  }
   497  
   498  template <typename T>
   499  PosixErrorOr<std::unique_ptr<AddrFDSocketPair>>
   500  CreateUDPBidirectionalBindSocketPair(FileDescriptor sock1, FileDescriptor sock2,
   501                                       int type, bool dual_stack) {
   502    ASSIGN_OR_RETURN_ERRNO(
   503        auto socks, CreateUDPBoundSocketPair<T>(
   504                        std::move(sock1), std::move(sock2), type, dual_stack));
   505  
   506    // Connect sock1 to sock2.
   507    RETURN_ERROR_IF_SYSCALL_FAIL(connect(socks->first_fd(), socks->second_addr(),
   508                                         socks->second_addr_size()));
   509    MaybeSave();  // Successful connection.
   510  
   511    // Connect sock2 to sock1.
   512    RETURN_ERROR_IF_SYSCALL_FAIL(connect(socks->second_fd(), socks->first_addr(),
   513                                         socks->first_addr_size()));
   514    MaybeSave();  // Successful connection.
   515  
   516    return socks;
   517  }
   518  
   519  Creator<SocketPair> UDPBidirectionalBindSocketPairCreator(int domain, int type,
   520                                                            int protocol,
   521                                                            bool dual_stack) {
   522    return [=]() -> PosixErrorOr<std::unique_ptr<AddrFDSocketPair>> {
   523      ASSIGN_OR_RETURN_ERRNO(auto sock1, Socket(domain, type, protocol));
   524      MaybeSave();  // Successful socket creation.
   525  
   526      ASSIGN_OR_RETURN_ERRNO(auto sock2, Socket(domain, type, protocol));
   527      MaybeSave();  // Successful socket creation.
   528  
   529      if (domain == AF_INET) {
   530        return CreateUDPBidirectionalBindSocketPair<sockaddr_in>(
   531            std::move(sock1), std::move(sock2), type, dual_stack);
   532      }
   533      return CreateUDPBidirectionalBindSocketPair<sockaddr_in6>(
   534          std::move(sock1), std::move(sock2), type, dual_stack);
   535    };
   536  }
   537  
   538  Creator<SocketPair> UDPUnboundSocketPairCreator(int domain, int type,
   539                                                  int protocol, bool dual_stack) {
   540    return [=]() -> PosixErrorOr<std::unique_ptr<FDSocketPair>> {
   541      ASSIGN_OR_RETURN_ERRNO(auto sock1, Socket(domain, type, protocol));
   542      MaybeSave();  // Successful socket creation.
   543  
   544      ASSIGN_OR_RETURN_ERRNO(auto sock2, Socket(domain, type, protocol));
   545      MaybeSave();  // Successful socket creation.
   546  
   547      return std::make_unique<FDSocketPair>(std::move(sock1), std::move(sock2));
   548    };
   549  }
   550  
   551  SocketPairKind Reversed(SocketPairKind const& base) {
   552    auto const& creator = base.creator;
   553    return SocketPairKind{
   554        absl::StrCat("reversed ", base.description), base.domain, base.type,
   555        base.protocol,
   556        [creator]() -> PosixErrorOr<std::unique_ptr<ReversedSocketPair>> {
   557          ASSIGN_OR_RETURN_ERRNO(auto creator_value, creator());
   558          return std::make_unique<ReversedSocketPair>(std::move(creator_value));
   559        }};
   560  }
   561  
   562  Creator<FileDescriptor> UnboundSocketCreator(int domain, int type,
   563                                               int protocol) {
   564    return [=]() -> PosixErrorOr<std::unique_ptr<FileDescriptor>> {
   565      int sock;
   566      RETURN_ERROR_IF_SYSCALL_FAIL(sock = socket(domain, type, protocol));
   567      MaybeSave();  // Successful socket creation.
   568  
   569      return std::make_unique<FileDescriptor>(sock);
   570    };
   571  }
   572  
   573  std::vector<SocketPairKind> IncludeReversals(std::vector<SocketPairKind> vec) {
   574    return ApplyVecToVec<SocketPairKind>(std::vector<Middleware>{NoOp, Reversed},
   575                                         vec);
   576  }
   577  
   578  SocketPairKind NoOp(SocketPairKind const& base) { return base; }
   579  
   580  void TransferTest(int fd1, int fd2) {
   581    char buf1[20];
   582    RandomizeBuffer(buf1, sizeof(buf1));
   583    ASSERT_THAT(WriteFd(fd1, buf1, sizeof(buf1)),
   584                SyscallSucceedsWithValue(sizeof(buf1)));
   585  
   586    char buf2[20];
   587    ASSERT_THAT(ReadFd(fd2, buf2, sizeof(buf2)),
   588                SyscallSucceedsWithValue(sizeof(buf2)));
   589  
   590    EXPECT_EQ(0, memcmp(buf1, buf2, sizeof(buf1)));
   591  
   592    RandomizeBuffer(buf1, sizeof(buf1));
   593    ASSERT_THAT(WriteFd(fd2, buf1, sizeof(buf1)),
   594                SyscallSucceedsWithValue(sizeof(buf1)));
   595  
   596    ASSERT_THAT(ReadFd(fd1, buf2, sizeof(buf2)),
   597                SyscallSucceedsWithValue(sizeof(buf2)));
   598  
   599    EXPECT_EQ(0, memcmp(buf1, buf2, sizeof(buf1)));
   600  }
   601  
   602  size_t CalculateUnixSockAddrLen(const char* sun_path) {
   603    // Abstract addresses always return the full length.
   604    if (sun_path[0] == 0) {
   605      return sizeof(sockaddr_un);
   606    }
   607    // Filesystem addresses use the address length plus the 2 byte sun_family
   608    // and null terminator.
   609    return strlen(sun_path) + 3;
   610  }
   611  
   612  struct sockaddr_storage AddrFDSocketPair::to_storage(const sockaddr_un& addr) {
   613    struct sockaddr_storage addr_storage = {};
   614    memcpy(&addr_storage, &addr, sizeof(addr));
   615    return addr_storage;
   616  }
   617  
   618  struct sockaddr_storage AddrFDSocketPair::to_storage(const sockaddr_in& addr) {
   619    struct sockaddr_storage addr_storage = {};
   620    memcpy(&addr_storage, &addr, sizeof(addr));
   621    return addr_storage;
   622  }
   623  
   624  struct sockaddr_storage AddrFDSocketPair::to_storage(const sockaddr_in6& addr) {
   625    struct sockaddr_storage addr_storage = {};
   626    memcpy(&addr_storage, &addr, sizeof(addr));
   627    return addr_storage;
   628  }
   629  
   630  SocketKind SimpleSocket(int fam, int type, int proto) {
   631    return SocketKind{
   632        absl::StrCat("Family ", fam, ", type ", type, ", proto ", proto), fam,
   633        type, proto, SyscallSocketCreator(fam, type, proto)};
   634  }
   635  
   636  ssize_t SendLargeSendMsg(const std::unique_ptr<SocketPair>& sockets,
   637                           size_t size, bool reader) {
   638    const int rfd = sockets->second_fd();
   639    ScopedThread t([rfd, size, reader] {
   640      if (!reader) {
   641        return;
   642      }
   643  
   644      // Potentially too many syscalls in the loop.
   645      const DisableSave ds;
   646  
   647      std::vector<char> buf(size);
   648      size_t total = 0;
   649  
   650      while (total < size) {
   651        int ret = read(rfd, buf.data(), buf.size());
   652        if (ret == -1 && errno == EAGAIN) {
   653          continue;
   654        }
   655        if (ret > 0) {
   656          total += ret;
   657        }
   658  
   659        // Assert to return on first failure.
   660        ASSERT_THAT(ret, SyscallSucceeds());
   661      }
   662    });
   663  
   664    std::vector<char> buf(size);
   665  
   666    struct iovec iov = {};
   667    iov.iov_base = buf.data();
   668    iov.iov_len = buf.size();
   669  
   670    struct msghdr msg = {};
   671    msg.msg_iov = &iov;
   672    msg.msg_iovlen = 1;
   673  
   674    return RetryEINTR(sendmsg)(sockets->first_fd(), &msg, 0);
   675  }
   676  
   677  namespace internal {
   678  PosixErrorOr<int> TryPortAvailable(int port, AddressFamily family,
   679                                     SocketType type, bool reuse_addr) {
   680    if (port < 0) {
   681      return PosixError(EINVAL, "Invalid port");
   682    }
   683  
   684    // Both Ipv6 and Dualstack are AF_INET6.
   685    int sock_fam = (family == AddressFamily::kIpv4 ? AF_INET : AF_INET6);
   686    int sock_type = (type == SocketType::kTcp ? SOCK_STREAM : SOCK_DGRAM);
   687    ASSIGN_OR_RETURN_ERRNO(auto fd, Socket(sock_fam, sock_type, 0));
   688  
   689    if (reuse_addr) {
   690      int one = 1;
   691      RETURN_ERROR_IF_SYSCALL_FAIL(
   692          setsockopt(fd.get(), SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)));
   693    }
   694  
   695    // Try to bind.
   696    sockaddr_storage storage = {};
   697    int storage_size = 0;
   698    if (family == AddressFamily::kIpv4) {
   699      sockaddr_in* addr = reinterpret_cast<sockaddr_in*>(&storage);
   700      storage_size = sizeof(*addr);
   701      addr->sin_family = AF_INET;
   702      addr->sin_port = htons(port);
   703      addr->sin_addr.s_addr = htonl(INADDR_ANY);
   704    } else {
   705      sockaddr_in6* addr = reinterpret_cast<sockaddr_in6*>(&storage);
   706      storage_size = sizeof(*addr);
   707      addr->sin6_family = AF_INET6;
   708      addr->sin6_port = htons(port);
   709      if (family == AddressFamily::kDualStack) {
   710        inet_pton(AF_INET6, "::ffff:0.0.0.0",
   711                  reinterpret_cast<void*>(&addr->sin6_addr.s6_addr));
   712      } else {
   713        addr->sin6_addr = in6addr_any;
   714      }
   715    }
   716  
   717    RETURN_ERROR_IF_SYSCALL_FAIL(
   718        bind(fd.get(), AsSockAddr(&storage), storage_size));
   719  
   720    // If the user specified 0 as the port, we will return the port that the
   721    // kernel gave us, otherwise we will validate that this socket bound to the
   722    // requested port.
   723    sockaddr_storage bound_storage = {};
   724    socklen_t bound_storage_size = sizeof(bound_storage);
   725    RETURN_ERROR_IF_SYSCALL_FAIL(
   726        getsockname(fd.get(), AsSockAddr(&bound_storage), &bound_storage_size));
   727  
   728    int available_port = -1;
   729    if (bound_storage.ss_family == AF_INET) {
   730      sockaddr_in* addr = reinterpret_cast<sockaddr_in*>(&bound_storage);
   731      available_port = ntohs(addr->sin_port);
   732    } else if (bound_storage.ss_family == AF_INET6) {
   733      sockaddr_in6* addr = reinterpret_cast<sockaddr_in6*>(&bound_storage);
   734      available_port = ntohs(addr->sin6_port);
   735    } else {
   736      return PosixError(EPROTOTYPE, "Getsockname returned invalid family");
   737    }
   738  
   739    // If we requested a specific port make sure our bound port is that port.
   740    if (port != 0 && available_port != port) {
   741      return PosixError(EINVAL,
   742                        absl::StrCat("Bound port ", available_port,
   743                                     " was not equal to requested port ", port));
   744    }
   745  
   746    // If we're trying to do a TCP socket, let's also try to listen.
   747    if (type == SocketType::kTcp) {
   748      RETURN_ERROR_IF_SYSCALL_FAIL(listen(fd.get(), 1));
   749    }
   750  
   751    return available_port;
   752  }
   753  }  // namespace internal
   754  
   755  PosixErrorOr<int> SendMsg(int sock, msghdr* msg, char buf[], int buf_size) {
   756    struct iovec iov;
   757    iov.iov_base = buf;
   758    iov.iov_len = buf_size;
   759    msg->msg_iov = &iov;
   760    msg->msg_iovlen = 1;
   761  
   762    int ret;
   763    RETURN_ERROR_IF_SYSCALL_FAIL(ret = RetryEINTR(sendmsg)(sock, msg, 0));
   764    return ret;
   765  }
   766  
   767  PosixErrorOr<int> RecvTimeout(int sock, char buf[], int buf_size, int timeout) {
   768    fd_set rfd;
   769    struct timeval to = {.tv_sec = timeout, .tv_usec = 0};
   770    struct timeval* to_ptr = timeout < 0 ? nullptr : &to;
   771    FD_ZERO(&rfd);
   772    FD_SET(sock, &rfd);
   773    int ret;
   774    RETURN_ERROR_IF_SYSCALL_FAIL(ret =
   775                                     select(sock + 1, &rfd, NULL, NULL, to_ptr));
   776    RETURN_ERROR_IF_SYSCALL_FAIL(
   777        ret = RetryEINTR(recv)(sock, buf, buf_size, MSG_DONTWAIT));
   778    return ret;
   779  }
   780  
   781  PosixErrorOr<int> RecvMsgTimeout(int sock, struct msghdr* msg, int timeout) {
   782    fd_set rfd;
   783    struct timeval to = {.tv_sec = timeout, .tv_usec = 0};
   784    struct timeval* to_ptr = timeout < 0 ? nullptr : &to;
   785    FD_ZERO(&rfd);
   786    FD_SET(sock, &rfd);
   787  
   788    int ret;
   789    RETURN_ERROR_IF_SYSCALL_FAIL(ret =
   790                                     select(sock + 1, &rfd, NULL, NULL, to_ptr));
   791    RETURN_ERROR_IF_SYSCALL_FAIL(
   792        ret = RetryEINTR(recvmsg)(sock, msg, MSG_DONTWAIT));
   793    return ret;
   794  }
   795  
   796  void RecvNoData(int sock) {
   797    char data = 0;
   798    struct iovec iov;
   799    iov.iov_base = &data;
   800    iov.iov_len = 1;
   801    struct msghdr msg = {};
   802    msg.msg_iov = &iov;
   803    msg.msg_iovlen = 1;
   804    ASSERT_THAT(RetryEINTR(recvmsg)(sock, &msg, MSG_DONTWAIT),
   805                SyscallFailsWithErrno(EAGAIN));
   806  }
   807  
   808  TestAddress TestAddress::WithPort(uint16_t port) const {
   809    TestAddress addr = *this;
   810    switch (addr.family()) {
   811      case AF_INET:
   812        reinterpret_cast<sockaddr_in*>(&addr.addr)->sin_port = htons(port);
   813        break;
   814      case AF_INET6:
   815        reinterpret_cast<sockaddr_in6*>(&addr.addr)->sin6_port = htons(port);
   816        break;
   817    }
   818    return addr;
   819  }
   820  
   821  namespace {
   822  
   823  TestAddress V4Addr(std::string description, in_addr_t addr) {
   824    TestAddress t(std::move(description));
   825    t.addr.ss_family = AF_INET;
   826    t.addr_len = sizeof(sockaddr_in);
   827    reinterpret_cast<sockaddr_in*>(&t.addr)->sin_addr.s_addr = addr;
   828    return t;
   829  }
   830  
   831  TestAddress V6Addr(std::string description, const in6_addr& addr) {
   832    TestAddress t(std::move(description));
   833    t.addr.ss_family = AF_INET6;
   834    t.addr_len = sizeof(sockaddr_in6);
   835    reinterpret_cast<sockaddr_in6*>(&t.addr)->sin6_addr = addr;
   836    return t;
   837  }
   838  
   839  }  // namespace
   840  
   841  TestAddress V4AddrStr(std::string description, const char* addr) {
   842    in_addr_t s_addr;
   843    inet_pton(AF_INET, addr, &s_addr);
   844    return V4Addr(description, s_addr);
   845  }
   846  
   847  TestAddress V6AddrStr(std::string description, const char* addr) {
   848    struct in6_addr s_addr;
   849    inet_pton(AF_INET6, addr, &s_addr);
   850    return V6Addr(description, s_addr);
   851  }
   852  
   853  TestAddress V4Any() { return V4Addr("V4Any", htonl(INADDR_ANY)); }
   854  
   855  TestAddress V4Broadcast() {
   856    return V4Addr("V4Broadcast", htonl(INADDR_BROADCAST));
   857  }
   858  
   859  TestAddress V4Loopback() {
   860    return V4Addr("V4Loopback", htonl(INADDR_LOOPBACK));
   861  }
   862  
   863  TestAddress V4LoopbackSubnetBroadcast() {
   864    return V4AddrStr("V4LoopbackSubnetBroadcast", "127.255.255.255");
   865  }
   866  
   867  TestAddress V4MappedAny() { return V6AddrStr("V4MappedAny", "::ffff:0.0.0.0"); }
   868  
   869  TestAddress V4MappedLoopback() {
   870    return V6AddrStr("V4MappedLoopback", "::ffff:127.0.0.1");
   871  }
   872  
   873  TestAddress V4Multicast() {
   874    return V4Addr("V4Multicast", inet_addr(kMulticastAddress));
   875  }
   876  
   877  TestAddress V4MulticastAllHosts() {
   878    return V4Addr("V4MulticastAllHosts", htonl(INADDR_ALLHOSTS_GROUP));
   879  }
   880  
   881  TestAddress V6Any() { return V6Addr("V6Any", in6addr_any); }
   882  
   883  TestAddress V6Loopback() { return V6Addr("V6Loopback", in6addr_loopback); }
   884  
   885  TestAddress V6Multicast() { return V6AddrStr("V6Multicast", "ff05::1234"); }
   886  
   887  TestAddress V6MulticastInterfaceLocalAllNodes() {
   888    return V6AddrStr("V6MulticastInterfaceLocalAllNodes", "ff01::1");
   889  }
   890  
   891  TestAddress V6MulticastLinkLocalAllNodes() {
   892    return V6AddrStr("V6MulticastLinkLocalAllNodes", "ff02::1");
   893  }
   894  
   895  TestAddress V6MulticastLinkLocalAllRouters() {
   896    return V6AddrStr("V6MulticastLinkLocalAllRouters", "ff02::2");
   897  }
   898  
   899  // Checksum computes the internet checksum of a buffer.
   900  uint16_t Checksum(uint16_t* buf, ssize_t buf_size) {
   901    // Add up the 16-bit values in the buffer.
   902    uint32_t total = 0;
   903    for (unsigned int i = 0; i < buf_size; i += sizeof(*buf)) {
   904      total += *buf;
   905      buf++;
   906    }
   907  
   908    // If buf has an odd size, add the remaining byte.
   909    if (buf_size % 2) {
   910      total += *(reinterpret_cast<unsigned char*>(buf) - 1);
   911    }
   912  
   913    // This carries any bits past the lower 16 until everything fits in 16 bits.
   914    while (total >> 16) {
   915      uint16_t lower = total & 0xffff;
   916      uint16_t upper = total >> 16;
   917      total = lower + upper;
   918    }
   919  
   920    return ~total;
   921  }
   922  
   923  uint16_t IPChecksum(struct iphdr ip) {
   924    return Checksum(reinterpret_cast<uint16_t*>(&ip), sizeof(ip));
   925  }
   926  
   927  // The pseudo-header defined in RFC 768 for calculating the UDP checksum.
   928  struct udp_pseudo_hdr {
   929    uint32_t srcip;
   930    uint32_t destip;
   931    char zero;
   932    char protocol;
   933    uint16_t udplen;
   934  };
   935  
   936  static_assert(sizeof(udp_pseudo_hdr) == 12);
   937  
   938  uint16_t UDPChecksum(struct iphdr iphdr, struct udphdr udphdr,
   939                       const char* payload, ssize_t payload_len) {
   940    struct udp_pseudo_hdr phdr = {};
   941    phdr.srcip = iphdr.saddr;
   942    phdr.destip = iphdr.daddr;
   943    phdr.zero = 0;
   944    phdr.protocol = IPPROTO_UDP;
   945    phdr.udplen = udphdr.len;
   946  
   947    ssize_t buf_size = sizeof(phdr) + sizeof(udphdr) + payload_len;
   948    char* buf = static_cast<char*>(malloc(buf_size));
   949    memcpy(buf, &phdr, sizeof(phdr));
   950    memcpy(buf + sizeof(phdr), &udphdr, sizeof(udphdr));
   951    memcpy(buf + sizeof(phdr) + sizeof(udphdr), payload, payload_len);
   952  
   953    uint16_t csum = Checksum(reinterpret_cast<uint16_t*>(buf), buf_size);
   954    free(buf);
   955    return csum;
   956  }
   957  
   958  // IPv6 pseudo-header for UDP checksum calculation.
   959  struct udpv6_pseudo_hdr {
   960    in6_addr srcip;
   961    in6_addr destip;
   962    char zero;
   963    char protocol;
   964    uint16_t udplen;
   965  };
   966  static_assert(sizeof(udpv6_pseudo_hdr) == 36);
   967  
   968  uint16_t UDPChecksum(struct ip6_hdr iphdr, struct udphdr udphdr,
   969                       const char* payload, ssize_t payload_len) {
   970    struct udpv6_pseudo_hdr phdr = {};
   971    phdr.srcip = iphdr.ip6_src;
   972    phdr.destip = iphdr.ip6_dst;
   973    phdr.zero = 0;
   974    phdr.protocol = IPPROTO_UDP;
   975    phdr.udplen = udphdr.len;
   976  
   977    ssize_t buf_size = sizeof(phdr) + sizeof(udphdr) + payload_len;
   978    char* buf = static_cast<char*>(malloc(buf_size));
   979    memcpy(buf, &phdr, sizeof(phdr));
   980    memcpy(buf + sizeof(phdr), &udphdr, sizeof(udphdr));
   981    memcpy(buf + sizeof(phdr) + sizeof(udphdr), payload, payload_len);
   982  
   983    uint16_t csum = Checksum(reinterpret_cast<uint16_t*>(buf), buf_size);
   984    free(buf);
   985    return csum;
   986  }
   987  
   988  uint16_t ICMPChecksum(struct icmphdr icmphdr, const char* payload,
   989                        ssize_t payload_len) {
   990    ssize_t buf_size = sizeof(icmphdr) + payload_len;
   991    char* buf = static_cast<char*>(malloc(buf_size));
   992    memcpy(buf, &icmphdr, sizeof(icmphdr));
   993    memcpy(buf + sizeof(icmphdr), payload, payload_len);
   994  
   995    uint16_t csum = Checksum(reinterpret_cast<uint16_t*>(buf), buf_size);
   996    free(buf);
   997    return csum;
   998  }
   999  
  1000  PosixErrorOr<uint16_t> AddrPort(int family, sockaddr_storage const& addr) {
  1001    switch (family) {
  1002      case AF_INET:
  1003        return static_cast<uint16_t>(
  1004            reinterpret_cast<sockaddr_in const*>(&addr)->sin_port);
  1005      case AF_INET6:
  1006        return static_cast<uint16_t>(
  1007            reinterpret_cast<sockaddr_in6 const*>(&addr)->sin6_port);
  1008      default:
  1009        return PosixError(EINVAL,
  1010                          absl::StrCat("unknown socket family: ", family));
  1011    }
  1012  }
  1013  
  1014  PosixError SetAddrPort(int family, sockaddr_storage* addr, uint16_t port) {
  1015    switch (family) {
  1016      case AF_INET:
  1017        reinterpret_cast<sockaddr_in*>(addr)->sin_port = port;
  1018        return NoError();
  1019      case AF_INET6:
  1020        reinterpret_cast<sockaddr_in6*>(addr)->sin6_port = port;
  1021        return NoError();
  1022      default:
  1023        return PosixError(EINVAL,
  1024                          absl::StrCat("unknown socket family: ", family));
  1025    }
  1026  }
  1027  
  1028  sockaddr_storage InetLoopbackAddr(int family) {
  1029    struct sockaddr_storage addr;
  1030    memset(&addr, 0, sizeof(addr));
  1031    AsSockAddr(&addr)->sa_family = family;
  1032  
  1033    if (family == AF_INET) {
  1034      auto sin = reinterpret_cast<struct sockaddr_in*>(&addr);
  1035      sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  1036      sin->sin_port = htons(0);
  1037      return addr;
  1038    }
  1039    auto sin6 = reinterpret_cast<struct sockaddr_in6*>(&addr);
  1040    sin6->sin6_addr = in6addr_loopback;
  1041    sin6->sin6_port = htons(0);
  1042    return addr;
  1043  }
  1044  
  1045  void SetupTimeWaitClose(const TestAddress* listener,
  1046                          const TestAddress* connector, bool reuse,
  1047                          bool accept_close, sockaddr_storage* listen_addr,
  1048                          sockaddr_storage* conn_bound_addr) {
  1049    // Create the listening socket.
  1050    FileDescriptor listen_fd = ASSERT_NO_ERRNO_AND_VALUE(
  1051        Socket(listener->family(), SOCK_STREAM, IPPROTO_TCP));
  1052    if (reuse) {
  1053      ASSERT_THAT(setsockopt(listen_fd.get(), SOL_SOCKET, SO_REUSEADDR,
  1054                             &kSockOptOn, sizeof(kSockOptOn)),
  1055                  SyscallSucceeds());
  1056    }
  1057    ASSERT_THAT(
  1058        bind(listen_fd.get(), AsSockAddr(listen_addr), listener->addr_len),
  1059        SyscallSucceeds());
  1060    ASSERT_THAT(listen(listen_fd.get(), SOMAXCONN), SyscallSucceeds());
  1061  
  1062    // Get the port bound by the listening socket.
  1063    socklen_t addrlen = listener->addr_len;
  1064    ASSERT_THAT(getsockname(listen_fd.get(), AsSockAddr(listen_addr), &addrlen),
  1065                SyscallSucceeds());
  1066  
  1067    uint16_t const port =
  1068        ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener->family(), *listen_addr));
  1069  
  1070    // Connect to the listening socket.
  1071    FileDescriptor conn_fd = ASSERT_NO_ERRNO_AND_VALUE(
  1072        Socket(connector->family(), SOCK_STREAM, IPPROTO_TCP));
  1073  
  1074    // We disable saves after this point as a S/R causes the netstack seed
  1075    // to be regenerated which changes what ports/ISN is picked for a given
  1076    // tuple (src ip,src port, dst ip, dst port). This can cause the final
  1077    // SYN to use a sequence number that looks like one from the current
  1078    // connection in TIME_WAIT and will not be accepted causing the test
  1079    // to timeout.
  1080    //
  1081    // TODO(gvisor.dev/issue/940): S/R portSeed/portHint
  1082    DisableSave ds;
  1083  
  1084    sockaddr_storage conn_addr = connector->addr;
  1085    ASSERT_NO_ERRNO(SetAddrPort(connector->family(), &conn_addr, port));
  1086    ASSERT_THAT(RetryEINTR(connect)(conn_fd.get(), AsSockAddr(&conn_addr),
  1087                                    connector->addr_len),
  1088                SyscallSucceeds());
  1089  
  1090    // Accept the connection.
  1091    auto accepted =
  1092        ASSERT_NO_ERRNO_AND_VALUE(Accept(listen_fd.get(), nullptr, nullptr));
  1093  
  1094    // Get the address/port bound by the connecting socket.
  1095    socklen_t conn_addrlen = connector->addr_len;
  1096    ASSERT_THAT(
  1097        getsockname(conn_fd.get(), AsSockAddr(conn_bound_addr), &conn_addrlen),
  1098        SyscallSucceeds());
  1099  
  1100    FileDescriptor active_closefd, passive_closefd;
  1101    if (accept_close) {
  1102      active_closefd = std::move(accepted);
  1103      passive_closefd = std::move(conn_fd);
  1104    } else {
  1105      active_closefd = std::move(conn_fd);
  1106      passive_closefd = std::move(accepted);
  1107    }
  1108  
  1109    // shutdown to trigger TIME_WAIT.
  1110    ASSERT_THAT(shutdown(active_closefd.get(), SHUT_WR), SyscallSucceeds());
  1111    {
  1112      constexpr int kTimeout = 10000;
  1113      pollfd pfd = {
  1114          .fd = passive_closefd.get(),
  1115          .events = POLLIN,
  1116      };
  1117      ASSERT_THAT(poll(&pfd, 1, kTimeout), SyscallSucceedsWithValue(1));
  1118      ASSERT_EQ(pfd.revents, POLLIN);
  1119    }
  1120    // Send/recv some data to be sure that the fin packet has been acked.
  1121    char c = 0;
  1122    ASSERT_THAT(send(passive_closefd.get(), &c, 1, 0),
  1123                SyscallSucceedsWithValue(sizeof(c)));
  1124    ASSERT_THAT(recv(active_closefd.get(), &c, 1, 0),
  1125                SyscallSucceedsWithValue(sizeof(c)));
  1126    ASSERT_THAT(shutdown(passive_closefd.get(), SHUT_WR), SyscallSucceeds());
  1127    {
  1128      constexpr int kTimeout = 10000;
  1129      constexpr int16_t want_events = POLLHUP;
  1130      pollfd pfd = {
  1131          .fd = active_closefd.get(),
  1132          .events = want_events,
  1133      };
  1134      ASSERT_THAT(poll(&pfd, 1, kTimeout), SyscallSucceedsWithValue(1));
  1135    }
  1136  
  1137    // This sleep is needed to reduce flake to ensure that the passive-close
  1138    // ensures the state transitions to CLOSE from LAST_ACK.
  1139    absl::SleepFor(absl::Seconds(1));
  1140  }
  1141  
  1142  constexpr char kRangeFile[] = "/proc/sys/net/ipv4/ip_local_port_range";
  1143  
  1144  PosixErrorOr<int> MaybeLimitEphemeralPorts() {
  1145    int min = 0;
  1146    int max = 1 << 16;
  1147  
  1148    // Read the ephemeral range from /proc.
  1149    ASSIGN_OR_RETURN_ERRNO(std::string rangefile, GetContents(kRangeFile));
  1150    const std::string err_msg =
  1151        absl::StrFormat("%s has invalid content: %s", kRangeFile, rangefile);
  1152    if (rangefile.back() != '\n') {
  1153      return PosixError(EINVAL, err_msg);
  1154    }
  1155    rangefile.pop_back();
  1156    std::vector<std::string> range =
  1157        absl::StrSplit(rangefile, absl::ByAnyChar("\t "));
  1158    if (range.size() < 2 || !absl::SimpleAtoi(range.front(), &min) ||
  1159        !absl::SimpleAtoi(range.back(), &max)) {
  1160      return PosixError(EINVAL, err_msg);
  1161    }
  1162  
  1163    // If we can open as writable, limit the range.
  1164    if (!access(kRangeFile, W_OK)) {
  1165      ASSIGN_OR_RETURN_ERRNO(FileDescriptor fd,
  1166                             Open(kRangeFile, O_WRONLY | O_TRUNC, 0));
  1167      int newMax = min + 50;
  1168      const std::string small_range = absl::StrFormat("%d %d", min, newMax);
  1169      int n = write(fd.get(), small_range.c_str(), small_range.size());
  1170      if (n < 0) {
  1171        // Hostinet doesn't allow modifying the host port range. And if we're root
  1172        // (as we are in some tests), access and open will succeed even if the
  1173        // file mode is readonly.
  1174        if (errno != EACCES) {
  1175          return PosixError(
  1176              errno,
  1177              absl::StrFormat("write(%d [%s], \"%s\", %d)", fd.get(), kRangeFile,
  1178                              small_range.c_str(), small_range.size()));
  1179        }
  1180      } else {
  1181        max = newMax;
  1182      }
  1183    }
  1184    return max - min;
  1185  }
  1186  
  1187  PosixErrorOr<std::function<PosixError()>> AllowMartianPacketsOnLoopback() {
  1188    if (IsRunningOnGvisor()) {
  1189      return std::function<PosixError()>([]() { return NoError(); });
  1190    }
  1191  
  1192    constexpr std::array<const char*, 2> files = {
  1193        "/proc/sys/net/ipv4/conf/lo/accept_local",
  1194        "/proc/sys/net/ipv4/conf/lo/route_localnet",
  1195    };
  1196    std::stack<std::pair<const char*, char>> initial_configs;
  1197  
  1198    // Record and update the initial configurations.
  1199    PosixError err = [&]() -> PosixError {
  1200      for (const char* f : files) {
  1201        ASSIGN_OR_RETURN_ERRNO(FileDescriptor fd, Open(f, O_RDWR));
  1202        char initial_config;
  1203        RETURN_ERROR_IF_SYSCALL_FAIL(
  1204            read(fd.get(), &initial_config, sizeof(initial_config)));
  1205  
  1206        constexpr char kEnabled = '1';
  1207        RETURN_ERROR_IF_SYSCALL_FAIL(lseek(fd.get(), 0, SEEK_SET));
  1208        RETURN_ERROR_IF_SYSCALL_FAIL(
  1209            write(fd.get(), &kEnabled, sizeof(kEnabled)));
  1210        initial_configs.push(std::make_pair(f, initial_config));
  1211      }
  1212      return NoError();
  1213    }();
  1214  
  1215    // Only define the restore function after we're done updating the config to
  1216    // capture the initialized initial_configs std::stack.
  1217    std::function<PosixError()> restore = [initial_configs]() mutable {
  1218      while (!initial_configs.empty()) {
  1219        std::pair<const char*, char> cfg = initial_configs.top();
  1220        initial_configs.pop();
  1221        ASSIGN_OR_RETURN_ERRNO(FileDescriptor fd, Open(cfg.first, O_WRONLY));
  1222        RETURN_ERROR_IF_SYSCALL_FAIL(
  1223            write(fd.get(), &cfg.second, sizeof(cfg.second)));
  1224      }
  1225      return NoError();
  1226    };
  1227  
  1228    if (!err.ok()) {
  1229      restore().IgnoreError();
  1230      return err;
  1231    }
  1232  
  1233    return restore;
  1234  }
  1235  
  1236  }  // namespace testing
  1237  }  // namespace gvisor