blob: 8a2e6ed89bc912c5e0dae77b5361736df9c83e6c [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2016 gRPC authors.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005 * 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
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080010 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011 * 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.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080016 *
17 */
18
Craig Tiller9533d042016-03-25 17:11:06 -070019#include "src/core/lib/iomgr/sockaddr_utils.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080020
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080021#include <errno.h>
Yash Tibrewalfcd26bc2017-09-25 15:08:28 -070022#include <inttypes.h>
ctiller18b49ab2014-12-09 14:39:16 -080023#include <string.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080024
Craig Tiller1b22b9d2015-07-20 13:42:22 -070025#include <grpc/support/alloc.h>
nnoble0c475f02014-12-05 15:37:39 -080026#include <grpc/support/host_port.h>
nnoble0c475f02014-12-05 15:37:39 -080027#include <grpc/support/log.h>
28#include <grpc/support/port_platform.h>
Masood Malekghassemi701af602015-06-03 15:01:17 -070029#include <grpc/support/string_util.h>
nnoble0c475f02014-12-05 15:37:39 -080030
murgatroid997871f732016-09-23 13:49:05 -070031#include "src/core/lib/iomgr/sockaddr.h"
murgatroid9931963632016-08-09 14:00:41 -070032#include "src/core/lib/iomgr/socket_utils.h"
Craig Tiller9533d042016-03-25 17:11:06 -070033#include "src/core/lib/iomgr/unix_sockets_posix.h"
34#include "src/core/lib/support/string.h"
Craig Tiller1b22b9d2015-07-20 13:42:22 -070035
Craig Tiller7536af02015-12-22 13:49:30 -080036static const uint8_t kV4MappedPrefix[] = {0, 0, 0, 0, 0, 0,
37 0, 0, 0, 0, 0xff, 0xff};
nnoble0c475f02014-12-05 15:37:39 -080038
murgatroid997871f732016-09-23 13:49:05 -070039int grpc_sockaddr_is_v4mapped(const grpc_resolved_address *resolved_addr,
40 grpc_resolved_address *resolved_addr4_out) {
41 GPR_ASSERT(resolved_addr != resolved_addr4_out);
42 const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
murgatroid99dedb9232016-09-26 13:54:04 -070043 struct sockaddr_in *addr4_out =
Craig Tiller7fea7512017-04-12 09:43:34 -070044 resolved_addr4_out == NULL
45 ? NULL
46 : (struct sockaddr_in *)resolved_addr4_out->addr;
nnoble0c475f02014-12-05 15:37:39 -080047 if (addr->sa_family == AF_INET6) {
48 const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
49 if (memcmp(addr6->sin6_addr.s6_addr, kV4MappedPrefix,
50 sizeof(kV4MappedPrefix)) == 0) {
murgatroid997871f732016-09-23 13:49:05 -070051 if (resolved_addr4_out != NULL) {
nnoble0c475f02014-12-05 15:37:39 -080052 /* Normalize ::ffff:0.0.0.0/96 to IPv4. */
murgatroid997871f732016-09-23 13:49:05 -070053 memset(resolved_addr4_out, 0, sizeof(*resolved_addr4_out));
nnoble0c475f02014-12-05 15:37:39 -080054 addr4_out->sin_family = AF_INET;
55 /* s6_addr32 would be nice, but it's non-standard. */
56 memcpy(&addr4_out->sin_addr, &addr6->sin6_addr.s6_addr[12], 4);
57 addr4_out->sin_port = addr6->sin6_port;
murgatroid997871f732016-09-23 13:49:05 -070058 resolved_addr4_out->len = sizeof(struct sockaddr_in);
nnoble0c475f02014-12-05 15:37:39 -080059 }
60 return 1;
61 }
62 }
63 return 0;
64}
65
murgatroid997871f732016-09-23 13:49:05 -070066int grpc_sockaddr_to_v4mapped(const grpc_resolved_address *resolved_addr,
67 grpc_resolved_address *resolved_addr6_out) {
68 GPR_ASSERT(resolved_addr != resolved_addr6_out);
69 const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
murgatroid99dedb9232016-09-26 13:54:04 -070070 struct sockaddr_in6 *addr6_out =
71 (struct sockaddr_in6 *)resolved_addr6_out->addr;
nnoble0c475f02014-12-05 15:37:39 -080072 if (addr->sa_family == AF_INET) {
73 const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
murgatroid997871f732016-09-23 13:49:05 -070074 memset(resolved_addr6_out, 0, sizeof(*resolved_addr6_out));
nnoble0c475f02014-12-05 15:37:39 -080075 addr6_out->sin6_family = AF_INET6;
76 memcpy(&addr6_out->sin6_addr.s6_addr[0], kV4MappedPrefix, 12);
77 memcpy(&addr6_out->sin6_addr.s6_addr[12], &addr4->sin_addr, 4);
78 addr6_out->sin6_port = addr4->sin_port;
murgatroid997871f732016-09-23 13:49:05 -070079 resolved_addr6_out->len = sizeof(struct sockaddr_in6);
nnoble0c475f02014-12-05 15:37:39 -080080 return 1;
81 }
82 return 0;
83}
84
murgatroid99dedb9232016-09-26 13:54:04 -070085int grpc_sockaddr_is_wildcard(const grpc_resolved_address *resolved_addr,
86 int *port_out) {
murgatroid997871f732016-09-23 13:49:05 -070087 const struct sockaddr *addr;
88 grpc_resolved_address addr4_normalized;
89 if (grpc_sockaddr_is_v4mapped(resolved_addr, &addr4_normalized)) {
90 resolved_addr = &addr4_normalized;
nnoble0c475f02014-12-05 15:37:39 -080091 }
murgatroid997871f732016-09-23 13:49:05 -070092 addr = (const struct sockaddr *)resolved_addr->addr;
nnoble0c475f02014-12-05 15:37:39 -080093 if (addr->sa_family == AF_INET) {
94 /* Check for 0.0.0.0 */
95 const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
96 if (addr4->sin_addr.s_addr != 0) {
97 return 0;
98 }
99 *port_out = ntohs(addr4->sin_port);
100 return 1;
101 } else if (addr->sa_family == AF_INET6) {
102 /* Check for :: */
103 const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
104 int i;
105 for (i = 0; i < 16; i++) {
106 if (addr6->sin6_addr.s6_addr[i] != 0) {
107 return 0;
108 }
109 }
110 *port_out = ntohs(addr6->sin6_port);
111 return 1;
112 } else {
113 return 0;
114 }
115}
116
murgatroid997871f732016-09-23 13:49:05 -0700117void grpc_sockaddr_make_wildcards(int port, grpc_resolved_address *wild4_out,
118 grpc_resolved_address *wild6_out) {
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100119 grpc_sockaddr_make_wildcard4(port, wild4_out);
120 grpc_sockaddr_make_wildcard6(port, wild6_out);
121}
nnoble0c475f02014-12-05 15:37:39 -0800122
murgatroid99dedb9232016-09-26 13:54:04 -0700123void grpc_sockaddr_make_wildcard4(int port,
124 grpc_resolved_address *resolved_wild_out) {
murgatroid997871f732016-09-23 13:49:05 -0700125 struct sockaddr_in *wild_out = (struct sockaddr_in *)resolved_wild_out->addr;
Craig Tiller6a6b36c2015-09-10 16:00:22 -0700126 GPR_ASSERT(port >= 0 && port < 65536);
murgatroid997871f732016-09-23 13:49:05 -0700127 memset(resolved_wild_out, 0, sizeof(*resolved_wild_out));
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100128 wild_out->sin_family = AF_INET;
Craig Tiller7536af02015-12-22 13:49:30 -0800129 wild_out->sin_port = htons((uint16_t)port);
murgatroid997871f732016-09-23 13:49:05 -0700130 resolved_wild_out->len = sizeof(struct sockaddr_in);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100131}
132
murgatroid99dedb9232016-09-26 13:54:04 -0700133void grpc_sockaddr_make_wildcard6(int port,
134 grpc_resolved_address *resolved_wild_out) {
135 struct sockaddr_in6 *wild_out =
136 (struct sockaddr_in6 *)resolved_wild_out->addr;
Craig Tiller6a6b36c2015-09-10 16:00:22 -0700137 GPR_ASSERT(port >= 0 && port < 65536);
murgatroid997871f732016-09-23 13:49:05 -0700138 memset(resolved_wild_out, 0, sizeof(*resolved_wild_out));
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100139 wild_out->sin6_family = AF_INET6;
Craig Tiller7536af02015-12-22 13:49:30 -0800140 wild_out->sin6_port = htons((uint16_t)port);
murgatroid997871f732016-09-23 13:49:05 -0700141 resolved_wild_out->len = sizeof(struct sockaddr_in6);
nnoble0c475f02014-12-05 15:37:39 -0800142}
143
murgatroid99dedb9232016-09-26 13:54:04 -0700144int grpc_sockaddr_to_string(char **out,
145 const grpc_resolved_address *resolved_addr,
nnoble0c475f02014-12-05 15:37:39 -0800146 int normalize) {
murgatroid997871f732016-09-23 13:49:05 -0700147 const struct sockaddr *addr;
nnoble0c475f02014-12-05 15:37:39 -0800148 const int save_errno = errno;
murgatroid997871f732016-09-23 13:49:05 -0700149 grpc_resolved_address addr_normalized;
nnoble0c475f02014-12-05 15:37:39 -0800150 char ntop_buf[INET6_ADDRSTRLEN];
151 const void *ip = NULL;
152 int port;
Yuchen Zengaa76d3d2017-02-15 14:00:01 -0800153 uint32_t sin6_scope_id = 0;
nnoble0c475f02014-12-05 15:37:39 -0800154 int ret;
155
156 *out = NULL;
murgatroid997871f732016-09-23 13:49:05 -0700157 if (normalize && grpc_sockaddr_is_v4mapped(resolved_addr, &addr_normalized)) {
158 resolved_addr = &addr_normalized;
nnoble0c475f02014-12-05 15:37:39 -0800159 }
murgatroid997871f732016-09-23 13:49:05 -0700160 addr = (const struct sockaddr *)resolved_addr->addr;
nnoble0c475f02014-12-05 15:37:39 -0800161 if (addr->sa_family == AF_INET) {
162 const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
163 ip = &addr4->sin_addr;
164 port = ntohs(addr4->sin_port);
165 } else if (addr->sa_family == AF_INET6) {
166 const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
167 ip = &addr6->sin6_addr;
168 port = ntohs(addr6->sin6_port);
Yuchen Zengaa76d3d2017-02-15 14:00:01 -0800169 sin6_scope_id = addr6->sin6_scope_id;
nnoble0c475f02014-12-05 15:37:39 -0800170 }
171 if (ip != NULL &&
murgatroid997e924a02016-08-10 10:06:43 -0700172 grpc_inet_ntop(addr->sa_family, ip, ntop_buf, sizeof(ntop_buf)) != NULL) {
Yuchen Zengaa76d3d2017-02-15 14:00:01 -0800173 if (sin6_scope_id != 0) {
174 char *host_with_scope;
175 /* Enclose sin6_scope_id with the format defined in RFC 6784 section 2. */
176 gpr_asprintf(&host_with_scope, "%s%%25%" PRIu32, ntop_buf, sin6_scope_id);
177 ret = gpr_join_host_port(out, host_with_scope, port);
178 gpr_free(host_with_scope);
179 } else {
180 ret = gpr_join_host_port(out, ntop_buf, port);
181 }
nnoble0c475f02014-12-05 15:37:39 -0800182 } else {
183 ret = gpr_asprintf(out, "(sockaddr family=%d)", addr->sa_family);
184 }
185 /* This is probably redundant, but we wouldn't want to log the wrong error. */
186 errno = save_errno;
187 return ret;
188}
ctiller570d1f42015-01-12 16:29:52 -0800189
murgatroid997871f732016-09-23 13:49:05 -0700190char *grpc_sockaddr_to_uri(const grpc_resolved_address *resolved_addr) {
murgatroid997871f732016-09-23 13:49:05 -0700191 grpc_resolved_address addr_normalized;
murgatroid997871f732016-09-23 13:49:05 -0700192 if (grpc_sockaddr_is_v4mapped(resolved_addr, &addr_normalized)) {
193 resolved_addr = &addr_normalized;
Paul Marks63541a12015-08-04 15:05:00 -0700194 }
David Garcia Quintas01291502017-02-07 13:26:41 -0800195 const char *scheme = grpc_sockaddr_get_uri_scheme(resolved_addr);
196 if (scheme == NULL || strcmp("unix", scheme) == 0) {
197 return grpc_sockaddr_to_uri_unix_if_possible(resolved_addr);
198 }
199 char *path = NULL;
200 char *uri_str = NULL;
201 if (grpc_sockaddr_to_string(&path, resolved_addr,
202 false /* suppress errors */) &&
203 scheme != NULL) {
204 gpr_asprintf(&uri_str, "%s:%s", scheme, path);
205 }
206 gpr_free(path);
207 return uri_str != NULL ? uri_str : NULL;
208}
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700209
David Garcia Quintas01291502017-02-07 13:26:41 -0800210const char *grpc_sockaddr_get_uri_scheme(
211 const grpc_resolved_address *resolved_addr) {
212 const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700213 switch (addr->sa_family) {
214 case AF_INET:
David Garcia Quintas01291502017-02-07 13:26:41 -0800215 return "ipv4";
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700216 case AF_INET6:
David Garcia Quintas01291502017-02-07 13:26:41 -0800217 return "ipv6";
218 case AF_UNIX:
219 return "unix";
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700220 }
David Garcia Quintas01291502017-02-07 13:26:41 -0800221 return NULL;
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700222}
223
murgatroid9966177902017-07-18 18:00:38 -0700224int grpc_sockaddr_get_family(const grpc_resolved_address *resolved_addr) {
225 const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
226 return addr->sa_family;
227}
228
murgatroid997871f732016-09-23 13:49:05 -0700229int grpc_sockaddr_get_port(const grpc_resolved_address *resolved_addr) {
230 const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
ctiller570d1f42015-01-12 16:29:52 -0800231 switch (addr->sa_family) {
232 case AF_INET:
233 return ntohs(((struct sockaddr_in *)addr)->sin_port);
234 case AF_INET6:
235 return ntohs(((struct sockaddr_in6 *)addr)->sin6_port);
236 default:
murgatroid997871f732016-09-23 13:49:05 -0700237 if (grpc_is_unix_socket(resolved_addr)) {
ahedberg80d6b122016-03-17 17:37:35 -0400238 return 1;
239 }
Craig Tillerd6c98df2015-08-18 09:33:44 -0700240 gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_get_port",
241 addr->sa_family);
ctiller570d1f42015-01-12 16:29:52 -0800242 return 0;
243 }
244}
245
murgatroid99dedb9232016-09-26 13:54:04 -0700246int grpc_sockaddr_set_port(const grpc_resolved_address *resolved_addr,
247 int port) {
murgatroid997871f732016-09-23 13:49:05 -0700248 const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
ctiller570d1f42015-01-12 16:29:52 -0800249 switch (addr->sa_family) {
250 case AF_INET:
Craig Tiller6a6b36c2015-09-10 16:00:22 -0700251 GPR_ASSERT(port >= 0 && port < 65536);
Craig Tiller7536af02015-12-22 13:49:30 -0800252 ((struct sockaddr_in *)addr)->sin_port = htons((uint16_t)port);
ctiller570d1f42015-01-12 16:29:52 -0800253 return 1;
254 case AF_INET6:
Craig Tiller6a6b36c2015-09-10 16:00:22 -0700255 GPR_ASSERT(port >= 0 && port < 65536);
Craig Tiller7536af02015-12-22 13:49:30 -0800256 ((struct sockaddr_in6 *)addr)->sin6_port = htons((uint16_t)port);
ctiller570d1f42015-01-12 16:29:52 -0800257 return 1;
258 default:
Craig Tillerd6c98df2015-08-18 09:33:44 -0700259 gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_set_port",
260 addr->sa_family);
ctiller570d1f42015-01-12 16:29:52 -0800261 return 0;
262 }
Craig Tiller190d3602015-02-18 09:23:38 -0800263}