Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Host/common/SocketAddress.cpp
39606 views
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
SocketAddress::SocketAddress() { Clear(); }
76
77
SocketAddress::SocketAddress(const struct sockaddr &s) { m_socket_addr.sa = s; }
78
79
SocketAddress::SocketAddress(const struct sockaddr_in &s) {
80
m_socket_addr.sa_ipv4 = s;
81
}
82
83
SocketAddress::SocketAddress(const struct sockaddr_in6 &s) {
84
m_socket_addr.sa_ipv6 = s;
85
}
86
87
SocketAddress::SocketAddress(const struct sockaddr_storage &s) {
88
m_socket_addr.sa_storage = s;
89
}
90
91
SocketAddress::SocketAddress(const struct addrinfo *addr_info) {
92
*this = addr_info;
93
}
94
95
// Destructor
96
SocketAddress::~SocketAddress() = default;
97
98
void SocketAddress::Clear() {
99
memset(&m_socket_addr, 0, sizeof(m_socket_addr));
100
}
101
102
bool SocketAddress::IsValid() const { return GetLength() != 0; }
103
104
static socklen_t GetFamilyLength(sa_family_t family) {
105
switch (family) {
106
case AF_INET:
107
return sizeof(struct sockaddr_in);
108
case AF_INET6:
109
return sizeof(struct sockaddr_in6);
110
}
111
assert(0 && "Unsupported address family");
112
return 0;
113
}
114
115
socklen_t SocketAddress::GetLength() const {
116
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
117
defined(__OpenBSD__)
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
defined(__OpenBSD__)
134
m_socket_addr.sa.sa_len = GetFamilyLength(family);
135
#endif
136
}
137
138
std::string SocketAddress::GetIPAddress() const {
139
char str[INET6_ADDRSTRLEN] = {0};
140
switch (GetFamily()) {
141
case AF_INET:
142
if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv4.sin_addr, str,
143
sizeof(str)))
144
return str;
145
break;
146
case AF_INET6:
147
if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv6.sin6_addr, str,
148
sizeof(str)))
149
return str;
150
break;
151
}
152
return "";
153
}
154
155
uint16_t SocketAddress::GetPort() const {
156
switch (GetFamily()) {
157
case AF_INET:
158
return ntohs(m_socket_addr.sa_ipv4.sin_port);
159
case AF_INET6:
160
return ntohs(m_socket_addr.sa_ipv6.sin6_port);
161
}
162
return 0;
163
}
164
165
bool SocketAddress::SetPort(uint16_t port) {
166
switch (GetFamily()) {
167
case AF_INET:
168
m_socket_addr.sa_ipv4.sin_port = htons(port);
169
return true;
170
171
case AF_INET6:
172
m_socket_addr.sa_ipv6.sin6_port = htons(port);
173
return true;
174
}
175
return false;
176
}
177
178
// SocketAddress assignment operator
179
const SocketAddress &SocketAddress::
180
operator=(const struct addrinfo *addr_info) {
181
Clear();
182
if (addr_info && addr_info->ai_addr && addr_info->ai_addrlen > 0 &&
183
size_t(addr_info->ai_addrlen) <= sizeof m_socket_addr) {
184
::memcpy(&m_socket_addr, addr_info->ai_addr, addr_info->ai_addrlen);
185
}
186
return *this;
187
}
188
189
const SocketAddress &SocketAddress::operator=(const struct sockaddr &s) {
190
m_socket_addr.sa = s;
191
return *this;
192
}
193
194
const SocketAddress &SocketAddress::operator=(const struct sockaddr_in &s) {
195
m_socket_addr.sa_ipv4 = s;
196
return *this;
197
}
198
199
const SocketAddress &SocketAddress::operator=(const struct sockaddr_in6 &s) {
200
m_socket_addr.sa_ipv6 = s;
201
return *this;
202
}
203
204
const SocketAddress &SocketAddress::
205
operator=(const struct sockaddr_storage &s) {
206
m_socket_addr.sa_storage = s;
207
return *this;
208
}
209
210
bool SocketAddress::getaddrinfo(const char *host, const char *service,
211
int ai_family, int ai_socktype, int ai_protocol,
212
int ai_flags) {
213
Clear();
214
215
auto addresses = GetAddressInfo(host, service, ai_family, ai_socktype,
216
ai_protocol, ai_flags);
217
if (!addresses.empty())
218
*this = addresses[0];
219
return IsValid();
220
}
221
222
std::vector<SocketAddress>
223
SocketAddress::GetAddressInfo(const char *hostname, const char *servname,
224
int ai_family, int ai_socktype, int ai_protocol,
225
int ai_flags) {
226
std::vector<SocketAddress> addr_list;
227
228
struct addrinfo hints;
229
memset(&hints, 0, sizeof(hints));
230
hints.ai_family = ai_family;
231
hints.ai_socktype = ai_socktype;
232
hints.ai_protocol = ai_protocol;
233
hints.ai_flags = ai_flags;
234
235
struct addrinfo *service_info_list = nullptr;
236
int err = ::getaddrinfo(hostname, servname, &hints, &service_info_list);
237
if (err == 0 && service_info_list) {
238
for (struct addrinfo *service_ptr = service_info_list;
239
service_ptr != nullptr; service_ptr = service_ptr->ai_next) {
240
addr_list.emplace_back(SocketAddress(service_ptr));
241
}
242
}
243
244
if (service_info_list)
245
::freeaddrinfo(service_info_list);
246
return addr_list;
247
}
248
249
bool SocketAddress::SetToLocalhost(sa_family_t family, uint16_t port) {
250
switch (family) {
251
case AF_INET:
252
SetFamily(AF_INET);
253
if (SetPort(port)) {
254
m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
255
return true;
256
}
257
break;
258
259
case AF_INET6:
260
SetFamily(AF_INET6);
261
if (SetPort(port)) {
262
m_socket_addr.sa_ipv6.sin6_addr = in6addr_loopback;
263
return true;
264
}
265
break;
266
}
267
Clear();
268
return false;
269
}
270
271
bool SocketAddress::SetToAnyAddress(sa_family_t family, uint16_t port) {
272
switch (family) {
273
case AF_INET:
274
SetFamily(AF_INET);
275
if (SetPort(port)) {
276
m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
277
return true;
278
}
279
break;
280
281
case AF_INET6:
282
SetFamily(AF_INET6);
283
if (SetPort(port)) {
284
m_socket_addr.sa_ipv6.sin6_addr = in6addr_any;
285
return true;
286
}
287
break;
288
}
289
Clear();
290
return false;
291
}
292
293
bool SocketAddress::IsAnyAddr() const {
294
return (GetFamily() == AF_INET)
295
? m_socket_addr.sa_ipv4.sin_addr.s_addr == htonl(INADDR_ANY)
296
: 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, &in6addr_any, 16);
297
}
298
299
bool SocketAddress::IsLocalhost() const {
300
return (GetFamily() == AF_INET)
301
? m_socket_addr.sa_ipv4.sin_addr.s_addr == htonl(INADDR_LOOPBACK)
302
: 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, &in6addr_loopback,
303
16);
304
}
305
306
bool SocketAddress::operator==(const SocketAddress &rhs) const {
307
if (GetFamily() != rhs.GetFamily())
308
return false;
309
if (GetLength() != rhs.GetLength())
310
return false;
311
switch (GetFamily()) {
312
case AF_INET:
313
return m_socket_addr.sa_ipv4.sin_addr.s_addr ==
314
rhs.m_socket_addr.sa_ipv4.sin_addr.s_addr;
315
case AF_INET6:
316
return 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr,
317
&rhs.m_socket_addr.sa_ipv6.sin6_addr, 16);
318
}
319
return false;
320
}
321
322
bool SocketAddress::operator!=(const SocketAddress &rhs) const {
323
return !(*this == rhs);
324
}
325
326