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