1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 #include <netinet/in.h>
8 #include <sys/socket.h>
10 #include "fake_ppapi/fake_pepper_interface.h"
11 #include "gtest/gtest.h"
12 #include "nacl_io/kernel_intercept.h"
14 using namespace nacl_io;
15 using namespace sdk_util;
19 class HostResolverTest : public ::testing::Test {
32 #define FAKE_HOSTNAME "example.com"
33 #define FAKE_IP 0x01020304
35 class FakeHostResolverTest : public ::testing::Test {
37 FakeHostResolverTest() : pepper_(NULL), fake_resolver_(NULL) {}
40 pepper_ = new FakePepperInterface();
41 fake_resolver_ = static_cast<FakeHostResolverInterface*>(
42 pepper_->GetHostResolverInterface());
44 // Seed the fake resolver with some data
45 fake_resolver_->fake_hostname = FAKE_HOSTNAME;
46 AddFakeAddress(AF_INET);
48 ki_init_interface(NULL, pepper_);
51 void AddFakeAddress(int family) {
52 if (family == AF_INET) {
53 int address_count = fake_resolver_->fake_addresses_v4.size();
54 // Each new address we add is FAKE_IP incremented by 1
55 // each time to be unique.
56 sockaddr_in fake_addr;
57 fake_addr.sin_family = family;
58 fake_addr.sin_addr.s_addr = htonl(FAKE_IP + address_count);
59 fake_resolver_->fake_addresses_v4.push_back(fake_addr);
60 } else if (family == AF_INET6) {
61 sockaddr_in6 fake_addr;
62 fake_addr.sin6_family = family;
63 int address_count = fake_resolver_->fake_addresses_v6.size();
64 for (uint8_t i = 0; i < 16; i++) {
65 fake_addr.sin6_addr.s6_addr[i] = i + address_count;
67 fake_resolver_->fake_addresses_v6.push_back(fake_addr);
77 FakePepperInterface* pepper_;
78 FakeHostResolverInterface* fake_resolver_;
83 #define NULL_INFO ((struct addrinfo*)NULL)
84 #define NULL_ADDR ((struct sockaddr*)NULL)
85 #define NULL_HOST (static_cast<hostent*>(NULL))
87 TEST_F(HostResolverTest, Getaddrinfo_Numeric) {
88 struct addrinfo* ai = NULL;
89 struct sockaddr_in* in;
90 struct addrinfo hints;
93 memset(&hints, 0, sizeof(hints));
94 hints.ai_family = AF_INET;
95 hints.ai_socktype = SOCK_STREAM;
97 uint32_t expected_addr = htonl(0x01020304);
98 ASSERT_EQ(0, ki_getaddrinfo("1.2.3.4", NULL, &hints, &ai));
99 ASSERT_NE(NULL_INFO, ai);
100 ASSERT_NE(NULL_ADDR, ai->ai_addr);
101 ASSERT_EQ(AF_INET, ai->ai_family);
102 ASSERT_EQ(SOCK_STREAM, ai->ai_socktype);
103 in = (struct sockaddr_in*)ai->ai_addr;
104 ASSERT_EQ(expected_addr, in->sin_addr.s_addr);
105 ASSERT_EQ(NULL_INFO, ai->ai_next);
110 TEST_F(HostResolverTest, Getaddrinfo_MissingPPAPI) {
111 // Verify that full lookups fail due to lack of PPAPI interfaces
112 struct addrinfo* ai = NULL;
113 ASSERT_EQ(EAI_SYSTEM, ki_getaddrinfo("google.com", NULL, NULL, &ai));
116 TEST_F(HostResolverTest, Getaddrinfo_Passive) {
117 struct addrinfo* ai = NULL;
118 struct sockaddr_in* in;
119 struct sockaddr_in6* in6;
120 struct addrinfo hints;
121 memset(&hints, 0, sizeof(hints));
123 uint32_t expected_port = htons(22);
124 in_addr_t expected_addr = htonl(INADDR_ANY);
125 in6_addr expected_addr6 = IN6ADDR_ANY_INIT;
127 // AI_PASSIVE means that the returned address will be a wildcard
128 // address suitable for binding and listening. This should not
129 // hit PPAPI at all, so we don't need fakes.
130 hints.ai_family = AF_INET;
131 hints.ai_flags = AI_PASSIVE;
132 hints.ai_socktype = SOCK_DGRAM;
133 ASSERT_EQ(0, ki_getaddrinfo(NULL, "22", &hints, &ai));
134 ASSERT_NE(NULL_INFO, ai);
135 ASSERT_NE(NULL_ADDR, ai->ai_addr);
136 ASSERT_EQ(NULL_INFO, ai->ai_next);
137 in = (struct sockaddr_in*)ai->ai_addr;
138 ASSERT_EQ(expected_addr, in->sin_addr.s_addr);
139 ASSERT_EQ(expected_port, in->sin_port);
140 ASSERT_EQ(AF_INET, in->sin_family);
143 // Same test with AF_INET6
144 hints.ai_family = AF_INET6;
145 ASSERT_EQ(0, ki_getaddrinfo(NULL, "22", &hints, &ai));
146 ASSERT_NE(NULL_INFO, ai);
147 ASSERT_NE(NULL_ADDR, ai->ai_addr);
148 ASSERT_EQ(NULL_INFO, ai->ai_next);
149 in6 = (struct sockaddr_in6*)ai->ai_addr;
150 ASSERT_EQ(expected_port, in6->sin6_port);
151 ASSERT_EQ(AF_INET6, in6->sin6_family);
152 ASSERT_EQ(0, memcmp(in6->sin6_addr.s6_addr,
154 sizeof(expected_addr6)));
158 TEST_F(HostResolverTest, Getaddrinfo_Passive_Any) {
159 // Similar to Getaddrinfo_Passive but don't set
160 // ai_family in the hints, so we should get muplitple
161 // results back for the different families.
162 struct addrinfo* ai = NULL;
163 struct sockaddr_in* in;
164 struct sockaddr_in6* in6;
165 struct addrinfo hints;
166 memset(&hints, 0, sizeof(hints));
168 uint32_t expected_port = htons(22);
169 in_addr_t expected_addr = htonl(INADDR_ANY);
170 in6_addr expected_addr6 = IN6ADDR_ANY_INIT;
172 hints.ai_flags = AI_PASSIVE;
173 hints.ai_socktype = SOCK_DGRAM;
174 ASSERT_EQ(0, ki_getaddrinfo(NULL, "22", &hints, &ai));
175 ASSERT_NE(NULL_INFO, ai);
180 ASSERT_NE(NULL_ADDR, ai->ai_addr);
181 switch (ai->ai_addr->sa_family) {
183 in = (struct sockaddr_in*)ai->ai_addr;
184 ASSERT_EQ(expected_port, in->sin_port);
185 ASSERT_EQ(AF_INET, in->sin_family);
186 ASSERT_EQ(expected_addr, in->sin_addr.s_addr);
190 in6 = (struct sockaddr_in6*)ai->ai_addr;
191 ASSERT_EQ(expected_port, in6->sin6_port);
192 ASSERT_EQ(AF_INET6, in6->sin6_family);
193 ASSERT_EQ(0, memcmp(in6->sin6_addr.s6_addr,
195 sizeof(expected_addr6)));
199 ASSERT_TRUE(false) << "Unknown address type: " << ai->ai_addr;
211 TEST_F(FakeHostResolverTest, Getaddrinfo_Lookup) {
212 struct addrinfo* ai = NULL;
213 struct sockaddr_in* in;
214 struct addrinfo hints;
215 memset(&hints, 0, sizeof(hints));
217 in_addr_t expected_addr = htonl(FAKE_IP);
219 // Lookup the fake hostname using getaddrinfo
220 hints.ai_family = AF_INET;
221 hints.ai_socktype = SOCK_STREAM;
222 ASSERT_EQ(0, ki_getaddrinfo(FAKE_HOSTNAME, NULL, &hints, &ai));
223 ASSERT_NE(NULL_INFO, ai);
224 ASSERT_NE(NULL_ADDR, ai->ai_addr);
225 ASSERT_EQ(AF_INET, ai->ai_family);
226 ASSERT_EQ(SOCK_STREAM, ai->ai_socktype);
227 in = (struct sockaddr_in*)ai->ai_addr;
228 ASSERT_EQ(expected_addr, in->sin_addr.s_addr);
229 ASSERT_EQ(NULL_INFO, ai->ai_next);
234 TEST_F(FakeHostResolverTest, Getaddrinfo_Multi) {
235 struct addrinfo* ai = NULL;
236 struct addrinfo hints;
237 memset(&hints, 0, sizeof(hints));
239 // Add four fake address on top of the initial one
240 // that the fixture creates.
241 AddFakeAddress(AF_INET);
242 AddFakeAddress(AF_INET);
243 AddFakeAddress(AF_INET6);
244 AddFakeAddress(AF_INET6);
246 hints.ai_socktype = SOCK_STREAM;
248 // First we test with AF_INET
249 hints.ai_family = AF_INET;
250 ASSERT_EQ(0, ki_getaddrinfo(FAKE_HOSTNAME, NULL, &hints, &ai));
251 ASSERT_NE(NULL_INFO, ai);
253 // We expect to be returned 3 AF_INET address with
254 // address FAKE_IP, FAKE_IP+1 and FAKE_IP+2, since that
255 // is that the fake was seeded with.
256 uint32_t expected_addr = htonl(FAKE_IP);
258 struct addrinfo* current = ai;
259 while (current != NULL) {
260 ASSERT_NE(NULL_ADDR, current->ai_addr);
261 ASSERT_EQ(AF_INET, current->ai_family);
262 ASSERT_EQ(SOCK_STREAM, current->ai_socktype);
263 sockaddr_in* in = (sockaddr_in*)current->ai_addr;
264 ASSERT_EQ(expected_addr, in->sin_addr.s_addr);
265 expected_addr += htonl(1);
266 current = current->ai_next;
272 // Same test but with AF_INET6
273 hints.ai_family = AF_INET6;
274 ASSERT_EQ(0, ki_getaddrinfo(FAKE_HOSTNAME, NULL, &hints, &ai));
275 ASSERT_NE(NULL_INFO, ai);
279 while (current != NULL) {
280 ASSERT_NE(NULL_ADDR, current->ai_addr);
281 ASSERT_EQ(AF_INET6, current->ai_family);
282 ASSERT_EQ(SOCK_STREAM, current->ai_socktype);
283 sockaddr_in6* in = (sockaddr_in6*)current->ai_addr;
284 for (int i = 0; i < 16; i++) {
285 ASSERT_EQ(i + count, in->sin6_addr.s6_addr[i]);
287 current = current->ai_next;
293 // Same test but with AF_UNSPEC. Here we expect to get
294 // 5 address back: 3 * v4 and 2 * v6.
295 hints.ai_family = AF_UNSPEC;
296 ASSERT_EQ(0, ki_getaddrinfo(FAKE_HOSTNAME, NULL, &hints, &ai));
297 ASSERT_NE(NULL_INFO, ai);
301 while (current != NULL) {
302 ASSERT_NE(NULL_ADDR, ai->ai_addr);
303 ASSERT_EQ(SOCK_STREAM, ai->ai_socktype);
304 current = current->ai_next;
312 TEST_F(FakeHostResolverTest, Gethostbyname) {
313 hostent* host = ki_gethostbyname(FAKE_HOSTNAME);
315 // Verify the returned hostent structure
316 ASSERT_NE(NULL_HOST, host);
317 ASSERT_EQ(AF_INET, host->h_addrtype);
318 ASSERT_EQ(sizeof(in_addr_t), host->h_length);
319 ASSERT_STREQ(FAKE_HOSTNAME, host->h_name);
321 in_addr_t** addr_list = reinterpret_cast<in_addr_t**>(host->h_addr_list);
322 ASSERT_NE(reinterpret_cast<in_addr_t**>(NULL), addr_list);
323 ASSERT_EQ(NULL, addr_list[1]);
324 in_addr_t exptected_addr = htonl(FAKE_IP);
325 ASSERT_EQ(exptected_addr, *addr_list[0]);
328 TEST_F(FakeHostResolverTest, Gethostbyname_Failure) {
329 hostent* host = ki_gethostbyname("nosuchhost.com");
330 ASSERT_EQ(NULL_HOST, host);
331 ASSERT_EQ(HOST_NOT_FOUND, h_errno);
334 // Looking up purely numeric hostnames should work without PPAPI
335 // so we don't need the fakes for this test
336 TEST_F(HostResolverTest, Gethostbyname_Numeric) {
337 struct hostent* host = ki_gethostbyname("8.8.8.8");
339 // Verify the returned hostent structure
340 ASSERT_NE(NULL_HOST, host);
341 ASSERT_EQ(AF_INET, host->h_addrtype);
342 ASSERT_EQ(sizeof(in_addr_t), host->h_length);
343 ASSERT_STREQ("8.8.8.8", host->h_name);
345 in_addr_t** addr_list = reinterpret_cast<in_addr_t**>(host->h_addr_list);
346 ASSERT_NE(reinterpret_cast<in_addr_t**>(NULL), addr_list);
347 ASSERT_EQ(NULL, addr_list[1]);
348 ASSERT_EQ(inet_addr("8.8.8.8"), *addr_list[0]);
351 // These utility functions are only used for newlib (glibc provides its own
352 // implementations of these functions).
353 #if !defined(__GLIBC__)
355 TEST(SocketUtilityFunctions, Hstrerror) {
356 EXPECT_STREQ("Unknown error in gethostbyname: 2718.", hstrerror(2718));
359 TEST(SocketUtilityFunctions, Gai_Strerror) {
360 EXPECT_STREQ("Unknown error in getaddrinfo: 2719.", gai_strerror(2719));
363 #endif // !defined(__GLIBC__)