xref: /openbsd-src/gnu/llvm/lldb/source/Host/common/SocketAddress.cpp (revision a0747c9f67a4ae71ccb71e62a28d1ea19e06a63c)
1dda28197Spatrick //===-- SocketAddress.cpp -------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick //
9061da546Spatrick // Note: This file is used on Darwin by debugserver, so it needs to remain as
10061da546Spatrick //       self contained as possible, and devoid of references to LLVM unless
11061da546Spatrick //       there is compelling reason.
12061da546Spatrick //
13061da546Spatrick //===----------------------------------------------------------------------===//
14061da546Spatrick 
15061da546Spatrick #if defined(_MSC_VER)
16061da546Spatrick #define _WINSOCK_DEPRECATED_NO_WARNINGS
17061da546Spatrick #endif
18061da546Spatrick 
19061da546Spatrick #include "lldb/Host/SocketAddress.h"
20*a0747c9fSpatrick #include <cstddef>
21*a0747c9fSpatrick #include <cstdio>
22061da546Spatrick 
23061da546Spatrick #if !defined(_WIN32)
24061da546Spatrick #include <arpa/inet.h>
25061da546Spatrick #endif
26061da546Spatrick 
27*a0747c9fSpatrick #include <cassert>
28*a0747c9fSpatrick #include <cstring>
29061da546Spatrick 
30061da546Spatrick #include "lldb/Host/PosixApi.h"
31061da546Spatrick 
32061da546Spatrick // WindowsXP needs an inet_ntop implementation
33061da546Spatrick #ifdef _WIN32
34061da546Spatrick 
35061da546Spatrick #ifndef INET6_ADDRSTRLEN // might not be defined in older Windows SDKs
36061da546Spatrick #define INET6_ADDRSTRLEN 46
37061da546Spatrick #endif
38061da546Spatrick 
39061da546Spatrick // TODO: implement shortened form "::" for runs of zeros
inet_ntop(int af,const void * src,char * dst,socklen_t size)40061da546Spatrick const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) {
41061da546Spatrick   if (size == 0) {
42061da546Spatrick     return nullptr;
43061da546Spatrick   }
44061da546Spatrick 
45061da546Spatrick   switch (af) {
46061da546Spatrick   case AF_INET: {
47061da546Spatrick     {
48061da546Spatrick       const char *formatted = inet_ntoa(*static_cast<const in_addr *>(src));
49061da546Spatrick       if (formatted && strlen(formatted) < static_cast<size_t>(size)) {
50061da546Spatrick         return ::strcpy(dst, formatted);
51061da546Spatrick       }
52061da546Spatrick     }
53061da546Spatrick     return nullptr;
54061da546Spatrick   case AF_INET6: {
55061da546Spatrick     char tmp[INET6_ADDRSTRLEN] = {0};
56061da546Spatrick     const uint16_t *src16 = static_cast<const uint16_t *>(src);
57061da546Spatrick     int full_size = ::snprintf(
58061da546Spatrick         tmp, sizeof(tmp), "%x:%x:%x:%x:%x:%x:%x:%x", ntohs(src16[0]),
59061da546Spatrick         ntohs(src16[1]), ntohs(src16[2]), ntohs(src16[3]), ntohs(src16[4]),
60061da546Spatrick         ntohs(src16[5]), ntohs(src16[6]), ntohs(src16[7]));
61061da546Spatrick     if (full_size < static_cast<int>(size)) {
62061da546Spatrick       return ::strcpy(dst, tmp);
63061da546Spatrick     }
64061da546Spatrick     return nullptr;
65061da546Spatrick   }
66061da546Spatrick   }
67061da546Spatrick   }
68061da546Spatrick   return nullptr;
69061da546Spatrick }
70061da546Spatrick #endif
71061da546Spatrick 
72061da546Spatrick using namespace lldb_private;
73061da546Spatrick 
74061da546Spatrick // SocketAddress constructor
SocketAddress()75061da546Spatrick SocketAddress::SocketAddress() { Clear(); }
76061da546Spatrick 
SocketAddress(const struct sockaddr & s)77061da546Spatrick SocketAddress::SocketAddress(const struct sockaddr &s) { m_socket_addr.sa = s; }
78061da546Spatrick 
SocketAddress(const struct sockaddr_in & s)79061da546Spatrick SocketAddress::SocketAddress(const struct sockaddr_in &s) {
80061da546Spatrick   m_socket_addr.sa_ipv4 = s;
81061da546Spatrick }
82061da546Spatrick 
SocketAddress(const struct sockaddr_in6 & s)83061da546Spatrick SocketAddress::SocketAddress(const struct sockaddr_in6 &s) {
84061da546Spatrick   m_socket_addr.sa_ipv6 = s;
85061da546Spatrick }
86061da546Spatrick 
SocketAddress(const struct sockaddr_storage & s)87061da546Spatrick SocketAddress::SocketAddress(const struct sockaddr_storage &s) {
88061da546Spatrick   m_socket_addr.sa_storage = s;
89061da546Spatrick }
90061da546Spatrick 
SocketAddress(const struct addrinfo * addr_info)91061da546Spatrick SocketAddress::SocketAddress(const struct addrinfo *addr_info) {
92061da546Spatrick   *this = addr_info;
93061da546Spatrick }
94061da546Spatrick 
95061da546Spatrick // Destructor
96*a0747c9fSpatrick SocketAddress::~SocketAddress() = default;
97061da546Spatrick 
Clear()98061da546Spatrick void SocketAddress::Clear() {
99061da546Spatrick   memset(&m_socket_addr, 0, sizeof(m_socket_addr));
100061da546Spatrick }
101061da546Spatrick 
IsValid() const102061da546Spatrick bool SocketAddress::IsValid() const { return GetLength() != 0; }
103061da546Spatrick 
GetFamilyLength(sa_family_t family)104061da546Spatrick static socklen_t GetFamilyLength(sa_family_t family) {
105061da546Spatrick   switch (family) {
106061da546Spatrick   case AF_INET:
107061da546Spatrick     return sizeof(struct sockaddr_in);
108061da546Spatrick   case AF_INET6:
109061da546Spatrick     return sizeof(struct sockaddr_in6);
110061da546Spatrick   }
111061da546Spatrick   assert(0 && "Unsupported address family");
112061da546Spatrick   return 0;
113061da546Spatrick }
114061da546Spatrick 
GetLength() const115061da546Spatrick socklen_t SocketAddress::GetLength() const {
116adae0cfdSpatrick #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
117061da546Spatrick   return m_socket_addr.sa.sa_len;
118061da546Spatrick #else
119061da546Spatrick   return GetFamilyLength(GetFamily());
120061da546Spatrick #endif
121061da546Spatrick }
122061da546Spatrick 
GetMaxLength()123061da546Spatrick socklen_t SocketAddress::GetMaxLength() { return sizeof(sockaddr_t); }
124061da546Spatrick 
GetFamily() const125061da546Spatrick sa_family_t SocketAddress::GetFamily() const {
126061da546Spatrick   return m_socket_addr.sa.sa_family;
127061da546Spatrick }
128061da546Spatrick 
SetFamily(sa_family_t family)129061da546Spatrick void SocketAddress::SetFamily(sa_family_t family) {
130061da546Spatrick   m_socket_addr.sa.sa_family = family;
131adae0cfdSpatrick #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
132061da546Spatrick   m_socket_addr.sa.sa_len = GetFamilyLength(family);
133061da546Spatrick #endif
134061da546Spatrick }
135061da546Spatrick 
GetIPAddress() const136061da546Spatrick std::string SocketAddress::GetIPAddress() const {
137061da546Spatrick   char str[INET6_ADDRSTRLEN] = {0};
138061da546Spatrick   switch (GetFamily()) {
139061da546Spatrick   case AF_INET:
140061da546Spatrick     if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv4.sin_addr, str,
141061da546Spatrick                   sizeof(str)))
142061da546Spatrick       return str;
143061da546Spatrick     break;
144061da546Spatrick   case AF_INET6:
145061da546Spatrick     if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv6.sin6_addr, str,
146061da546Spatrick                   sizeof(str)))
147061da546Spatrick       return str;
148061da546Spatrick     break;
149061da546Spatrick   }
150061da546Spatrick   return "";
151061da546Spatrick }
152061da546Spatrick 
GetPort() const153061da546Spatrick uint16_t SocketAddress::GetPort() const {
154061da546Spatrick   switch (GetFamily()) {
155061da546Spatrick   case AF_INET:
156061da546Spatrick     return ntohs(m_socket_addr.sa_ipv4.sin_port);
157061da546Spatrick   case AF_INET6:
158061da546Spatrick     return ntohs(m_socket_addr.sa_ipv6.sin6_port);
159061da546Spatrick   }
160061da546Spatrick   return 0;
161061da546Spatrick }
162061da546Spatrick 
SetPort(uint16_t port)163061da546Spatrick bool SocketAddress::SetPort(uint16_t port) {
164061da546Spatrick   switch (GetFamily()) {
165061da546Spatrick   case AF_INET:
166061da546Spatrick     m_socket_addr.sa_ipv4.sin_port = htons(port);
167061da546Spatrick     return true;
168061da546Spatrick 
169061da546Spatrick   case AF_INET6:
170061da546Spatrick     m_socket_addr.sa_ipv6.sin6_port = htons(port);
171061da546Spatrick     return true;
172061da546Spatrick   }
173061da546Spatrick   return false;
174061da546Spatrick }
175061da546Spatrick 
176061da546Spatrick // SocketAddress assignment operator
177061da546Spatrick const SocketAddress &SocketAddress::
operator =(const struct addrinfo * addr_info)178061da546Spatrick operator=(const struct addrinfo *addr_info) {
179061da546Spatrick   Clear();
180061da546Spatrick   if (addr_info && addr_info->ai_addr && addr_info->ai_addrlen > 0 &&
181061da546Spatrick       size_t(addr_info->ai_addrlen) <= sizeof m_socket_addr) {
182061da546Spatrick     ::memcpy(&m_socket_addr, addr_info->ai_addr, addr_info->ai_addrlen);
183061da546Spatrick   }
184061da546Spatrick   return *this;
185061da546Spatrick }
186061da546Spatrick 
operator =(const struct sockaddr & s)187061da546Spatrick const SocketAddress &SocketAddress::operator=(const struct sockaddr &s) {
188061da546Spatrick   m_socket_addr.sa = s;
189061da546Spatrick   return *this;
190061da546Spatrick }
191061da546Spatrick 
operator =(const struct sockaddr_in & s)192061da546Spatrick const SocketAddress &SocketAddress::operator=(const struct sockaddr_in &s) {
193061da546Spatrick   m_socket_addr.sa_ipv4 = s;
194061da546Spatrick   return *this;
195061da546Spatrick }
196061da546Spatrick 
operator =(const struct sockaddr_in6 & s)197061da546Spatrick const SocketAddress &SocketAddress::operator=(const struct sockaddr_in6 &s) {
198061da546Spatrick   m_socket_addr.sa_ipv6 = s;
199061da546Spatrick   return *this;
200061da546Spatrick }
201061da546Spatrick 
202061da546Spatrick const SocketAddress &SocketAddress::
operator =(const struct sockaddr_storage & s)203061da546Spatrick operator=(const struct sockaddr_storage &s) {
204061da546Spatrick   m_socket_addr.sa_storage = s;
205061da546Spatrick   return *this;
206061da546Spatrick }
207061da546Spatrick 
getaddrinfo(const char * host,const char * service,int ai_family,int ai_socktype,int ai_protocol,int ai_flags)208061da546Spatrick bool SocketAddress::getaddrinfo(const char *host, const char *service,
209061da546Spatrick                                 int ai_family, int ai_socktype, int ai_protocol,
210061da546Spatrick                                 int ai_flags) {
211061da546Spatrick   Clear();
212061da546Spatrick 
213061da546Spatrick   auto addresses = GetAddressInfo(host, service, ai_family, ai_socktype,
214061da546Spatrick                                   ai_protocol, ai_flags);
215061da546Spatrick   if (!addresses.empty())
216061da546Spatrick     *this = addresses[0];
217061da546Spatrick   return IsValid();
218061da546Spatrick }
219061da546Spatrick 
220061da546Spatrick std::vector<SocketAddress>
GetAddressInfo(const char * hostname,const char * servname,int ai_family,int ai_socktype,int ai_protocol,int ai_flags)221061da546Spatrick SocketAddress::GetAddressInfo(const char *hostname, const char *servname,
222061da546Spatrick                               int ai_family, int ai_socktype, int ai_protocol,
223061da546Spatrick                               int ai_flags) {
224061da546Spatrick   std::vector<SocketAddress> addr_list;
225061da546Spatrick 
226061da546Spatrick   struct addrinfo hints;
227061da546Spatrick   memset(&hints, 0, sizeof(hints));
228061da546Spatrick   hints.ai_family = ai_family;
229061da546Spatrick   hints.ai_socktype = ai_socktype;
230061da546Spatrick   hints.ai_protocol = ai_protocol;
231061da546Spatrick   hints.ai_flags = ai_flags;
232061da546Spatrick 
233061da546Spatrick   struct addrinfo *service_info_list = nullptr;
234061da546Spatrick   int err = ::getaddrinfo(hostname, servname, &hints, &service_info_list);
235061da546Spatrick   if (err == 0 && service_info_list) {
236061da546Spatrick     for (struct addrinfo *service_ptr = service_info_list;
237061da546Spatrick          service_ptr != nullptr; service_ptr = service_ptr->ai_next) {
238061da546Spatrick       addr_list.emplace_back(SocketAddress(service_ptr));
239061da546Spatrick     }
240061da546Spatrick   }
241061da546Spatrick 
242061da546Spatrick   if (service_info_list)
243061da546Spatrick     ::freeaddrinfo(service_info_list);
244061da546Spatrick   return addr_list;
245061da546Spatrick }
246061da546Spatrick 
SetToLocalhost(sa_family_t family,uint16_t port)247061da546Spatrick bool SocketAddress::SetToLocalhost(sa_family_t family, uint16_t port) {
248061da546Spatrick   switch (family) {
249061da546Spatrick   case AF_INET:
250061da546Spatrick     SetFamily(AF_INET);
251061da546Spatrick     if (SetPort(port)) {
252061da546Spatrick       m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
253061da546Spatrick       return true;
254061da546Spatrick     }
255061da546Spatrick     break;
256061da546Spatrick 
257061da546Spatrick   case AF_INET6:
258061da546Spatrick     SetFamily(AF_INET6);
259061da546Spatrick     if (SetPort(port)) {
260061da546Spatrick       m_socket_addr.sa_ipv6.sin6_addr = in6addr_loopback;
261061da546Spatrick       return true;
262061da546Spatrick     }
263061da546Spatrick     break;
264061da546Spatrick   }
265061da546Spatrick   Clear();
266061da546Spatrick   return false;
267061da546Spatrick }
268061da546Spatrick 
SetToAnyAddress(sa_family_t family,uint16_t port)269061da546Spatrick bool SocketAddress::SetToAnyAddress(sa_family_t family, uint16_t port) {
270061da546Spatrick   switch (family) {
271061da546Spatrick   case AF_INET:
272061da546Spatrick     SetFamily(AF_INET);
273061da546Spatrick     if (SetPort(port)) {
274061da546Spatrick       m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
275061da546Spatrick       return true;
276061da546Spatrick     }
277061da546Spatrick     break;
278061da546Spatrick 
279061da546Spatrick   case AF_INET6:
280061da546Spatrick     SetFamily(AF_INET6);
281061da546Spatrick     if (SetPort(port)) {
282061da546Spatrick       m_socket_addr.sa_ipv6.sin6_addr = in6addr_any;
283061da546Spatrick       return true;
284061da546Spatrick     }
285061da546Spatrick     break;
286061da546Spatrick   }
287061da546Spatrick   Clear();
288061da546Spatrick   return false;
289061da546Spatrick }
290061da546Spatrick 
IsAnyAddr() const291061da546Spatrick bool SocketAddress::IsAnyAddr() const {
292061da546Spatrick   return (GetFamily() == AF_INET)
293061da546Spatrick              ? m_socket_addr.sa_ipv4.sin_addr.s_addr == htonl(INADDR_ANY)
294061da546Spatrick              : 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, &in6addr_any, 16);
295061da546Spatrick }
296061da546Spatrick 
IsLocalhost() const297061da546Spatrick bool SocketAddress::IsLocalhost() const {
298061da546Spatrick   return (GetFamily() == AF_INET)
299061da546Spatrick              ? m_socket_addr.sa_ipv4.sin_addr.s_addr == htonl(INADDR_LOOPBACK)
300061da546Spatrick              : 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, &in6addr_loopback,
301061da546Spatrick                            16);
302061da546Spatrick }
303061da546Spatrick 
operator ==(const SocketAddress & rhs) const304061da546Spatrick bool SocketAddress::operator==(const SocketAddress &rhs) const {
305061da546Spatrick   if (GetFamily() != rhs.GetFamily())
306061da546Spatrick     return false;
307061da546Spatrick   if (GetLength() != rhs.GetLength())
308061da546Spatrick     return false;
309061da546Spatrick   switch (GetFamily()) {
310061da546Spatrick   case AF_INET:
311061da546Spatrick     return m_socket_addr.sa_ipv4.sin_addr.s_addr ==
312061da546Spatrick            rhs.m_socket_addr.sa_ipv4.sin_addr.s_addr;
313061da546Spatrick   case AF_INET6:
314061da546Spatrick     return 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr,
315061da546Spatrick                        &rhs.m_socket_addr.sa_ipv6.sin6_addr, 16);
316061da546Spatrick   }
317061da546Spatrick   return false;
318061da546Spatrick }
319061da546Spatrick 
operator !=(const SocketAddress & rhs) const320061da546Spatrick bool SocketAddress::operator!=(const SocketAddress &rhs) const {
321061da546Spatrick   return !(*this == rhs);
322061da546Spatrick }
323