parse_address.cc
Go to the documentation of this file.
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 
20 
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #ifdef GRPC_HAVE_UNIX_SOCKET
27 #include <sys/un.h>
28 #endif
29 #include <string>
30 
31 #include "absl/strings/str_cat.h"
32 #include "absl/strings/strip.h"
33 
34 #include <grpc/support/log.h>
35 
43 
44 #ifdef GRPC_HAVE_UNIX_SOCKET
45 
46 bool grpc_parse_unix(const grpc_core::URI& uri,
47  grpc_resolved_address* resolved_addr) {
48  if (uri.scheme() != "unix") {
49  gpr_log(GPR_ERROR, "Expected 'unix' scheme, got '%s'",
50  uri.scheme().c_str());
51  return false;
52  }
54  grpc_core::UnixSockaddrPopulate(uri.path(), resolved_addr);
55  if (!GRPC_ERROR_IS_NONE(error)) {
58  return false;
59  }
60  return true;
61 }
62 
64  grpc_resolved_address* resolved_addr) {
65  if (uri.scheme() != "unix-abstract") {
66  gpr_log(GPR_ERROR, "Expected 'unix-abstract' scheme, got '%s'",
67  uri.scheme().c_str());
68  return false;
69  }
71  grpc_core::UnixAbstractSockaddrPopulate(uri.path(), resolved_addr);
72  if (!GRPC_ERROR_IS_NONE(error)) {
75  return false;
76  }
77  return true;
78 }
79 
80 namespace grpc_core {
81 
83  grpc_resolved_address* resolved_addr) {
84  memset(resolved_addr, 0, sizeof(*resolved_addr));
85  struct sockaddr_un* un =
86  reinterpret_cast<struct sockaddr_un*>(resolved_addr->addr);
87  const size_t maxlen = sizeof(un->sun_path) - 1;
88  if (path.size() > maxlen) {
90  "Path name should not have more than ", maxlen, " characters"));
91  }
92  un->sun_family = AF_UNIX;
93  path.copy(un->sun_path, path.size());
94  un->sun_path[path.size()] = '\0';
95  resolved_addr->len = static_cast<socklen_t>(sizeof(*un));
96  return GRPC_ERROR_NONE;
97 }
98 
100  absl::string_view path, grpc_resolved_address* resolved_addr) {
101  memset(resolved_addr, 0, sizeof(*resolved_addr));
102  struct sockaddr_un* un =
103  reinterpret_cast<struct sockaddr_un*>(resolved_addr->addr);
104  const size_t maxlen = sizeof(un->sun_path) - 1;
105  if (path.size() > maxlen) {
107  "Path name should not have more than ", maxlen, " characters"));
108  }
109  un->sun_family = AF_UNIX;
110  un->sun_path[0] = '\0';
111  path.copy(un->sun_path + 1, path.size());
112  resolved_addr->len =
113  static_cast<socklen_t>(sizeof(un->sun_family) + path.size() + 1);
114  return GRPC_ERROR_NONE;
115 }
116 
117 } // namespace grpc_core
118 
119 #else /* GRPC_HAVE_UNIX_SOCKET */
120 
121 bool grpc_parse_unix(const grpc_core::URI& /* uri */,
122  grpc_resolved_address* /* resolved_addr */) {
123  abort();
124 }
125 
127  grpc_resolved_address* /* resolved_addr */) {
128  abort();
129 }
130 
131 namespace grpc_core {
132 
134  absl::string_view /* path */, grpc_resolved_address* /* resolved_addr */) {
135  abort();
136 }
137 
139  absl::string_view /* path */, grpc_resolved_address* /* resolved_addr */) {
140  abort();
141 }
142 
143 } // namespace grpc_core
144 #endif /* GRPC_HAVE_UNIX_SOCKET */
145 
147  grpc_resolved_address* addr, bool log_errors) {
148  bool success = false;
149  // Split host and port.
150  std::string host;
152  if (!grpc_core::SplitHostPort(hostport, &host, &port)) {
153  if (log_errors) {
154  gpr_log(GPR_ERROR, "Failed gpr_split_host_port(%s, ...)",
155  std::string(hostport).c_str());
156  }
157  return false;
158  }
159  // Parse IP address.
160  memset(addr, 0, sizeof(*addr));
161  addr->len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in));
162  grpc_sockaddr_in* in = reinterpret_cast<grpc_sockaddr_in*>(addr->addr);
163  in->sin_family = GRPC_AF_INET;
164  if (grpc_inet_pton(GRPC_AF_INET, host.c_str(), &in->sin_addr) == 0) {
165  if (log_errors) {
166  gpr_log(GPR_ERROR, "invalid ipv4 address: '%s'", host.c_str());
167  }
168  goto done;
169  }
170  // Parse port.
171  if (port.empty()) {
172  if (log_errors) gpr_log(GPR_ERROR, "no port given for ipv4 scheme");
173  goto done;
174  }
175  int port_num;
176  if (sscanf(port.c_str(), "%d", &port_num) != 1 || port_num < 0 ||
177  port_num > 65535) {
178  if (log_errors) gpr_log(GPR_ERROR, "invalid ipv4 port: '%s'", port.c_str());
179  goto done;
180  }
181  in->sin_port = grpc_htons(static_cast<uint16_t>(port_num));
182  success = true;
183 done:
184  return success;
185 }
186 
188  grpc_resolved_address* resolved_addr) {
189  if (uri.scheme() != "ipv4") {
190  gpr_log(GPR_ERROR, "Expected 'ipv4' scheme, got '%s'",
191  uri.scheme().c_str());
192  return false;
193  }
195  resolved_addr, true /* log_errors */);
196 }
197 
199  grpc_resolved_address* addr, bool log_errors) {
200  bool success = false;
201  // Split host and port.
202  std::string host;
204  if (!grpc_core::SplitHostPort(hostport, &host, &port)) {
205  if (log_errors) {
206  gpr_log(GPR_ERROR, "Failed gpr_split_host_port(%s, ...)",
207  std::string(hostport).c_str());
208  }
209  return false;
210  }
211  // Parse IP address.
212  memset(addr, 0, sizeof(*addr));
213  addr->len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in6));
214  grpc_sockaddr_in6* in6 = reinterpret_cast<grpc_sockaddr_in6*>(addr->addr);
215  in6->sin6_family = GRPC_AF_INET6;
216  // Handle the RFC6874 syntax for IPv6 zone identifiers.
217  char* host_end =
218  static_cast<char*>(gpr_memrchr(host.c_str(), '%', host.size()));
219  if (host_end != nullptr) {
220  GPR_ASSERT(host_end >= host.c_str());
221  char host_without_scope[GRPC_INET6_ADDRSTRLEN + 1];
222  size_t host_without_scope_len =
223  static_cast<size_t>(host_end - host.c_str());
224  uint32_t sin6_scope_id = 0;
225  if (host_without_scope_len > GRPC_INET6_ADDRSTRLEN) {
226  if (log_errors) {
227  gpr_log(
228  GPR_ERROR,
229  "invalid ipv6 address length %zu. Length cannot be greater than "
230  "GRPC_INET6_ADDRSTRLEN i.e %d)",
231  host_without_scope_len, GRPC_INET6_ADDRSTRLEN);
232  }
233  goto done;
234  }
235  strncpy(host_without_scope, host.c_str(), host_without_scope_len);
236  host_without_scope[host_without_scope_len] = '\0';
237  if (grpc_inet_pton(GRPC_AF_INET6, host_without_scope, &in6->sin6_addr) ==
238  0) {
239  if (log_errors) {
240  gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host_without_scope);
241  }
242  goto done;
243  }
244  if (gpr_parse_bytes_to_uint32(host_end + 1,
245  host.size() - host_without_scope_len - 1,
246  &sin6_scope_id) == 0) {
247  if ((sin6_scope_id = grpc_if_nametoindex(host_end + 1)) == 0) {
249  "Invalid interface name: '%s'. "
250  "Non-numeric and failed if_nametoindex.",
251  host_end + 1);
252  goto done;
253  }
254  }
255  // Handle "sin6_scope_id" being type "u_long". See grpc issue #10027.
256  in6->sin6_scope_id = sin6_scope_id;
257  } else {
258  if (grpc_inet_pton(GRPC_AF_INET6, host.c_str(), &in6->sin6_addr) == 0) {
259  if (log_errors) {
260  gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host.c_str());
261  }
262  goto done;
263  }
264  }
265  // Parse port.
266  if (port.empty()) {
267  if (log_errors) gpr_log(GPR_ERROR, "no port given for ipv6 scheme");
268  goto done;
269  }
270  int port_num;
271  if (sscanf(port.c_str(), "%d", &port_num) != 1 || port_num < 0 ||
272  port_num > 65535) {
273  if (log_errors) gpr_log(GPR_ERROR, "invalid ipv6 port: '%s'", port.c_str());
274  goto done;
275  }
276  in6->sin6_port = grpc_htons(static_cast<uint16_t>(port_num));
277  success = true;
278 done:
279  return success;
280 }
281 
283  grpc_resolved_address* resolved_addr) {
284  if (uri.scheme() != "ipv6") {
285  gpr_log(GPR_ERROR, "Expected 'ipv6' scheme, got '%s'",
286  uri.scheme().c_str());
287  return false;
288  }
290  resolved_addr, true /* log_errors */);
291 }
292 
294  grpc_resolved_address* resolved_addr) {
295  if (uri.scheme() == "unix") {
296  return grpc_parse_unix(uri, resolved_addr);
297  }
298  if (uri.scheme() == "unix-abstract") {
299  return grpc_parse_unix_abstract(uri, resolved_addr);
300  }
301  if (uri.scheme() == "ipv4") {
302  return grpc_parse_ipv4(uri, resolved_addr);
303  }
304  if (uri.scheme() == "ipv6") {
305  return grpc_parse_ipv6(uri, resolved_addr);
306  }
307  gpr_log(GPR_ERROR, "Can't parse scheme '%s'", uri.scheme().c_str());
308  return false;
309 }
310 
312  if (strcmp(port, "http") == 0) {
313  return htons(80);
314  } else if (strcmp(port, "https") == 0) {
315  return htons(443);
316  }
317  return htons(static_cast<unsigned short>(atoi(port)));
318 }
319 
321  const char* addr, int port) {
322  memset(out, 0, sizeof(grpc_resolved_address));
323  grpc_sockaddr_in6* addr6 = reinterpret_cast<grpc_sockaddr_in6*>(out->addr);
324  grpc_sockaddr_in* addr4 = reinterpret_cast<grpc_sockaddr_in*>(out->addr);
325  if (grpc_inet_pton(GRPC_AF_INET6, addr, &addr6->sin6_addr) == 1) {
326  addr6->sin6_family = GRPC_AF_INET6;
327  out->len = sizeof(grpc_sockaddr_in6);
328  } else if (grpc_inet_pton(GRPC_AF_INET, addr, &addr4->sin_addr) == 1) {
329  addr4->sin_family = GRPC_AF_INET;
330  out->len = sizeof(grpc_sockaddr_in);
331  } else {
333  absl::StrCat("Failed to parse address:", addr));
334  }
336  return GRPC_ERROR_NONE;
337 }
gen_build_yaml.out
dictionary out
Definition: src/benchmark/gen_build_yaml.py:24
GRPC_ERROR_NONE
#define GRPC_ERROR_NONE
Definition: error.h:234
log.h
grpc_parse_unix_abstract
bool grpc_parse_unix_abstract(const grpc_core::URI &, grpc_resolved_address *)
Definition: parse_address.cc:126
sockaddr_utils.h
absl::StrCat
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: abseil-cpp/absl/strings/str_cat.cc:98
memset
return memset(p, 0, total)
uint16_t
unsigned short uint16_t
Definition: stdint-msvc2008.h:79
grpc_core
Definition: call_metric_recorder.h:31
string.h
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
grpc_parse_ipv6
bool grpc_parse_ipv6(const grpc_core::URI &uri, grpc_resolved_address *resolved_addr)
Definition: parse_address.cc:282
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
error
grpc_error_handle error
Definition: retry_filter.cc:499
grpc_core::URI
Definition: uri_parser.h:31
grpc_resolved_address
Definition: resolved_address.h:34
grpc_core::SplitHostPort
bool SplitHostPort(absl::string_view name, absl::string_view *host, absl::string_view *port)
Definition: host_port.cc:88
check_documentation.path
path
Definition: check_documentation.py:57
absl::StripPrefix
ABSL_MUST_USE_RESULT absl::string_view StripPrefix(absl::string_view str, absl::string_view prefix)
Definition: abseil-cpp/absl/strings/strip.h:73
grpc_inet_pton
int grpc_inet_pton(int af, const char *src, void *dst)
sockaddr.h
gen_build_yaml.struct
def struct(**kwargs)
Definition: test/core/end2end/gen_build_yaml.py:30
grpc_core::URI::path
const std::string & path() const
Definition: uri_parser.h:70
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
grpc_parse_uri
bool grpc_parse_uri(const grpc_core::URI &uri, grpc_resolved_address *resolved_addr)
Definition: parse_address.cc:293
socket_utils.h
grpc_core::UnixAbstractSockaddrPopulate
grpc_error_handle UnixAbstractSockaddrPopulate(absl::string_view, grpc_resolved_address *)
Definition: parse_address.cc:138
in
const char * in
Definition: third_party/abseil-cpp/absl/strings/internal/str_format/parser_test.cc:391
parse_address.h
grpc_if_nametoindex
uint32_t grpc_if_nametoindex(char *name)
Definition: grpc_if_nametoindex_unsupported.cc:29
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
gen_stats_data.c_str
def c_str(s, encoding='ascii')
Definition: gen_stats_data.py:38
grpc_string_to_sockaddr
grpc_error_handle grpc_string_to_sockaddr(grpc_resolved_address *out, const char *addr, int port)
Definition: parse_address.cc:320
grpc_sockaddr_set_port
int grpc_sockaddr_set_port(grpc_resolved_address *resolved_addr, int port)
Definition: sockaddr_utils.cc:324
gpr_log
GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format,...) GPR_PRINT_FORMAT_CHECK(4
gpr_memrchr
void * gpr_memrchr(const void *s, int c, size_t n)
Definition: string.cc:313
done
struct tab * done
Definition: bloaty/third_party/zlib/examples/enough.c:176
addr6
static struct sockaddr_in6 addr6
Definition: test-getnameinfo.c:34
grpc_core::UnixSockaddrPopulate
grpc_error_handle UnixSockaddrPopulate(absl::string_view, grpc_resolved_address *)
Definition: parse_address.cc:133
grpc_parse_ipv6_hostport
bool grpc_parse_ipv6_hostport(absl::string_view hostport, grpc_resolved_address *addr, bool log_errors)
Definition: parse_address.cc:198
grpc_strhtons
uint16_t grpc_strhtons(const char *port)
Definition: parse_address.cc:311
grpc_resolved_address::len
socklen_t len
Definition: resolved_address.h:36
sockaddr_in6::sin6_family
unsigned short sin6_family
Definition: ares_ipv6.h:27
grpc_if_nametoindex.h
host_port.h
GPR_ERROR
#define GPR_ERROR
Definition: include/grpc/impl/codegen/log.h:57
grpc_parse_unix
bool grpc_parse_unix(const grpc_core::URI &, grpc_resolved_address *)
Definition: parse_address.cc:121
grpc_htons
uint16_t grpc_htons(uint16_t hostshort)
tests.unit._exit_scenarios.port
port
Definition: _exit_scenarios.py:179
addr4
static struct sockaddr_in addr4
Definition: test-getnameinfo.c:33
grpc_core::URI::scheme
const std::string & scheme() const
Definition: uri_parser.h:68
port.h
grpc_error_std_string
std::string grpc_error_std_string(grpc_error_handle error)
Definition: error.cc:944
gpr_parse_bytes_to_uint32
int gpr_parse_bytes_to_uint32(const char *buf, size_t len, uint32_t *result)
Definition: string.cc:149
GRPC_ERROR_CREATE_FROM_CPP_STRING
#define GRPC_ERROR_CREATE_FROM_CPP_STRING(desc)
Definition: error.h:297
GRPC_ERROR_UNREF
#define GRPC_ERROR_UNREF(err)
Definition: error.h:262
sockaddr_in6::sin6_addr
struct ares_in6_addr sin6_addr
Definition: ares_ipv6.h:30
grpc_parse_ipv4_hostport
bool grpc_parse_ipv4_hostport(absl::string_view hostport, grpc_resolved_address *addr, bool log_errors)
Definition: parse_address.cc:146
grpc_parse_ipv4
bool grpc_parse_ipv4(const grpc_core::URI &uri, grpc_resolved_address *resolved_addr)
Definition: parse_address.cc:187
grpc_error
Definition: error_internal.h:42
grpc_resolved_address::addr
char addr[GRPC_MAX_SOCKADDR_SIZE]
Definition: resolved_address.h:35
addr
struct sockaddr_in addr
Definition: libuv/docs/code/tcp-echo-server/main.c:10
GRPC_ERROR_IS_NONE
#define GRPC_ERROR_IS_NONE(err)
Definition: error.h:241
port_platform.h


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:00:49