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