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