1 // Copyright 2017 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 "net/base/network_interfaces_getifaddrs.h"
6 
7 #include <string>
8 
9 #include "build/build_config.h"
10 #include "net/base/ip_endpoint.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 
13 #include <ifaddrs.h>
14 #include <net/if.h>
15 #include <netinet/in.h>
16 
17 namespace net {
18 namespace {
19 
20 class IPAttributesGetterTest : public internal::IPAttributesGetter {
21  public:
IPAttributesGetterTest()22   IPAttributesGetterTest() {}
23 
24   // internal::IPAttributesGetter interface.
IsInitialized() const25   bool IsInitialized() const override { return true; }
GetAddressAttributes(const ifaddrs * if_addr,int * attributes)26   bool GetAddressAttributes(const ifaddrs* if_addr, int* attributes) override {
27     *attributes = attributes_;
28     return true;
29   }
GetNetworkInterfaceType(const ifaddrs * if_addr)30   NetworkChangeNotifier::ConnectionType GetNetworkInterfaceType(
31       const ifaddrs* if_addr) override {
32     return NetworkChangeNotifier::CONNECTION_UNKNOWN;
33   }
34 
set_attributes(int attributes)35   void set_attributes(int attributes) { attributes_ = attributes; }
36 
37  private:
38   int attributes_ = 0;
39 };
40 
41 // Helper function to create a single valid ifaddrs
FillIfaddrs(ifaddrs * interfaces,const char * ifname,uint flags,const IPAddress & ip_address,const IPAddress & ip_netmask,sockaddr_storage sock_addrs[2])42 bool FillIfaddrs(ifaddrs* interfaces,
43                  const char* ifname,
44                  uint flags,
45                  const IPAddress& ip_address,
46                  const IPAddress& ip_netmask,
47                  sockaddr_storage sock_addrs[2]) {
48   interfaces->ifa_next = nullptr;
49   interfaces->ifa_name = const_cast<char*>(ifname);
50   interfaces->ifa_flags = flags;
51 
52   socklen_t sock_len = sizeof(sockaddr_storage);
53 
54   // Convert to sockaddr for next check.
55   if (!IPEndPoint(ip_address, 0)
56            .ToSockAddr(reinterpret_cast<sockaddr*>(&sock_addrs[0]),
57                        &sock_len)) {
58     return false;
59   }
60   interfaces->ifa_addr = reinterpret_cast<sockaddr*>(&sock_addrs[0]);
61 
62   sock_len = sizeof(sockaddr_storage);
63   if (!IPEndPoint(ip_netmask, 0)
64            .ToSockAddr(reinterpret_cast<sockaddr*>(&sock_addrs[1]),
65                        &sock_len)) {
66     return false;
67   }
68   interfaces->ifa_netmask = reinterpret_cast<sockaddr*>(&sock_addrs[1]);
69 
70   return true;
71 }
72 
73 static const char kIfnameEm1[] = "em1";
74 static const char kIfnameVmnet[] = "vmnet";
75 
76 static const unsigned char kIPv6LocalAddr[] = {0, 0, 0, 0, 0, 0, 0, 0,
77                                                0, 0, 0, 0, 0, 0, 0, 1};
78 
79 // The following 3 addresses need to be changed together. IPv6Addr is the IPv6
80 // address. IPv6Netmask is the mask address with as many leading bits set to 1
81 // as the prefix length. IPv6AddrPrefix needs to match IPv6Addr with the same
82 // number of bits as the prefix length.
83 static const unsigned char kIPv6Addr[] = {0x24, 0x01, 0xfa, 0x00, 0x00, 0x04,
84                                           0x10, 0x00, 0xbe, 0x30, 0x5b, 0xff,
85                                           0xfe, 0xe5, 0x00, 0xc3};
86 
87 static const unsigned char kIPv6Netmask[] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
88                                              0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89                                              0x00, 0x00, 0x00, 0x00};
90 
TEST(NetworkInterfacesTest,IfaddrsToNetworkInterfaceList)91 TEST(NetworkInterfacesTest, IfaddrsToNetworkInterfaceList) {
92   IPAddress ipv6_local_address(kIPv6LocalAddr);
93   IPAddress ipv6_address(kIPv6Addr);
94   IPAddress ipv6_netmask(kIPv6Netmask);
95 
96   NetworkInterfaceList results;
97   IPAttributesGetterTest ip_attributes_getter;
98   sockaddr_storage addresses[2];
99   ifaddrs interface;
100 
101   // Address of offline links should be ignored.
102   ASSERT_TRUE(FillIfaddrs(&interface, kIfnameEm1, IFF_UP, ipv6_address,
103                           ipv6_netmask, addresses));
104   EXPECT_TRUE(internal::IfaddrsToNetworkInterfaceList(
105       INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &interface, &ip_attributes_getter,
106       &results));
107   EXPECT_EQ(results.size(), 0ul);
108 
109   // Local address should be trimmed out.
110   ASSERT_TRUE(FillIfaddrs(&interface, kIfnameEm1, IFF_RUNNING,
111                           ipv6_local_address, ipv6_netmask, addresses));
112   EXPECT_TRUE(internal::IfaddrsToNetworkInterfaceList(
113       INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &interface, &ip_attributes_getter,
114       &results));
115   EXPECT_EQ(results.size(), 0ul);
116 
117   // vmware address should return by default.
118   ASSERT_TRUE(FillIfaddrs(&interface, kIfnameVmnet, IFF_RUNNING, ipv6_address,
119                           ipv6_netmask, addresses));
120   EXPECT_TRUE(internal::IfaddrsToNetworkInterfaceList(
121       INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &interface, &ip_attributes_getter,
122       &results));
123   EXPECT_EQ(results.size(), 1ul);
124   EXPECT_EQ(results[0].name, kIfnameVmnet);
125   EXPECT_EQ(results[0].prefix_length, 1ul);
126   EXPECT_EQ(results[0].address, ipv6_address);
127   results.clear();
128 
129   // vmware address should be trimmed out if policy specified so.
130   ASSERT_TRUE(FillIfaddrs(&interface, kIfnameVmnet, IFF_RUNNING, ipv6_address,
131                           ipv6_netmask, addresses));
132   EXPECT_TRUE(internal::IfaddrsToNetworkInterfaceList(
133       EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &interface, &ip_attributes_getter,
134       &results));
135   EXPECT_EQ(results.size(), 0ul);
136   results.clear();
137 
138   // Addresses with banned attributes should be ignored.
139   ip_attributes_getter.set_attributes(IP_ADDRESS_ATTRIBUTE_ANYCAST);
140   ASSERT_TRUE(FillIfaddrs(&interface, kIfnameEm1, IFF_RUNNING, ipv6_address,
141                           ipv6_netmask, addresses));
142   EXPECT_TRUE(internal::IfaddrsToNetworkInterfaceList(
143       INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &interface, &ip_attributes_getter,
144       &results));
145   EXPECT_EQ(results.size(), 0ul);
146   results.clear();
147 
148   // Addresses with allowed attribute IFA_F_TEMPORARY should be returned and
149   // attributes should be translated correctly.
150   ip_attributes_getter.set_attributes(IP_ADDRESS_ATTRIBUTE_TEMPORARY);
151   ASSERT_TRUE(FillIfaddrs(&interface, kIfnameEm1, IFF_RUNNING, ipv6_address,
152                           ipv6_netmask, addresses));
153   EXPECT_TRUE(internal::IfaddrsToNetworkInterfaceList(
154       INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &interface, &ip_attributes_getter,
155       &results));
156   EXPECT_EQ(results.size(), 1ul);
157   EXPECT_EQ(results[0].name, kIfnameEm1);
158   EXPECT_EQ(results[0].prefix_length, 1ul);
159   EXPECT_EQ(results[0].address, ipv6_address);
160   EXPECT_EQ(results[0].ip_address_attributes, IP_ADDRESS_ATTRIBUTE_TEMPORARY);
161   results.clear();
162 
163   // Addresses with allowed attribute IFA_F_DEPRECATED should be returned and
164   // attributes should be translated correctly.
165   ip_attributes_getter.set_attributes(IP_ADDRESS_ATTRIBUTE_DEPRECATED);
166   ASSERT_TRUE(FillIfaddrs(&interface, kIfnameEm1, IFF_RUNNING, ipv6_address,
167                           ipv6_netmask, addresses));
168   EXPECT_TRUE(internal::IfaddrsToNetworkInterfaceList(
169       INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &interface, &ip_attributes_getter,
170       &results));
171   EXPECT_EQ(results.size(), 1ul);
172   EXPECT_EQ(results[0].name, kIfnameEm1);
173   EXPECT_EQ(results[0].prefix_length, 1ul);
174   EXPECT_EQ(results[0].address, ipv6_address);
175   EXPECT_EQ(results[0].ip_address_attributes, IP_ADDRESS_ATTRIBUTE_DEPRECATED);
176   results.clear();
177 }
178 
179 }  // namespace
180 }  // namespace net
181