• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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