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
{
24 ASSERT_EQ(0, ki_push_state_for_testing());
25 ASSERT_EQ(0, ki_init(NULL
));
33 #define FAKE_HOSTNAME "example.com"
34 #define FAKE_IP 0x01020304
36 class FakeHostResolverTest
: public ::testing::Test
{
38 FakeHostResolverTest() : fake_resolver_(NULL
) {}
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 ASSERT_EQ(0, ki_push_state_for_testing());
49 ASSERT_EQ(0, ki_init_interface(NULL
, &pepper_
));
52 void AddFakeAddress(int family
) {
53 if (family
== AF_INET
) {
54 int address_count
= fake_resolver_
->fake_addresses_v4
.size();
55 // Each new address we add is FAKE_IP incremented by 1
56 // each time to be unique.
57 sockaddr_in fake_addr
;
58 fake_addr
.sin_family
= family
;
59 fake_addr
.sin_addr
.s_addr
= htonl(FAKE_IP
+ address_count
);
60 fake_resolver_
->fake_addresses_v4
.push_back(fake_addr
);
61 } else if (family
== AF_INET6
) {
62 sockaddr_in6 fake_addr
;
63 fake_addr
.sin6_family
= family
;
64 int address_count
= fake_resolver_
->fake_addresses_v6
.size();
65 for (uint8_t i
= 0; i
< 16; i
++) {
66 fake_addr
.sin6_addr
.s6_addr
[i
] = i
+ address_count
;
68 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_NumericService
) {
111 struct addrinfo
* ai
= NULL
;
112 struct sockaddr_in
* in
;
113 struct addrinfo hints
;
115 memset(&hints
, 0, sizeof(hints
));
116 hints
.ai_family
= AF_INET
;
117 hints
.ai_socktype
= SOCK_STREAM
;
119 ASSERT_EQ(0, ki_getaddrinfo("1.2.3.4", "0", &hints
, &ai
));
120 ASSERT_NE(NULL_INFO
, ai
);
121 ASSERT_NE(NULL_ADDR
, ai
->ai_addr
);
122 in
= (struct sockaddr_in
*)ai
->ai_addr
;
123 uint16_t expected_port
= htons(0);
124 ASSERT_EQ(expected_port
, in
->sin_port
);
125 ASSERT_EQ(NULL_INFO
, ai
->ai_next
);
128 ASSERT_EQ(0, ki_getaddrinfo("1.2.3.4", "65000", &hints
, &ai
));
129 ASSERT_NE(NULL_INFO
, ai
);
130 ASSERT_NE(NULL_ADDR
, ai
->ai_addr
);
131 in
= (struct sockaddr_in
*)ai
->ai_addr
;
132 expected_port
= htons(65000);
133 ASSERT_EQ(expected_port
, in
->sin_port
);
134 ASSERT_EQ(NULL_INFO
, ai
->ai_next
);
138 TEST_F(HostResolverTest
, Getaddrinfo_MissingPPAPI
) {
139 // Verify that full lookups fail due to lack of PPAPI interfaces
140 struct addrinfo
* ai
= NULL
;
141 ASSERT_EQ(EAI_SYSTEM
, ki_getaddrinfo("google.com", NULL
, NULL
, &ai
));
144 TEST_F(HostResolverTest
, Getaddrinfo_Passive
) {
145 struct addrinfo
* ai
= NULL
;
146 struct sockaddr_in
* in
;
147 struct sockaddr_in6
* in6
;
148 struct addrinfo hints
;
149 memset(&hints
, 0, sizeof(hints
));
151 uint32_t expected_port
= htons(22);
152 in_addr_t expected_addr
= htonl(INADDR_ANY
);
153 in6_addr expected_addr6
= IN6ADDR_ANY_INIT
;
155 // AI_PASSIVE means that the returned address will be a wildcard
156 // address suitable for binding and listening. This should not
157 // hit PPAPI at all, so we don't need fakes.
158 hints
.ai_family
= AF_INET
;
159 hints
.ai_flags
= AI_PASSIVE
;
160 hints
.ai_socktype
= SOCK_DGRAM
;
161 ASSERT_EQ(0, ki_getaddrinfo(NULL
, "22", &hints
, &ai
));
162 ASSERT_NE(NULL_INFO
, ai
);
163 ASSERT_NE(NULL_ADDR
, ai
->ai_addr
);
164 ASSERT_EQ(NULL_INFO
, ai
->ai_next
);
165 in
= (struct sockaddr_in
*)ai
->ai_addr
;
166 ASSERT_EQ(expected_addr
, in
->sin_addr
.s_addr
);
167 ASSERT_EQ(expected_port
, in
->sin_port
);
168 ASSERT_EQ(AF_INET
, in
->sin_family
);
171 // Same test with AF_INET6
172 hints
.ai_family
= AF_INET6
;
173 ASSERT_EQ(0, ki_getaddrinfo(NULL
, "22", &hints
, &ai
));
174 ASSERT_NE(NULL_INFO
, ai
);
175 ASSERT_NE(NULL_ADDR
, ai
->ai_addr
);
176 ASSERT_EQ(NULL_INFO
, ai
->ai_next
);
177 in6
= (struct sockaddr_in6
*)ai
->ai_addr
;
178 ASSERT_EQ(expected_port
, in6
->sin6_port
);
179 ASSERT_EQ(AF_INET6
, in6
->sin6_family
);
180 ASSERT_EQ(0, memcmp(in6
->sin6_addr
.s6_addr
,
182 sizeof(expected_addr6
)));
186 TEST_F(HostResolverTest
, Getaddrinfo_Passive_Any
) {
187 // Similar to Getaddrinfo_Passive but don't set
188 // ai_family in the hints, so we should get muplitple
189 // results back for the different families.
190 struct addrinfo
* ai
= NULL
;
191 struct addrinfo
* ai_orig
= NULL
;
192 struct sockaddr_in
* in
;
193 struct sockaddr_in6
* in6
;
194 struct addrinfo hints
;
195 memset(&hints
, 0, sizeof(hints
));
197 uint32_t expected_port
= htons(22);
198 in_addr_t expected_addr
= htonl(INADDR_ANY
);
199 in6_addr expected_addr6
= IN6ADDR_ANY_INIT
;
201 hints
.ai_flags
= AI_PASSIVE
;
202 hints
.ai_socktype
= SOCK_DGRAM
;
203 ASSERT_EQ(0, ki_getaddrinfo(NULL
, "22", &hints
, &ai
));
205 ASSERT_NE(NULL_INFO
, ai
);
210 ASSERT_NE(NULL_ADDR
, ai
->ai_addr
);
211 switch (ai
->ai_addr
->sa_family
) {
213 in
= (struct sockaddr_in
*)ai
->ai_addr
;
214 ASSERT_EQ(expected_port
, in
->sin_port
);
215 ASSERT_EQ(AF_INET
, in
->sin_family
);
216 ASSERT_EQ(expected_addr
, in
->sin_addr
.s_addr
);
220 in6
= (struct sockaddr_in6
*)ai
->ai_addr
;
221 ASSERT_EQ(expected_port
, in6
->sin6_port
);
222 ASSERT_EQ(AF_INET6
, in6
->sin6_family
);
223 ASSERT_EQ(0, memcmp(in6
->sin6_addr
.s6_addr
,
225 sizeof(expected_addr6
)));
229 ASSERT_TRUE(false) << "Unknown address type: " << ai
->ai_addr
;
240 ki_freeaddrinfo(ai_orig
);
243 TEST_F(FakeHostResolverTest
, Getaddrinfo_Lookup
) {
244 struct addrinfo
* ai
= NULL
;
245 struct sockaddr_in
* in
;
246 struct addrinfo hints
;
247 memset(&hints
, 0, sizeof(hints
));
249 in_addr_t expected_addr
= htonl(FAKE_IP
);
251 // Lookup the fake hostname using getaddrinfo
252 hints
.ai_family
= AF_INET
;
253 hints
.ai_socktype
= SOCK_STREAM
;
254 ASSERT_EQ(0, ki_getaddrinfo(FAKE_HOSTNAME
, NULL
, &hints
, &ai
));
255 ASSERT_NE(NULL_INFO
, ai
);
256 ASSERT_NE(NULL_ADDR
, ai
->ai_addr
);
257 ASSERT_EQ(AF_INET
, ai
->ai_family
);
258 ASSERT_EQ(SOCK_STREAM
, ai
->ai_socktype
);
259 in
= (struct sockaddr_in
*)ai
->ai_addr
;
260 ASSERT_EQ(expected_addr
, in
->sin_addr
.s_addr
);
261 ASSERT_EQ(NULL_INFO
, ai
->ai_next
);
266 TEST_F(FakeHostResolverTest
, Getaddrinfo_Multi
) {
267 struct addrinfo
* ai
= NULL
;
268 struct addrinfo hints
;
269 memset(&hints
, 0, sizeof(hints
));
271 // Add four fake address on top of the initial one
272 // that the fixture creates.
273 AddFakeAddress(AF_INET
);
274 AddFakeAddress(AF_INET
);
275 AddFakeAddress(AF_INET6
);
276 AddFakeAddress(AF_INET6
);
278 hints
.ai_socktype
= SOCK_STREAM
;
280 // First we test with AF_INET
281 hints
.ai_family
= AF_INET
;
282 ASSERT_EQ(0, ki_getaddrinfo(FAKE_HOSTNAME
, NULL
, &hints
, &ai
));
283 ASSERT_NE(NULL_INFO
, ai
);
285 // We expect to be returned 3 AF_INET address with
286 // address FAKE_IP, FAKE_IP+1 and FAKE_IP+2, since that
287 // is that the fake was seeded with.
288 uint32_t expected_addr
= htonl(FAKE_IP
);
290 struct addrinfo
* current
= ai
;
291 while (current
!= NULL
) {
292 ASSERT_NE(NULL_ADDR
, current
->ai_addr
);
293 ASSERT_EQ(AF_INET
, current
->ai_family
);
294 ASSERT_EQ(SOCK_STREAM
, current
->ai_socktype
);
295 sockaddr_in
* in
= (sockaddr_in
*)current
->ai_addr
;
296 ASSERT_EQ(expected_addr
, in
->sin_addr
.s_addr
);
297 expected_addr
+= htonl(1);
298 current
= current
->ai_next
;
304 // Same test but with AF_INET6
305 hints
.ai_family
= AF_INET6
;
306 ASSERT_EQ(0, ki_getaddrinfo(FAKE_HOSTNAME
, NULL
, &hints
, &ai
));
307 ASSERT_NE(NULL_INFO
, ai
);
311 while (current
!= NULL
) {
312 ASSERT_NE(NULL_ADDR
, current
->ai_addr
);
313 ASSERT_EQ(AF_INET6
, current
->ai_family
);
314 ASSERT_EQ(SOCK_STREAM
, current
->ai_socktype
);
315 sockaddr_in6
* in
= (sockaddr_in6
*)current
->ai_addr
;
316 for (int i
= 0; i
< 16; i
++) {
317 ASSERT_EQ(i
+ count
, in
->sin6_addr
.s6_addr
[i
]);
319 current
= current
->ai_next
;
325 // Same test but with AF_UNSPEC. Here we expect to get
326 // 5 address back: 3 * v4 and 2 * v6.
327 hints
.ai_family
= AF_UNSPEC
;
328 ASSERT_EQ(0, ki_getaddrinfo(FAKE_HOSTNAME
, NULL
, &hints
, &ai
));
329 ASSERT_NE(NULL_INFO
, ai
);
333 while (current
!= NULL
) {
334 ASSERT_NE(NULL_ADDR
, ai
->ai_addr
);
335 ASSERT_EQ(SOCK_STREAM
, ai
->ai_socktype
);
336 current
= current
->ai_next
;
344 TEST_F(FakeHostResolverTest
, Gethostbyname
) {
345 hostent
* host
= ki_gethostbyname(FAKE_HOSTNAME
);
347 // Verify the returned hostent structure
348 ASSERT_NE(NULL_HOST
, host
);
349 ASSERT_EQ(AF_INET
, host
->h_addrtype
);
350 ASSERT_EQ(sizeof(in_addr_t
), host
->h_length
);
351 ASSERT_STREQ(FAKE_HOSTNAME
, host
->h_name
);
353 in_addr_t
** addr_list
= reinterpret_cast<in_addr_t
**>(host
->h_addr_list
);
354 ASSERT_NE(reinterpret_cast<in_addr_t
**>(NULL
), addr_list
);
355 ASSERT_EQ(NULL
, addr_list
[1]);
356 in_addr_t expected_addr
= htonl(FAKE_IP
);
357 ASSERT_EQ(expected_addr
, *addr_list
[0]);
358 // Check that h_addr also matches as in some libc's it may be a separate
360 in_addr_t
* first_addr
= reinterpret_cast<in_addr_t
*>(host
->h_addr
);
361 ASSERT_EQ(expected_addr
, *first_addr
);
364 TEST_F(FakeHostResolverTest
, Gethostbyname_Failure
) {
365 hostent
* host
= ki_gethostbyname("nosuchhost.com");
366 ASSERT_EQ(NULL_HOST
, host
);
367 ASSERT_EQ(HOST_NOT_FOUND
, h_errno
);
370 // Looking up purely numeric hostnames should work without PPAPI
371 // so we don't need the fakes for this test
372 TEST_F(HostResolverTest
, Gethostbyname_Numeric
) {
373 struct hostent
* host
= ki_gethostbyname("8.8.8.8");
375 // Verify the returned hostent structure
376 ASSERT_NE(NULL_HOST
, host
);
377 ASSERT_EQ(AF_INET
, host
->h_addrtype
);
378 ASSERT_EQ(sizeof(in_addr_t
), host
->h_length
);
379 ASSERT_STREQ("8.8.8.8", host
->h_name
);
381 in_addr_t
** addr_list
= reinterpret_cast<in_addr_t
**>(host
->h_addr_list
);
382 ASSERT_NE(reinterpret_cast<in_addr_t
**>(NULL
), addr_list
);
383 ASSERT_EQ(NULL
, addr_list
[1]);
384 ASSERT_EQ(inet_addr("8.8.8.8"), *addr_list
[0]);
385 // Check that h_addr also matches as in some libc's it may be a separate
387 in_addr_t
* first_addr
= reinterpret_cast<in_addr_t
*>(host
->h_addr
);
388 ASSERT_EQ(inet_addr("8.8.8.8"), *first_addr
);
391 // These utility functions are only used for newlib (glibc provides its own
392 // implementations of these functions).
393 #if !defined(__GLIBC__)
395 TEST(SocketUtilityFunctions
, Hstrerror
) {
396 EXPECT_STREQ("Unknown error in gethostbyname: 2718.", hstrerror(2718));
399 TEST(SocketUtilityFunctions
, Gai_Strerror
) {
400 EXPECT_STREQ("Unknown error in getaddrinfo: 2719.", gai_strerror(2719));
403 #endif // !defined(__GLIBC__)