Line data Source code
1 : /*
2 : *
3 : * Copyright 2015, Google Inc.
4 : * 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 :
34 : #include "src/core/iomgr/sockaddr_utils.h"
35 :
36 : #include <errno.h>
37 : #include <string.h>
38 :
39 : #ifdef GPR_POSIX_SOCKET
40 : #include <sys/un.h>
41 : #endif
42 :
43 : #include <grpc/support/alloc.h>
44 : #include <grpc/support/host_port.h>
45 : #include <grpc/support/log.h>
46 : #include <grpc/support/port_platform.h>
47 : #include <grpc/support/string_util.h>
48 :
49 : #include "src/core/support/string.h"
50 :
51 : static const gpr_uint8 kV4MappedPrefix[] = {0, 0, 0, 0, 0, 0,
52 : 0, 0, 0, 0, 0xff, 0xff};
53 :
54 23628 : int grpc_sockaddr_is_v4mapped(const struct sockaddr *addr,
55 : struct sockaddr_in *addr4_out) {
56 23628 : GPR_ASSERT(addr != (struct sockaddr *)addr4_out);
57 23628 : if (addr->sa_family == AF_INET6) {
58 17341 : const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
59 17514 : if (memcmp(addr6->sin6_addr.s6_addr, kV4MappedPrefix,
60 : sizeof(kV4MappedPrefix)) == 0) {
61 7858 : if (addr4_out != NULL) {
62 : /* Normalize ::ffff:0.0.0.0/96 to IPv4. */
63 7743 : memset(addr4_out, 0, sizeof(*addr4_out));
64 7743 : addr4_out->sin_family = AF_INET;
65 : /* s6_addr32 would be nice, but it's non-standard. */
66 7743 : memcpy(&addr4_out->sin_addr, &addr6->sin6_addr.s6_addr[12], 4);
67 7743 : addr4_out->sin_port = addr6->sin6_port;
68 : }
69 7826 : return 1;
70 : }
71 : }
72 15582 : return 0;
73 : }
74 :
75 16350 : int grpc_sockaddr_to_v4mapped(const struct sockaddr *addr,
76 : struct sockaddr_in6 *addr6_out) {
77 16350 : GPR_ASSERT(addr != (struct sockaddr *)addr6_out);
78 16350 : if (addr->sa_family == AF_INET) {
79 7340 : const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
80 7372 : memset(addr6_out, 0, sizeof(*addr6_out));
81 7372 : addr6_out->sin6_family = AF_INET6;
82 7372 : memcpy(&addr6_out->sin6_addr.s6_addr[0], kV4MappedPrefix, 12);
83 7372 : memcpy(&addr6_out->sin6_addr.s6_addr[12], &addr4->sin_addr, 4);
84 7372 : addr6_out->sin6_port = addr4->sin_port;
85 7372 : return 1;
86 : }
87 8878 : return 0;
88 : }
89 :
90 4556 : int grpc_sockaddr_is_wildcard(const struct sockaddr *addr, int *port_out) {
91 : struct sockaddr_in addr4_normalized;
92 4556 : if (grpc_sockaddr_is_v4mapped(addr, &addr4_normalized)) {
93 2202 : addr = (struct sockaddr *)&addr4_normalized;
94 : }
95 4556 : if (addr->sa_family == AF_INET) {
96 : /* Check for 0.0.0.0 */
97 2204 : const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
98 2234 : if (addr4->sin_addr.s_addr != 0) {
99 2154 : return 0;
100 : }
101 63 : *port_out = ntohs(addr4->sin_port);
102 63 : return 1;
103 2322 : } else if (addr->sa_family == AF_INET6) {
104 : /* Check for :: */
105 1808 : const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
106 : int i;
107 29181 : for (i = 0; i < 16; i++) {
108 29170 : if (addr6->sin6_addr.s6_addr[i] != 0) {
109 1780 : return 0;
110 : }
111 : }
112 28 : *port_out = ntohs(addr6->sin6_port);
113 28 : return 1;
114 : } else {
115 497 : return 0;
116 : }
117 : }
118 :
119 89 : void grpc_sockaddr_make_wildcards(int port, struct sockaddr_in *wild4_out,
120 : struct sockaddr_in6 *wild6_out) {
121 89 : grpc_sockaddr_make_wildcard4(port, wild4_out);
122 89 : grpc_sockaddr_make_wildcard6(port, wild6_out);
123 89 : }
124 :
125 89 : void grpc_sockaddr_make_wildcard4(int port, struct sockaddr_in *wild_out) {
126 89 : GPR_ASSERT(port >= 0 && port < 65536);
127 89 : memset(wild_out, 0, sizeof(*wild_out));
128 89 : wild_out->sin_family = AF_INET;
129 89 : wild_out->sin_port = htons((gpr_uint16)port);
130 89 : }
131 :
132 89 : void grpc_sockaddr_make_wildcard6(int port, struct sockaddr_in6 *wild_out) {
133 89 : GPR_ASSERT(port >= 0 && port < 65536);
134 89 : memset(wild_out, 0, sizeof(*wild_out));
135 89 : wild_out->sin6_family = AF_INET6;
136 89 : wild_out->sin6_port = htons((gpr_uint16)port);
137 89 : }
138 :
139 17789 : int grpc_sockaddr_to_string(char **out, const struct sockaddr *addr,
140 : int normalize) {
141 17789 : const int save_errno = errno;
142 : struct sockaddr_in addr_normalized;
143 : char ntop_buf[INET6_ADDRSTRLEN];
144 17616 : const void *ip = NULL;
145 : int port;
146 : int ret;
147 :
148 17789 : *out = NULL;
149 17789 : if (normalize && grpc_sockaddr_is_v4mapped(addr, &addr_normalized)) {
150 1 : addr = (const struct sockaddr *)&addr_normalized;
151 : }
152 17789 : if (addr->sa_family == AF_INET) {
153 5516 : const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
154 5518 : ip = &addr4->sin_addr;
155 5518 : port = ntohs(addr4->sin_port);
156 12271 : } else if (addr->sa_family == AF_INET6) {
157 7581 : const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
158 7705 : ip = &addr6->sin6_addr;
159 7705 : port = ntohs(addr6->sin6_port);
160 : }
161 : /* Windows inet_ntop wants a mutable ip pointer */
162 31011 : if (ip != NULL &&
163 13223 : inet_ntop(addr->sa_family, (void *)ip, ntop_buf, sizeof(ntop_buf)) !=
164 : NULL) {
165 13222 : ret = gpr_join_host_port(out, ntop_buf, port);
166 : } else {
167 4566 : ret = gpr_asprintf(out, "(sockaddr family=%d)", addr->sa_family);
168 : }
169 : /* This is probably redundant, but we wouldn't want to log the wrong error. */
170 17789 : errno = save_errno;
171 17789 : return ret;
172 : }
173 :
174 14128 : char *grpc_sockaddr_to_uri(const struct sockaddr *addr) {
175 : char *temp;
176 : char *result;
177 : struct sockaddr_in addr_normalized;
178 :
179 14128 : if (grpc_sockaddr_is_v4mapped(addr, &addr_normalized)) {
180 5393 : addr = (const struct sockaddr *)&addr_normalized;
181 : }
182 :
183 14128 : switch (addr->sa_family) {
184 : case AF_INET:
185 5515 : grpc_sockaddr_to_string(&temp, addr, 0);
186 5515 : gpr_asprintf(&result, "ipv4:%s", temp);
187 5515 : gpr_free(temp);
188 5515 : return result;
189 : case AF_INET6:
190 7700 : grpc_sockaddr_to_string(&temp, addr, 0);
191 7700 : gpr_asprintf(&result, "ipv6:%s", temp);
192 7700 : gpr_free(temp);
193 7700 : return result;
194 : #ifdef GPR_POSIX_SOCKET
195 : case AF_UNIX:
196 912 : gpr_asprintf(&result, "unix:%s", ((struct sockaddr_un *)addr)->sun_path);
197 912 : return result;
198 : #endif
199 : }
200 :
201 1 : return NULL;
202 : }
203 :
204 9155 : int grpc_sockaddr_get_port(const struct sockaddr *addr) {
205 9155 : switch (addr->sa_family) {
206 : case AF_INET:
207 2254 : return ntohs(((struct sockaddr_in *)addr)->sin_port);
208 : case AF_INET6:
209 5909 : return ntohs(((struct sockaddr_in6 *)addr)->sin6_port);
210 : case AF_UNIX:
211 992 : return 1;
212 : default:
213 0 : gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_get_port",
214 0 : addr->sa_family);
215 0 : return 0;
216 : }
217 : }
218 :
219 42 : int grpc_sockaddr_set_port(const struct sockaddr *addr, int port) {
220 42 : switch (addr->sa_family) {
221 : case AF_INET:
222 42 : GPR_ASSERT(port >= 0 && port < 65536);
223 42 : ((struct sockaddr_in *)addr)->sin_port = htons((gpr_uint16)port);
224 42 : return 1;
225 : case AF_INET6:
226 0 : GPR_ASSERT(port >= 0 && port < 65536);
227 0 : ((struct sockaddr_in6 *)addr)->sin6_port = htons((gpr_uint16)port);
228 0 : return 1;
229 : default:
230 0 : gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_set_port",
231 0 : addr->sa_family);
232 0 : return 0;
233 : }
234 : }
|