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