SocketAddress.cpp revision 360784
1184610Salfred//===-- SocketAddress.cpp ---------------------------------------*- C++ -*-===// 2184610Salfred// 3184610Salfred// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4184610Salfred// See https://llvm.org/LICENSE.txt for license information. 5184610Salfred// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6184610Salfred// 7184610Salfred//===----------------------------------------------------------------------===// 8184610Salfred// 9184610Salfred// Note: This file is used on Darwin by debugserver, so it needs to remain as 10184610Salfred// self contained as possible, and devoid of references to LLVM unless 11184610Salfred// there is compelling reason. 12184610Salfred// 13184610Salfred//===----------------------------------------------------------------------===// 14184610Salfred 15184610Salfred#if defined(_MSC_VER) 16184610Salfred#define _WINSOCK_DEPRECATED_NO_WARNINGS 17184610Salfred#endif 18184610Salfred 19184610Salfred#include "lldb/Host/SocketAddress.h" 20184610Salfred#include <stddef.h> 21184610Salfred#include <stdio.h> 22184610Salfred 23184610Salfred#if !defined(_WIN32) 24184610Salfred#include <arpa/inet.h> 25184610Salfred#endif 26184610Salfred 27184610Salfred#include <assert.h> 28184610Salfred#include <string.h> 29184610Salfred 30184610Salfred#include "lldb/Host/PosixApi.h" 31184610Salfred 32184610Salfred// WindowsXP needs an inet_ntop implementation 33184610Salfred#ifdef _WIN32 34184610Salfred 35184610Salfred#ifndef INET6_ADDRSTRLEN // might not be defined in older Windows SDKs 36184610Salfred#define INET6_ADDRSTRLEN 46 37184610Salfred#endif 38184610Salfred 39184610Salfred// TODO: implement shortened form "::" for runs of zeros 40184610Salfredconst char *inet_ntop(int af, const void *src, char *dst, socklen_t size) { 41184610Salfred if (size == 0) { 42184610Salfred return nullptr; 43184610Salfred } 44194677Sthompsa 45194677Sthompsa switch (af) { 46194677Sthompsa case AF_INET: { 47194677Sthompsa { 48194677Sthompsa const char *formatted = inet_ntoa(*static_cast<const in_addr *>(src)); 49194677Sthompsa if (formatted && strlen(formatted) < static_cast<size_t>(size)) { 50194677Sthompsa return ::strcpy(dst, formatted); 51194677Sthompsa } 52194677Sthompsa } 53194677Sthompsa return nullptr; 54194677Sthompsa case AF_INET6: { 55194677Sthompsa char tmp[INET6_ADDRSTRLEN] = {0}; 56194677Sthompsa const uint16_t *src16 = static_cast<const uint16_t *>(src); 57194677Sthompsa int full_size = ::snprintf( 58194677Sthompsa tmp, sizeof(tmp), "%x:%x:%x:%x:%x:%x:%x:%x", ntohs(src16[0]), 59194677Sthompsa ntohs(src16[1]), ntohs(src16[2]), ntohs(src16[3]), ntohs(src16[4]), 60194677Sthompsa ntohs(src16[5]), ntohs(src16[6]), ntohs(src16[7])); 61194677Sthompsa if (full_size < static_cast<int>(size)) { 62223989Shselasky return ::strcpy(dst, tmp); 63223989Shselasky } 64198152Sthompsa return nullptr; 65194677Sthompsa } 66188942Sthompsa } 67194677Sthompsa } 68194677Sthompsa return nullptr; 69188942Sthompsa} 70184610Salfred#endif 71184610Salfred 72188942Sthompsausing namespace lldb_private; 73184610Salfred 74188942Sthompsa// SocketAddress constructor 75184610SalfredSocketAddress::SocketAddress() { Clear(); } 76184610Salfred 77184610SalfredSocketAddress::SocketAddress(const struct sockaddr &s) { m_socket_addr.sa = s; } 78184610Salfred 79184610SalfredSocketAddress::SocketAddress(const struct sockaddr_in &s) { 80184610Salfred m_socket_addr.sa_ipv4 = s; 81184610Salfred} 82184610Salfred 83184610SalfredSocketAddress::SocketAddress(const struct sockaddr_in6 &s) { 84184610Salfred m_socket_addr.sa_ipv6 = s; 85184610Salfred} 86184610Salfred 87184610SalfredSocketAddress::SocketAddress(const struct sockaddr_storage &s) { 88184610Salfred m_socket_addr.sa_storage = s; 89184610Salfred} 90184610Salfred 91184610SalfredSocketAddress::SocketAddress(const struct addrinfo *addr_info) { 92207077Sthompsa *this = addr_info; 93184610Salfred} 94196489Salfred 95253332Shselasky// Destructor 96184610SalfredSocketAddress::~SocketAddress() {} 97253332Shselasky 98267992Shselaskyvoid SocketAddress::Clear() { 99184610Salfred memset(&m_socket_addr, 0, sizeof(m_socket_addr)); 100267992Shselasky} 101196489Salfred 102267992Shselaskybool SocketAddress::IsValid() const { return GetLength() != 0; } 103253332Shselasky 104184610Salfredstatic socklen_t GetFamilyLength(sa_family_t family) { 105184610Salfred switch (family) { 106184610Salfred case AF_INET: 107184610Salfred return sizeof(struct sockaddr_in); 108184610Salfred case AF_INET6: 109184610Salfred return sizeof(struct sockaddr_in6); 110184610Salfred } 111305644Shselasky assert(0 && "Unsupported address family"); 112184610Salfred return 0; 113223755Shselasky} 114184610Salfred 115184610Salfredsocklen_t SocketAddress::GetLength() const { 116223755Shselasky#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) 117184610Salfred return m_socket_addr.sa.sa_len; 118184610Salfred#else 119184610Salfred return GetFamilyLength(GetFamily()); 120184610Salfred#endif 121184610Salfred} 122184610Salfred 123184610Salfredsocklen_t SocketAddress::GetMaxLength() { return sizeof(sockaddr_t); } 124184610Salfred 125223755Shselaskysa_family_t SocketAddress::GetFamily() const { 126223755Shselasky return m_socket_addr.sa.sa_family; 127223755Shselasky} 128184610Salfred 129192925Sthompsavoid SocketAddress::SetFamily(sa_family_t family) { 130184610Salfred m_socket_addr.sa.sa_family = family; 131187259Sthompsa#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) 132305644Shselasky m_socket_addr.sa.sa_len = GetFamilyLength(family); 133305644Shselasky#endif 134187259Sthompsa} 135192925Sthompsa 136187259Sthompsastd::string SocketAddress::GetIPAddress() const { 137187259Sthompsa char str[INET6_ADDRSTRLEN] = {0}; 138184610Salfred switch (GetFamily()) { 139184610Salfred case AF_INET: 140184610Salfred if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv4.sin_addr, str, 141184610Salfred sizeof(str))) 142184610Salfred return str; 143192925Sthompsa break; 144192925Sthompsa case AF_INET6: 145223755Shselasky if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv6.sin6_addr, str, 146223755Shselasky sizeof(str))) 147223755Shselasky return str; 148223755Shselasky break; 149223755Shselasky } 150223755Shselasky return ""; 151223755Shselasky} 152223755Shselasky 153223755Shselaskyuint16_t SocketAddress::GetPort() const { 154223755Shselasky switch (GetFamily()) { 155223755Shselasky case AF_INET: 156223755Shselasky return ntohs(m_socket_addr.sa_ipv4.sin_port); 157192984Sthompsa case AF_INET6: 158184610Salfred return ntohs(m_socket_addr.sa_ipv6.sin6_port); 159184610Salfred } 160184610Salfred return 0; 161203896Sthompsa} 162192984Sthompsa 163192984Sthompsabool SocketAddress::SetPort(uint16_t port) { 164192984Sthompsa switch (GetFamily()) { 165184610Salfred case AF_INET: 166184610Salfred m_socket_addr.sa_ipv4.sin_port = htons(port); 167184610Salfred return true; 168184610Salfred 169184610Salfred case AF_INET6: 170184610Salfred m_socket_addr.sa_ipv6.sin6_port = htons(port); 171184610Salfred return true; 172184610Salfred } 173184610Salfred return false; 174184610Salfred} 175223755Shselasky 176223755Shselasky// SocketAddress assignment operator 177223755Shselaskyconst SocketAddress &SocketAddress:: 178223755Shselaskyoperator=(const struct addrinfo *addr_info) { 179223755Shselasky Clear(); 180184610Salfred if (addr_info && addr_info->ai_addr && addr_info->ai_addrlen > 0 && 181223755Shselasky size_t(addr_info->ai_addrlen) <= sizeof m_socket_addr) { 182223755Shselasky ::memcpy(&m_socket_addr, addr_info->ai_addr, addr_info->ai_addrlen); 183223755Shselasky } 184223755Shselasky return *this; 185223755Shselasky} 186223755Shselasky 187223755Shselaskyconst SocketAddress &SocketAddress::operator=(const struct sockaddr &s) { 188223755Shselasky m_socket_addr.sa = s; 189223755Shselasky return *this; 190223755Shselasky} 191223755Shselasky 192223755Shselaskyconst SocketAddress &SocketAddress::operator=(const struct sockaddr_in &s) { 193223755Shselasky m_socket_addr.sa_ipv4 = s; 194223755Shselasky return *this; 195223755Shselasky} 196223755Shselasky 197223755Shselaskyconst SocketAddress &SocketAddress::operator=(const struct sockaddr_in6 &s) { 198223755Shselasky m_socket_addr.sa_ipv6 = s; 199203896Sthompsa return *this; 200203896Sthompsa} 201203896Sthompsa 202304124Shselaskyconst SocketAddress &SocketAddress:: 203223755Shselaskyoperator=(const struct sockaddr_storage &s) { 204223755Shselasky m_socket_addr.sa_storage = s; 205184610Salfred return *this; 206184610Salfred} 207184610Salfred 208184610Salfredbool SocketAddress::getaddrinfo(const char *host, const char *service, 209223755Shselasky int ai_family, int ai_socktype, int ai_protocol, 210184610Salfred int ai_flags) { 211184610Salfred Clear(); 212184610Salfred 213184610Salfred auto addresses = GetAddressInfo(host, service, ai_family, ai_socktype, 214223755Shselasky ai_protocol, ai_flags); 215223755Shselasky if (!addresses.empty()) 216223755Shselasky *this = addresses[0]; 217223755Shselasky return IsValid(); 218223755Shselasky} 219223755Shselasky 220223755Shselaskystd::vector<SocketAddress> 221223755ShselaskySocketAddress::GetAddressInfo(const char *hostname, const char *servname, 222223755Shselasky int ai_family, int ai_socktype, int ai_protocol, 223223755Shselasky int ai_flags) { 224223755Shselasky std::vector<SocketAddress> addr_list; 225223755Shselasky 226223755Shselasky struct addrinfo hints; 227223755Shselasky memset(&hints, 0, sizeof(hints)); 228223755Shselasky hints.ai_family = ai_family; 229192925Sthompsa hints.ai_socktype = ai_socktype; 230223755Shselasky hints.ai_protocol = ai_protocol; 231223755Shselasky hints.ai_flags = ai_flags; 232184610Salfred 233184610Salfred struct addrinfo *service_info_list = nullptr; 234184610Salfred int err = ::getaddrinfo(hostname, servname, &hints, &service_info_list); 235184610Salfred if (err == 0 && service_info_list) { 236184610Salfred for (struct addrinfo *service_ptr = service_info_list; 237184610Salfred service_ptr != nullptr; service_ptr = service_ptr->ai_next) { 238184610Salfred addr_list.emplace_back(SocketAddress(service_ptr)); 239184610Salfred } 240184610Salfred } 241184610Salfred 242184610Salfred if (service_info_list) 243184610Salfred ::freeaddrinfo(service_info_list); 244184610Salfred return addr_list; 245184610Salfred} 246184610Salfred 247184610Salfredbool SocketAddress::SetToLocalhost(sa_family_t family, uint16_t port) { 248184610Salfred switch (family) { 249184610Salfred case AF_INET: 250228765Savg SetFamily(AF_INET); 251228765Savg if (SetPort(port)) { 252228765Savg m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 253228765Savg return true; 254228765Savg } 255228765Savg break; 256228765Savg 257228765Savg case AF_INET6: 258228765Savg SetFamily(AF_INET6); 259228765Savg if (SetPort(port)) { 260228765Savg m_socket_addr.sa_ipv6.sin6_addr = in6addr_loopback; 261228765Savg return true; 262228765Savg } 263228765Savg break; 264228765Savg } 265228765Savg Clear(); 266228765Savg return false; 267228765Savg} 268228765Savg 269228765Savgbool SocketAddress::SetToAnyAddress(sa_family_t family, uint16_t port) { 270228765Savg switch (family) { 271228765Savg case AF_INET: 272228765Savg SetFamily(AF_INET); 273228765Savg if (SetPort(port)) { 274228765Savg m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl(INADDR_ANY); 275228765Savg return true; 276228765Savg } 277184610Salfred break; 278184610Salfred 279184610Salfred case AF_INET6: 280184610Salfred SetFamily(AF_INET6); 281184610Salfred if (SetPort(port)) { 282184610Salfred m_socket_addr.sa_ipv6.sin6_addr = in6addr_any; 283184610Salfred return true; 284184610Salfred } 285184610Salfred break; 286184610Salfred } 287184610Salfred Clear(); 288184610Salfred return false; 289184610Salfred} 290184610Salfred 291184610Salfredbool SocketAddress::IsAnyAddr() const { 292184610Salfred return (GetFamily() == AF_INET) 293184610Salfred ? m_socket_addr.sa_ipv4.sin_addr.s_addr == htonl(INADDR_ANY) 294184610Salfred : 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, &in6addr_any, 16); 295184610Salfred} 296184610Salfred 297184610Salfredbool SocketAddress::IsLocalhost() const { 298184610Salfred return (GetFamily() == AF_INET) 299184610Salfred ? m_socket_addr.sa_ipv4.sin_addr.s_addr == htonl(INADDR_LOOPBACK) 300184610Salfred : 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, &in6addr_loopback, 301184610Salfred 16); 302184610Salfred} 303184610Salfred 304291146Shselaskybool SocketAddress::operator==(const SocketAddress &rhs) const { 305291146Shselasky if (GetFamily() != rhs.GetFamily()) 306291146Shselasky return false; 307291146Shselasky if (GetLength() != rhs.GetLength()) 308184610Salfred return false; 309184610Salfred switch (GetFamily()) { 310184610Salfred case AF_INET: 311184610Salfred return m_socket_addr.sa_ipv4.sin_addr.s_addr == 312184610Salfred rhs.m_socket_addr.sa_ipv4.sin_addr.s_addr; 313184610Salfred case AF_INET6: 314184610Salfred return 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, 315184610Salfred &rhs.m_socket_addr.sa_ipv6.sin6_addr, 16); 316184610Salfred } 317184610Salfred return false; 318184610Salfred} 319184610Salfred 320184610Salfredbool SocketAddress::operator!=(const SocketAddress &rhs) const { 321184610Salfred return !(*this == rhs); 322184610Salfred} 323184610Salfred