Home | History | Annotate | Download | only in nacl_io_test
      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 
     14 using namespace nacl_io;
     15 using namespace sdk_util;
     16 
     17 namespace {
     18 
     19 class 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 
     36 class 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 
     87 TEST_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 
    110 TEST_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 
    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));
    142 }
    143 
    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));
    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 
    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));
    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 
    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));
    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 
    266 TEST_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 
    344 TEST_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 
    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);
    368 }
    369 
    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");
    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 
    395 TEST(SocketUtilityFunctions, Hstrerror) {
    396   EXPECT_STREQ("Unknown error in gethostbyname: 2718.", hstrerror(2718));
    397 }
    398 
    399 TEST(SocketUtilityFunctions, Gai_Strerror) {
    400   EXPECT_STREQ("Unknown error in getaddrinfo: 2719.", gai_strerror(2719));
    401 }
    402 
    403 #endif  // !defined(__GLIBC__)
    404