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