180814287SRaphael Isemann //===-- SocketAddress.cpp -------------------------------------------------===//
2ad440da3SGreg Clayton //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ad440da3SGreg Clayton //
7ad440da3SGreg Clayton //===----------------------------------------------------------------------===//
829618779SChris Bieneman //
929618779SChris Bieneman // Note: This file is used on Darwin by debugserver, so it needs to remain as
1029618779SChris Bieneman //       self contained as possible, and devoid of references to LLVM unless
1129618779SChris Bieneman //       there is compelling reason.
1229618779SChris Bieneman //
1329618779SChris Bieneman //===----------------------------------------------------------------------===//
14ad440da3SGreg Clayton 
155a8ad459SZachary Turner #if defined(_MSC_VER)
165a8ad459SZachary Turner #define _WINSOCK_DEPRECATED_NO_WARNINGS
175a8ad459SZachary Turner #endif
185a8ad459SZachary Turner 
19ad440da3SGreg Clayton #include "lldb/Host/SocketAddress.h"
2076e47d48SRaphael Isemann #include <cstddef>
2176e47d48SRaphael Isemann #include <cstdio>
22ad440da3SGreg Clayton 
236eff1019SHafiz Abid Qadeer #if !defined(_WIN32)
241e0621ceSJoerg Sonnenberger #include <arpa/inet.h>
25d66b50c9SDeepak Panickal #endif
26f343968fSZachary Turner 
2776e47d48SRaphael Isemann #include <cassert>
2876e47d48SRaphael Isemann #include <cstring>
29ad440da3SGreg Clayton 
30f343968fSZachary Turner #include "lldb/Host/PosixApi.h"
31ad440da3SGreg Clayton 
32014bb7daSVince Harron // WindowsXP needs an inet_ntop implementation
33014bb7daSVince Harron #ifdef _WIN32
34014bb7daSVince Harron 
35014bb7daSVince Harron #ifndef INET6_ADDRSTRLEN // might not be defined in older Windows SDKs
36014bb7daSVince Harron #define INET6_ADDRSTRLEN 46
37014bb7daSVince Harron #endif
38014bb7daSVince Harron 
39014bb7daSVince Harron // TODO: implement shortened form "::" for runs of zeros
inet_ntop(int af,const void * src,char * dst,socklen_t size)40b9c1b51eSKate Stone const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) {
41b9c1b51eSKate Stone   if (size == 0) {
42014bb7daSVince Harron     return nullptr;
43014bb7daSVince Harron   }
44014bb7daSVince Harron 
45b9c1b51eSKate Stone   switch (af) {
46b9c1b51eSKate Stone   case AF_INET: {
47ded5ff6fSVince Harron     {
48014bb7daSVince Harron       const char *formatted = inet_ntoa(*static_cast<const in_addr *>(src));
495a8ad459SZachary Turner       if (formatted && strlen(formatted) < static_cast<size_t>(size)) {
50686b1fe6SIlia K         return ::strcpy(dst, formatted);
51014bb7daSVince Harron       }
52ded5ff6fSVince Harron     }
53014bb7daSVince Harron     return nullptr;
54b9c1b51eSKate Stone   case AF_INET6: {
55014bb7daSVince Harron     char tmp[INET6_ADDRSTRLEN] = {0};
56014bb7daSVince Harron     const uint16_t *src16 = static_cast<const uint16_t *>(src);
57b9c1b51eSKate Stone     int full_size = ::snprintf(
58b9c1b51eSKate Stone         tmp, sizeof(tmp), "%x:%x:%x:%x:%x:%x:%x:%x", ntohs(src16[0]),
59b9c1b51eSKate Stone         ntohs(src16[1]), ntohs(src16[2]), ntohs(src16[3]), ntohs(src16[4]),
60b9c1b51eSKate Stone         ntohs(src16[5]), ntohs(src16[6]), ntohs(src16[7]));
61b9c1b51eSKate Stone     if (full_size < static_cast<int>(size)) {
62686b1fe6SIlia K       return ::strcpy(dst, tmp);
63014bb7daSVince Harron     }
64014bb7daSVince Harron     return nullptr;
65014bb7daSVince Harron   }
66014bb7daSVince Harron   }
67ded5ff6fSVince Harron   }
68014bb7daSVince Harron   return nullptr;
69014bb7daSVince Harron }
70014bb7daSVince Harron #endif
71014bb7daSVince Harron 
72ad440da3SGreg Clayton using namespace lldb_private;
73ad440da3SGreg Clayton 
74ad440da3SGreg Clayton // SocketAddress constructor
SocketAddress()75b9c1b51eSKate Stone SocketAddress::SocketAddress() { Clear(); }
76ad440da3SGreg Clayton 
SocketAddress(const struct sockaddr & s)77b9c1b51eSKate Stone SocketAddress::SocketAddress(const struct sockaddr &s) { m_socket_addr.sa = s; }
789189b208SGreg Clayton 
SocketAddress(const struct sockaddr_in & s)79b9c1b51eSKate Stone SocketAddress::SocketAddress(const struct sockaddr_in &s) {
809189b208SGreg Clayton   m_socket_addr.sa_ipv4 = s;
819189b208SGreg Clayton }
829189b208SGreg Clayton 
SocketAddress(const struct sockaddr_in6 & s)83b9c1b51eSKate Stone SocketAddress::SocketAddress(const struct sockaddr_in6 &s) {
849189b208SGreg Clayton   m_socket_addr.sa_ipv6 = s;
859189b208SGreg Clayton }
869189b208SGreg Clayton 
SocketAddress(const struct sockaddr_storage & s)87b9c1b51eSKate Stone SocketAddress::SocketAddress(const struct sockaddr_storage &s) {
889189b208SGreg Clayton   m_socket_addr.sa_storage = s;
899189b208SGreg Clayton }
909189b208SGreg Clayton 
SocketAddress(const struct addrinfo * addr_info)91a4f532e0SChris Bieneman SocketAddress::SocketAddress(const struct addrinfo *addr_info) {
92a4f532e0SChris Bieneman   *this = addr_info;
93a4f532e0SChris Bieneman }
94a4f532e0SChris Bieneman 
95ad440da3SGreg Clayton // Destructor
96*fd2433e1SJonas Devlieghere SocketAddress::~SocketAddress() = default;
97ad440da3SGreg Clayton 
Clear()98b9c1b51eSKate Stone void SocketAddress::Clear() {
99ad440da3SGreg Clayton   memset(&m_socket_addr, 0, sizeof(m_socket_addr));
100ad440da3SGreg Clayton }
101ad440da3SGreg Clayton 
IsValid() const102b9c1b51eSKate Stone bool SocketAddress::IsValid() const { return GetLength() != 0; }
103ad440da3SGreg Clayton 
GetFamilyLength(sa_family_t family)104b9c1b51eSKate Stone static socklen_t GetFamilyLength(sa_family_t family) {
105b9c1b51eSKate Stone   switch (family) {
106b9c1b51eSKate Stone   case AF_INET:
107b9c1b51eSKate Stone     return sizeof(struct sockaddr_in);
108b9c1b51eSKate Stone   case AF_INET6:
109b9c1b51eSKate Stone     return sizeof(struct sockaddr_in6);
1109a8d848cSPeter Collingbourne   }
1119a8d848cSPeter Collingbourne   assert(0 && "Unsupported address family");
1120a70a845STodd Fiala   return 0;
1139a8d848cSPeter Collingbourne }
1149a8d848cSPeter Collingbourne 
GetLength() const115b9c1b51eSKate Stone socklen_t SocketAddress::GetLength() const {
11610565b61SEd Maste #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
117ad440da3SGreg Clayton   return m_socket_addr.sa.sa_len;
1189a8d848cSPeter Collingbourne #else
1199a8d848cSPeter Collingbourne   return GetFamilyLength(GetFamily());
1209a8d848cSPeter Collingbourne #endif
121ad440da3SGreg Clayton }
122ad440da3SGreg Clayton 
GetMaxLength()123b9c1b51eSKate Stone socklen_t SocketAddress::GetMaxLength() { return sizeof(sockaddr_t); }
124ad440da3SGreg Clayton 
GetFamily() const125b9c1b51eSKate Stone sa_family_t SocketAddress::GetFamily() const {
126ad440da3SGreg Clayton   return m_socket_addr.sa.sa_family;
127ad440da3SGreg Clayton }
128ad440da3SGreg Clayton 
SetFamily(sa_family_t family)129b9c1b51eSKate Stone void SocketAddress::SetFamily(sa_family_t family) {
130ad440da3SGreg Clayton   m_socket_addr.sa.sa_family = family;
13110565b61SEd Maste #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
1329a8d848cSPeter Collingbourne   m_socket_addr.sa.sa_len = GetFamilyLength(family);
1339a8d848cSPeter Collingbourne #endif
134ad440da3SGreg Clayton }
135ad440da3SGreg Clayton 
GetIPAddress() const136b9c1b51eSKate Stone std::string SocketAddress::GetIPAddress() const {
137014bb7daSVince Harron   char str[INET6_ADDRSTRLEN] = {0};
138b9c1b51eSKate Stone   switch (GetFamily()) {
139014bb7daSVince Harron   case AF_INET:
140b9c1b51eSKate Stone     if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv4.sin_addr, str,
141b9c1b51eSKate Stone                   sizeof(str)))
142014bb7daSVince Harron       return str;
143cec91ef9SGreg Clayton     break;
144014bb7daSVince Harron   case AF_INET6:
145b9c1b51eSKate Stone     if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv6.sin6_addr, str,
146b9c1b51eSKate Stone                   sizeof(str)))
147014bb7daSVince Harron       return str;
148cec91ef9SGreg Clayton     break;
149014bb7daSVince Harron   }
150014bb7daSVince Harron   return "";
151014bb7daSVince Harron }
152014bb7daSVince Harron 
GetPort() const153b9c1b51eSKate Stone uint16_t SocketAddress::GetPort() const {
154b9c1b51eSKate Stone   switch (GetFamily()) {
155b9c1b51eSKate Stone   case AF_INET:
156b9c1b51eSKate Stone     return ntohs(m_socket_addr.sa_ipv4.sin_port);
157b9c1b51eSKate Stone   case AF_INET6:
158b9c1b51eSKate Stone     return ntohs(m_socket_addr.sa_ipv6.sin6_port);
159ad440da3SGreg Clayton   }
160ad440da3SGreg Clayton   return 0;
161ad440da3SGreg Clayton }
162ad440da3SGreg Clayton 
SetPort(uint16_t port)163b9c1b51eSKate Stone bool SocketAddress::SetPort(uint16_t port) {
164b9c1b51eSKate Stone   switch (GetFamily()) {
1659189b208SGreg Clayton   case AF_INET:
1669189b208SGreg Clayton     m_socket_addr.sa_ipv4.sin_port = htons(port);
1679189b208SGreg Clayton     return true;
1689189b208SGreg Clayton 
1699189b208SGreg Clayton   case AF_INET6:
1709189b208SGreg Clayton     m_socket_addr.sa_ipv6.sin6_port = htons(port);
1719189b208SGreg Clayton     return true;
1729189b208SGreg Clayton   }
1739189b208SGreg Clayton   return false;
1749189b208SGreg Clayton }
1759189b208SGreg Clayton 
176ad440da3SGreg Clayton // SocketAddress assignment operator
177b9c1b51eSKate Stone const SocketAddress &SocketAddress::
operator =(const struct addrinfo * addr_info)178b9c1b51eSKate Stone operator=(const struct addrinfo *addr_info) {
179ad440da3SGreg Clayton   Clear();
180b9c1b51eSKate Stone   if (addr_info && addr_info->ai_addr && addr_info->ai_addrlen > 0 &&
181ef7aff50SPavel Labath       size_t(addr_info->ai_addrlen) <= sizeof m_socket_addr) {
182b9c1b51eSKate Stone     ::memcpy(&m_socket_addr, addr_info->ai_addr, addr_info->ai_addrlen);
183ad440da3SGreg Clayton   }
184ad440da3SGreg Clayton   return *this;
185ad440da3SGreg Clayton }
186ad440da3SGreg Clayton 
operator =(const struct sockaddr & s)187b9c1b51eSKate Stone const SocketAddress &SocketAddress::operator=(const struct sockaddr &s) {
1889189b208SGreg Clayton   m_socket_addr.sa = s;
1899189b208SGreg Clayton   return *this;
1909189b208SGreg Clayton }
1919189b208SGreg Clayton 
operator =(const struct sockaddr_in & s)192b9c1b51eSKate Stone const SocketAddress &SocketAddress::operator=(const struct sockaddr_in &s) {
1939189b208SGreg Clayton   m_socket_addr.sa_ipv4 = s;
1949189b208SGreg Clayton   return *this;
1959189b208SGreg Clayton }
1969189b208SGreg Clayton 
operator =(const struct sockaddr_in6 & s)197b9c1b51eSKate Stone const SocketAddress &SocketAddress::operator=(const struct sockaddr_in6 &s) {
1989189b208SGreg Clayton   m_socket_addr.sa_ipv6 = s;
1999189b208SGreg Clayton   return *this;
2009189b208SGreg Clayton }
2019189b208SGreg Clayton 
202b9c1b51eSKate Stone const SocketAddress &SocketAddress::
operator =(const struct sockaddr_storage & s)203b9c1b51eSKate Stone operator=(const struct sockaddr_storage &s) {
2049189b208SGreg Clayton   m_socket_addr.sa_storage = s;
2059189b208SGreg Clayton   return *this;
2069189b208SGreg Clayton }
2079189b208SGreg Clayton 
getaddrinfo(const char * host,const char * service,int ai_family,int ai_socktype,int ai_protocol,int ai_flags)208b9c1b51eSKate Stone bool SocketAddress::getaddrinfo(const char *host, const char *service,
209b9c1b51eSKate Stone                                 int ai_family, int ai_socktype, int ai_protocol,
210b9c1b51eSKate Stone                                 int ai_flags) {
211e13d71c5SOleksiy Vyalov   Clear();
212e13d71c5SOleksiy Vyalov 
21311827799SChris Bieneman   auto addresses = GetAddressInfo(host, service, ai_family, ai_socktype,
21411827799SChris Bieneman                                   ai_protocol, ai_flags);
215df0497c4SPavel Labath   if (!addresses.empty())
216df0497c4SPavel Labath     *this = addresses[0];
217df0497c4SPavel Labath   return IsValid();
218df0497c4SPavel Labath }
219df0497c4SPavel Labath 
220df0497c4SPavel Labath std::vector<SocketAddress>
GetAddressInfo(const char * hostname,const char * servname,int ai_family,int ai_socktype,int ai_protocol,int ai_flags)221df0497c4SPavel Labath SocketAddress::GetAddressInfo(const char *hostname, const char *servname,
222df0497c4SPavel Labath                               int ai_family, int ai_socktype, int ai_protocol,
223df0497c4SPavel Labath                               int ai_flags) {
224df0497c4SPavel Labath   std::vector<SocketAddress> addr_list;
225df0497c4SPavel Labath 
22600fe87b4SGreg Clayton   struct addrinfo hints;
22700fe87b4SGreg Clayton   memset(&hints, 0, sizeof(hints));
22800fe87b4SGreg Clayton   hints.ai_family = ai_family;
22900fe87b4SGreg Clayton   hints.ai_socktype = ai_socktype;
23000fe87b4SGreg Clayton   hints.ai_protocol = ai_protocol;
23100fe87b4SGreg Clayton   hints.ai_flags = ai_flags;
23200fe87b4SGreg Clayton 
233248a1305SKonrad Kleine   struct addrinfo *service_info_list = nullptr;
234df0497c4SPavel Labath   int err = ::getaddrinfo(hostname, servname, &hints, &service_info_list);
235a4f532e0SChris Bieneman   if (err == 0 && service_info_list) {
236248a1305SKonrad Kleine     for (struct addrinfo *service_ptr = service_info_list;
237248a1305SKonrad Kleine          service_ptr != nullptr; service_ptr = service_ptr->ai_next) {
238a4f532e0SChris Bieneman       addr_list.emplace_back(SocketAddress(service_ptr));
239a4f532e0SChris Bieneman     }
240a4f532e0SChris Bieneman   }
241a4f532e0SChris Bieneman 
242a4f532e0SChris Bieneman   if (service_info_list)
243a4f532e0SChris Bieneman     ::freeaddrinfo(service_info_list);
244a4f532e0SChris Bieneman   return addr_list;
245a4f532e0SChris Bieneman }
246a4f532e0SChris Bieneman 
SetToLocalhost(sa_family_t family,uint16_t port)247b9c1b51eSKate Stone bool SocketAddress::SetToLocalhost(sa_family_t family, uint16_t port) {
248b9c1b51eSKate Stone   switch (family) {
2499189b208SGreg Clayton   case AF_INET:
2509189b208SGreg Clayton     SetFamily(AF_INET);
251b9c1b51eSKate Stone     if (SetPort(port)) {
25200fe87b4SGreg Clayton       m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
25300fe87b4SGreg Clayton       return true;
25400fe87b4SGreg Clayton     }
25500fe87b4SGreg Clayton     break;
25600fe87b4SGreg Clayton 
25700fe87b4SGreg Clayton   case AF_INET6:
25800fe87b4SGreg Clayton     SetFamily(AF_INET6);
259b9c1b51eSKate Stone     if (SetPort(port)) {
26000fe87b4SGreg Clayton       m_socket_addr.sa_ipv6.sin6_addr = in6addr_loopback;
26100fe87b4SGreg Clayton       return true;
26200fe87b4SGreg Clayton     }
26300fe87b4SGreg Clayton     break;
26400fe87b4SGreg Clayton   }
26500fe87b4SGreg Clayton   Clear();
26600fe87b4SGreg Clayton   return false;
26700fe87b4SGreg Clayton }
26800fe87b4SGreg Clayton 
SetToAnyAddress(sa_family_t family,uint16_t port)269b9c1b51eSKate Stone bool SocketAddress::SetToAnyAddress(sa_family_t family, uint16_t port) {
270b9c1b51eSKate Stone   switch (family) {
27100fe87b4SGreg Clayton   case AF_INET:
27200fe87b4SGreg Clayton     SetFamily(AF_INET);
273b9c1b51eSKate Stone     if (SetPort(port)) {
2749189b208SGreg Clayton       m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
2759189b208SGreg Clayton       return true;
2769189b208SGreg Clayton     }
2779189b208SGreg Clayton     break;
2789189b208SGreg Clayton 
2799189b208SGreg Clayton   case AF_INET6:
2809189b208SGreg Clayton     SetFamily(AF_INET6);
281b9c1b51eSKate Stone     if (SetPort(port)) {
2829189b208SGreg Clayton       m_socket_addr.sa_ipv6.sin6_addr = in6addr_any;
2839189b208SGreg Clayton       return true;
2849189b208SGreg Clayton     }
2859189b208SGreg Clayton     break;
2869189b208SGreg Clayton   }
2879189b208SGreg Clayton   Clear();
2889189b208SGreg Clayton   return false;
2899189b208SGreg Clayton }
290a4f532e0SChris Bieneman 
IsAnyAddr() const291a4f532e0SChris Bieneman bool SocketAddress::IsAnyAddr() const {
292a4f532e0SChris Bieneman   return (GetFamily() == AF_INET)
293a4f532e0SChris Bieneman              ? m_socket_addr.sa_ipv4.sin_addr.s_addr == htonl(INADDR_ANY)
294a4f532e0SChris Bieneman              : 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, &in6addr_any, 16);
295a4f532e0SChris Bieneman }
296a4f532e0SChris Bieneman 
IsLocalhost() const2977dc58b23SChris Bieneman bool SocketAddress::IsLocalhost() const {
2987dc58b23SChris Bieneman   return (GetFamily() == AF_INET)
2997dc58b23SChris Bieneman              ? m_socket_addr.sa_ipv4.sin_addr.s_addr == htonl(INADDR_LOOPBACK)
3007dc58b23SChris Bieneman              : 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, &in6addr_loopback,
3017dc58b23SChris Bieneman                            16);
3027dc58b23SChris Bieneman }
3037dc58b23SChris Bieneman 
operator ==(const SocketAddress & rhs) const304a4f532e0SChris Bieneman bool SocketAddress::operator==(const SocketAddress &rhs) const {
305a4f532e0SChris Bieneman   if (GetFamily() != rhs.GetFamily())
306a4f532e0SChris Bieneman     return false;
307a4f532e0SChris Bieneman   if (GetLength() != rhs.GetLength())
308a4f532e0SChris Bieneman     return false;
309a4f532e0SChris Bieneman   switch (GetFamily()) {
310a4f532e0SChris Bieneman   case AF_INET:
311a4f532e0SChris Bieneman     return m_socket_addr.sa_ipv4.sin_addr.s_addr ==
312a4f532e0SChris Bieneman            rhs.m_socket_addr.sa_ipv4.sin_addr.s_addr;
313a4f532e0SChris Bieneman   case AF_INET6:
314a4f532e0SChris Bieneman     return 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr,
315a4f532e0SChris Bieneman                        &rhs.m_socket_addr.sa_ipv6.sin6_addr, 16);
316a4f532e0SChris Bieneman   }
317a4f532e0SChris Bieneman   return false;
318a4f532e0SChris Bieneman }
319a4f532e0SChris Bieneman 
operator !=(const SocketAddress & rhs) const320a4f532e0SChris Bieneman bool SocketAddress::operator!=(const SocketAddress &rhs) const {
321a4f532e0SChris Bieneman   return !(*this == rhs);
322a4f532e0SChris Bieneman }
323