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