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

     1  // Copyright 2020 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/socket_ipv4_udp_unbound_netlink.h"
    16  
    17  #include <arpa/inet.h>
    18  #include <poll.h>
    19  
    20  #include "gtest/gtest.h"
    21  #include "test/syscalls/linux/socket_netlink_route_util.h"
    22  #include "test/util/capability_util.h"
    23  #include "test/util/cleanup.h"
    24  
    25  namespace gvisor {
    26  namespace testing {
    27  
    28  constexpr size_t kSendBufSize = 200;
    29  
    30  // Checks that the loopback interface considers itself bound to all IPs in an
    31  // associated subnet.
    32  TEST_P(IPv4UDPUnboundSocketNetlinkTest, JoinSubnet) {
    33    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_ADMIN)));
    34  
    35    // Add an IP address to the loopback interface.
    36    Link loopback_link = ASSERT_NO_ERRNO_AND_VALUE(LoopbackLink());
    37    struct in_addr addr;
    38    ASSERT_EQ(1, inet_pton(AF_INET, "192.0.2.1", &addr));
    39    ASSERT_NO_ERRNO(LinkAddLocalAddr(loopback_link.index, AF_INET,
    40                                     /*prefixlen=*/24, &addr, sizeof(addr)));
    41    Cleanup defer_addr_removal = Cleanup(
    42        [loopback_link = std::move(loopback_link), addr = std::move(addr)] {
    43          EXPECT_NO_ERRNO(LinkDelLocalAddr(loopback_link.index, AF_INET,
    44                                           /*prefixlen=*/24, &addr,
    45                                           sizeof(addr)));
    46        });
    47  
    48    auto snd_sock = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
    49    auto rcv_sock = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
    50  
    51    // Send from an unassigned address but an address that is in the subnet
    52    // associated with the loopback interface.
    53    TestAddress sender_addr("V4NotAssignd1");
    54    sender_addr.addr.ss_family = AF_INET;
    55    sender_addr.addr_len = sizeof(sockaddr_in);
    56    ASSERT_EQ(1, inet_pton(AF_INET, "192.0.2.2",
    57                           &(reinterpret_cast<sockaddr_in*>(&sender_addr.addr)
    58                                 ->sin_addr.s_addr)));
    59    ASSERT_THAT(bind(snd_sock->get(), AsSockAddr(&sender_addr.addr),
    60                     sender_addr.addr_len),
    61                SyscallSucceeds());
    62  
    63    // Send the packet to an unassigned address but an address that is in the
    64    // subnet associated with the loopback interface.
    65    TestAddress receiver_addr("V4NotAssigned2");
    66    receiver_addr.addr.ss_family = AF_INET;
    67    receiver_addr.addr_len = sizeof(sockaddr_in);
    68    ASSERT_EQ(1, inet_pton(AF_INET, "192.0.2.254",
    69                           &(reinterpret_cast<sockaddr_in*>(&receiver_addr.addr)
    70                                 ->sin_addr.s_addr)));
    71    ASSERT_THAT(bind(rcv_sock->get(), AsSockAddr(&receiver_addr.addr),
    72                     receiver_addr.addr_len),
    73                SyscallSucceeds());
    74    socklen_t receiver_addr_len = receiver_addr.addr_len;
    75    ASSERT_THAT(getsockname(rcv_sock->get(), AsSockAddr(&receiver_addr.addr),
    76                            &receiver_addr_len),
    77                SyscallSucceeds());
    78    ASSERT_EQ(receiver_addr_len, receiver_addr.addr_len);
    79    char send_buf[kSendBufSize];
    80    RandomizeBuffer(send_buf, kSendBufSize);
    81    ASSERT_THAT(RetryEINTR(sendto)(snd_sock->get(), send_buf, kSendBufSize, 0,
    82                                   AsSockAddr(&receiver_addr.addr),
    83                                   receiver_addr.addr_len),
    84                SyscallSucceedsWithValue(kSendBufSize));
    85  
    86    // Check that we received the packet.
    87    char recv_buf[kSendBufSize] = {};
    88    ASSERT_THAT(RetryEINTR(recv)(rcv_sock->get(), recv_buf, kSendBufSize, 0),
    89                SyscallSucceedsWithValue(kSendBufSize));
    90    ASSERT_EQ(0, memcmp(send_buf, recv_buf, kSendBufSize));
    91  }
    92  
    93  // Tests that broadcast packets are delivered to all interested sockets
    94  // (wildcard and broadcast address specified sockets).
    95  //
    96  // Note, we cannot test the IPv4 Broadcast (255.255.255.255) because we do
    97  // not have a route to it.
    98  TEST_P(IPv4UDPUnboundSocketNetlinkTest, ReuseAddrSubnetDirectedBroadcast) {
    99    constexpr uint16_t kPort = 9876;
   100    // Wait up to 20 seconds for the data.
   101    constexpr int kPollTimeoutMs = 20000;
   102    // Number of sockets per socket type.
   103    constexpr int kNumSocketsPerType = 2;
   104  
   105    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_ADMIN)));
   106  
   107    // Add an IP address to the loopback interface.
   108    Link loopback_link = ASSERT_NO_ERRNO_AND_VALUE(LoopbackLink());
   109    struct in_addr addr;
   110    ASSERT_EQ(1, inet_pton(AF_INET, "192.0.2.1", &addr));
   111    ASSERT_NO_ERRNO(LinkAddLocalAddr(loopback_link.index, AF_INET,
   112                                     24 /* prefixlen */, &addr, sizeof(addr)));
   113    Cleanup defer_addr_removal = Cleanup(
   114        [loopback_link = std::move(loopback_link), addr = std::move(addr)] {
   115          EXPECT_NO_ERRNO(LinkDelLocalAddr(loopback_link.index, AF_INET,
   116                                           /*prefixlen=*/24, &addr,
   117                                           sizeof(addr)));
   118        });
   119  
   120    TestAddress broadcast_address("SubnetBroadcastAddress");
   121    broadcast_address.addr.ss_family = AF_INET;
   122    broadcast_address.addr_len = sizeof(sockaddr_in);
   123    auto broadcast_address_in =
   124        reinterpret_cast<sockaddr_in*>(&broadcast_address.addr);
   125    ASSERT_EQ(1, inet_pton(AF_INET, "192.0.2.255",
   126                           &broadcast_address_in->sin_addr.s_addr));
   127    broadcast_address_in->sin_port = htons(kPort);
   128  
   129    TestAddress any_address = V4Any();
   130    reinterpret_cast<sockaddr_in*>(&any_address.addr)->sin_port = htons(kPort);
   131  
   132    // We create sockets bound to both the wildcard address and the broadcast
   133    // address to make sure both of these types of "broadcast interested" sockets
   134    // receive broadcast packets.
   135    std::vector<std::unique_ptr<FileDescriptor>> socks;
   136    for (bool bind_wildcard : {false, true}) {
   137      // Create multiple sockets for each type of "broadcast interested"
   138      // socket so we can test that all sockets receive the broadcast packet.
   139      for (int i = 0; i < kNumSocketsPerType; i++) {
   140        auto sock = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
   141        auto idx = socks.size();
   142  
   143        ASSERT_THAT(setsockopt(sock->get(), SOL_SOCKET, SO_REUSEADDR, &kSockOptOn,
   144                               sizeof(kSockOptOn)),
   145                    SyscallSucceedsWithValue(0))
   146            << "socks[" << idx << "]";
   147  
   148        ASSERT_THAT(setsockopt(sock->get(), SOL_SOCKET, SO_BROADCAST, &kSockOptOn,
   149                               sizeof(kSockOptOn)),
   150                    SyscallSucceedsWithValue(0))
   151            << "socks[" << idx << "]";
   152  
   153        if (bind_wildcard) {
   154          ASSERT_THAT(bind(sock->get(), AsSockAddr(&any_address.addr),
   155                           any_address.addr_len),
   156                      SyscallSucceeds())
   157              << "socks[" << idx << "]";
   158        } else {
   159          ASSERT_THAT(bind(sock->get(), AsSockAddr(&broadcast_address.addr),
   160                           broadcast_address.addr_len),
   161                      SyscallSucceeds())
   162              << "socks[" << idx << "]";
   163        }
   164  
   165        socks.push_back(std::move(sock));
   166      }
   167    }
   168  
   169    char send_buf[kSendBufSize];
   170    RandomizeBuffer(send_buf, kSendBufSize);
   171  
   172    // Broadcasts from each socket should be received by every socket (including
   173    // the sending socket).
   174    for (size_t w = 0; w < socks.size(); w++) {
   175      auto& w_sock = socks[w];
   176      ASSERT_THAT(RetryEINTR(sendto)(w_sock->get(), send_buf, kSendBufSize, 0,
   177                                     AsSockAddr(&broadcast_address.addr),
   178                                     broadcast_address.addr_len),
   179                  SyscallSucceedsWithValue(kSendBufSize))
   180          << "write socks[" << w << "]";
   181  
   182      // Check that we received the packet on all sockets.
   183      for (size_t r = 0; r < socks.size(); r++) {
   184        auto& r_sock = socks[r];
   185  
   186        struct pollfd poll_fd = {r_sock->get(), POLLIN, 0};
   187        EXPECT_THAT(RetryEINTR(poll)(&poll_fd, 1, kPollTimeoutMs),
   188                    SyscallSucceedsWithValue(1))
   189            << "write socks[" << w << "] & read socks[" << r << "]";
   190  
   191        char recv_buf[kSendBufSize] = {};
   192        EXPECT_THAT(RetryEINTR(recv)(r_sock->get(), recv_buf, kSendBufSize, 0),
   193                    SyscallSucceedsWithValue(kSendBufSize))
   194            << "write socks[" << w << "] & read socks[" << r << "]";
   195        EXPECT_EQ(0, memcmp(send_buf, recv_buf, kSendBufSize))
   196            << "write socks[" << w << "] & read socks[" << r << "]";
   197      }
   198    }
   199  }
   200  
   201  }  // namespace testing
   202  }  // namespace gvisor