15ffd83dbSDimitry Andric //===-- SocketAddress.cpp -------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Note: This file is used on Darwin by debugserver, so it needs to remain as
100b57cec5SDimitry Andric //       self contained as possible, and devoid of references to LLVM unless
110b57cec5SDimitry Andric //       there is compelling reason.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #if defined(_MSC_VER)
160b57cec5SDimitry Andric #define _WINSOCK_DEPRECATED_NO_WARNINGS
170b57cec5SDimitry Andric #endif
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric #include "lldb/Host/SocketAddress.h"
20fe6060f1SDimitry Andric #include <cstddef>
21fe6060f1SDimitry Andric #include <cstdio>
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric #if !defined(_WIN32)
240b57cec5SDimitry Andric #include <arpa/inet.h>
250b57cec5SDimitry Andric #endif
260b57cec5SDimitry Andric 
27fe6060f1SDimitry Andric #include <cassert>
28fe6060f1SDimitry Andric #include <cstring>
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric #include "lldb/Host/PosixApi.h"
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric // WindowsXP needs an inet_ntop implementation
330b57cec5SDimitry Andric #ifdef _WIN32
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric #ifndef INET6_ADDRSTRLEN // might not be defined in older Windows SDKs
360b57cec5SDimitry Andric #define INET6_ADDRSTRLEN 46
370b57cec5SDimitry Andric #endif
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric // TODO: implement shortened form "::" for runs of zeros
inet_ntop(int af,const void * src,char * dst,socklen_t size)400b57cec5SDimitry Andric const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) {
410b57cec5SDimitry Andric   if (size == 0) {
420b57cec5SDimitry Andric     return nullptr;
430b57cec5SDimitry Andric   }
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric   switch (af) {
460b57cec5SDimitry Andric   case AF_INET: {
470b57cec5SDimitry Andric     {
480b57cec5SDimitry Andric       const char *formatted = inet_ntoa(*static_cast<const in_addr *>(src));
490b57cec5SDimitry Andric       if (formatted && strlen(formatted) < static_cast<size_t>(size)) {
500b57cec5SDimitry Andric         return ::strcpy(dst, formatted);
510b57cec5SDimitry Andric       }
520b57cec5SDimitry Andric     }
530b57cec5SDimitry Andric     return nullptr;
540b57cec5SDimitry Andric   case AF_INET6: {
550b57cec5SDimitry Andric     char tmp[INET6_ADDRSTRLEN] = {0};
560b57cec5SDimitry Andric     const uint16_t *src16 = static_cast<const uint16_t *>(src);
570b57cec5SDimitry Andric     int full_size = ::snprintf(
580b57cec5SDimitry Andric         tmp, sizeof(tmp), "%x:%x:%x:%x:%x:%x:%x:%x", ntohs(src16[0]),
590b57cec5SDimitry Andric         ntohs(src16[1]), ntohs(src16[2]), ntohs(src16[3]), ntohs(src16[4]),
600b57cec5SDimitry Andric         ntohs(src16[5]), ntohs(src16[6]), ntohs(src16[7]));
610b57cec5SDimitry Andric     if (full_size < static_cast<int>(size)) {
620b57cec5SDimitry Andric       return ::strcpy(dst, tmp);
630b57cec5SDimitry Andric     }
640b57cec5SDimitry Andric     return nullptr;
650b57cec5SDimitry Andric   }
660b57cec5SDimitry Andric   }
670b57cec5SDimitry Andric   }
680b57cec5SDimitry Andric   return nullptr;
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric #endif
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric using namespace lldb_private;
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric // SocketAddress constructor
SocketAddress()750b57cec5SDimitry Andric SocketAddress::SocketAddress() { Clear(); }
760b57cec5SDimitry Andric 
SocketAddress(const struct sockaddr & s)770b57cec5SDimitry Andric SocketAddress::SocketAddress(const struct sockaddr &s) { m_socket_addr.sa = s; }
780b57cec5SDimitry Andric 
SocketAddress(const struct sockaddr_in & s)790b57cec5SDimitry Andric SocketAddress::SocketAddress(const struct sockaddr_in &s) {
800b57cec5SDimitry Andric   m_socket_addr.sa_ipv4 = s;
810b57cec5SDimitry Andric }
820b57cec5SDimitry Andric 
SocketAddress(const struct sockaddr_in6 & s)830b57cec5SDimitry Andric SocketAddress::SocketAddress(const struct sockaddr_in6 &s) {
840b57cec5SDimitry Andric   m_socket_addr.sa_ipv6 = s;
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric 
SocketAddress(const struct sockaddr_storage & s)870b57cec5SDimitry Andric SocketAddress::SocketAddress(const struct sockaddr_storage &s) {
880b57cec5SDimitry Andric   m_socket_addr.sa_storage = s;
890b57cec5SDimitry Andric }
900b57cec5SDimitry Andric 
SocketAddress(const struct addrinfo * addr_info)910b57cec5SDimitry Andric SocketAddress::SocketAddress(const struct addrinfo *addr_info) {
920b57cec5SDimitry Andric   *this = addr_info;
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric // Destructor
96fe6060f1SDimitry Andric SocketAddress::~SocketAddress() = default;
970b57cec5SDimitry Andric 
Clear()980b57cec5SDimitry Andric void SocketAddress::Clear() {
990b57cec5SDimitry Andric   memset(&m_socket_addr, 0, sizeof(m_socket_addr));
1000b57cec5SDimitry Andric }
1010b57cec5SDimitry Andric 
IsValid() const1020b57cec5SDimitry Andric bool SocketAddress::IsValid() const { return GetLength() != 0; }
1030b57cec5SDimitry Andric 
GetFamilyLength(sa_family_t family)1040b57cec5SDimitry Andric static socklen_t GetFamilyLength(sa_family_t family) {
1050b57cec5SDimitry Andric   switch (family) {
1060b57cec5SDimitry Andric   case AF_INET:
1070b57cec5SDimitry Andric     return sizeof(struct sockaddr_in);
1080b57cec5SDimitry Andric   case AF_INET6:
1090b57cec5SDimitry Andric     return sizeof(struct sockaddr_in6);
1100b57cec5SDimitry Andric   }
1110b57cec5SDimitry Andric   assert(0 && "Unsupported address family");
1120b57cec5SDimitry Andric   return 0;
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric 
GetLength() const1150b57cec5SDimitry Andric socklen_t SocketAddress::GetLength() const {
1165f757f3fSDimitry Andric #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) ||       \
1175f757f3fSDimitry Andric     defined(__OpenBSD__)
1180b57cec5SDimitry Andric   return m_socket_addr.sa.sa_len;
1190b57cec5SDimitry Andric #else
1200b57cec5SDimitry Andric   return GetFamilyLength(GetFamily());
1210b57cec5SDimitry Andric #endif
1220b57cec5SDimitry Andric }
1230b57cec5SDimitry Andric 
GetMaxLength()1240b57cec5SDimitry Andric socklen_t SocketAddress::GetMaxLength() { return sizeof(sockaddr_t); }
1250b57cec5SDimitry Andric 
GetFamily() const1260b57cec5SDimitry Andric sa_family_t SocketAddress::GetFamily() const {
1270b57cec5SDimitry Andric   return m_socket_addr.sa.sa_family;
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric 
SetFamily(sa_family_t family)1300b57cec5SDimitry Andric void SocketAddress::SetFamily(sa_family_t family) {
1310b57cec5SDimitry Andric   m_socket_addr.sa.sa_family = family;
1325f757f3fSDimitry Andric #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) ||       \
1335f757f3fSDimitry Andric     defined(__OpenBSD__)
1340b57cec5SDimitry Andric   m_socket_addr.sa.sa_len = GetFamilyLength(family);
1350b57cec5SDimitry Andric #endif
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric 
GetIPAddress() const1380b57cec5SDimitry Andric std::string SocketAddress::GetIPAddress() const {
1390b57cec5SDimitry Andric   char str[INET6_ADDRSTRLEN] = {0};
1400b57cec5SDimitry Andric   switch (GetFamily()) {
1410b57cec5SDimitry Andric   case AF_INET:
1420b57cec5SDimitry Andric     if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv4.sin_addr, str,
1430b57cec5SDimitry Andric                   sizeof(str)))
1440b57cec5SDimitry Andric       return str;
1450b57cec5SDimitry Andric     break;
1460b57cec5SDimitry Andric   case AF_INET6:
1470b57cec5SDimitry Andric     if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv6.sin6_addr, str,
1480b57cec5SDimitry Andric                   sizeof(str)))
1490b57cec5SDimitry Andric       return str;
1500b57cec5SDimitry Andric     break;
1510b57cec5SDimitry Andric   }
1520b57cec5SDimitry Andric   return "";
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric 
GetPort() const1550b57cec5SDimitry Andric uint16_t SocketAddress::GetPort() const {
1560b57cec5SDimitry Andric   switch (GetFamily()) {
1570b57cec5SDimitry Andric   case AF_INET:
1580b57cec5SDimitry Andric     return ntohs(m_socket_addr.sa_ipv4.sin_port);
1590b57cec5SDimitry Andric   case AF_INET6:
1600b57cec5SDimitry Andric     return ntohs(m_socket_addr.sa_ipv6.sin6_port);
1610b57cec5SDimitry Andric   }
1620b57cec5SDimitry Andric   return 0;
1630b57cec5SDimitry Andric }
1640b57cec5SDimitry Andric 
SetPort(uint16_t port)1650b57cec5SDimitry Andric bool SocketAddress::SetPort(uint16_t port) {
1660b57cec5SDimitry Andric   switch (GetFamily()) {
1670b57cec5SDimitry Andric   case AF_INET:
1680b57cec5SDimitry Andric     m_socket_addr.sa_ipv4.sin_port = htons(port);
1690b57cec5SDimitry Andric     return true;
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric   case AF_INET6:
1720b57cec5SDimitry Andric     m_socket_addr.sa_ipv6.sin6_port = htons(port);
1730b57cec5SDimitry Andric     return true;
1740b57cec5SDimitry Andric   }
1750b57cec5SDimitry Andric   return false;
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric // SocketAddress assignment operator
1790b57cec5SDimitry Andric const SocketAddress &SocketAddress::
operator =(const struct addrinfo * addr_info)1800b57cec5SDimitry Andric operator=(const struct addrinfo *addr_info) {
1810b57cec5SDimitry Andric   Clear();
1820b57cec5SDimitry Andric   if (addr_info && addr_info->ai_addr && addr_info->ai_addrlen > 0 &&
1830b57cec5SDimitry Andric       size_t(addr_info->ai_addrlen) <= sizeof m_socket_addr) {
1840b57cec5SDimitry Andric     ::memcpy(&m_socket_addr, addr_info->ai_addr, addr_info->ai_addrlen);
1850b57cec5SDimitry Andric   }
1860b57cec5SDimitry Andric   return *this;
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric 
operator =(const struct sockaddr & s)1890b57cec5SDimitry Andric const SocketAddress &SocketAddress::operator=(const struct sockaddr &s) {
1900b57cec5SDimitry Andric   m_socket_addr.sa = s;
1910b57cec5SDimitry Andric   return *this;
1920b57cec5SDimitry Andric }
1930b57cec5SDimitry Andric 
operator =(const struct sockaddr_in & s)1940b57cec5SDimitry Andric const SocketAddress &SocketAddress::operator=(const struct sockaddr_in &s) {
1950b57cec5SDimitry Andric   m_socket_addr.sa_ipv4 = s;
1960b57cec5SDimitry Andric   return *this;
1970b57cec5SDimitry Andric }
1980b57cec5SDimitry Andric 
operator =(const struct sockaddr_in6 & s)1990b57cec5SDimitry Andric const SocketAddress &SocketAddress::operator=(const struct sockaddr_in6 &s) {
2000b57cec5SDimitry Andric   m_socket_addr.sa_ipv6 = s;
2010b57cec5SDimitry Andric   return *this;
2020b57cec5SDimitry Andric }
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric const SocketAddress &SocketAddress::
operator =(const struct sockaddr_storage & s)2050b57cec5SDimitry Andric operator=(const struct sockaddr_storage &s) {
2060b57cec5SDimitry Andric   m_socket_addr.sa_storage = s;
2070b57cec5SDimitry Andric   return *this;
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric 
getaddrinfo(const char * host,const char * service,int ai_family,int ai_socktype,int ai_protocol,int ai_flags)2100b57cec5SDimitry Andric bool SocketAddress::getaddrinfo(const char *host, const char *service,
2110b57cec5SDimitry Andric                                 int ai_family, int ai_socktype, int ai_protocol,
2120b57cec5SDimitry Andric                                 int ai_flags) {
2130b57cec5SDimitry Andric   Clear();
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   auto addresses = GetAddressInfo(host, service, ai_family, ai_socktype,
2160b57cec5SDimitry Andric                                   ai_protocol, ai_flags);
2170b57cec5SDimitry Andric   if (!addresses.empty())
2180b57cec5SDimitry Andric     *this = addresses[0];
2190b57cec5SDimitry Andric   return IsValid();
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric std::vector<SocketAddress>
GetAddressInfo(const char * hostname,const char * servname,int ai_family,int ai_socktype,int ai_protocol,int ai_flags)2230b57cec5SDimitry Andric SocketAddress::GetAddressInfo(const char *hostname, const char *servname,
2240b57cec5SDimitry Andric                               int ai_family, int ai_socktype, int ai_protocol,
2250b57cec5SDimitry Andric                               int ai_flags) {
2260b57cec5SDimitry Andric   std::vector<SocketAddress> addr_list;
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric   struct addrinfo hints;
2290b57cec5SDimitry Andric   memset(&hints, 0, sizeof(hints));
2300b57cec5SDimitry Andric   hints.ai_family = ai_family;
2310b57cec5SDimitry Andric   hints.ai_socktype = ai_socktype;
2320b57cec5SDimitry Andric   hints.ai_protocol = ai_protocol;
2330b57cec5SDimitry Andric   hints.ai_flags = ai_flags;
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   struct addrinfo *service_info_list = nullptr;
2360b57cec5SDimitry Andric   int err = ::getaddrinfo(hostname, servname, &hints, &service_info_list);
2370b57cec5SDimitry Andric   if (err == 0 && service_info_list) {
2380b57cec5SDimitry Andric     for (struct addrinfo *service_ptr = service_info_list;
2390b57cec5SDimitry Andric          service_ptr != nullptr; service_ptr = service_ptr->ai_next) {
2400b57cec5SDimitry Andric       addr_list.emplace_back(SocketAddress(service_ptr));
2410b57cec5SDimitry Andric     }
2420b57cec5SDimitry Andric   }
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric   if (service_info_list)
2450b57cec5SDimitry Andric     ::freeaddrinfo(service_info_list);
2460b57cec5SDimitry Andric   return addr_list;
2470b57cec5SDimitry Andric }
2480b57cec5SDimitry Andric 
SetToLocalhost(sa_family_t family,uint16_t port)2490b57cec5SDimitry Andric bool SocketAddress::SetToLocalhost(sa_family_t family, uint16_t port) {
2500b57cec5SDimitry Andric   switch (family) {
2510b57cec5SDimitry Andric   case AF_INET:
2520b57cec5SDimitry Andric     SetFamily(AF_INET);
2530b57cec5SDimitry Andric     if (SetPort(port)) {
2540b57cec5SDimitry Andric       m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
2550b57cec5SDimitry Andric       return true;
2560b57cec5SDimitry Andric     }
2570b57cec5SDimitry Andric     break;
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   case AF_INET6:
2600b57cec5SDimitry Andric     SetFamily(AF_INET6);
2610b57cec5SDimitry Andric     if (SetPort(port)) {
2620b57cec5SDimitry Andric       m_socket_addr.sa_ipv6.sin6_addr = in6addr_loopback;
2630b57cec5SDimitry Andric       return true;
2640b57cec5SDimitry Andric     }
2650b57cec5SDimitry Andric     break;
2660b57cec5SDimitry Andric   }
2670b57cec5SDimitry Andric   Clear();
2680b57cec5SDimitry Andric   return false;
2690b57cec5SDimitry Andric }
2700b57cec5SDimitry Andric 
SetToAnyAddress(sa_family_t family,uint16_t port)2710b57cec5SDimitry Andric bool SocketAddress::SetToAnyAddress(sa_family_t family, uint16_t port) {
2720b57cec5SDimitry Andric   switch (family) {
2730b57cec5SDimitry Andric   case AF_INET:
2740b57cec5SDimitry Andric     SetFamily(AF_INET);
2750b57cec5SDimitry Andric     if (SetPort(port)) {
2760b57cec5SDimitry Andric       m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
2770b57cec5SDimitry Andric       return true;
2780b57cec5SDimitry Andric     }
2790b57cec5SDimitry Andric     break;
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric   case AF_INET6:
2820b57cec5SDimitry Andric     SetFamily(AF_INET6);
2830b57cec5SDimitry Andric     if (SetPort(port)) {
2840b57cec5SDimitry Andric       m_socket_addr.sa_ipv6.sin6_addr = in6addr_any;
2850b57cec5SDimitry Andric       return true;
2860b57cec5SDimitry Andric     }
2870b57cec5SDimitry Andric     break;
2880b57cec5SDimitry Andric   }
2890b57cec5SDimitry Andric   Clear();
2900b57cec5SDimitry Andric   return false;
2910b57cec5SDimitry Andric }
2920b57cec5SDimitry Andric 
IsAnyAddr() const2930b57cec5SDimitry Andric bool SocketAddress::IsAnyAddr() const {
2940b57cec5SDimitry Andric   return (GetFamily() == AF_INET)
2950b57cec5SDimitry Andric              ? m_socket_addr.sa_ipv4.sin_addr.s_addr == htonl(INADDR_ANY)
2960b57cec5SDimitry Andric              : 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, &in6addr_any, 16);
2970b57cec5SDimitry Andric }
2980b57cec5SDimitry Andric 
IsLocalhost() const2990b57cec5SDimitry Andric bool SocketAddress::IsLocalhost() const {
3000b57cec5SDimitry Andric   return (GetFamily() == AF_INET)
3010b57cec5SDimitry Andric              ? m_socket_addr.sa_ipv4.sin_addr.s_addr == htonl(INADDR_LOOPBACK)
3020b57cec5SDimitry Andric              : 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, &in6addr_loopback,
3030b57cec5SDimitry Andric                            16);
3040b57cec5SDimitry Andric }
3050b57cec5SDimitry Andric 
operator ==(const SocketAddress & rhs) const3060b57cec5SDimitry Andric bool SocketAddress::operator==(const SocketAddress &rhs) const {
3070b57cec5SDimitry Andric   if (GetFamily() != rhs.GetFamily())
3080b57cec5SDimitry Andric     return false;
3090b57cec5SDimitry Andric   if (GetLength() != rhs.GetLength())
3100b57cec5SDimitry Andric     return false;
3110b57cec5SDimitry Andric   switch (GetFamily()) {
3120b57cec5SDimitry Andric   case AF_INET:
3130b57cec5SDimitry Andric     return m_socket_addr.sa_ipv4.sin_addr.s_addr ==
3140b57cec5SDimitry Andric            rhs.m_socket_addr.sa_ipv4.sin_addr.s_addr;
3150b57cec5SDimitry Andric   case AF_INET6:
3160b57cec5SDimitry Andric     return 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr,
3170b57cec5SDimitry Andric                        &rhs.m_socket_addr.sa_ipv6.sin6_addr, 16);
3180b57cec5SDimitry Andric   }
3190b57cec5SDimitry Andric   return false;
3200b57cec5SDimitry Andric }
3210b57cec5SDimitry Andric 
operator !=(const SocketAddress & rhs) const3220b57cec5SDimitry Andric bool SocketAddress::operator!=(const SocketAddress &rhs) const {
3230b57cec5SDimitry Andric   return !(*this == rhs);
3240b57cec5SDimitry Andric }
325