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