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