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