| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/base/network_interfaces_getifaddrs.h" |
| |
| #include <string> |
| |
| #include "starboard/types.h" |
| |
| #include "build/build_config.h" |
| #include "net/base/ip_endpoint.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| #include <ifaddrs.h> |
| #include <net/if.h> |
| #include <netinet/in.h> |
| |
| // Starboard platforms do not have socklen_t defined. |
| #if !defined(STARBOARD) |
| |
| namespace net { |
| namespace { |
| |
| class IPAttributesGetterTest : public internal::IPAttributesGetter { |
| public: |
| IPAttributesGetterTest() {} |
| |
| // internal::IPAttributesGetter interface. |
| bool IsInitialized() const override { return true; } |
| bool GetAddressAttributes(const ifaddrs* if_addr, int* attributes) override { |
| *attributes = attributes_; |
| return true; |
| } |
| NetworkChangeNotifier::ConnectionType GetNetworkInterfaceType( |
| const ifaddrs* if_addr) override { |
| return NetworkChangeNotifier::CONNECTION_UNKNOWN; |
| } |
| |
| void set_attributes(int attributes) { attributes_ = attributes; } |
| |
| private: |
| int attributes_ = 0; |
| }; |
| |
| // Helper function to create a single valid ifaddrs |
| bool FillIfaddrs(ifaddrs* interfaces, |
| const char* ifname, |
| uint flags, |
| const IPAddress& ip_address, |
| const IPAddress& ip_netmask, |
| sockaddr_storage sock_addrs[2]) { |
| interfaces->ifa_next = nullptr; |
| interfaces->ifa_name = const_cast<char*>(ifname); |
| interfaces->ifa_flags = flags; |
| |
| socklen_t sock_len = sizeof(sockaddr_storage); |
| |
| // Convert to sockaddr for next check. |
| if (!IPEndPoint(ip_address, 0) |
| .ToSockAddr(reinterpret_cast<sockaddr*>(&sock_addrs[0]), |
| &sock_len)) { |
| return false; |
| } |
| interfaces->ifa_addr = reinterpret_cast<sockaddr*>(&sock_addrs[0]); |
| |
| sock_len = sizeof(sockaddr_storage); |
| if (!IPEndPoint(ip_netmask, 0) |
| .ToSockAddr(reinterpret_cast<sockaddr*>(&sock_addrs[1]), |
| &sock_len)) { |
| return false; |
| } |
| interfaces->ifa_netmask = reinterpret_cast<sockaddr*>(&sock_addrs[1]); |
| |
| return true; |
| } |
| |
| static const char kIfnameEm1[] = "em1"; |
| static const char kIfnameVmnet[] = "vmnet"; |
| |
| static const unsigned char kIPv6LocalAddr[] = {0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 1}; |
| |
| // The following 3 addresses need to be changed together. IPv6Addr is the IPv6 |
| // address. IPv6Netmask is the mask address with as many leading bits set to 1 |
| // as the prefix length. IPv6AddrPrefix needs to match IPv6Addr with the same |
| // number of bits as the prefix length. |
| static const unsigned char kIPv6Addr[] = {0x24, 0x01, 0xfa, 0x00, 0x00, 0x04, |
| 0x10, 0x00, 0xbe, 0x30, 0x5b, 0xff, |
| 0xfe, 0xe5, 0x00, 0xc3}; |
| |
| static const unsigned char kIPv6Netmask[] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00}; |
| |
| TEST(NetworkInterfacesTest, IfaddrsToNetworkInterfaceList) { |
| IPAddress ipv6_local_address(kIPv6LocalAddr); |
| IPAddress ipv6_address(kIPv6Addr); |
| IPAddress ipv6_netmask(kIPv6Netmask); |
| |
| NetworkInterfaceList results; |
| IPAttributesGetterTest ip_attributes_getter; |
| sockaddr_storage addresses[2]; |
| ifaddrs interface; |
| |
| // Address of offline links should be ignored. |
| ASSERT_TRUE(FillIfaddrs(&interface, kIfnameEm1, IFF_UP, ipv6_address, |
| ipv6_netmask, addresses)); |
| EXPECT_TRUE(internal::IfaddrsToNetworkInterfaceList( |
| INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &interface, &ip_attributes_getter, |
| &results)); |
| EXPECT_EQ(results.size(), 0ul); |
| |
| // Local address should be trimmed out. |
| ASSERT_TRUE(FillIfaddrs(&interface, kIfnameEm1, IFF_RUNNING, |
| ipv6_local_address, ipv6_netmask, addresses)); |
| EXPECT_TRUE(internal::IfaddrsToNetworkInterfaceList( |
| INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &interface, &ip_attributes_getter, |
| &results)); |
| EXPECT_EQ(results.size(), 0ul); |
| |
| // vmware address should return by default. |
| ASSERT_TRUE(FillIfaddrs(&interface, kIfnameVmnet, IFF_RUNNING, ipv6_address, |
| ipv6_netmask, addresses)); |
| EXPECT_TRUE(internal::IfaddrsToNetworkInterfaceList( |
| INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &interface, &ip_attributes_getter, |
| &results)); |
| EXPECT_EQ(results.size(), 1ul); |
| EXPECT_EQ(results[0].name, kIfnameVmnet); |
| EXPECT_EQ(results[0].prefix_length, 1ul); |
| EXPECT_EQ(results[0].address, ipv6_address); |
| results.clear(); |
| |
| // vmware address should be trimmed out if policy specified so. |
| ASSERT_TRUE(FillIfaddrs(&interface, kIfnameVmnet, IFF_RUNNING, ipv6_address, |
| ipv6_netmask, addresses)); |
| EXPECT_TRUE(internal::IfaddrsToNetworkInterfaceList( |
| EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &interface, &ip_attributes_getter, |
| &results)); |
| EXPECT_EQ(results.size(), 0ul); |
| results.clear(); |
| |
| // Addresses with banned attributes should be ignored. |
| ip_attributes_getter.set_attributes(IP_ADDRESS_ATTRIBUTE_ANYCAST); |
| ASSERT_TRUE(FillIfaddrs(&interface, kIfnameEm1, IFF_RUNNING, ipv6_address, |
| ipv6_netmask, addresses)); |
| EXPECT_TRUE(internal::IfaddrsToNetworkInterfaceList( |
| INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &interface, &ip_attributes_getter, |
| &results)); |
| EXPECT_EQ(results.size(), 0ul); |
| results.clear(); |
| |
| // Addresses with allowed attribute IFA_F_TEMPORARY should be returned and |
| // attributes should be translated correctly. |
| ip_attributes_getter.set_attributes(IP_ADDRESS_ATTRIBUTE_TEMPORARY); |
| ASSERT_TRUE(FillIfaddrs(&interface, kIfnameEm1, IFF_RUNNING, ipv6_address, |
| ipv6_netmask, addresses)); |
| EXPECT_TRUE(internal::IfaddrsToNetworkInterfaceList( |
| INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &interface, &ip_attributes_getter, |
| &results)); |
| EXPECT_EQ(results.size(), 1ul); |
| EXPECT_EQ(results[0].name, kIfnameEm1); |
| EXPECT_EQ(results[0].prefix_length, 1ul); |
| EXPECT_EQ(results[0].address, ipv6_address); |
| EXPECT_EQ(results[0].ip_address_attributes, IP_ADDRESS_ATTRIBUTE_TEMPORARY); |
| results.clear(); |
| |
| // Addresses with allowed attribute IFA_F_DEPRECATED should be returned and |
| // attributes should be translated correctly. |
| ip_attributes_getter.set_attributes(IP_ADDRESS_ATTRIBUTE_DEPRECATED); |
| ASSERT_TRUE(FillIfaddrs(&interface, kIfnameEm1, IFF_RUNNING, ipv6_address, |
| ipv6_netmask, addresses)); |
| EXPECT_TRUE(internal::IfaddrsToNetworkInterfaceList( |
| INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &interface, &ip_attributes_getter, |
| &results)); |
| EXPECT_EQ(results.size(), 1ul); |
| EXPECT_EQ(results[0].name, kIfnameEm1); |
| EXPECT_EQ(results[0].prefix_length, 1ul); |
| EXPECT_EQ(results[0].address, ipv6_address); |
| EXPECT_EQ(results[0].ip_address_attributes, IP_ADDRESS_ATTRIBUTE_DEPRECATED); |
| results.clear(); |
| } |
| |
| } // namespace |
| } // namespace net |
| |
| #endif // !defined(STARBOARD) |