• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 //
3 // Copyright 2017 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 "src/core/lib/address_utils/parse_address.h"
20 #ifdef GRPC_HAVE_UNIX_SOCKET
21 #ifdef GPR_WINDOWS
22 // clang-format off
23 #include <ws2def.h>
24 #include <afunix.h>
25 // clang-format on
26 #else
27 #include <sys/un.h>
28 #endif  // GPR_WINDOWS
29 #endif  // GRPC_HAVE_UNIX_SOCKET
30 
31 #ifdef GRPC_HAVE_VSOCK
32 #include <linux/vm_sockets.h>
33 #endif
34 
35 #include <grpc/grpc.h>
36 
37 #include <string>
38 
39 #include "absl/log/log.h"
40 #include "absl/status/status.h"
41 #include "absl/strings/match.h"
42 #include "gtest/gtest.h"
43 #include "src/core/lib/iomgr/exec_ctx.h"
44 #include "src/core/lib/iomgr/port.h"
45 #include "src/core/lib/iomgr/sockaddr.h"
46 #include "src/core/lib/iomgr/socket_utils.h"
47 #include "test/core/test_util/test_config.h"
48 
49 #ifdef GRPC_HAVE_UNIX_SOCKET
50 
test_grpc_parse_unix(const char * uri_text,const char * pathname)51 static void test_grpc_parse_unix(const char* uri_text, const char* pathname) {
52   grpc_core::ExecCtx exec_ctx;
53   absl::StatusOr<grpc_core::URI> uri = grpc_core::URI::Parse(uri_text);
54   if (!uri.ok()) {
55     LOG(ERROR) << uri.status();
56     ASSERT_TRUE(uri.ok());
57   }
58   grpc_resolved_address addr;
59 
60   ASSERT_TRUE(grpc_parse_uri(*uri, &addr));
61   struct sockaddr_un* addr_un =
62       reinterpret_cast<struct sockaddr_un*>(addr.addr);
63   ASSERT_EQ(AF_UNIX, addr_un->sun_family);
64   ASSERT_STREQ(addr_un->sun_path, pathname);
65 }
66 
test_grpc_parse_unix_abstract(const char * uri_text,const char * pathname)67 static void test_grpc_parse_unix_abstract(const char* uri_text,
68                                           const char* pathname) {
69   grpc_core::ExecCtx exec_ctx;
70   absl::StatusOr<grpc_core::URI> uri = grpc_core::URI::Parse(uri_text);
71   if (!uri.ok()) {
72     LOG(ERROR) << uri.status();
73     ASSERT_TRUE(uri.ok());
74   }
75   grpc_resolved_address addr;
76 
77   ASSERT_TRUE(grpc_parse_uri(*uri, &addr));
78   struct sockaddr_un* addr_un =
79       reinterpret_cast<struct sockaddr_un*>(addr.addr);
80   ASSERT_EQ(AF_UNIX, addr_un->sun_family);
81   ASSERT_EQ('\0', addr_un->sun_path[0]);
82   ASSERT_TRUE(absl::StartsWith(addr_un->sun_path + 1, pathname));
83 }
84 
85 #else  // GRPC_HAVE_UNIX_SOCKET
86 
test_grpc_parse_unix(const char * uri_text,const char * pathname)87 static void test_grpc_parse_unix(const char* uri_text, const char* pathname) {}
test_grpc_parse_unix_abstract(const char * uri_text,const char * pathname)88 static void test_grpc_parse_unix_abstract(const char* uri_text,
89                                           const char* pathname) {}
90 
91 #endif  // GRPC_HAVE_UNIX_SOCKET
92 
93 #ifdef GRPC_HAVE_VSOCK
94 
test_grpc_parse_vsock(const char * uri_text,uint32_t cid,uint32_t port)95 static void test_grpc_parse_vsock(const char* uri_text, uint32_t cid,
96                                   uint32_t port) {
97   grpc_core::ExecCtx exec_ctx;
98   absl::StatusOr<grpc_core::URI> uri = grpc_core::URI::Parse(uri_text);
99   if (!uri.ok()) {
100     LOG(ERROR) << uri.status();
101     ASSERT_TRUE(uri.ok());
102   }
103   grpc_resolved_address addr;
104 
105   ASSERT_TRUE(grpc_parse_uri(*uri, &addr));
106   struct sockaddr_vm* addr_vm =
107       reinterpret_cast<struct sockaddr_vm*>(addr.addr);
108   ASSERT_EQ(AF_VSOCK, addr_vm->svm_family);
109   ASSERT_EQ(grpc_ntohl(addr_vm->svm_cid), cid);
110   ASSERT_EQ(addr_vm->svm_port, port);
111 }
112 
113 #else  // GRPC_HAVE_VSOCK
114 
test_grpc_parse_vsock(const char *,...)115 static void test_grpc_parse_vsock(const char* /* uri_text */, ...) {}
116 
117 #endif  // GRPC_HAVE_VSOCK
118 
test_grpc_parse_ipv4(const char * uri_text,const char * host,unsigned short port)119 static void test_grpc_parse_ipv4(const char* uri_text, const char* host,
120                                  unsigned short port) {
121   grpc_core::ExecCtx exec_ctx;
122   absl::StatusOr<grpc_core::URI> uri = grpc_core::URI::Parse(uri_text);
123   if (!uri.ok()) {
124     LOG(ERROR) << uri.status();
125     ASSERT_TRUE(uri.ok());
126   }
127   grpc_resolved_address addr;
128   char ntop_buf[GRPC_INET_ADDRSTRLEN];
129 
130   ASSERT_TRUE(grpc_parse_ipv4(*uri, &addr));
131   grpc_sockaddr_in* addr_in = reinterpret_cast<grpc_sockaddr_in*>(addr.addr);
132   ASSERT_EQ(GRPC_AF_INET, addr_in->sin_family);
133   ASSERT_NE(nullptr, grpc_inet_ntop(GRPC_AF_INET, &addr_in->sin_addr, ntop_buf,
134                                     sizeof(ntop_buf)));
135   ASSERT_STREQ(ntop_buf, host);
136   ASSERT_EQ(grpc_ntohs(addr_in->sin_port), port);
137 }
138 
test_grpc_parse_ipv6(const char * uri_text,const char * host,unsigned short port,uint32_t scope_id)139 static void test_grpc_parse_ipv6(const char* uri_text, const char* host,
140                                  unsigned short port, uint32_t scope_id) {
141   grpc_core::ExecCtx exec_ctx;
142   absl::StatusOr<grpc_core::URI> uri = grpc_core::URI::Parse(uri_text);
143   if (!uri.ok()) {
144     LOG(ERROR) << uri.status();
145     ASSERT_TRUE(uri.ok());
146   }
147   grpc_resolved_address addr;
148   char ntop_buf[GRPC_INET6_ADDRSTRLEN];
149   ASSERT_TRUE(grpc_parse_ipv6(*uri, &addr));
150   grpc_sockaddr_in6* addr_in6 = reinterpret_cast<grpc_sockaddr_in6*>(addr.addr);
151   ASSERT_EQ(GRPC_AF_INET6, addr_in6->sin6_family);
152   ASSERT_NE(nullptr, grpc_inet_ntop(GRPC_AF_INET6, &addr_in6->sin6_addr,
153                                     ntop_buf, sizeof(ntop_buf)));
154   ASSERT_STREQ(ntop_buf, host);
155   ASSERT_EQ(grpc_ntohs(addr_in6->sin6_port), port);
156   ASSERT_EQ(addr_in6->sin6_scope_id, scope_id);
157 }
158 
159 // Test parsing invalid ipv6 addresses (valid uri_text but invalid ipv6 addr)
test_grpc_parse_ipv6_invalid(const char * uri_text)160 static void test_grpc_parse_ipv6_invalid(const char* uri_text) {
161   grpc_core::ExecCtx exec_ctx;
162   absl::StatusOr<grpc_core::URI> uri = grpc_core::URI::Parse(uri_text);
163   if (!uri.ok()) {
164     LOG(ERROR) << uri.status();
165     ASSERT_TRUE(uri.ok());
166   }
167   grpc_resolved_address addr;
168   ASSERT_FALSE(grpc_parse_ipv6(*uri, &addr));
169 }
170 
TEST(ParseAddressTest,MainTest)171 TEST(ParseAddressTest, MainTest) {
172   grpc_init();
173 
174   test_grpc_parse_unix("unix:/path/name", "/path/name");
175   test_grpc_parse_unix_abstract("unix-abstract:foobar", "foobar");
176   test_grpc_parse_vsock("vsock:-1:12345", -1, 12345);
177   test_grpc_parse_ipv4("ipv4:192.0.2.1:12345", "192.0.2.1", 12345);
178   test_grpc_parse_ipv6("ipv6:[2001:db8::1]:12345", "2001:db8::1", 12345, 0);
179   test_grpc_parse_ipv6("ipv6:[2001:db8::1%252]:12345", "2001:db8::1", 12345, 2);
180 
181   // Address length greater than GRPC_INET6_ADDRSTRLEN
182   test_grpc_parse_ipv6_invalid(
183       "ipv6:WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW45%"
184       "25v6:45%25x$1*");
185 
186   grpc_shutdown();
187 }
188 
main(int argc,char ** argv)189 int main(int argc, char** argv) {
190   grpc::testing::TestEnvironment env(&argc, argv);
191   ::testing::InitGoogleTest(&argc, argv);
192   return RUN_ALL_TESTS();
193 }
194