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