blob: 44bc2f968be54fb71a790ba0453bb5d850b36a28 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
ahedberg8afb88d2016-03-22 13:57:47 -04003 * Copyright 2016, Google Inc.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
Craig Tiller9533d042016-03-25 17:11:06 -070034#include "src/core/lib/iomgr/sockaddr_utils.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080035
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080036#include <errno.h>
ctiller18b49ab2014-12-09 14:39:16 -080037#include <string.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080038
Craig Tiller1b22b9d2015-07-20 13:42:22 -070039#include <grpc/support/alloc.h>
nnoble0c475f02014-12-05 15:37:39 -080040#include <grpc/support/host_port.h>
nnoble0c475f02014-12-05 15:37:39 -080041#include <grpc/support/log.h>
42#include <grpc/support/port_platform.h>
Masood Malekghassemi701af602015-06-03 15:01:17 -070043#include <grpc/support/string_util.h>
nnoble0c475f02014-12-05 15:37:39 -080044
murgatroid997871f732016-09-23 13:49:05 -070045#include "src/core/lib/iomgr/sockaddr.h"
murgatroid9931963632016-08-09 14:00:41 -070046#include "src/core/lib/iomgr/socket_utils.h"
Craig Tiller9533d042016-03-25 17:11:06 -070047#include "src/core/lib/iomgr/unix_sockets_posix.h"
48#include "src/core/lib/support/string.h"
Craig Tiller1b22b9d2015-07-20 13:42:22 -070049
Craig Tiller7536af02015-12-22 13:49:30 -080050static const uint8_t kV4MappedPrefix[] = {0, 0, 0, 0, 0, 0,
51 0, 0, 0, 0, 0xff, 0xff};
nnoble0c475f02014-12-05 15:37:39 -080052
murgatroid997871f732016-09-23 13:49:05 -070053int grpc_sockaddr_is_v4mapped(const grpc_resolved_address *resolved_addr,
54 grpc_resolved_address *resolved_addr4_out) {
55 GPR_ASSERT(resolved_addr != resolved_addr4_out);
56 const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
murgatroid99dedb9232016-09-26 13:54:04 -070057 struct sockaddr_in *addr4_out =
58 (struct sockaddr_in *)resolved_addr4_out->addr;
nnoble0c475f02014-12-05 15:37:39 -080059 if (addr->sa_family == AF_INET6) {
60 const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
61 if (memcmp(addr6->sin6_addr.s6_addr, kV4MappedPrefix,
62 sizeof(kV4MappedPrefix)) == 0) {
murgatroid997871f732016-09-23 13:49:05 -070063 if (resolved_addr4_out != NULL) {
nnoble0c475f02014-12-05 15:37:39 -080064 /* Normalize ::ffff:0.0.0.0/96 to IPv4. */
murgatroid997871f732016-09-23 13:49:05 -070065 memset(resolved_addr4_out, 0, sizeof(*resolved_addr4_out));
nnoble0c475f02014-12-05 15:37:39 -080066 addr4_out->sin_family = AF_INET;
67 /* s6_addr32 would be nice, but it's non-standard. */
68 memcpy(&addr4_out->sin_addr, &addr6->sin6_addr.s6_addr[12], 4);
69 addr4_out->sin_port = addr6->sin6_port;
murgatroid997871f732016-09-23 13:49:05 -070070 resolved_addr4_out->len = sizeof(struct sockaddr_in);
nnoble0c475f02014-12-05 15:37:39 -080071 }
72 return 1;
73 }
74 }
75 return 0;
76}
77
murgatroid997871f732016-09-23 13:49:05 -070078int grpc_sockaddr_to_v4mapped(const grpc_resolved_address *resolved_addr,
79 grpc_resolved_address *resolved_addr6_out) {
80 GPR_ASSERT(resolved_addr != resolved_addr6_out);
81 const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
murgatroid99dedb9232016-09-26 13:54:04 -070082 struct sockaddr_in6 *addr6_out =
83 (struct sockaddr_in6 *)resolved_addr6_out->addr;
nnoble0c475f02014-12-05 15:37:39 -080084 if (addr->sa_family == AF_INET) {
85 const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
murgatroid997871f732016-09-23 13:49:05 -070086 memset(resolved_addr6_out, 0, sizeof(*resolved_addr6_out));
nnoble0c475f02014-12-05 15:37:39 -080087 addr6_out->sin6_family = AF_INET6;
88 memcpy(&addr6_out->sin6_addr.s6_addr[0], kV4MappedPrefix, 12);
89 memcpy(&addr6_out->sin6_addr.s6_addr[12], &addr4->sin_addr, 4);
90 addr6_out->sin6_port = addr4->sin_port;
murgatroid997871f732016-09-23 13:49:05 -070091 resolved_addr6_out->len = sizeof(struct sockaddr_in6);
nnoble0c475f02014-12-05 15:37:39 -080092 return 1;
93 }
94 return 0;
95}
96
murgatroid99dedb9232016-09-26 13:54:04 -070097int grpc_sockaddr_is_wildcard(const grpc_resolved_address *resolved_addr,
98 int *port_out) {
murgatroid997871f732016-09-23 13:49:05 -070099 const struct sockaddr *addr;
100 grpc_resolved_address addr4_normalized;
101 if (grpc_sockaddr_is_v4mapped(resolved_addr, &addr4_normalized)) {
102 resolved_addr = &addr4_normalized;
nnoble0c475f02014-12-05 15:37:39 -0800103 }
murgatroid997871f732016-09-23 13:49:05 -0700104 addr = (const struct sockaddr *)resolved_addr->addr;
nnoble0c475f02014-12-05 15:37:39 -0800105 if (addr->sa_family == AF_INET) {
106 /* Check for 0.0.0.0 */
107 const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
108 if (addr4->sin_addr.s_addr != 0) {
109 return 0;
110 }
111 *port_out = ntohs(addr4->sin_port);
112 return 1;
113 } else if (addr->sa_family == AF_INET6) {
114 /* Check for :: */
115 const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
116 int i;
117 for (i = 0; i < 16; i++) {
118 if (addr6->sin6_addr.s6_addr[i] != 0) {
119 return 0;
120 }
121 }
122 *port_out = ntohs(addr6->sin6_port);
123 return 1;
124 } else {
125 return 0;
126 }
127}
128
murgatroid997871f732016-09-23 13:49:05 -0700129void grpc_sockaddr_make_wildcards(int port, grpc_resolved_address *wild4_out,
130 grpc_resolved_address *wild6_out) {
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100131 grpc_sockaddr_make_wildcard4(port, wild4_out);
132 grpc_sockaddr_make_wildcard6(port, wild6_out);
133}
nnoble0c475f02014-12-05 15:37:39 -0800134
murgatroid99dedb9232016-09-26 13:54:04 -0700135void grpc_sockaddr_make_wildcard4(int port,
136 grpc_resolved_address *resolved_wild_out) {
murgatroid997871f732016-09-23 13:49:05 -0700137 struct sockaddr_in *wild_out = (struct sockaddr_in *)resolved_wild_out->addr;
Craig Tiller6a6b36c2015-09-10 16:00:22 -0700138 GPR_ASSERT(port >= 0 && port < 65536);
murgatroid997871f732016-09-23 13:49:05 -0700139 memset(resolved_wild_out, 0, sizeof(*resolved_wild_out));
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100140 wild_out->sin_family = AF_INET;
Craig Tiller7536af02015-12-22 13:49:30 -0800141 wild_out->sin_port = htons((uint16_t)port);
murgatroid997871f732016-09-23 13:49:05 -0700142 resolved_wild_out->len = sizeof(struct sockaddr_in);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100143}
144
murgatroid99dedb9232016-09-26 13:54:04 -0700145void grpc_sockaddr_make_wildcard6(int port,
146 grpc_resolved_address *resolved_wild_out) {
147 struct sockaddr_in6 *wild_out =
148 (struct sockaddr_in6 *)resolved_wild_out->addr;
Craig Tiller6a6b36c2015-09-10 16:00:22 -0700149 GPR_ASSERT(port >= 0 && port < 65536);
murgatroid997871f732016-09-23 13:49:05 -0700150 memset(resolved_wild_out, 0, sizeof(*resolved_wild_out));
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100151 wild_out->sin6_family = AF_INET6;
Craig Tiller7536af02015-12-22 13:49:30 -0800152 wild_out->sin6_port = htons((uint16_t)port);
murgatroid997871f732016-09-23 13:49:05 -0700153 resolved_wild_out->len = sizeof(struct sockaddr_in6);
nnoble0c475f02014-12-05 15:37:39 -0800154}
155
murgatroid99dedb9232016-09-26 13:54:04 -0700156int grpc_sockaddr_to_string(char **out,
157 const grpc_resolved_address *resolved_addr,
nnoble0c475f02014-12-05 15:37:39 -0800158 int normalize) {
murgatroid997871f732016-09-23 13:49:05 -0700159 const struct sockaddr *addr;
nnoble0c475f02014-12-05 15:37:39 -0800160 const int save_errno = errno;
murgatroid997871f732016-09-23 13:49:05 -0700161 grpc_resolved_address addr_normalized;
nnoble0c475f02014-12-05 15:37:39 -0800162 char ntop_buf[INET6_ADDRSTRLEN];
163 const void *ip = NULL;
164 int port;
165 int ret;
166
167 *out = NULL;
murgatroid997871f732016-09-23 13:49:05 -0700168 if (normalize && grpc_sockaddr_is_v4mapped(resolved_addr, &addr_normalized)) {
169 resolved_addr = &addr_normalized;
nnoble0c475f02014-12-05 15:37:39 -0800170 }
murgatroid997871f732016-09-23 13:49:05 -0700171 addr = (const struct sockaddr *)resolved_addr->addr;
nnoble0c475f02014-12-05 15:37:39 -0800172 if (addr->sa_family == AF_INET) {
173 const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
174 ip = &addr4->sin_addr;
175 port = ntohs(addr4->sin_port);
176 } else if (addr->sa_family == AF_INET6) {
177 const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
178 ip = &addr6->sin6_addr;
179 port = ntohs(addr6->sin6_port);
180 }
181 if (ip != NULL &&
murgatroid997e924a02016-08-10 10:06:43 -0700182 grpc_inet_ntop(addr->sa_family, ip, ntop_buf, sizeof(ntop_buf)) != NULL) {
nnoble0c475f02014-12-05 15:37:39 -0800183 ret = gpr_join_host_port(out, ntop_buf, port);
184 } else {
185 ret = gpr_asprintf(out, "(sockaddr family=%d)", addr->sa_family);
186 }
187 /* This is probably redundant, but we wouldn't want to log the wrong error. */
188 errno = save_errno;
189 return ret;
190}
ctiller570d1f42015-01-12 16:29:52 -0800191
murgatroid997871f732016-09-23 13:49:05 -0700192char *grpc_sockaddr_to_uri(const grpc_resolved_address *resolved_addr) {
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700193 char *temp;
194 char *result;
murgatroid997871f732016-09-23 13:49:05 -0700195 grpc_resolved_address addr_normalized;
196 const struct sockaddr *addr;
Paul Marks63541a12015-08-04 15:05:00 -0700197
murgatroid997871f732016-09-23 13:49:05 -0700198 if (grpc_sockaddr_is_v4mapped(resolved_addr, &addr_normalized)) {
199 resolved_addr = &addr_normalized;
Paul Marks63541a12015-08-04 15:05:00 -0700200 }
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700201
murgatroid997871f732016-09-23 13:49:05 -0700202 addr = (const struct sockaddr *)resolved_addr->addr;
203
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700204 switch (addr->sa_family) {
205 case AF_INET:
murgatroid997871f732016-09-23 13:49:05 -0700206 grpc_sockaddr_to_string(&temp, resolved_addr, 0);
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700207 gpr_asprintf(&result, "ipv4:%s", temp);
208 gpr_free(temp);
209 return result;
210 case AF_INET6:
murgatroid997871f732016-09-23 13:49:05 -0700211 grpc_sockaddr_to_string(&temp, resolved_addr, 0);
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700212 gpr_asprintf(&result, "ipv6:%s", temp);
213 gpr_free(temp);
214 return result;
ahedberg80d6b122016-03-17 17:37:35 -0400215 default:
murgatroid997871f732016-09-23 13:49:05 -0700216 return grpc_sockaddr_to_uri_unix_if_possible(resolved_addr);
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700217 }
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700218}
219
murgatroid997871f732016-09-23 13:49:05 -0700220int grpc_sockaddr_get_port(const grpc_resolved_address *resolved_addr) {
221 const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
ctiller570d1f42015-01-12 16:29:52 -0800222 switch (addr->sa_family) {
223 case AF_INET:
224 return ntohs(((struct sockaddr_in *)addr)->sin_port);
225 case AF_INET6:
226 return ntohs(((struct sockaddr_in6 *)addr)->sin6_port);
227 default:
murgatroid997871f732016-09-23 13:49:05 -0700228 if (grpc_is_unix_socket(resolved_addr)) {
ahedberg80d6b122016-03-17 17:37:35 -0400229 return 1;
230 }
Craig Tillerd6c98df2015-08-18 09:33:44 -0700231 gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_get_port",
232 addr->sa_family);
ctiller570d1f42015-01-12 16:29:52 -0800233 return 0;
234 }
235}
236
murgatroid99dedb9232016-09-26 13:54:04 -0700237int grpc_sockaddr_set_port(const grpc_resolved_address *resolved_addr,
238 int port) {
murgatroid997871f732016-09-23 13:49:05 -0700239 const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
ctiller570d1f42015-01-12 16:29:52 -0800240 switch (addr->sa_family) {
241 case AF_INET:
Craig Tiller6a6b36c2015-09-10 16:00:22 -0700242 GPR_ASSERT(port >= 0 && port < 65536);
Craig Tiller7536af02015-12-22 13:49:30 -0800243 ((struct sockaddr_in *)addr)->sin_port = htons((uint16_t)port);
ctiller570d1f42015-01-12 16:29:52 -0800244 return 1;
245 case AF_INET6:
Craig Tiller6a6b36c2015-09-10 16:00:22 -0700246 GPR_ASSERT(port >= 0 && port < 65536);
Craig Tiller7536af02015-12-22 13:49:30 -0800247 ((struct sockaddr_in6 *)addr)->sin6_port = htons((uint16_t)port);
ctiller570d1f42015-01-12 16:29:52 -0800248 return 1;
249 default:
Craig Tillerd6c98df2015-08-18 09:33:44 -0700250 gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_set_port",
251 addr->sa_family);
ctiller570d1f42015-01-12 16:29:52 -0800252 return 0;
253 }
Craig Tiller190d3602015-02-18 09:23:38 -0800254}