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 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 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 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 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 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 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 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 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 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 } 228 char* path = nullptr; 229 char* uri_str = nullptr; 230 if (grpc_sockaddr_to_string(&path, resolved_addr, 231 false /* suppress errors */) && 232 scheme != nullptr) { 233 gpr_asprintf(&uri_str, "%s:%s", scheme, path); 234 } 235 gpr_free(path); 236 return uri_str != nullptr ? uri_str : nullptr; 237 } 238 239 const char* grpc_sockaddr_get_uri_scheme( 240 const grpc_resolved_address* resolved_addr) { 241 const grpc_sockaddr* addr = 242 reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr); 243 switch (addr->sa_family) { 244 case GRPC_AF_INET: 245 return "ipv4"; 246 case GRPC_AF_INET6: 247 return "ipv6"; 248 case GRPC_AF_UNIX: 249 return "unix"; 250 } 251 return nullptr; 252 } 253 254 int grpc_sockaddr_get_family(const grpc_resolved_address* resolved_addr) { 255 const grpc_sockaddr* addr = 256 reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr); 257 return addr->sa_family; 258 } 259 260 int grpc_sockaddr_get_port(const grpc_resolved_address* resolved_addr) { 261 const grpc_sockaddr* addr = 262 reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr); 263 switch (addr->sa_family) { 264 case GRPC_AF_INET: 265 return grpc_ntohs(((grpc_sockaddr_in*)addr)->sin_port); 266 case GRPC_AF_INET6: 267 return grpc_ntohs(((grpc_sockaddr_in6*)addr)->sin6_port); 268 default: 269 if (grpc_is_unix_socket(resolved_addr)) { 270 return 1; 271 } 272 gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_get_port", 273 addr->sa_family); 274 return 0; 275 } 276 } 277 278 int grpc_sockaddr_set_port(const grpc_resolved_address* resolved_addr, 279 int port) { 280 const grpc_sockaddr* addr = 281 reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr); 282 switch (addr->sa_family) { 283 case GRPC_AF_INET: 284 GPR_ASSERT(port >= 0 && port < 65536); 285 ((grpc_sockaddr_in*)addr)->sin_port = 286 grpc_htons(static_cast<uint16_t>(port)); 287 return 1; 288 case GRPC_AF_INET6: 289 GPR_ASSERT(port >= 0 && port < 65536); 290 ((grpc_sockaddr_in6*)addr)->sin6_port = 291 grpc_htons(static_cast<uint16_t>(port)); 292 return 1; 293 default: 294 gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_set_port", 295 addr->sa_family); 296 return 0; 297 } 298 } 299