/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Host/common/SocketAddress.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- SocketAddress.cpp -------------------------------------------------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // Note: This file is used on Darwin by debugserver, so it needs to remain as |
10 | | // self contained as possible, and devoid of references to LLVM unless |
11 | | // there is compelling reason. |
12 | | // |
13 | | //===----------------------------------------------------------------------===// |
14 | | |
15 | | #if defined(_MSC_VER) |
16 | | #define _WINSOCK_DEPRECATED_NO_WARNINGS |
17 | | #endif |
18 | | |
19 | | #include "lldb/Host/SocketAddress.h" |
20 | | #include <cstddef> |
21 | | #include <cstdio> |
22 | | |
23 | | #if !defined(_WIN32) |
24 | | #include <arpa/inet.h> |
25 | | #endif |
26 | | |
27 | | #include <cassert> |
28 | | #include <cstring> |
29 | | |
30 | | #include "lldb/Host/PosixApi.h" |
31 | | |
32 | | // WindowsXP needs an inet_ntop implementation |
33 | | #ifdef _WIN32 |
34 | | |
35 | | #ifndef INET6_ADDRSTRLEN // might not be defined in older Windows SDKs |
36 | | #define INET6_ADDRSTRLEN 46 |
37 | | #endif |
38 | | |
39 | | // TODO: implement shortened form "::" for runs of zeros |
40 | | const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) { |
41 | | if (size == 0) { |
42 | | return nullptr; |
43 | | } |
44 | | |
45 | | switch (af) { |
46 | | case AF_INET: { |
47 | | { |
48 | | const char *formatted = inet_ntoa(*static_cast<const in_addr *>(src)); |
49 | | if (formatted && strlen(formatted) < static_cast<size_t>(size)) { |
50 | | return ::strcpy(dst, formatted); |
51 | | } |
52 | | } |
53 | | return nullptr; |
54 | | case AF_INET6: { |
55 | | char tmp[INET6_ADDRSTRLEN] = {0}; |
56 | | const uint16_t *src16 = static_cast<const uint16_t *>(src); |
57 | | int full_size = ::snprintf( |
58 | | tmp, sizeof(tmp), "%x:%x:%x:%x:%x:%x:%x:%x", ntohs(src16[0]), |
59 | | ntohs(src16[1]), ntohs(src16[2]), ntohs(src16[3]), ntohs(src16[4]), |
60 | | ntohs(src16[5]), ntohs(src16[6]), ntohs(src16[7])); |
61 | | if (full_size < static_cast<int>(size)) { |
62 | | return ::strcpy(dst, tmp); |
63 | | } |
64 | | return nullptr; |
65 | | } |
66 | | } |
67 | | } |
68 | | return nullptr; |
69 | | } |
70 | | #endif |
71 | | |
72 | | using namespace lldb_private; |
73 | | |
74 | | // SocketAddress constructor |
75 | 311 | SocketAddress::SocketAddress() { Clear(); } |
76 | | |
77 | 0 | SocketAddress::SocketAddress(const struct sockaddr &s) { m_socket_addr.sa = s; } |
78 | | |
79 | 0 | SocketAddress::SocketAddress(const struct sockaddr_in &s) { |
80 | 0 | m_socket_addr.sa_ipv4 = s; |
81 | 0 | } |
82 | | |
83 | 0 | SocketAddress::SocketAddress(const struct sockaddr_in6 &s) { |
84 | 0 | m_socket_addr.sa_ipv6 = s; |
85 | 0 | } |
86 | | |
87 | 0 | SocketAddress::SocketAddress(const struct sockaddr_storage &s) { |
88 | 0 | m_socket_addr.sa_storage = s; |
89 | 0 | } |
90 | | |
91 | 330 | SocketAddress::SocketAddress(const struct addrinfo *addr_info) { |
92 | 330 | *this = addr_info; |
93 | 330 | } |
94 | | |
95 | | // Destructor |
96 | 1.36k | SocketAddress::~SocketAddress() = default; |
97 | | |
98 | 645 | void SocketAddress::Clear() { |
99 | 645 | memset(&m_socket_addr, 0, sizeof(m_socket_addr)); |
100 | 645 | } |
101 | | |
102 | 0 | bool SocketAddress::IsValid() const { return GetLength() != 0; } |
103 | | |
104 | 9 | static socklen_t GetFamilyLength(sa_family_t family) { |
105 | 9 | switch (family) { |
106 | 8 | case AF_INET: |
107 | 8 | return sizeof(struct sockaddr_in); |
108 | 1 | case AF_INET6: |
109 | 1 | return sizeof(struct sockaddr_in6); |
110 | 9 | } |
111 | 0 | assert(0 && "Unsupported address family"); |
112 | 0 | return 0; |
113 | 0 | } |
114 | | |
115 | 460 | socklen_t SocketAddress::GetLength() const { |
116 | 460 | #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) |
117 | 460 | return m_socket_addr.sa.sa_len; |
118 | | #else |
119 | | return GetFamilyLength(GetFamily()); |
120 | | #endif |
121 | 460 | } |
122 | | |
123 | 194 | socklen_t SocketAddress::GetMaxLength() { return sizeof(sockaddr_t); } |
124 | | |
125 | 1.16k | sa_family_t SocketAddress::GetFamily() const { |
126 | 1.16k | return m_socket_addr.sa.sa_family; |
127 | 1.16k | } |
128 | | |
129 | 9 | void SocketAddress::SetFamily(sa_family_t family) { |
130 | 9 | m_socket_addr.sa.sa_family = family; |
131 | 9 | #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) |
132 | 9 | m_socket_addr.sa.sa_len = GetFamilyLength(family); |
133 | 9 | #endif |
134 | 9 | } |
135 | | |
136 | 46 | std::string SocketAddress::GetIPAddress() const { |
137 | 46 | char str[INET6_ADDRSTRLEN] = {0}; |
138 | 46 | switch (GetFamily()) { |
139 | 11 | case AF_INET: |
140 | 11 | if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv4.sin_addr, str, |
141 | 11 | sizeof(str))) |
142 | 11 | return str; |
143 | 0 | break; |
144 | 35 | case AF_INET6: |
145 | 35 | if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv6.sin6_addr, str, |
146 | 35 | sizeof(str))) |
147 | 35 | return str; |
148 | 0 | break; |
149 | 46 | } |
150 | 0 | return ""; |
151 | 46 | } |
152 | | |
153 | 177 | uint16_t SocketAddress::GetPort() const { |
154 | 177 | switch (GetFamily()) { |
155 | 44 | case AF_INET: |
156 | 44 | return ntohs(m_socket_addr.sa_ipv4.sin_port); |
157 | 133 | case AF_INET6: |
158 | 133 | return ntohs(m_socket_addr.sa_ipv6.sin6_port); |
159 | 177 | } |
160 | 0 | return 0; |
161 | 177 | } |
162 | | |
163 | 299 | bool SocketAddress::SetPort(uint16_t port) { |
164 | 299 | switch (GetFamily()) { |
165 | 76 | case AF_INET: |
166 | 76 | m_socket_addr.sa_ipv4.sin_port = htons(port); |
167 | 76 | return true; |
168 | | |
169 | 223 | case AF_INET6: |
170 | 223 | m_socket_addr.sa_ipv6.sin6_port = htons(port); |
171 | 223 | return true; |
172 | 299 | } |
173 | 0 | return false; |
174 | 299 | } |
175 | | |
176 | | // SocketAddress assignment operator |
177 | | const SocketAddress &SocketAddress:: |
178 | 334 | operator=(const struct addrinfo *addr_info) { |
179 | 334 | Clear(); |
180 | 334 | if (addr_info && addr_info->ai_addr && addr_info->ai_addrlen > 0 && |
181 | 334 | size_t(addr_info->ai_addrlen) <= sizeof m_socket_addr) { |
182 | 334 | ::memcpy(&m_socket_addr, addr_info->ai_addr, addr_info->ai_addrlen); |
183 | 334 | } |
184 | 334 | return *this; |
185 | 334 | } |
186 | | |
187 | 0 | const SocketAddress &SocketAddress::operator=(const struct sockaddr &s) { |
188 | 0 | m_socket_addr.sa = s; |
189 | 0 | return *this; |
190 | 0 | } |
191 | | |
192 | 0 | const SocketAddress &SocketAddress::operator=(const struct sockaddr_in &s) { |
193 | 0 | m_socket_addr.sa_ipv4 = s; |
194 | 0 | return *this; |
195 | 0 | } |
196 | | |
197 | 0 | const SocketAddress &SocketAddress::operator=(const struct sockaddr_in6 &s) { |
198 | 0 | m_socket_addr.sa_ipv6 = s; |
199 | 0 | return *this; |
200 | 0 | } |
201 | | |
202 | | const SocketAddress &SocketAddress:: |
203 | 0 | operator=(const struct sockaddr_storage &s) { |
204 | 0 | m_socket_addr.sa_storage = s; |
205 | 0 | return *this; |
206 | 0 | } |
207 | | |
208 | | bool SocketAddress::getaddrinfo(const char *host, const char *service, |
209 | | int ai_family, int ai_socktype, int ai_protocol, |
210 | 0 | int ai_flags) { |
211 | 0 | Clear(); |
212 | |
|
213 | 0 | auto addresses = GetAddressInfo(host, service, ai_family, ai_socktype, |
214 | 0 | ai_protocol, ai_flags); |
215 | 0 | if (!addresses.empty()) |
216 | 0 | *this = addresses[0]; |
217 | 0 | return IsValid(); |
218 | 0 | } |
219 | | |
220 | | std::vector<SocketAddress> |
221 | | SocketAddress::GetAddressInfo(const char *hostname, const char *servname, |
222 | | int ai_family, int ai_socktype, int ai_protocol, |
223 | 247 | int ai_flags) { |
224 | 247 | std::vector<SocketAddress> addr_list; |
225 | | |
226 | 247 | struct addrinfo hints; |
227 | 247 | memset(&hints, 0, sizeof(hints)); |
228 | 247 | hints.ai_family = ai_family; |
229 | 247 | hints.ai_socktype = ai_socktype; |
230 | 247 | hints.ai_protocol = ai_protocol; |
231 | 247 | hints.ai_flags = ai_flags; |
232 | | |
233 | 247 | struct addrinfo *service_info_list = nullptr; |
234 | 247 | int err = ::getaddrinfo(hostname, servname, &hints, &service_info_list); |
235 | 247 | if (err == 0 && service_info_list) { |
236 | 247 | for (struct addrinfo *service_ptr = service_info_list; |
237 | 577 | service_ptr != nullptr; service_ptr = service_ptr->ai_next330 ) { |
238 | 330 | addr_list.emplace_back(SocketAddress(service_ptr)); |
239 | 330 | } |
240 | 247 | } |
241 | | |
242 | 247 | if (service_info_list) |
243 | 247 | ::freeaddrinfo(service_info_list); |
244 | 247 | return addr_list; |
245 | 247 | } |
246 | | |
247 | 6 | bool SocketAddress::SetToLocalhost(sa_family_t family, uint16_t port) { |
248 | 6 | switch (family) { |
249 | 5 | case AF_INET: |
250 | 5 | SetFamily(AF_INET); |
251 | 5 | if (SetPort(port)) { |
252 | 5 | m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
253 | 5 | return true; |
254 | 5 | } |
255 | 0 | break; |
256 | | |
257 | 1 | case AF_INET6: |
258 | 1 | SetFamily(AF_INET6); |
259 | 1 | if (SetPort(port)) { |
260 | 1 | m_socket_addr.sa_ipv6.sin6_addr = in6addr_loopback; |
261 | 1 | return true; |
262 | 1 | } |
263 | 0 | break; |
264 | 6 | } |
265 | 0 | Clear(); |
266 | 0 | return false; |
267 | 6 | } |
268 | | |
269 | 3 | bool SocketAddress::SetToAnyAddress(sa_family_t family, uint16_t port) { |
270 | 3 | switch (family) { |
271 | 3 | case AF_INET: |
272 | 3 | SetFamily(AF_INET); |
273 | 3 | if (SetPort(port)) { |
274 | 3 | m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl(INADDR_ANY); |
275 | 3 | return true; |
276 | 3 | } |
277 | 0 | break; |
278 | | |
279 | 0 | case AF_INET6: |
280 | 0 | SetFamily(AF_INET6); |
281 | 0 | if (SetPort(port)) { |
282 | 0 | m_socket_addr.sa_ipv6.sin6_addr = in6addr_any; |
283 | 0 | return true; |
284 | 0 | } |
285 | 0 | break; |
286 | 3 | } |
287 | 0 | Clear(); |
288 | 0 | return false; |
289 | 3 | } |
290 | | |
291 | 50 | bool SocketAddress::IsAnyAddr() const { |
292 | 50 | return (GetFamily() == AF_INET) |
293 | 50 | ? m_socket_addr.sa_ipv4.sin_addr.s_addr == htonl6 (INADDR_ANY) |
294 | 50 | : 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, &in6addr_any, 16)44 ; |
295 | 50 | } |
296 | | |
297 | 108 | bool SocketAddress::IsLocalhost() const { |
298 | 108 | return (GetFamily() == AF_INET) |
299 | 108 | ? m_socket_addr.sa_ipv4.sin_addr.s_addr == htonl60 (INADDR_LOOPBACK) |
300 | 108 | : 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, &in6addr_loopback, |
301 | 48 | 16); |
302 | 108 | } |
303 | | |
304 | 50 | bool SocketAddress::operator==(const SocketAddress &rhs) const { |
305 | 50 | if (GetFamily() != rhs.GetFamily()) |
306 | 0 | return false; |
307 | 50 | if (GetLength() != rhs.GetLength()) |
308 | 0 | return false; |
309 | 50 | switch (GetFamily()) { |
310 | 6 | case AF_INET: |
311 | 6 | return m_socket_addr.sa_ipv4.sin_addr.s_addr == |
312 | 6 | rhs.m_socket_addr.sa_ipv4.sin_addr.s_addr; |
313 | 44 | case AF_INET6: |
314 | 44 | return 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, |
315 | 44 | &rhs.m_socket_addr.sa_ipv6.sin6_addr, 16); |
316 | 50 | } |
317 | 0 | return false; |
318 | 50 | } |
319 | | |
320 | 50 | bool SocketAddress::operator!=(const SocketAddress &rhs) const { |
321 | 50 | return !(*this == rhs); |
322 | 50 | } |