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.
4
5#include <arpa/inet.h>
6#include <netinet/in.h>
7#include <sys/types.h>
8#include <sys/socket.h>
9
10#include "fake_ppapi/fake_pepper_interface.h"
11#include "gtest/gtest.h"
12#include "nacl_io/kernel_intercept.h"
13
14using namespace nacl_io;
15using namespace sdk_util;
16
17namespace {
18
19class HostResolverTest : public ::testing::Test {
20 public:
21  HostResolverTest() {}
22
23  void SetUp() {
24    ASSERT_EQ(0, ki_push_state_for_testing());
25    ASSERT_EQ(0, ki_init(NULL));
26  }
27
28  void TearDown() {
29    ki_uninit();
30  }
31};
32
33#define FAKE_HOSTNAME "example.com"
34#define FAKE_IP 0x01020304
35
36class FakeHostResolverTest : public ::testing::Test {
37 public:
38  FakeHostResolverTest() : fake_resolver_(NULL) {}
39
40  void SetUp() {
41    fake_resolver_ = static_cast<FakeHostResolverInterface*>(
42        pepper_.GetHostResolverInterface());
43
44    // Seed the fake resolver with some data
45    fake_resolver_->fake_hostname = FAKE_HOSTNAME;
46    AddFakeAddress(AF_INET);
47
48    ASSERT_EQ(0, ki_push_state_for_testing());
49    ASSERT_EQ(0, ki_init_interface(NULL, &pepper_));
50  }
51
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;
67      }
68      fake_resolver_->fake_addresses_v6.push_back(fake_addr);
69    }
70  }
71
72  void TearDown() {
73    ki_uninit();
74  }
75
76 protected:
77  FakePepperInterface pepper_;
78  FakeHostResolverInterface* fake_resolver_;
79};
80
81}  // namespace
82
83#define NULL_INFO ((struct addrinfo*)NULL)
84#define NULL_ADDR ((struct sockaddr*)NULL)
85#define NULL_HOST (static_cast<hostent*>(NULL))
86
87TEST_F(HostResolverTest, Getaddrinfo_Numeric) {
88  struct addrinfo* ai = NULL;
89  struct sockaddr_in* in;
90  struct addrinfo hints;
91
92  // Numeric only
93  memset(&hints, 0, sizeof(hints));
94  hints.ai_family = AF_INET;
95  hints.ai_socktype = SOCK_STREAM;
96
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);
106
107  ki_freeaddrinfo(ai);
108}
109
110TEST_F(HostResolverTest, Getaddrinfo_NumericService) {
111  struct addrinfo* ai = NULL;
112  struct sockaddr_in* in;
113  struct addrinfo hints;
114
115  memset(&hints, 0, sizeof(hints));
116  hints.ai_family = AF_INET;
117  hints.ai_socktype = SOCK_STREAM;
118
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);
126  ki_freeaddrinfo(ai);
127
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);
135  ki_freeaddrinfo(ai);
136}
137
138TEST_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));
142}
143
144TEST_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));
150
151  uint32_t expected_port = htons(22);
152  in_addr_t expected_addr = htonl(INADDR_ANY);
153  in6_addr expected_addr6 = IN6ADDR_ANY_INIT;
154
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);
169  ki_freeaddrinfo(ai);
170
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,
181               &expected_addr6,
182               sizeof(expected_addr6)));
183  ki_freeaddrinfo(ai);
184}
185
186TEST_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));
196
197  uint32_t expected_port = htons(22);
198  in_addr_t expected_addr = htonl(INADDR_ANY);
199  in6_addr expected_addr6 = IN6ADDR_ANY_INIT;
200
201  hints.ai_flags = AI_PASSIVE;
202  hints.ai_socktype = SOCK_DGRAM;
203  ASSERT_EQ(0, ki_getaddrinfo(NULL, "22", &hints, &ai));
204  ai_orig = ai;
205  ASSERT_NE(NULL_INFO, ai);
206  int count = 0;
207  bool got_v4 = false;
208  bool got_v6 = false;
209  while (ai) {
210    ASSERT_NE(NULL_ADDR, ai->ai_addr);
211    switch (ai->ai_addr->sa_family) {
212      case AF_INET:
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);
217        got_v4 = true;
218        break;
219      case AF_INET6:
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,
224                            &expected_addr6,
225                            sizeof(expected_addr6)));
226        got_v6 = true;
227        break;
228      default:
229        ASSERT_TRUE(false) << "Unknown address type: " << ai->ai_addr;
230        break;
231    }
232    ai = ai->ai_next;
233    count++;
234  }
235
236  ASSERT_EQ(2, count);
237  ASSERT_TRUE(got_v4);
238  ASSERT_TRUE(got_v6);
239
240  ki_freeaddrinfo(ai_orig);
241}
242
243TEST_F(FakeHostResolverTest, Getaddrinfo_Lookup) {
244  struct addrinfo* ai = NULL;
245  struct sockaddr_in* in;
246  struct addrinfo hints;
247  memset(&hints, 0, sizeof(hints));
248
249  in_addr_t expected_addr = htonl(FAKE_IP);
250
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);
262
263  ki_freeaddrinfo(ai);
264}
265
266TEST_F(FakeHostResolverTest, Getaddrinfo_Multi) {
267  struct addrinfo* ai = NULL;
268  struct addrinfo hints;
269  memset(&hints, 0, sizeof(hints));
270
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);
277
278  hints.ai_socktype = SOCK_STREAM;
279
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);
284
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);
289  int count = 0;
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;
299    count++;
300  }
301  ASSERT_EQ(3, count);
302  ki_freeaddrinfo(ai);
303
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);
308
309  count = 0;
310  current = 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]);
318    }
319    current = current->ai_next;
320    count++;
321  }
322  ASSERT_EQ(2, count);
323  ki_freeaddrinfo(ai);
324
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);
330
331  count = 0;
332  current = 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;
337    count++;
338  }
339  ASSERT_EQ(5, count);
340
341  ki_freeaddrinfo(ai);
342}
343
344TEST_F(FakeHostResolverTest, Gethostbyname) {
345  hostent* host = ki_gethostbyname(FAKE_HOSTNAME);
346
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);
352
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
359  // member.
360  in_addr_t* first_addr = reinterpret_cast<in_addr_t*>(host->h_addr);
361  ASSERT_EQ(expected_addr, *first_addr);
362}
363
364TEST_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);
368}
369
370// Looking up purely numeric hostnames should work without PPAPI
371// so we don't need the fakes for this test
372TEST_F(HostResolverTest, Gethostbyname_Numeric) {
373  struct hostent* host = ki_gethostbyname("8.8.8.8");
374
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);
380
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
386  // member.
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);
389}
390
391// These utility functions are only used for newlib (glibc provides its own
392// implementations of these functions).
393#if !defined(__GLIBC__)
394
395TEST(SocketUtilityFunctions, Hstrerror) {
396  EXPECT_STREQ("Unknown error in gethostbyname: 2718.", hstrerror(2718));
397}
398
399TEST(SocketUtilityFunctions, Gai_Strerror) {
400  EXPECT_STREQ("Unknown error in getaddrinfo: 2719.", gai_strerror(2719));
401}
402
403#endif  // !defined(__GLIBC__)
404