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