• 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 <grpc/support/port_platform.h>
20 
21 #include "src/core/lib/iomgr/sockaddr_utils.h"
22 
23 #include <errno.h>
24 #include <inttypes.h>
25 #include <string.h>
26 
27 #include <grpc/support/alloc.h>
28 #include <grpc/support/log.h>
29 #include <grpc/support/string_util.h>
30 
31 #include "src/core/lib/gpr/host_port.h"
32 #include "src/core/lib/gpr/string.h"
33 #include "src/core/lib/iomgr/sockaddr.h"
34 #include "src/core/lib/iomgr/socket_utils.h"
35 #include "src/core/lib/iomgr/unix_sockets_posix.h"
36 
37 static const uint8_t kV4MappedPrefix[] = {0, 0, 0, 0, 0,    0,
38                                           0, 0, 0, 0, 0xff, 0xff};
39 
grpc_sockaddr_is_v4mapped(const grpc_resolved_address * resolved_addr,grpc_resolved_address * resolved_addr4_out)40 int grpc_sockaddr_is_v4mapped(const grpc_resolved_address* resolved_addr,
41                               grpc_resolved_address* resolved_addr4_out) {
42   GPR_ASSERT(resolved_addr != resolved_addr4_out);
43   const grpc_sockaddr* addr =
44       reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr);
45   grpc_sockaddr_in* addr4_out =
46       resolved_addr4_out == nullptr
47           ? nullptr
48           : reinterpret_cast<grpc_sockaddr_in*>(resolved_addr4_out->addr);
49   if (addr->sa_family == GRPC_AF_INET6) {
50     const grpc_sockaddr_in6* addr6 =
51         reinterpret_cast<const grpc_sockaddr_in6*>(addr);
52     if (memcmp(addr6->sin6_addr.s6_addr, kV4MappedPrefix,
53                sizeof(kV4MappedPrefix)) == 0) {
54       if (resolved_addr4_out != nullptr) {
55         /* Normalize ::ffff:0.0.0.0/96 to IPv4. */
56         memset(resolved_addr4_out, 0, sizeof(*resolved_addr4_out));
57         addr4_out->sin_family = GRPC_AF_INET;
58         /* s6_addr32 would be nice, but it's non-standard. */
59         memcpy(&addr4_out->sin_addr, &addr6->sin6_addr.s6_addr[12], 4);
60         addr4_out->sin_port = addr6->sin6_port;
61         resolved_addr4_out->len =
62             static_cast<socklen_t>(sizeof(grpc_sockaddr_in));
63       }
64       return 1;
65     }
66   }
67   return 0;
68 }
69 
grpc_sockaddr_to_v4mapped(const grpc_resolved_address * resolved_addr,grpc_resolved_address * resolved_addr6_out)70 int grpc_sockaddr_to_v4mapped(const grpc_resolved_address* resolved_addr,
71                               grpc_resolved_address* resolved_addr6_out) {
72   GPR_ASSERT(resolved_addr != resolved_addr6_out);
73   const grpc_sockaddr* addr =
74       reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr);
75   grpc_sockaddr_in6* addr6_out =
76       reinterpret_cast<grpc_sockaddr_in6*>(resolved_addr6_out->addr);
77   if (addr->sa_family == GRPC_AF_INET) {
78     const grpc_sockaddr_in* addr4 =
79         reinterpret_cast<const grpc_sockaddr_in*>(addr);
80     memset(resolved_addr6_out, 0, sizeof(*resolved_addr6_out));
81     addr6_out->sin6_family = GRPC_AF_INET6;
82     memcpy(&addr6_out->sin6_addr.s6_addr[0], kV4MappedPrefix, 12);
83     memcpy(&addr6_out->sin6_addr.s6_addr[12], &addr4->sin_addr, 4);
84     addr6_out->sin6_port = addr4->sin_port;
85     resolved_addr6_out->len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in6));
86     return 1;
87   }
88   return 0;
89 }
90 
grpc_sockaddr_is_wildcard(const grpc_resolved_address * resolved_addr,int * port_out)91 int grpc_sockaddr_is_wildcard(const grpc_resolved_address* resolved_addr,
92                               int* port_out) {
93   const grpc_sockaddr* addr;
94   grpc_resolved_address addr4_normalized;
95   if (grpc_sockaddr_is_v4mapped(resolved_addr, &addr4_normalized)) {
96     resolved_addr = &addr4_normalized;
97   }
98   addr = reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr);
99   if (addr->sa_family == GRPC_AF_INET) {
100     /* Check for 0.0.0.0 */
101     const grpc_sockaddr_in* addr4 =
102         reinterpret_cast<const grpc_sockaddr_in*>(addr);
103     if (addr4->sin_addr.s_addr != 0) {
104       return 0;
105     }
106     *port_out = grpc_ntohs(addr4->sin_port);
107     return 1;
108   } else if (addr->sa_family == GRPC_AF_INET6) {
109     /* Check for :: */
110     const grpc_sockaddr_in6* addr6 =
111         reinterpret_cast<const grpc_sockaddr_in6*>(addr);
112     int i;
113     for (i = 0; i < 16; i++) {
114       if (addr6->sin6_addr.s6_addr[i] != 0) {
115         return 0;
116       }
117     }
118     *port_out = grpc_ntohs(addr6->sin6_port);
119     return 1;
120   } else {
121     return 0;
122   }
123 }
124 
grpc_sockaddr_make_wildcards(int port,grpc_resolved_address * wild4_out,grpc_resolved_address * wild6_out)125 void grpc_sockaddr_make_wildcards(int port, grpc_resolved_address* wild4_out,
126                                   grpc_resolved_address* wild6_out) {
127   grpc_sockaddr_make_wildcard4(port, wild4_out);
128   grpc_sockaddr_make_wildcard6(port, wild6_out);
129 }
130 
grpc_sockaddr_make_wildcard4(int port,grpc_resolved_address * resolved_wild_out)131 void grpc_sockaddr_make_wildcard4(int port,
132                                   grpc_resolved_address* resolved_wild_out) {
133   grpc_sockaddr_in* wild_out =
134       reinterpret_cast<grpc_sockaddr_in*>(resolved_wild_out->addr);
135   GPR_ASSERT(port >= 0 && port < 65536);
136   memset(resolved_wild_out, 0, sizeof(*resolved_wild_out));
137   wild_out->sin_family = GRPC_AF_INET;
138   wild_out->sin_port = grpc_htons(static_cast<uint16_t>(port));
139   resolved_wild_out->len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in));
140 }
141 
grpc_sockaddr_make_wildcard6(int port,grpc_resolved_address * resolved_wild_out)142 void grpc_sockaddr_make_wildcard6(int port,
143                                   grpc_resolved_address* resolved_wild_out) {
144   grpc_sockaddr_in6* wild_out =
145       reinterpret_cast<grpc_sockaddr_in6*>(resolved_wild_out->addr);
146   GPR_ASSERT(port >= 0 && port < 65536);
147   memset(resolved_wild_out, 0, sizeof(*resolved_wild_out));
148   wild_out->sin6_family = GRPC_AF_INET6;
149   wild_out->sin6_port = grpc_htons(static_cast<uint16_t>(port));
150   resolved_wild_out->len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in6));
151 }
152 
grpc_sockaddr_to_string(char ** out,const grpc_resolved_address * resolved_addr,int normalize)153 int grpc_sockaddr_to_string(char** out,
154                             const grpc_resolved_address* resolved_addr,
155                             int normalize) {
156   const grpc_sockaddr* addr;
157   const int save_errno = errno;
158   grpc_resolved_address addr_normalized;
159   char ntop_buf[GRPC_INET6_ADDRSTRLEN];
160   const void* ip = nullptr;
161   int port = 0;
162   uint32_t sin6_scope_id = 0;
163   int ret;
164 
165   *out = nullptr;
166   if (normalize && grpc_sockaddr_is_v4mapped(resolved_addr, &addr_normalized)) {
167     resolved_addr = &addr_normalized;
168   }
169   addr = reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr);
170   if (addr->sa_family == GRPC_AF_INET) {
171     const grpc_sockaddr_in* addr4 =
172         reinterpret_cast<const grpc_sockaddr_in*>(addr);
173     ip = &addr4->sin_addr;
174     port = grpc_ntohs(addr4->sin_port);
175   } else if (addr->sa_family == GRPC_AF_INET6) {
176     const grpc_sockaddr_in6* addr6 =
177         reinterpret_cast<const grpc_sockaddr_in6*>(addr);
178     ip = &addr6->sin6_addr;
179     port = grpc_ntohs(addr6->sin6_port);
180     sin6_scope_id = addr6->sin6_scope_id;
181   }
182   if (ip != nullptr && grpc_inet_ntop(addr->sa_family, ip, ntop_buf,
183                                       sizeof(ntop_buf)) != nullptr) {
184     if (sin6_scope_id != 0) {
185       char* host_with_scope;
186       /* Enclose sin6_scope_id with the format defined in RFC 6784 section 2. */
187       gpr_asprintf(&host_with_scope, "%s%%25%" PRIu32, ntop_buf, sin6_scope_id);
188       ret = gpr_join_host_port(out, host_with_scope, port);
189       gpr_free(host_with_scope);
190     } else {
191       ret = gpr_join_host_port(out, ntop_buf, port);
192     }
193   } else {
194     ret = gpr_asprintf(out, "(sockaddr family=%d)", addr->sa_family);
195   }
196   /* This is probably redundant, but we wouldn't want to log the wrong error. */
197   errno = save_errno;
198   return ret;
199 }
200 
grpc_string_to_sockaddr(grpc_resolved_address * out,char * addr,int port)201 void grpc_string_to_sockaddr(grpc_resolved_address* out, char* addr, int port) {
202   grpc_sockaddr_in6* addr6 = (grpc_sockaddr_in6*)out->addr;
203   grpc_sockaddr_in* addr4 = (grpc_sockaddr_in*)out->addr;
204 
205   if (grpc_inet_pton(GRPC_AF_INET6, addr, &addr6->sin6_addr) == 1) {
206     addr6->sin6_family = GRPC_AF_INET6;
207     addr6->sin6_flowinfo = 0;
208     addr6->sin6_scope_id = 0;
209     out->len = sizeof(grpc_sockaddr_in6);
210   } else if (grpc_inet_pton(GRPC_AF_INET, addr, &addr4->sin_addr) == 1) {
211     addr4->sin_family = GRPC_AF_INET;
212     out->len = sizeof(grpc_sockaddr_in);
213   } else {
214     GPR_ASSERT(0);
215   }
216   grpc_sockaddr_set_port(out, port);
217 }
218 
grpc_sockaddr_to_uri(const grpc_resolved_address * resolved_addr)219 char* grpc_sockaddr_to_uri(const grpc_resolved_address* resolved_addr) {
220   grpc_resolved_address addr_normalized;
221   if (grpc_sockaddr_is_v4mapped(resolved_addr, &addr_normalized)) {
222     resolved_addr = &addr_normalized;
223   }
224   const char* scheme = grpc_sockaddr_get_uri_scheme(resolved_addr);
225   if (scheme == nullptr || strcmp("unix", scheme) == 0) {
226     return grpc_sockaddr_to_uri_unix_if_possible(resolved_addr);
227   } else if (strcmp("vsock", scheme) == 0) {
228     return grpc_sockaddr_to_uri_vsock_if_possible(resolved_addr);
229   }
230   char* path = nullptr;
231   char* uri_str = nullptr;
232   if (grpc_sockaddr_to_string(&path, resolved_addr,
233                               false /* suppress errors */) &&
234       scheme != nullptr) {
235     gpr_asprintf(&uri_str, "%s:%s", scheme, path);
236   }
237   gpr_free(path);
238   return uri_str != nullptr ? uri_str : nullptr;
239 }
240 
grpc_sockaddr_get_uri_scheme(const grpc_resolved_address * resolved_addr)241 const char* grpc_sockaddr_get_uri_scheme(
242     const grpc_resolved_address* resolved_addr) {
243   const grpc_sockaddr* addr =
244       reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr);
245   switch (addr->sa_family) {
246     case GRPC_AF_INET:
247       return "ipv4";
248     case GRPC_AF_INET6:
249       return "ipv6";
250     case GRPC_AF_UNIX:
251       return "unix";
252 #ifdef GRPC_AF_VSOCK
253     case GRPC_AF_VSOCK:
254       return "vsock";
255 #endif /* GRPC_AF_VSOCK */
256   }
257   return nullptr;
258 }
259 
grpc_sockaddr_get_family(const grpc_resolved_address * resolved_addr)260 int grpc_sockaddr_get_family(const grpc_resolved_address* resolved_addr) {
261   const grpc_sockaddr* addr =
262       reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr);
263   return addr->sa_family;
264 }
265 
grpc_sockaddr_get_port(const grpc_resolved_address * resolved_addr)266 int grpc_sockaddr_get_port(const grpc_resolved_address* resolved_addr) {
267   const grpc_sockaddr* addr =
268       reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr);
269   switch (addr->sa_family) {
270     case GRPC_AF_INET:
271       return grpc_ntohs(((grpc_sockaddr_in*)addr)->sin_port);
272     case GRPC_AF_INET6:
273       return grpc_ntohs(((grpc_sockaddr_in6*)addr)->sin6_port);
274 #ifdef GRPC_AF_VSOCK
275     case GRPC_AF_VSOCK:
276 #ifdef GRPC_HAVE_LINUX_VSOCK
277       return static_cast<int>(reinterpret_cast<const struct sockaddr_vm *>(addr)->svm_port);
278 #else /* GRPC_HAVE_LINUX_VSOCK */
279       gpr_log(GPR_ERROR, "Unknown vsock implementation");
280       return 0;
281 #endif /* GRPC_HAVE_LINUX_VSOCK */
282 #endif /* GRPC_AF_VSOCK */
283     default:
284       if (grpc_is_unix_socket(resolved_addr)) {
285         return 1;
286       }
287       gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_get_port",
288               addr->sa_family);
289       return 0;
290   }
291 }
292 
grpc_sockaddr_set_port(const grpc_resolved_address * resolved_addr,int port)293 int grpc_sockaddr_set_port(const grpc_resolved_address* resolved_addr,
294                            int port) {
295   grpc_sockaddr* addr =
296       const_cast<grpc_sockaddr*>(reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr));
297   switch (addr->sa_family) {
298     case GRPC_AF_INET:
299       GPR_ASSERT(port >= 0 && port < 65536);
300       ((grpc_sockaddr_in*)addr)->sin_port =
301           grpc_htons(static_cast<uint16_t>(port));
302       return 1;
303     case GRPC_AF_INET6:
304       GPR_ASSERT(port >= 0 && port < 65536);
305       ((grpc_sockaddr_in6*)addr)->sin6_port =
306           grpc_htons(static_cast<uint16_t>(port));
307       return 1;
308 #ifdef GRPC_AF_VSOCK
309     case GRPC_AF_VSOCK:
310 #ifdef GRPC_HAVE_LINUX_VSOCK
311       reinterpret_cast<struct sockaddr_vm *>(addr)->svm_port = static_cast<unsigned int>(port);
312       return 1;
313 #else /* GRPC_HAVE_LINUX_VSOCK */
314       gpr_log(GPR_ERROR, "Unknown vsock implementation");
315       return 0;
316 #endif /* GRPC_HAVE_LINUX_VSOCK */
317 #endif /* GRPC_AF_VSOCK */
318     default:
319       gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_set_port",
320               addr->sa_family);
321       return 0;
322   }
323 }
324