1 //===-- SocketAddress.cpp ---------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Note: This file is used on Darwin by debugserver, so it needs to remain as 10 // self contained as possible, and devoid of references to LLVM unless 11 // there is compelling reason. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #if defined(_MSC_VER) 16 #define _WINSOCK_DEPRECATED_NO_WARNINGS 17 #endif 18 19 #include "lldb/Host/SocketAddress.h" 20 #include <stddef.h> 21 #include <stdio.h> 22 23 #if !defined(_WIN32) 24 #include <arpa/inet.h> 25 #endif 26 27 #include <assert.h> 28 #include <string.h> 29 30 #include "lldb/Host/PosixApi.h" 31 32 // WindowsXP needs an inet_ntop implementation 33 #ifdef _WIN32 34 35 #ifndef INET6_ADDRSTRLEN // might not be defined in older Windows SDKs 36 #define INET6_ADDRSTRLEN 46 37 #endif 38 39 // TODO: implement shortened form "::" for runs of zeros 40 const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) { 41 if (size == 0) { 42 return nullptr; 43 } 44 45 switch (af) { 46 case AF_INET: { 47 { 48 const char *formatted = inet_ntoa(*static_cast<const in_addr *>(src)); 49 if (formatted && strlen(formatted) < static_cast<size_t>(size)) { 50 return ::strcpy(dst, formatted); 51 } 52 } 53 return nullptr; 54 case AF_INET6: { 55 char tmp[INET6_ADDRSTRLEN] = {0}; 56 const uint16_t *src16 = static_cast<const uint16_t *>(src); 57 int full_size = ::snprintf( 58 tmp, sizeof(tmp), "%x:%x:%x:%x:%x:%x:%x:%x", ntohs(src16[0]), 59 ntohs(src16[1]), ntohs(src16[2]), ntohs(src16[3]), ntohs(src16[4]), 60 ntohs(src16[5]), ntohs(src16[6]), ntohs(src16[7])); 61 if (full_size < static_cast<int>(size)) { 62 return ::strcpy(dst, tmp); 63 } 64 return nullptr; 65 } 66 } 67 } 68 return nullptr; 69 } 70 #endif 71 72 using namespace lldb_private; 73 74 //---------------------------------------------------------------------- 75 // SocketAddress constructor 76 //---------------------------------------------------------------------- 77 SocketAddress::SocketAddress() { Clear(); } 78 79 SocketAddress::SocketAddress(const struct sockaddr &s) { m_socket_addr.sa = s; } 80 81 SocketAddress::SocketAddress(const struct sockaddr_in &s) { 82 m_socket_addr.sa_ipv4 = s; 83 } 84 85 SocketAddress::SocketAddress(const struct sockaddr_in6 &s) { 86 m_socket_addr.sa_ipv6 = s; 87 } 88 89 SocketAddress::SocketAddress(const struct sockaddr_storage &s) { 90 m_socket_addr.sa_storage = s; 91 } 92 93 SocketAddress::SocketAddress(const struct addrinfo *addr_info) { 94 *this = addr_info; 95 } 96 97 //---------------------------------------------------------------------- 98 // SocketAddress copy constructor 99 //---------------------------------------------------------------------- 100 SocketAddress::SocketAddress(const SocketAddress &rhs) 101 : m_socket_addr(rhs.m_socket_addr) {} 102 103 //---------------------------------------------------------------------- 104 // Destructor 105 //---------------------------------------------------------------------- 106 SocketAddress::~SocketAddress() {} 107 108 void SocketAddress::Clear() { 109 memset(&m_socket_addr, 0, sizeof(m_socket_addr)); 110 } 111 112 bool SocketAddress::IsValid() const { return GetLength() != 0; } 113 114 static socklen_t GetFamilyLength(sa_family_t family) { 115 switch (family) { 116 case AF_INET: 117 return sizeof(struct sockaddr_in); 118 case AF_INET6: 119 return sizeof(struct sockaddr_in6); 120 } 121 assert(0 && "Unsupported address family"); 122 return 0; 123 } 124 125 socklen_t SocketAddress::GetLength() const { 126 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) 127 return m_socket_addr.sa.sa_len; 128 #else 129 return GetFamilyLength(GetFamily()); 130 #endif 131 } 132 133 socklen_t SocketAddress::GetMaxLength() { return sizeof(sockaddr_t); } 134 135 sa_family_t SocketAddress::GetFamily() const { 136 return m_socket_addr.sa.sa_family; 137 } 138 139 void SocketAddress::SetFamily(sa_family_t family) { 140 m_socket_addr.sa.sa_family = family; 141 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) 142 m_socket_addr.sa.sa_len = GetFamilyLength(family); 143 #endif 144 } 145 146 std::string SocketAddress::GetIPAddress() const { 147 char str[INET6_ADDRSTRLEN] = {0}; 148 switch (GetFamily()) { 149 case AF_INET: 150 if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv4.sin_addr, str, 151 sizeof(str))) 152 return str; 153 break; 154 case AF_INET6: 155 if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv6.sin6_addr, str, 156 sizeof(str))) 157 return str; 158 break; 159 } 160 return ""; 161 } 162 163 uint16_t SocketAddress::GetPort() const { 164 switch (GetFamily()) { 165 case AF_INET: 166 return ntohs(m_socket_addr.sa_ipv4.sin_port); 167 case AF_INET6: 168 return ntohs(m_socket_addr.sa_ipv6.sin6_port); 169 } 170 return 0; 171 } 172 173 bool SocketAddress::SetPort(uint16_t port) { 174 switch (GetFamily()) { 175 case AF_INET: 176 m_socket_addr.sa_ipv4.sin_port = htons(port); 177 return true; 178 179 case AF_INET6: 180 m_socket_addr.sa_ipv6.sin6_port = htons(port); 181 return true; 182 } 183 return false; 184 } 185 186 //---------------------------------------------------------------------- 187 // SocketAddress assignment operator 188 //---------------------------------------------------------------------- 189 const SocketAddress &SocketAddress::operator=(const SocketAddress &rhs) { 190 if (this != &rhs) 191 m_socket_addr = rhs.m_socket_addr; 192 return *this; 193 } 194 195 const SocketAddress &SocketAddress:: 196 operator=(const struct addrinfo *addr_info) { 197 Clear(); 198 if (addr_info && addr_info->ai_addr && addr_info->ai_addrlen > 0 && 199 size_t(addr_info->ai_addrlen) <= sizeof m_socket_addr) { 200 ::memcpy(&m_socket_addr, addr_info->ai_addr, addr_info->ai_addrlen); 201 } 202 return *this; 203 } 204 205 const SocketAddress &SocketAddress::operator=(const struct sockaddr &s) { 206 m_socket_addr.sa = s; 207 return *this; 208 } 209 210 const SocketAddress &SocketAddress::operator=(const struct sockaddr_in &s) { 211 m_socket_addr.sa_ipv4 = s; 212 return *this; 213 } 214 215 const SocketAddress &SocketAddress::operator=(const struct sockaddr_in6 &s) { 216 m_socket_addr.sa_ipv6 = s; 217 return *this; 218 } 219 220 const SocketAddress &SocketAddress:: 221 operator=(const struct sockaddr_storage &s) { 222 m_socket_addr.sa_storage = s; 223 return *this; 224 } 225 226 bool SocketAddress::getaddrinfo(const char *host, const char *service, 227 int ai_family, int ai_socktype, int ai_protocol, 228 int ai_flags) { 229 Clear(); 230 231 auto addresses = GetAddressInfo(host, service, ai_family, ai_socktype, 232 ai_protocol, ai_flags); 233 if (!addresses.empty()) 234 *this = addresses[0]; 235 return IsValid(); 236 } 237 238 std::vector<SocketAddress> 239 SocketAddress::GetAddressInfo(const char *hostname, const char *servname, 240 int ai_family, int ai_socktype, int ai_protocol, 241 int ai_flags) { 242 std::vector<SocketAddress> addr_list; 243 244 struct addrinfo hints; 245 memset(&hints, 0, sizeof(hints)); 246 hints.ai_family = ai_family; 247 hints.ai_socktype = ai_socktype; 248 hints.ai_protocol = ai_protocol; 249 hints.ai_flags = ai_flags; 250 251 struct addrinfo *service_info_list = NULL; 252 int err = ::getaddrinfo(hostname, servname, &hints, &service_info_list); 253 if (err == 0 && service_info_list) { 254 for (struct addrinfo *service_ptr = service_info_list; service_ptr != NULL; 255 service_ptr = service_ptr->ai_next) { 256 addr_list.emplace_back(SocketAddress(service_ptr)); 257 } 258 } 259 260 if (service_info_list) 261 ::freeaddrinfo(service_info_list); 262 return addr_list; 263 } 264 265 bool SocketAddress::SetToLocalhost(sa_family_t family, uint16_t port) { 266 switch (family) { 267 case AF_INET: 268 SetFamily(AF_INET); 269 if (SetPort(port)) { 270 m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 271 return true; 272 } 273 break; 274 275 case AF_INET6: 276 SetFamily(AF_INET6); 277 if (SetPort(port)) { 278 m_socket_addr.sa_ipv6.sin6_addr = in6addr_loopback; 279 return true; 280 } 281 break; 282 } 283 Clear(); 284 return false; 285 } 286 287 bool SocketAddress::SetToAnyAddress(sa_family_t family, uint16_t port) { 288 switch (family) { 289 case AF_INET: 290 SetFamily(AF_INET); 291 if (SetPort(port)) { 292 m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl(INADDR_ANY); 293 return true; 294 } 295 break; 296 297 case AF_INET6: 298 SetFamily(AF_INET6); 299 if (SetPort(port)) { 300 m_socket_addr.sa_ipv6.sin6_addr = in6addr_any; 301 return true; 302 } 303 break; 304 } 305 Clear(); 306 return false; 307 } 308 309 bool SocketAddress::IsAnyAddr() const { 310 return (GetFamily() == AF_INET) 311 ? m_socket_addr.sa_ipv4.sin_addr.s_addr == htonl(INADDR_ANY) 312 : 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, &in6addr_any, 16); 313 } 314 315 bool SocketAddress::IsLocalhost() const { 316 return (GetFamily() == AF_INET) 317 ? m_socket_addr.sa_ipv4.sin_addr.s_addr == htonl(INADDR_LOOPBACK) 318 : 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, &in6addr_loopback, 319 16); 320 } 321 322 bool SocketAddress::operator==(const SocketAddress &rhs) const { 323 if (GetFamily() != rhs.GetFamily()) 324 return false; 325 if (GetLength() != rhs.GetLength()) 326 return false; 327 switch (GetFamily()) { 328 case AF_INET: 329 return m_socket_addr.sa_ipv4.sin_addr.s_addr == 330 rhs.m_socket_addr.sa_ipv4.sin_addr.s_addr; 331 case AF_INET6: 332 return 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, 333 &rhs.m_socket_addr.sa_ipv6.sin6_addr, 16); 334 } 335 return false; 336 } 337 338 bool SocketAddress::operator!=(const SocketAddress &rhs) const { 339 return !(*this == rhs); 340 } 341