blob: e01dc4e65c523c4d7980c5848a25cba5df4785a7 [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
Craig Tillerbaa14a92017-11-03 09:09:36 -070039int grpc_sockaddr_is_v4mapped(const grpc_resolved_address* resolved_addr,
40 grpc_resolved_address* resolved_addr4_out) {
murgatroid997871f732016-09-23 13:49:05 -070041 GPR_ASSERT(resolved_addr != resolved_addr4_out);
Craig Tillerbaa14a92017-11-03 09:09:36 -070042 const struct sockaddr* addr = (const struct sockaddr*)resolved_addr->addr;
43 struct sockaddr_in* addr4_out =
Craig Tiller4782d922017-11-10 09:53:21 -080044 resolved_addr4_out == nullptr
45 ? nullptr
Craig Tillerbaa14a92017-11-03 09:09:36 -070046 : (struct sockaddr_in*)resolved_addr4_out->addr;
nnoble0c475f02014-12-05 15:37:39 -080047 if (addr->sa_family == AF_INET6) {
Craig Tillerbaa14a92017-11-03 09:09:36 -070048 const struct sockaddr_in6* addr6 = (const struct sockaddr_in6*)addr;
nnoble0c475f02014-12-05 15:37:39 -080049 if (memcmp(addr6->sin6_addr.s6_addr, kV4MappedPrefix,
50 sizeof(kV4MappedPrefix)) == 0) {
Craig Tiller4782d922017-11-10 09:53:21 -080051 if (resolved_addr4_out != nullptr) {
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
Craig Tillerbaa14a92017-11-03 09:09:36 -070066int grpc_sockaddr_to_v4mapped(const grpc_resolved_address* resolved_addr,
67 grpc_resolved_address* resolved_addr6_out) {
murgatroid997871f732016-09-23 13:49:05 -070068 GPR_ASSERT(resolved_addr != resolved_addr6_out);
Craig Tillerbaa14a92017-11-03 09:09:36 -070069 const struct sockaddr* addr = (const struct sockaddr*)resolved_addr->addr;
70 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) {
Craig Tillerbaa14a92017-11-03 09:09:36 -070073 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
Craig Tillerbaa14a92017-11-03 09:09:36 -070085int grpc_sockaddr_is_wildcard(const grpc_resolved_address* resolved_addr,
86 int* port_out) {
87 const struct sockaddr* addr;
murgatroid997871f732016-09-23 13:49:05 -070088 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 }
Craig Tillerbaa14a92017-11-03 09:09:36 -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 */
Craig Tillerbaa14a92017-11-03 09:09:36 -070095 const struct sockaddr_in* addr4 = (const struct sockaddr_in*)addr;
nnoble0c475f02014-12-05 15:37:39 -080096 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 :: */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700103 const struct sockaddr_in6* addr6 = (const struct sockaddr_in6*)addr;
nnoble0c475f02014-12-05 15:37:39 -0800104 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
Craig Tillerbaa14a92017-11-03 09:09:36 -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,
Craig Tillerbaa14a92017-11-03 09:09:36 -0700124 grpc_resolved_address* resolved_wild_out) {
125 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,
Craig Tillerbaa14a92017-11-03 09:09:36 -0700134 grpc_resolved_address* resolved_wild_out) {
135 struct sockaddr_in6* wild_out = (struct sockaddr_in6*)resolved_wild_out->addr;
Craig Tiller6a6b36c2015-09-10 16:00:22 -0700136 GPR_ASSERT(port >= 0 && port < 65536);
murgatroid997871f732016-09-23 13:49:05 -0700137 memset(resolved_wild_out, 0, sizeof(*resolved_wild_out));
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100138 wild_out->sin6_family = AF_INET6;
Craig Tiller7536af02015-12-22 13:49:30 -0800139 wild_out->sin6_port = htons((uint16_t)port);
murgatroid997871f732016-09-23 13:49:05 -0700140 resolved_wild_out->len = sizeof(struct sockaddr_in6);
nnoble0c475f02014-12-05 15:37:39 -0800141}
142
Craig Tillerbaa14a92017-11-03 09:09:36 -0700143int grpc_sockaddr_to_string(char** out,
144 const grpc_resolved_address* resolved_addr,
nnoble0c475f02014-12-05 15:37:39 -0800145 int normalize) {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700146 const struct sockaddr* addr;
nnoble0c475f02014-12-05 15:37:39 -0800147 const int save_errno = errno;
murgatroid997871f732016-09-23 13:49:05 -0700148 grpc_resolved_address addr_normalized;
nnoble0c475f02014-12-05 15:37:39 -0800149 char ntop_buf[INET6_ADDRSTRLEN];
Craig Tiller4782d922017-11-10 09:53:21 -0800150 const void* ip = nullptr;
nnoble0c475f02014-12-05 15:37:39 -0800151 int port;
Yuchen Zengaa76d3d2017-02-15 14:00:01 -0800152 uint32_t sin6_scope_id = 0;
nnoble0c475f02014-12-05 15:37:39 -0800153 int ret;
154
Craig Tiller4782d922017-11-10 09:53:21 -0800155 *out = nullptr;
murgatroid997871f732016-09-23 13:49:05 -0700156 if (normalize && grpc_sockaddr_is_v4mapped(resolved_addr, &addr_normalized)) {
157 resolved_addr = &addr_normalized;
nnoble0c475f02014-12-05 15:37:39 -0800158 }
Craig Tillerbaa14a92017-11-03 09:09:36 -0700159 addr = (const struct sockaddr*)resolved_addr->addr;
nnoble0c475f02014-12-05 15:37:39 -0800160 if (addr->sa_family == AF_INET) {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700161 const struct sockaddr_in* addr4 = (const struct sockaddr_in*)addr;
nnoble0c475f02014-12-05 15:37:39 -0800162 ip = &addr4->sin_addr;
163 port = ntohs(addr4->sin_port);
164 } else if (addr->sa_family == AF_INET6) {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700165 const struct sockaddr_in6* addr6 = (const struct sockaddr_in6*)addr;
nnoble0c475f02014-12-05 15:37:39 -0800166 ip = &addr6->sin6_addr;
167 port = ntohs(addr6->sin6_port);
Yuchen Zengaa76d3d2017-02-15 14:00:01 -0800168 sin6_scope_id = addr6->sin6_scope_id;
nnoble0c475f02014-12-05 15:37:39 -0800169 }
Craig Tiller4782d922017-11-10 09:53:21 -0800170 if (ip != nullptr &&
171 grpc_inet_ntop(addr->sa_family, ip, ntop_buf, sizeof(ntop_buf)) != nullptr) {
Yuchen Zengaa76d3d2017-02-15 14:00:01 -0800172 if (sin6_scope_id != 0) {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700173 char* host_with_scope;
Yuchen Zengaa76d3d2017-02-15 14:00:01 -0800174 /* Enclose sin6_scope_id with the format defined in RFC 6784 section 2. */
175 gpr_asprintf(&host_with_scope, "%s%%25%" PRIu32, ntop_buf, sin6_scope_id);
176 ret = gpr_join_host_port(out, host_with_scope, port);
177 gpr_free(host_with_scope);
178 } else {
179 ret = gpr_join_host_port(out, ntop_buf, port);
180 }
nnoble0c475f02014-12-05 15:37:39 -0800181 } else {
182 ret = gpr_asprintf(out, "(sockaddr family=%d)", addr->sa_family);
183 }
184 /* This is probably redundant, but we wouldn't want to log the wrong error. */
185 errno = save_errno;
186 return ret;
187}
ctiller570d1f42015-01-12 16:29:52 -0800188
Craig Tillerbaa14a92017-11-03 09:09:36 -0700189char* grpc_sockaddr_to_uri(const grpc_resolved_address* resolved_addr) {
murgatroid997871f732016-09-23 13:49:05 -0700190 grpc_resolved_address addr_normalized;
murgatroid997871f732016-09-23 13:49:05 -0700191 if (grpc_sockaddr_is_v4mapped(resolved_addr, &addr_normalized)) {
192 resolved_addr = &addr_normalized;
Paul Marks63541a12015-08-04 15:05:00 -0700193 }
Craig Tillerbaa14a92017-11-03 09:09:36 -0700194 const char* scheme = grpc_sockaddr_get_uri_scheme(resolved_addr);
Craig Tiller4782d922017-11-10 09:53:21 -0800195 if (scheme == nullptr || strcmp("unix", scheme) == 0) {
David Garcia Quintas01291502017-02-07 13:26:41 -0800196 return grpc_sockaddr_to_uri_unix_if_possible(resolved_addr);
197 }
Craig Tiller4782d922017-11-10 09:53:21 -0800198 char* path = nullptr;
199 char* uri_str = nullptr;
David Garcia Quintas01291502017-02-07 13:26:41 -0800200 if (grpc_sockaddr_to_string(&path, resolved_addr,
201 false /* suppress errors */) &&
Craig Tiller4782d922017-11-10 09:53:21 -0800202 scheme != nullptr) {
David Garcia Quintas01291502017-02-07 13:26:41 -0800203 gpr_asprintf(&uri_str, "%s:%s", scheme, path);
204 }
205 gpr_free(path);
Craig Tiller4782d922017-11-10 09:53:21 -0800206 return uri_str != nullptr ? uri_str : nullptr;
David Garcia Quintas01291502017-02-07 13:26:41 -0800207}
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700208
Craig Tillerbaa14a92017-11-03 09:09:36 -0700209const char* grpc_sockaddr_get_uri_scheme(
210 const grpc_resolved_address* resolved_addr) {
211 const struct sockaddr* addr = (const struct sockaddr*)resolved_addr->addr;
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700212 switch (addr->sa_family) {
213 case AF_INET:
David Garcia Quintas01291502017-02-07 13:26:41 -0800214 return "ipv4";
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700215 case AF_INET6:
David Garcia Quintas01291502017-02-07 13:26:41 -0800216 return "ipv6";
217 case AF_UNIX:
218 return "unix";
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700219 }
Craig Tiller4782d922017-11-10 09:53:21 -0800220 return nullptr;
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700221}
222
Craig Tillerbaa14a92017-11-03 09:09:36 -0700223int grpc_sockaddr_get_family(const grpc_resolved_address* resolved_addr) {
224 const struct sockaddr* addr = (const struct sockaddr*)resolved_addr->addr;
murgatroid9966177902017-07-18 18:00:38 -0700225 return addr->sa_family;
226}
227
Craig Tillerbaa14a92017-11-03 09:09:36 -0700228int grpc_sockaddr_get_port(const grpc_resolved_address* resolved_addr) {
229 const struct sockaddr* addr = (const struct sockaddr*)resolved_addr->addr;
ctiller570d1f42015-01-12 16:29:52 -0800230 switch (addr->sa_family) {
231 case AF_INET:
Craig Tillerbaa14a92017-11-03 09:09:36 -0700232 return ntohs(((struct sockaddr_in*)addr)->sin_port);
ctiller570d1f42015-01-12 16:29:52 -0800233 case AF_INET6:
Craig Tillerbaa14a92017-11-03 09:09:36 -0700234 return ntohs(((struct sockaddr_in6*)addr)->sin6_port);
ctiller570d1f42015-01-12 16:29:52 -0800235 default:
murgatroid997871f732016-09-23 13:49:05 -0700236 if (grpc_is_unix_socket(resolved_addr)) {
ahedberg80d6b122016-03-17 17:37:35 -0400237 return 1;
238 }
Craig Tillerd6c98df2015-08-18 09:33:44 -0700239 gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_get_port",
240 addr->sa_family);
ctiller570d1f42015-01-12 16:29:52 -0800241 return 0;
242 }
243}
244
Craig Tillerbaa14a92017-11-03 09:09:36 -0700245int grpc_sockaddr_set_port(const grpc_resolved_address* resolved_addr,
murgatroid99dedb9232016-09-26 13:54:04 -0700246 int port) {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700247 const struct sockaddr* addr = (const struct sockaddr*)resolved_addr->addr;
ctiller570d1f42015-01-12 16:29:52 -0800248 switch (addr->sa_family) {
249 case AF_INET:
Craig Tiller6a6b36c2015-09-10 16:00:22 -0700250 GPR_ASSERT(port >= 0 && port < 65536);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700251 ((struct sockaddr_in*)addr)->sin_port = htons((uint16_t)port);
ctiller570d1f42015-01-12 16:29:52 -0800252 return 1;
253 case AF_INET6:
Craig Tiller6a6b36c2015-09-10 16:00:22 -0700254 GPR_ASSERT(port >= 0 && port < 65536);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700255 ((struct sockaddr_in6*)addr)->sin6_port = htons((uint16_t)port);
ctiller570d1f42015-01-12 16:29:52 -0800256 return 1;
257 default:
Craig Tillerd6c98df2015-08-18 09:33:44 -0700258 gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_set_port",
259 addr->sa_family);
ctiller570d1f42015-01-12 16:29:52 -0800260 return 0;
261 }
Craig Tiller190d3602015-02-18 09:23:38 -0800262}