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