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