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

     1  // Copyright 2019 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 <errno.h>
    16  #include <stdlib.h>
    17  #include <sys/socket.h>
    18  #include <sys/types.h>
    19  #include <sys/un.h>
    20  
    21  #include <string>
    22  #include <tuple>
    23  
    24  #include "gtest/gtest.h"
    25  #include "test/syscalls/linux/socket_test_util.h"
    26  #include "test/util/file_descriptor.h"
    27  #include "test/util/fs_util.h"
    28  #include "test/util/test_util.h"
    29  
    30  // This file contains tests specific to connecting to host UDS managed outside
    31  // the sandbox / test.
    32  //
    33  // A set of ultity sockets will be created externally in $TEST_UDS_TREE and
    34  // $TEST_UDS_ATTACH_TREE for these tests to interact with.
    35  
    36  namespace gvisor {
    37  namespace testing {
    38  
    39  namespace {
    40  
    41  struct ProtocolSocket {
    42    int protocol;
    43    std::string name;
    44  };
    45  
    46  // Parameter is (socket root dir, ProtocolSocket).
    47  using GoferStreamSeqpacketTest =
    48      ::testing::TestWithParam<std::tuple<std::string, ProtocolSocket>>;
    49  
    50  // Connect to a socket and verify that write/read work.
    51  //
    52  // An "echo" socket doesn't work for dgram sockets because our socket is
    53  // unnamed. The server thus has no way to reply to us.
    54  TEST_P(GoferStreamSeqpacketTest, Echo) {
    55    std::string env;
    56    ProtocolSocket proto;
    57    std::tie(env, proto) = GetParam();
    58  
    59    char* val = getenv(env.c_str());
    60    ASSERT_NE(val, nullptr);
    61    std::string root(val);
    62  
    63    FileDescriptor sock =
    64        ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_UNIX, proto.protocol, 0));
    65  
    66    std::string socket_path = JoinPath(root, proto.name, "echo");
    67  
    68    struct sockaddr_un addr = {};
    69    addr.sun_family = AF_UNIX;
    70    memcpy(addr.sun_path, socket_path.c_str(), socket_path.length());
    71  
    72    ASSERT_THAT(connect(sock.get(), reinterpret_cast<struct sockaddr*>(&addr),
    73                        sizeof(addr)),
    74                SyscallSucceeds());
    75  
    76    constexpr int kBufferSize = 64;
    77    char send_buffer[kBufferSize];
    78    memset(send_buffer, 'a', sizeof(send_buffer));
    79  
    80    ASSERT_THAT(WriteFd(sock.get(), send_buffer, sizeof(send_buffer)),
    81                SyscallSucceedsWithValue(sizeof(send_buffer)));
    82  
    83    char recv_buffer[kBufferSize];
    84    ASSERT_THAT(ReadFd(sock.get(), recv_buffer, sizeof(recv_buffer)),
    85                SyscallSucceedsWithValue(sizeof(recv_buffer)));
    86    ASSERT_EQ(0, memcmp(send_buffer, recv_buffer, sizeof(send_buffer)));
    87  }
    88  
    89  // It is not possible to connect to a bound but non-listening socket.
    90  TEST_P(GoferStreamSeqpacketTest, NonListening) {
    91    std::string env;
    92    ProtocolSocket proto;
    93    std::tie(env, proto) = GetParam();
    94  
    95    char* val = getenv(env.c_str());
    96    ASSERT_NE(val, nullptr);
    97    std::string root(val);
    98  
    99    FileDescriptor sock =
   100        ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_UNIX, proto.protocol, 0));
   101  
   102    std::string socket_path = JoinPath(root, proto.name, "nonlistening");
   103  
   104    struct sockaddr_un addr = {};
   105    addr.sun_family = AF_UNIX;
   106    memcpy(addr.sun_path, socket_path.c_str(), socket_path.length());
   107  
   108    ASSERT_THAT(connect(sock.get(), reinterpret_cast<struct sockaddr*>(&addr),
   109                        sizeof(addr)),
   110                SyscallFailsWithErrno(ECONNREFUSED));
   111  }
   112  
   113  INSTANTIATE_TEST_SUITE_P(
   114      StreamSeqpacket, GoferStreamSeqpacketTest,
   115      ::testing::Combine(
   116          // Test access via standard path and attach point.
   117          ::testing::Values("TEST_UDS_TREE", "TEST_UDS_ATTACH_TREE"),
   118          ::testing::Values(ProtocolSocket{SOCK_STREAM, "stream"},
   119                            ProtocolSocket{SOCK_SEQPACKET, "seqpacket"})));
   120  
   121  // Parameter is socket root dir.
   122  using GoferDgramTest = ::testing::TestWithParam<std::string>;
   123  
   124  // Connect to a socket and verify that write works.
   125  //
   126  // An "echo" socket doesn't work for dgram sockets because our socket is
   127  // unnamed. The server thus has no way to reply to us.
   128  TEST_P(GoferDgramTest, Null) {
   129    std::string env = GetParam();
   130    char* val = getenv(env.c_str());
   131    ASSERT_NE(val, nullptr);
   132    std::string root(val);
   133  
   134    FileDescriptor sock =
   135        ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_UNIX, SOCK_DGRAM, 0));
   136  
   137    std::string socket_path = JoinPath(root, "dgram/null");
   138  
   139    struct sockaddr_un addr = {};
   140    addr.sun_family = AF_UNIX;
   141    memcpy(addr.sun_path, socket_path.c_str(), socket_path.length());
   142  
   143    ASSERT_THAT(connect(sock.get(), reinterpret_cast<struct sockaddr*>(&addr),
   144                        sizeof(addr)),
   145                SyscallSucceeds());
   146  
   147    constexpr int kBufferSize = 64;
   148    char send_buffer[kBufferSize];
   149    memset(send_buffer, 'a', sizeof(send_buffer));
   150  
   151    ASSERT_THAT(WriteFd(sock.get(), send_buffer, sizeof(send_buffer)),
   152                SyscallSucceedsWithValue(sizeof(send_buffer)));
   153  }
   154  
   155  INSTANTIATE_TEST_SUITE_P(Dgram, GoferDgramTest,
   156                           // Test access via standard path and attach point.
   157                           ::testing::Values("TEST_UDS_TREE",
   158                                             "TEST_UDS_ATTACH_TREE"));
   159  
   160  }  // namespace
   161  
   162  }  // namespace testing
   163  }  // namespace gvisor