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