OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <arpa/inet.h> | 5 #include <arpa/inet.h> |
6 #include <netinet/in.h> | 6 #include <netinet/in.h> |
7 #include <sys/types.h> | 7 #include <sys/types.h> |
8 #include <sys/socket.h> | 8 #include <sys/socket.h> |
9 | 9 |
10 #include "fake_ppapi/fake_pepper_interface.h" | 10 #include "fake_ppapi/fake_pepper_interface.h" |
11 #include "gtest/gtest.h" | 11 #include "gtest/gtest.h" |
12 #include "nacl_io/kernel_intercept.h" | 12 #include "nacl_io/kernel_intercept.h" |
13 | 13 |
14 using namespace nacl_io; | 14 using namespace nacl_io; |
15 using namespace sdk_util; | 15 using namespace sdk_util; |
16 | 16 |
17 namespace { | 17 namespace { |
18 | 18 |
19 class HostResolverTest : public ::testing::Test { | 19 class HostResolverTest : public ::testing::Test { |
20 public: | 20 public: |
21 HostResolverTest() : pepper_(NULL) {} | 21 HostResolverTest() {} |
| 22 |
| 23 void SetUp() { |
| 24 ki_init(NULL); |
| 25 } |
| 26 |
| 27 void TearDown() { |
| 28 ki_uninit(); |
| 29 } |
| 30 }; |
| 31 |
| 32 #define FAKE_HOSTNAME "example.com" |
| 33 #define FAKE_IP 0x01020304 |
| 34 |
| 35 class FakeHostResolverTest : public ::testing::Test { |
| 36 public: |
| 37 FakeHostResolverTest() : pepper_(NULL), fake_resolver_(NULL) {} |
22 | 38 |
23 void SetUp() { | 39 void SetUp() { |
24 pepper_ = new FakePepperInterface(); | 40 pepper_ = new FakePepperInterface(); |
| 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 |
25 ki_init_interface(NULL, pepper_); | 48 ki_init_interface(NULL, pepper_); |
26 } | 49 } |
27 | 50 |
| 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; |
| 66 } |
| 67 fake_resolver_->fake_addresses_v6.push_back(fake_addr); |
| 68 } |
| 69 } |
| 70 |
28 void TearDown() { | 71 void TearDown() { |
29 ki_uninit(); | 72 ki_uninit(); |
30 pepper_ = NULL; | 73 pepper_ = NULL; |
31 } | 74 } |
32 | 75 |
33 protected: | 76 protected: |
34 FakePepperInterface* pepper_; | 77 FakePepperInterface* pepper_; |
| 78 FakeHostResolverInterface* fake_resolver_; |
35 }; | 79 }; |
36 | 80 |
37 } // namespace | 81 } // namespace |
38 | 82 |
| 83 #define NULL_INFO ((struct addrinfo*)NULL) |
| 84 #define NULL_ADDR ((struct sockaddr*)NULL) |
39 #define NULL_HOST (static_cast<hostent*>(NULL)) | 85 #define NULL_HOST (static_cast<hostent*>(NULL)) |
40 | 86 |
41 TEST_F(HostResolverTest, GethostbynameNumeric) { | 87 TEST_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 |
| 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)); |
| 114 } |
| 115 |
| 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)); |
| 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 |
| 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)); |
| 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 |
| 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)); |
| 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 |
| 234 TEST_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 |
| 312 TEST_F(FakeHostResolverTest, Gethostbyname) { |
42 hostent* host = ki_gethostbyname(FAKE_HOSTNAME); | 313 hostent* host = ki_gethostbyname(FAKE_HOSTNAME); |
43 | 314 |
44 // Verify the returned hostent structure | 315 // Verify the returned hostent structure |
45 ASSERT_NE(NULL_HOST, host); | 316 ASSERT_NE(NULL_HOST, host); |
46 ASSERT_EQ(AF_INET, host->h_addrtype); | 317 ASSERT_EQ(AF_INET, host->h_addrtype); |
47 ASSERT_EQ(sizeof(in_addr_t), host->h_length); | 318 ASSERT_EQ(sizeof(in_addr_t), host->h_length); |
48 ASSERT_STREQ(FAKE_HOSTNAME, host->h_name); | 319 ASSERT_STREQ(FAKE_HOSTNAME, host->h_name); |
49 | 320 |
50 in_addr_t** addr_list = reinterpret_cast<in_addr_t**>(host->h_addr_list); | 321 in_addr_t** addr_list = reinterpret_cast<in_addr_t**>(host->h_addr_list); |
51 ASSERT_NE(reinterpret_cast<in_addr_t**>(NULL), addr_list); | 322 ASSERT_NE(reinterpret_cast<in_addr_t**>(NULL), addr_list); |
52 ASSERT_EQ(NULL, addr_list[1]); | 323 ASSERT_EQ(NULL, addr_list[1]); |
53 in_addr_t exptected_addr = htonl(FAKE_IP); | 324 in_addr_t exptected_addr = htonl(FAKE_IP); |
54 ASSERT_EQ(exptected_addr, *addr_list[0]); | 325 ASSERT_EQ(exptected_addr, *addr_list[0]); |
55 } | 326 } |
| 327 |
| 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); |
| 332 } |
| 333 |
| 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"); |
| 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 |
| 355 TEST(SocketUtilityFunctions, Hstrerror) { |
| 356 EXPECT_STREQ("Unknown error in gethostbyname: 2718.", hstrerror(2718)); |
| 357 } |
| 358 |
| 359 TEST(SocketUtilityFunctions, Gai_Strerror) { |
| 360 EXPECT_STREQ("Unknown error in getaddrinfo: 2719.", gai_strerror(2719)); |
| 361 } |
| 362 |
| 363 #endif // !defined(__GLIBC__) |
OLD | NEW |