1 // Copyright 2022 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include "src/core/lib/event_engine/tcp_socket_utils.h"
15
16 #include <grpc/event_engine/event_engine.h>
17 #include <grpc/support/port_platform.h>
18
19 #include "src/core/lib/address_utils/parse_address.h"
20 #include "src/core/lib/iomgr/port.h"
21
22 #ifdef GRPC_POSIX_SOCKET_UTILS_COMMON
23 #include <arpa/inet.h> // IWYU pragma: keep
24
25 #ifdef GRPC_LINUX_TCP_H
26 #include <linux/tcp.h>
27 #else
28 #include <netinet/in.h> // IWYU pragma: keep
29 #endif
30 #include <sys/socket.h>
31 #endif // GRPC_POSIX_SOCKET_UTILS_COMMON
32
33 #ifdef GRPC_HAVE_UNIX_SOCKET
34 #ifdef GPR_WINDOWS
35 // clang-format off
36 #include <ws2def.h>
37 #include <afunix.h>
38 // clang-format on
39 #else
40 #include <sys/stat.h> // IWYU pragma: keep
41 #include <sys/un.h>
42 #endif // GPR_WINDOWS
43 #endif
44
45 #ifdef GRPC_HAVE_VSOCK
46 #include <linux/vm_sockets.h>
47 #endif
48
49 #include <errno.h>
50 #include <inttypes.h>
51 #include <stdlib.h>
52 #include <string.h>
53
54 #include <utility>
55
56 #include "absl/log/check.h"
57 #include "absl/log/log.h"
58 #include "absl/status/status.h"
59 #include "absl/strings/str_cat.h"
60 #include "absl/strings/str_format.h"
61 #include "src/core/lib/iomgr/resolved_address.h"
62 #include "src/core/util/host_port.h"
63 #include "src/core/util/status_helper.h"
64 #include "src/core/util/uri.h"
65
66 namespace grpc_event_engine {
67 namespace experimental {
68
69 namespace {
70 constexpr uint8_t kV4MappedPrefix[] = {0, 0, 0, 0, 0, 0,
71 0, 0, 0, 0, 0xff, 0xff};
GetScheme(const EventEngine::ResolvedAddress & resolved_address)72 absl::StatusOr<std::string> GetScheme(
73 const EventEngine::ResolvedAddress& resolved_address) {
74 switch (resolved_address.address()->sa_family) {
75 case AF_INET:
76 return "ipv4";
77 case AF_INET6:
78 return "ipv6";
79 case AF_UNIX:
80 return "unix";
81 #ifdef GRPC_HAVE_VSOCK
82 case AF_VSOCK:
83 return "vsock";
84 #endif
85 default:
86 return absl::InvalidArgumentError(
87 absl::StrFormat("Unknown sockaddr family: %d",
88 resolved_address.address()->sa_family));
89 }
90 }
91
92 #ifdef GRPC_HAVE_UNIX_SOCKET
ResolvedAddrToUnixPathIfPossible(const EventEngine::ResolvedAddress * resolved_addr)93 absl::StatusOr<std::string> ResolvedAddrToUnixPathIfPossible(
94 const EventEngine::ResolvedAddress* resolved_addr) {
95 const sockaddr* addr = resolved_addr->address();
96 if (addr->sa_family != AF_UNIX) {
97 return absl::InvalidArgumentError(
98 absl::StrCat("Socket family is not AF_UNIX: ", addr->sa_family));
99 }
100 const sockaddr_un* unix_addr = reinterpret_cast<const sockaddr_un*>(addr);
101 #ifdef GPR_APPLE
102 int len = resolved_addr->size() - sizeof(unix_addr->sun_family) -
103 sizeof(unix_addr->sun_len) - 1;
104 #else
105 int len = resolved_addr->size() - sizeof(unix_addr->sun_family) - 1;
106 #endif
107 if (len <= 0) return "";
108 std::string path;
109 if (unix_addr->sun_path[0] == '\0') {
110 // unix-abstract socket processing.
111 path = std::string(unix_addr->sun_path + 1, len);
112 path = absl::StrCat(std::string(1, '\0'), path);
113 } else {
114 size_t maxlen = sizeof(unix_addr->sun_path);
115 if (strnlen(unix_addr->sun_path, maxlen) == maxlen) {
116 return absl::InvalidArgumentError("UDS path is not null-terminated");
117 }
118 path = unix_addr->sun_path;
119 }
120 return path;
121 }
122
ResolvedAddrToUriUnixIfPossible(const EventEngine::ResolvedAddress * resolved_addr)123 absl::StatusOr<std::string> ResolvedAddrToUriUnixIfPossible(
124 const EventEngine::ResolvedAddress* resolved_addr) {
125 auto path = ResolvedAddrToUnixPathIfPossible(resolved_addr);
126 GRPC_RETURN_IF_ERROR(path.status());
127 std::string scheme;
128 std::string path_string;
129 if (!path->empty() && path->at(0) == '\0' && path->length() > 1) {
130 scheme = "unix-abstract";
131 path_string = path->substr(1, std::string::npos);
132 } else {
133 scheme = "unix";
134 path_string = std::move(*path);
135 }
136
137 absl::StatusOr<grpc_core::URI> uri = grpc_core::URI::Create(
138 std::move(scheme), /*authority=*/"", std::move(path_string),
139 /*query_parameter_pairs=*/{}, /*fragment=*/"");
140 if (!uri.ok()) return uri.status();
141 return uri->ToString();
142 }
143 #else
ResolvedAddrToUriUnixIfPossible(const EventEngine::ResolvedAddress *)144 absl::StatusOr<std::string> ResolvedAddrToUriUnixIfPossible(
145 const EventEngine::ResolvedAddress* /*resolved_addr*/) {
146 return absl::InvalidArgumentError("Unix socket is not supported.");
147 }
148 #endif
149
150 #ifdef GRPC_HAVE_VSOCK
ResolvedAddrToVsockPathIfPossible(const EventEngine::ResolvedAddress * resolved_addr)151 absl::StatusOr<std::string> ResolvedAddrToVsockPathIfPossible(
152 const EventEngine::ResolvedAddress* resolved_addr) {
153 const sockaddr* addr = resolved_addr->address();
154 if (addr->sa_family != AF_VSOCK) {
155 return absl::InvalidArgumentError(
156 absl::StrCat("Socket family is not AF_VSOCK: ", addr->sa_family));
157 }
158 const sockaddr_vm* vm_addr = reinterpret_cast<const sockaddr_vm*>(addr);
159 return absl::StrCat(vm_addr->svm_cid, ":", vm_addr->svm_port);
160 }
161
ResolvedAddrToUriVsockIfPossible(const EventEngine::ResolvedAddress * resolved_addr)162 absl::StatusOr<std::string> ResolvedAddrToUriVsockIfPossible(
163 const EventEngine::ResolvedAddress* resolved_addr) {
164 auto path = ResolvedAddrToVsockPathIfPossible(resolved_addr);
165 absl::StatusOr<grpc_core::URI> uri =
166 grpc_core::URI::Create("vsock", /*authority=*/"", std::move(*path),
167 /*query_parameter_pairs=*/{}, /*fragment=*/"");
168 if (!uri.ok()) return uri.status();
169 return uri->ToString();
170 }
171 #else
ResolvedAddrToVsockPathIfPossible(const EventEngine::ResolvedAddress *)172 absl::StatusOr<std::string> ResolvedAddrToVsockPathIfPossible(
173 const EventEngine::ResolvedAddress* /*resolved_addr*/) {
174 return absl::InvalidArgumentError("VSOCK is not supported.");
175 }
176
ResolvedAddrToUriVsockIfPossible(const EventEngine::ResolvedAddress *)177 absl::StatusOr<std::string> ResolvedAddrToUriVsockIfPossible(
178 const EventEngine::ResolvedAddress* /*resolved_addr*/) {
179 return absl::InvalidArgumentError("VSOCK is not supported.");
180 }
181 #endif
182
183 } // namespace
184
ResolvedAddressIsV4Mapped(const EventEngine::ResolvedAddress & resolved_addr,EventEngine::ResolvedAddress * resolved_addr4_out)185 bool ResolvedAddressIsV4Mapped(
186 const EventEngine::ResolvedAddress& resolved_addr,
187 EventEngine::ResolvedAddress* resolved_addr4_out) {
188 const sockaddr* addr = resolved_addr.address();
189 if (addr->sa_family == AF_INET6) {
190 const sockaddr_in6* addr6 = reinterpret_cast<const sockaddr_in6*>(addr);
191 sockaddr_in* addr4_out =
192 resolved_addr4_out == nullptr
193 ? nullptr
194 : reinterpret_cast<sockaddr_in*>(
195 const_cast<sockaddr*>(resolved_addr4_out->address()));
196
197 if (memcmp(addr6->sin6_addr.s6_addr, kV4MappedPrefix,
198 sizeof(kV4MappedPrefix)) == 0) {
199 if (resolved_addr4_out != nullptr) {
200 // Normalize ::ffff:0.0.0.0/96 to IPv4.
201 memset(addr4_out, 0, EventEngine::ResolvedAddress::MAX_SIZE_BYTES);
202 addr4_out->sin_family = AF_INET;
203 // s6_addr32 would be nice, but it's non-standard.
204 memcpy(&addr4_out->sin_addr, &addr6->sin6_addr.s6_addr[12], 4);
205 addr4_out->sin_port = addr6->sin6_port;
206 *resolved_addr4_out = EventEngine::ResolvedAddress(
207 reinterpret_cast<sockaddr*>(addr4_out),
208 static_cast<socklen_t>(sizeof(sockaddr_in)));
209 }
210 return true;
211 }
212 }
213 return false;
214 }
215
ResolvedAddressToV4Mapped(const EventEngine::ResolvedAddress & resolved_addr,EventEngine::ResolvedAddress * resolved_addr6_out)216 bool ResolvedAddressToV4Mapped(
217 const EventEngine::ResolvedAddress& resolved_addr,
218 EventEngine::ResolvedAddress* resolved_addr6_out) {
219 CHECK(&resolved_addr != resolved_addr6_out);
220 const sockaddr* addr = resolved_addr.address();
221 sockaddr_in6* addr6_out = const_cast<sockaddr_in6*>(
222 reinterpret_cast<const sockaddr_in6*>(resolved_addr6_out->address()));
223 if (addr->sa_family == AF_INET) {
224 const sockaddr_in* addr4 = reinterpret_cast<const sockaddr_in*>(addr);
225 memset(resolved_addr6_out, 0, sizeof(*resolved_addr6_out));
226 addr6_out->sin6_family = AF_INET6;
227 memcpy(&addr6_out->sin6_addr.s6_addr[0], kV4MappedPrefix, 12);
228 memcpy(&addr6_out->sin6_addr.s6_addr[12], &addr4->sin_addr, 4);
229 addr6_out->sin6_port = addr4->sin_port;
230 *resolved_addr6_out = EventEngine::ResolvedAddress(
231 reinterpret_cast<sockaddr*>(addr6_out), sizeof(sockaddr_in6));
232 return true;
233 }
234 return false;
235 }
236
ResolvedAddressMakeWild6(int port)237 EventEngine::ResolvedAddress ResolvedAddressMakeWild6(int port) {
238 EventEngine::ResolvedAddress resolved_wild_out;
239 sockaddr_in6* wild_out = reinterpret_cast<sockaddr_in6*>(
240 const_cast<sockaddr*>(resolved_wild_out.address()));
241 CHECK_GE(port, 0);
242 CHECK_LT(port, 65536);
243 memset(wild_out, 0, sizeof(sockaddr_in6));
244 wild_out->sin6_family = AF_INET6;
245 wild_out->sin6_port = htons(static_cast<uint16_t>(port));
246 return EventEngine::ResolvedAddress(
247 reinterpret_cast<sockaddr*>(wild_out),
248 static_cast<socklen_t>(sizeof(sockaddr_in6)));
249 }
250
ResolvedAddressMakeWild4(int port)251 EventEngine::ResolvedAddress ResolvedAddressMakeWild4(int port) {
252 EventEngine::ResolvedAddress resolved_wild_out;
253 sockaddr_in* wild_out = reinterpret_cast<sockaddr_in*>(
254 const_cast<sockaddr*>(resolved_wild_out.address()));
255 CHECK_GE(port, 0);
256 CHECK_LT(port, 65536);
257 memset(wild_out, 0, sizeof(sockaddr_in));
258 wild_out->sin_family = AF_INET;
259 wild_out->sin_port = htons(static_cast<uint16_t>(port));
260 return EventEngine::ResolvedAddress(
261 reinterpret_cast<sockaddr*>(wild_out),
262 static_cast<socklen_t>(sizeof(sockaddr_in)));
263 }
264
ResolvedAddressGetPort(const EventEngine::ResolvedAddress & resolved_addr)265 int ResolvedAddressGetPort(const EventEngine::ResolvedAddress& resolved_addr) {
266 const sockaddr* addr = resolved_addr.address();
267 switch (addr->sa_family) {
268 case AF_INET:
269 return ntohs((reinterpret_cast<const sockaddr_in*>(addr))->sin_port);
270 case AF_INET6:
271 return ntohs((reinterpret_cast<const sockaddr_in6*>(addr))->sin6_port);
272 #ifdef GRPC_HAVE_UNIX_SOCKET
273 case AF_UNIX:
274 return 1;
275 #endif
276 #ifdef GRPC_HAVE_VSOCK
277 case AF_VSOCK:
278 return 1;
279 #endif
280 default:
281 LOG(ERROR) << "Unknown socket family " << addr->sa_family
282 << " in ResolvedAddressGetPort";
283 abort();
284 }
285 }
286
ResolvedAddressSetPort(EventEngine::ResolvedAddress & resolved_addr,int port)287 void ResolvedAddressSetPort(EventEngine::ResolvedAddress& resolved_addr,
288 int port) {
289 sockaddr* addr = const_cast<sockaddr*>(resolved_addr.address());
290 switch (addr->sa_family) {
291 case AF_INET:
292 CHECK_GE(port, 0);
293 CHECK_LT(port, 65536);
294 (reinterpret_cast<sockaddr_in*>(addr))->sin_port =
295 htons(static_cast<uint16_t>(port));
296 return;
297 case AF_INET6:
298 CHECK_GE(port, 0);
299 CHECK_LT(port, 65536);
300 (reinterpret_cast<sockaddr_in6*>(addr))->sin6_port =
301 htons(static_cast<uint16_t>(port));
302 return;
303 default:
304 LOG(ERROR) << "Unknown socket family " << addr->sa_family
305 << " in grpc_sockaddr_set_port";
306 abort();
307 }
308 }
309
MaybeGetWildcardPortFromAddress(const EventEngine::ResolvedAddress & addr)310 absl::optional<int> MaybeGetWildcardPortFromAddress(
311 const EventEngine::ResolvedAddress& addr) {
312 const EventEngine::ResolvedAddress* resolved_addr = &addr;
313 EventEngine::ResolvedAddress addr4_normalized;
314 if (ResolvedAddressIsV4Mapped(addr, &addr4_normalized)) {
315 resolved_addr = &addr4_normalized;
316 }
317 if (resolved_addr->address()->sa_family == AF_INET) {
318 // Check for 0.0.0.0
319 const sockaddr_in* addr4 =
320 reinterpret_cast<const sockaddr_in*>(resolved_addr->address());
321 if (addr4->sin_addr.s_addr != 0) {
322 return absl::nullopt;
323 }
324 return static_cast<int>(ntohs(addr4->sin_port));
325 } else if (resolved_addr->address()->sa_family == AF_INET6) {
326 // Check for ::
327 const sockaddr_in6* addr6 =
328 reinterpret_cast<const sockaddr_in6*>(resolved_addr->address());
329 int i;
330 for (i = 0; i < 16; i++) {
331 if (addr6->sin6_addr.s6_addr[i] != 0) {
332 return absl::nullopt;
333 }
334 }
335 return static_cast<int>(ntohs(addr6->sin6_port));
336 } else {
337 return absl::nullopt;
338 }
339 }
340
ResolvedAddressIsVSock(const EventEngine::ResolvedAddress & resolved_addr)341 bool ResolvedAddressIsVSock(const EventEngine::ResolvedAddress& resolved_addr) {
342 #ifdef GRPC_HAVE_VSOCK
343 return resolved_addr.address()->sa_family == AF_VSOCK;
344 #else
345 (void)resolved_addr;
346 return false;
347 #endif
348 }
349
ResolvedAddressToNormalizedString(const EventEngine::ResolvedAddress & resolved_addr)350 absl::StatusOr<std::string> ResolvedAddressToNormalizedString(
351 const EventEngine::ResolvedAddress& resolved_addr) {
352 EventEngine::ResolvedAddress addr_normalized;
353 if (!ResolvedAddressIsV4Mapped(resolved_addr, &addr_normalized)) {
354 addr_normalized = resolved_addr;
355 }
356 return ResolvedAddressToString(addr_normalized);
357 }
358
ResolvedAddressToString(const EventEngine::ResolvedAddress & resolved_addr)359 absl::StatusOr<std::string> ResolvedAddressToString(
360 const EventEngine::ResolvedAddress& resolved_addr) {
361 const int save_errno = errno;
362 const sockaddr* addr = resolved_addr.address();
363 std::string out;
364 #ifdef GRPC_HAVE_UNIX_SOCKET
365 if (addr->sa_family == AF_UNIX) {
366 return ResolvedAddrToUnixPathIfPossible(&resolved_addr);
367 }
368 #endif // GRPC_HAVE_UNIX_SOCKET
369
370 if (ResolvedAddressIsVSock(resolved_addr)) {
371 return ResolvedAddrToVsockPathIfPossible(&resolved_addr);
372 }
373
374 const void* ip = nullptr;
375 int port = 0;
376 uint32_t sin6_scope_id = 0;
377 if (addr->sa_family == AF_INET) {
378 const sockaddr_in* addr4 = reinterpret_cast<const sockaddr_in*>(addr);
379 ip = &addr4->sin_addr;
380 port = ntohs(addr4->sin_port);
381 } else if (addr->sa_family == AF_INET6) {
382 const sockaddr_in6* addr6 = reinterpret_cast<const sockaddr_in6*>(addr);
383 ip = &addr6->sin6_addr;
384 port = ntohs(addr6->sin6_port);
385 sin6_scope_id = addr6->sin6_scope_id;
386 }
387 char ntop_buf[INET6_ADDRSTRLEN];
388 if (ip != nullptr &&
389 inet_ntop(addr->sa_family, ip, ntop_buf, sizeof(ntop_buf)) != nullptr) {
390 if (sin6_scope_id != 0) {
391 // Enclose sin6_scope_id with the format defined in RFC 6874
392 // section 2.
393 std::string host_with_scope =
394 absl::StrFormat("%s%%%" PRIu32, ntop_buf, sin6_scope_id);
395 out = grpc_core::JoinHostPort(host_with_scope, port);
396 } else {
397 out = grpc_core::JoinHostPort(ntop_buf, port);
398 }
399 } else {
400 return absl::InvalidArgumentError(
401 absl::StrCat("Unknown sockaddr family: ", addr->sa_family));
402 }
403 // This is probably redundant, but we wouldn't want to log the wrong
404 // error.
405 errno = save_errno;
406 return out;
407 }
408
ResolvedAddressToURI(const EventEngine::ResolvedAddress & resolved_address)409 absl::StatusOr<std::string> ResolvedAddressToURI(
410 const EventEngine::ResolvedAddress& resolved_address) {
411 if (resolved_address.size() == 0) {
412 return absl::InvalidArgumentError("Empty address");
413 }
414 EventEngine::ResolvedAddress addr = resolved_address;
415 EventEngine::ResolvedAddress addr_normalized;
416 if (ResolvedAddressIsV4Mapped(addr, &addr_normalized)) {
417 addr = addr_normalized;
418 }
419 auto scheme = GetScheme(addr);
420 GRPC_RETURN_IF_ERROR(scheme.status());
421 if (*scheme == "unix") {
422 return ResolvedAddrToUriUnixIfPossible(&addr);
423 }
424 if (*scheme == "vsock") {
425 return ResolvedAddrToUriVsockIfPossible(&addr);
426 }
427 auto path = ResolvedAddressToString(addr);
428 GRPC_RETURN_IF_ERROR(path.status());
429 absl::StatusOr<grpc_core::URI> uri =
430 grpc_core::URI::Create(*scheme, /*authority=*/"", std::move(path.value()),
431 /*query_parameter_pairs=*/{}, /*fragment=*/"");
432 if (!uri.ok()) return uri.status();
433 return uri->ToString();
434 }
435
URIToResolvedAddress(std::string address_str)436 absl::StatusOr<EventEngine::ResolvedAddress> URIToResolvedAddress(
437 std::string address_str) {
438 grpc_resolved_address addr;
439 absl::StatusOr<grpc_core::URI> uri = grpc_core::URI::Parse(address_str);
440 if (!uri.ok()) {
441 LOG(ERROR) << "Failed to parse URI. Error: " << uri.status();
442 }
443 GRPC_RETURN_IF_ERROR(uri.status());
444 CHECK(grpc_parse_uri(*uri, &addr));
445 return EventEngine::ResolvedAddress(
446 reinterpret_cast<const sockaddr*>(addr.addr), addr.len);
447 }
448
449 } // namespace experimental
450 } // namespace grpc_event_engine
451