]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Host/common/SocketAddress.cpp
Merge ^/head r312894 through r312967.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Host / common / SocketAddress.cpp
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
39 const 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
71 using namespace lldb_private;
72
73 //----------------------------------------------------------------------
74 // SocketAddress constructor
75 //----------------------------------------------------------------------
76 SocketAddress::SocketAddress() { Clear(); }
77
78 SocketAddress::SocketAddress(const struct sockaddr &s) { m_socket_addr.sa = s; }
79
80 SocketAddress::SocketAddress(const struct sockaddr_in &s) {
81   m_socket_addr.sa_ipv4 = s;
82 }
83
84 SocketAddress::SocketAddress(const struct sockaddr_in6 &s) {
85   m_socket_addr.sa_ipv6 = s;
86 }
87
88 SocketAddress::SocketAddress(const struct sockaddr_storage &s) {
89   m_socket_addr.sa_storage = s;
90 }
91
92 //----------------------------------------------------------------------
93 // SocketAddress copy constructor
94 //----------------------------------------------------------------------
95 SocketAddress::SocketAddress(const SocketAddress &rhs)
96     : m_socket_addr(rhs.m_socket_addr) {}
97
98 //----------------------------------------------------------------------
99 // Destructor
100 //----------------------------------------------------------------------
101 SocketAddress::~SocketAddress() {}
102
103 void SocketAddress::Clear() {
104   memset(&m_socket_addr, 0, sizeof(m_socket_addr));
105 }
106
107 bool SocketAddress::IsValid() const { return GetLength() != 0; }
108
109 static 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
120 socklen_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
128 socklen_t SocketAddress::GetMaxLength() { return sizeof(sockaddr_t); }
129
130 sa_family_t SocketAddress::GetFamily() const {
131   return m_socket_addr.sa.sa_family;
132 }
133
134 void 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
141 std::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
158 uint16_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
168 bool 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 //----------------------------------------------------------------------
184 const SocketAddress &SocketAddress::operator=(const SocketAddress &rhs) {
185   if (this != &rhs)
186     m_socket_addr = rhs.m_socket_addr;
187   return *this;
188 }
189
190 const SocketAddress &SocketAddress::
191 operator=(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
200 const SocketAddress &SocketAddress::operator=(const struct sockaddr &s) {
201   m_socket_addr.sa = s;
202   return *this;
203 }
204
205 const SocketAddress &SocketAddress::operator=(const struct sockaddr_in &s) {
206   m_socket_addr.sa_ipv4 = s;
207   return *this;
208 }
209
210 const SocketAddress &SocketAddress::operator=(const struct sockaddr_in6 &s) {
211   m_socket_addr.sa_ipv6 = s;
212   return *this;
213 }
214
215 const SocketAddress &SocketAddress::
216 operator=(const struct sockaddr_storage &s) {
217   m_socket_addr.sa_storage = s;
218   return *this;
219 }
220
221 bool 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
247 bool 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
269 bool 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 }