host_resolver_test.cc revision 010d83a9304c5a91596085d917d248abff47903a
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  // Numberic 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_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));
114}
115
116TEST_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));
122
123  uint32_t expected_port = htons(22);
124  in_addr_t expected_addr = htonl(INADDR_ANY);
125  in6_addr expected_addr6 = IN6ADDR_ANY_INIT;
126
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);
141  ki_freeaddrinfo(ai);
142
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,
153               &expected_addr6,
154               sizeof(expected_addr6)));
155  ki_freeaddrinfo(ai);
156}
157
158TEST_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));
167
168  uint32_t expected_port = htons(22);
169  in_addr_t expected_addr = htonl(INADDR_ANY);
170  in6_addr expected_addr6 = IN6ADDR_ANY_INIT;
171
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);
176  int count = 0;
177  bool got_v4 = false;
178  bool got_v6 = false;
179  while (ai) {
180    ASSERT_NE(NULL_ADDR, ai->ai_addr);
181    switch (ai->ai_addr->sa_family) {
182      case AF_INET:
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);
187        got_v4 = true;
188        break;
189      case AF_INET6:
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,
194                            &expected_addr6,
195                            sizeof(expected_addr6)));
196        got_v6 = true;
197        break;
198      default:
199        ASSERT_TRUE(false) << "Unknown address type: " << ai->ai_addr;
200        break;
201    }
202    ai = ai->ai_next;
203    count++;
204  }
205
206  ASSERT_EQ(2, count);
207  ASSERT_TRUE(got_v4);
208  ASSERT_TRUE(got_v6);
209}
210
211TEST_F(FakeHostResolverTest, Getaddrinfo_Lookup) {
212  struct addrinfo* ai = NULL;
213  struct sockaddr_in* in;
214  struct addrinfo hints;
215  memset(&hints, 0, sizeof(hints));
216
217  in_addr_t expected_addr = htonl(FAKE_IP);
218
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);
230
231  ki_freeaddrinfo(ai);
232}
233
234TEST_F(FakeHostResolverTest, Getaddrinfo_Multi) {
235  struct addrinfo* ai = NULL;
236  struct addrinfo hints;
237  memset(&hints, 0, sizeof(hints));
238
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);
245
246  hints.ai_socktype = SOCK_STREAM;
247
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);
252
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);
257  int count = 0;
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;
267    count++;
268  }
269  ASSERT_EQ(3, count);
270  ki_freeaddrinfo(ai);
271
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);
276
277  count = 0;
278  current = 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]);
286    }
287    current = current->ai_next;
288    count++;
289  }
290  ASSERT_EQ(2, count);
291  ki_freeaddrinfo(ai);
292
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);
298
299  count = 0;
300  current = 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;
305    count++;
306  }
307  ASSERT_EQ(5, count);
308
309  ki_freeaddrinfo(ai);
310}
311
312TEST_F(FakeHostResolverTest, Gethostbyname) {
313  hostent* host = ki_gethostbyname(FAKE_HOSTNAME);
314
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);
320
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]);
326}
327
328TEST_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);
332}
333
334// Looking up purely numeric hostnames should work without PPAPI
335// so we don't need the fakes for this test
336TEST_F(HostResolverTest, Gethostbyname_Numeric) {
337  struct hostent* host = ki_gethostbyname("8.8.8.8");
338
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);
344
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]);
349}
350
351// These utility functions are only used for newlib (glibc provides its own
352// implementations of these functions).
353#if !defined(__GLIBC__)
354
355TEST(SocketUtilityFunctions, Hstrerror) {
356  EXPECT_STREQ("Unknown error in gethostbyname: 2718.", hstrerror(2718));
357}
358
359TEST(SocketUtilityFunctions, Gai_Strerror) {
360  EXPECT_STREQ("Unknown error in getaddrinfo: 2719.", gai_strerror(2719));
361}
362
363#endif  // !defined(__GLIBC__)
364