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 using namespace lldb_private;
25 
26 //----------------------------------------------------------------------
27 // SocketAddress constructor
28 //----------------------------------------------------------------------
29 SocketAddress::SocketAddress ()
30 {
31     Clear ();
32 }
33 
34 SocketAddress::SocketAddress (const struct sockaddr &s)
35 {
36     m_socket_addr.sa = s;
37 }
38 
39 
40 SocketAddress::SocketAddress (const struct sockaddr_in &s)
41 {
42     m_socket_addr.sa_ipv4 = s;
43 }
44 
45 
46 SocketAddress::SocketAddress (const struct sockaddr_in6 &s)
47 {
48     m_socket_addr.sa_ipv6 = s;
49 }
50 
51 
52 SocketAddress::SocketAddress (const struct sockaddr_storage &s)
53 {
54     m_socket_addr.sa_storage = s;
55 }
56 
57 //----------------------------------------------------------------------
58 // SocketAddress copy constructor
59 //----------------------------------------------------------------------
60 SocketAddress::SocketAddress (const SocketAddress& rhs) :
61     m_socket_addr (rhs.m_socket_addr)
62 {
63 }
64 
65 //----------------------------------------------------------------------
66 // Destructor
67 //----------------------------------------------------------------------
68 SocketAddress::~SocketAddress()
69 {
70 }
71 
72 void
73 SocketAddress::Clear ()
74 {
75     memset (&m_socket_addr, 0, sizeof(m_socket_addr));
76 }
77 
78 bool
79 SocketAddress::IsValid () const
80 {
81     return GetLength () != 0;
82 }
83 
84 static socklen_t
85 GetFamilyLength (sa_family_t family)
86 {
87     switch (family)
88     {
89         case AF_INET:  return sizeof(struct sockaddr_in);
90         case AF_INET6: return sizeof(struct sockaddr_in6);
91     }
92     assert(0 && "Unsupported address family");
93     return 0;
94 }
95 
96 socklen_t
97 SocketAddress::GetLength () const
98 {
99 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
100     return m_socket_addr.sa.sa_len;
101 #else
102     return GetFamilyLength (GetFamily());
103 #endif
104 }
105 
106 socklen_t
107 SocketAddress::GetMaxLength ()
108 {
109     return sizeof (sockaddr_t);
110 }
111 
112 sa_family_t
113 SocketAddress::GetFamily () const
114 {
115     return m_socket_addr.sa.sa_family;
116 }
117 
118 void
119 SocketAddress::SetFamily (sa_family_t family)
120 {
121     m_socket_addr.sa.sa_family = family;
122 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
123     m_socket_addr.sa.sa_len = GetFamilyLength (family);
124 #endif
125 }
126 
127 uint16_t
128 SocketAddress::GetPort () const
129 {
130     switch (GetFamily())
131     {
132         case AF_INET:   return ntohs(m_socket_addr.sa_ipv4.sin_port);
133         case AF_INET6:  return ntohs(m_socket_addr.sa_ipv6.sin6_port);
134     }
135     return 0;
136 }
137 
138 bool
139 SocketAddress::SetPort (uint16_t port)
140 {
141     switch (GetFamily())
142     {
143         case AF_INET:
144             m_socket_addr.sa_ipv4.sin_port = htons(port);
145             return true;
146 
147         case AF_INET6:
148             m_socket_addr.sa_ipv6.sin6_port = htons(port);
149             return true;
150     }
151     return false;
152 }
153 
154 //----------------------------------------------------------------------
155 // SocketAddress assignment operator
156 //----------------------------------------------------------------------
157 const SocketAddress&
158 SocketAddress::operator=(const SocketAddress& rhs)
159 {
160     if (this != &rhs)
161         m_socket_addr = rhs.m_socket_addr;
162     return *this;
163 }
164 
165 const SocketAddress&
166 SocketAddress::operator=(const struct addrinfo *addr_info)
167 {
168     Clear();
169     if (addr_info &&
170         addr_info->ai_addr &&
171         addr_info->ai_addrlen > 0&&
172         addr_info->ai_addrlen <= sizeof m_socket_addr)
173     {
174         ::memcpy (&m_socket_addr,
175                   addr_info->ai_addr,
176                   addr_info->ai_addrlen);
177     }
178     return *this;
179 }
180 
181 const SocketAddress&
182 SocketAddress::operator=(const struct sockaddr &s)
183 {
184     m_socket_addr.sa = s;
185     return *this;
186 }
187 
188 const SocketAddress&
189 SocketAddress::operator=(const struct sockaddr_in &s)
190 {
191     m_socket_addr.sa_ipv4 = s;
192     return *this;
193 }
194 
195 const SocketAddress&
196 SocketAddress::operator=(const struct sockaddr_in6 &s)
197 {
198     m_socket_addr.sa_ipv6 = s;
199     return *this;
200 }
201 
202 const SocketAddress&
203 SocketAddress::operator=(const struct sockaddr_storage &s)
204 {
205     m_socket_addr.sa_storage = s;
206     return *this;
207 }
208 
209 bool
210 SocketAddress::getaddrinfo (const char *host,
211                             const char *service,
212                             int ai_family,
213                             int ai_socktype,
214                             int ai_protocol,
215                             int ai_flags)
216 {
217     Clear ();
218 
219     struct addrinfo hints;
220     memset(&hints, 0, sizeof(hints));
221     hints.ai_family = ai_family;
222     hints.ai_socktype = ai_socktype;
223     hints.ai_protocol = ai_protocol;
224     hints.ai_flags = ai_flags;
225 
226     bool result = false;
227     struct addrinfo *service_info_list = NULL;
228     int err = ::getaddrinfo (host, service, &hints, &service_info_list);
229     if (err == 0 && service_info_list)
230     {
231         *this = service_info_list;
232         result = IsValid ();
233     }
234 
235     :: freeaddrinfo (service_info_list);
236     return result;
237 }
238 
239 
240 bool
241 SocketAddress::SetToLocalhost (sa_family_t family, uint16_t port)
242 {
243     switch (family)
244     {
245         case AF_INET:
246             SetFamily (AF_INET);
247             if (SetPort (port))
248             {
249                 m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
250                 return true;
251             }
252             break;
253 
254         case AF_INET6:
255             SetFamily (AF_INET6);
256             if (SetPort (port))
257             {
258                 m_socket_addr.sa_ipv6.sin6_addr = in6addr_loopback;
259                 return true;
260             }
261             break;
262 
263     }
264     Clear();
265     return false;
266 }
267 
268 bool
269 SocketAddress::SetToAnyAddress (sa_family_t family, uint16_t port)
270 {
271     switch (family)
272     {
273         case AF_INET:
274             SetFamily (AF_INET);
275             if (SetPort (port))
276             {
277                 m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl (INADDR_ANY);
278                 return true;
279             }
280             break;
281 
282         case AF_INET6:
283             SetFamily (AF_INET6);
284             if (SetPort (port))
285             {
286                 m_socket_addr.sa_ipv6.sin6_addr = in6addr_any;
287                 return true;
288             }
289             break;
290 
291     }
292     Clear();
293     return false;
294 }
295