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