1 // Copyright (c) 2012 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.
5 #include "net/base/address_tracker_linux.h"
11 #include "base/bind.h"
12 #include "testing/gtest/include/gtest/gtest.h"
17 typedef std::vector
<char> Buffer
;
21 class AddressTrackerLinuxTest
: public testing::Test
{
23 AddressTrackerLinuxTest() : tracker_(base::Bind(&Noop
), base::Bind(&Noop
)) {}
25 bool HandleAddressMessage(const Buffer
& buf
) {
26 bool address_changed
= false;
27 bool link_changed
= false;
28 tracker_
.HandleMessage(&buf
[0], buf
.size(),
29 &address_changed
, &link_changed
);
30 EXPECT_FALSE(link_changed
);
31 return address_changed
;
34 bool HandleLinkMessage(const Buffer
& buf
) {
35 bool address_changed
= false;
36 bool link_changed
= false;
37 tracker_
.HandleMessage(&buf
[0], buf
.size(),
38 &address_changed
, &link_changed
);
39 EXPECT_FALSE(address_changed
);
43 AddressTrackerLinux::AddressMap
GetAddressMap() {
44 return tracker_
.GetAddressMap();
47 const base::hash_set
<int>* GetOnlineLinks() const {
48 return &tracker_
.online_links_
;
51 AddressTrackerLinux tracker_
;
56 class NetlinkMessage
{
58 explicit NetlinkMessage(uint16 type
) : buffer_(NLMSG_HDRLEN
) {
59 header()->nlmsg_type
= type
;
63 void AddPayload(const void* data
, size_t length
) {
64 CHECK_EQ(static_cast<size_t>(NLMSG_HDRLEN
),
65 buffer_
.size()) << "Payload must be added first";
70 void AddAttribute(uint16 type
, const void* data
, size_t length
) {
72 attr
.nla_len
= NLA_HDRLEN
+ length
;
74 Append(&attr
, sizeof(attr
));
80 void AppendTo(Buffer
* output
) const {
81 CHECK_EQ(NLMSG_ALIGN(output
->size()), output
->size());
82 output
->reserve(output
->size() + NLMSG_LENGTH(buffer_
.size()));
83 output
->insert(output
->end(), buffer_
.begin(), buffer_
.end());
87 void Append(const void* data
, size_t length
) {
88 const char* chardata
= reinterpret_cast<const char*>(data
);
89 buffer_
.insert(buffer_
.end(), chardata
, chardata
+ length
);
93 header()->nlmsg_len
= buffer_
.size();
94 buffer_
.insert(buffer_
.end(), NLMSG_ALIGN(buffer_
.size()) - buffer_
.size(),
96 CHECK(NLMSG_OK(header(), buffer_
.size()));
99 struct nlmsghdr
* header() {
100 return reinterpret_cast<struct nlmsghdr
*>(&buffer_
[0]);
106 void MakeAddrMessage(uint16 type
,
109 const IPAddressNumber
& address
,
110 const IPAddressNumber
& local
,
112 NetlinkMessage
nlmsg(type
);
113 struct ifaddrmsg msg
= {};
114 msg
.ifa_family
= family
;
115 msg
.ifa_flags
= flags
;
116 nlmsg
.AddPayload(&msg
, sizeof(msg
));
118 nlmsg
.AddAttribute(IFA_ADDRESS
, &address
[0], address
.size());
120 nlmsg
.AddAttribute(IFA_LOCAL
, &local
[0], local
.size());
121 nlmsg
.AppendTo(output
);
124 void MakeLinkMessage(uint16 type
, uint32 flags
, uint32 index
, Buffer
* output
) {
125 NetlinkMessage
nlmsg(type
);
126 struct ifinfomsg msg
= {};
127 msg
.ifi_index
= index
;
128 msg
.ifi_flags
= flags
;
129 nlmsg
.AddPayload(&msg
, sizeof(msg
));
131 nlmsg
.AppendTo(output
);
134 const unsigned char kAddress0
[] = { 127, 0, 0, 1 };
135 const unsigned char kAddress1
[] = { 10, 0, 0, 1 };
136 const unsigned char kAddress2
[] = { 192, 168, 0, 1 };
137 const unsigned char kAddress3
[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
139 const unsigned char kAddress4
[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255,
142 TEST_F(AddressTrackerLinuxTest
, NewAddress
) {
143 const IPAddressNumber kEmpty
;
144 const IPAddressNumber
kAddr0(kAddress0
, kAddress0
+ arraysize(kAddress0
));
145 const IPAddressNumber
kAddr1(kAddress1
, kAddress1
+ arraysize(kAddress1
));
146 const IPAddressNumber
kAddr2(kAddress2
, kAddress2
+ arraysize(kAddress2
));
147 const IPAddressNumber
kAddr3(kAddress3
, kAddress3
+ arraysize(kAddress3
));
150 MakeAddrMessage(RTM_NEWADDR
, IFA_F_TEMPORARY
, AF_INET
, kAddr0
, kEmpty
,
152 EXPECT_TRUE(HandleAddressMessage(buffer
));
153 AddressTrackerLinux::AddressMap map
= GetAddressMap();
154 EXPECT_EQ(1u, map
.size());
155 EXPECT_EQ(1u, map
.count(kAddr0
));
156 EXPECT_EQ(IFA_F_TEMPORARY
, map
[kAddr0
].ifa_flags
);
159 MakeAddrMessage(RTM_NEWADDR
, IFA_F_HOMEADDRESS
, AF_INET
, kAddr1
, kAddr2
,
161 EXPECT_TRUE(HandleAddressMessage(buffer
));
162 map
= GetAddressMap();
163 EXPECT_EQ(2u, map
.size());
164 EXPECT_EQ(1u, map
.count(kAddr0
));
165 EXPECT_EQ(1u, map
.count(kAddr2
));
166 EXPECT_EQ(IFA_F_HOMEADDRESS
, map
[kAddr2
].ifa_flags
);
169 MakeAddrMessage(RTM_NEWADDR
, 0, AF_INET6
, kEmpty
, kAddr3
, &buffer
);
170 EXPECT_TRUE(HandleAddressMessage(buffer
));
171 map
= GetAddressMap();
172 EXPECT_EQ(3u, map
.size());
173 EXPECT_EQ(1u, map
.count(kAddr3
));
176 TEST_F(AddressTrackerLinuxTest
, NewAddressChange
) {
177 const IPAddressNumber kEmpty
;
178 const IPAddressNumber
kAddr0(kAddress0
, kAddress0
+ arraysize(kAddress0
));
181 MakeAddrMessage(RTM_NEWADDR
, IFA_F_TEMPORARY
, AF_INET
, kAddr0
, kEmpty
,
183 EXPECT_TRUE(HandleAddressMessage(buffer
));
184 AddressTrackerLinux::AddressMap map
= GetAddressMap();
185 EXPECT_EQ(1u, map
.size());
186 EXPECT_EQ(1u, map
.count(kAddr0
));
187 EXPECT_EQ(IFA_F_TEMPORARY
, map
[kAddr0
].ifa_flags
);
190 MakeAddrMessage(RTM_NEWADDR
, IFA_F_HOMEADDRESS
, AF_INET
, kAddr0
, kEmpty
,
192 EXPECT_TRUE(HandleAddressMessage(buffer
));
193 map
= GetAddressMap();
194 EXPECT_EQ(1u, map
.size());
195 EXPECT_EQ(1u, map
.count(kAddr0
));
196 EXPECT_EQ(IFA_F_HOMEADDRESS
, map
[kAddr0
].ifa_flags
);
198 // Both messages in one buffer.
200 MakeAddrMessage(RTM_NEWADDR
, IFA_F_TEMPORARY
, AF_INET
, kAddr0
, kEmpty
,
202 MakeAddrMessage(RTM_NEWADDR
, IFA_F_HOMEADDRESS
, AF_INET
, kAddr0
, kEmpty
,
204 EXPECT_TRUE(HandleAddressMessage(buffer
));
205 map
= GetAddressMap();
206 EXPECT_EQ(1u, map
.size());
207 EXPECT_EQ(IFA_F_HOMEADDRESS
, map
[kAddr0
].ifa_flags
);
210 TEST_F(AddressTrackerLinuxTest
, NewAddressDuplicate
) {
211 const IPAddressNumber
kAddr0(kAddress0
, kAddress0
+ arraysize(kAddress0
));
214 MakeAddrMessage(RTM_NEWADDR
, IFA_F_TEMPORARY
, AF_INET
, kAddr0
, kAddr0
,
216 EXPECT_TRUE(HandleAddressMessage(buffer
));
217 AddressTrackerLinux::AddressMap map
= GetAddressMap();
218 EXPECT_EQ(1u, map
.size());
219 EXPECT_EQ(1u, map
.count(kAddr0
));
220 EXPECT_EQ(IFA_F_TEMPORARY
, map
[kAddr0
].ifa_flags
);
222 EXPECT_FALSE(HandleAddressMessage(buffer
));
223 map
= GetAddressMap();
224 EXPECT_EQ(1u, map
.size());
225 EXPECT_EQ(IFA_F_TEMPORARY
, map
[kAddr0
].ifa_flags
);
228 TEST_F(AddressTrackerLinuxTest
, DeleteAddress
) {
229 const IPAddressNumber kEmpty
;
230 const IPAddressNumber
kAddr0(kAddress0
, kAddress0
+ arraysize(kAddress0
));
231 const IPAddressNumber
kAddr1(kAddress1
, kAddress1
+ arraysize(kAddress1
));
232 const IPAddressNumber
kAddr2(kAddress2
, kAddress2
+ arraysize(kAddress2
));
235 MakeAddrMessage(RTM_NEWADDR
, 0, AF_INET
, kAddr0
, kEmpty
, &buffer
);
236 MakeAddrMessage(RTM_NEWADDR
, 0, AF_INET
, kAddr1
, kAddr2
, &buffer
);
237 EXPECT_TRUE(HandleAddressMessage(buffer
));
238 AddressTrackerLinux::AddressMap map
= GetAddressMap();
239 EXPECT_EQ(2u, map
.size());
242 MakeAddrMessage(RTM_DELADDR
, 0, AF_INET
, kEmpty
, kAddr0
, &buffer
);
243 EXPECT_TRUE(HandleAddressMessage(buffer
));
244 map
= GetAddressMap();
245 EXPECT_EQ(1u, map
.size());
246 EXPECT_EQ(0u, map
.count(kAddr0
));
247 EXPECT_EQ(1u, map
.count(kAddr2
));
250 MakeAddrMessage(RTM_DELADDR
, 0, AF_INET
, kAddr2
, kAddr1
, &buffer
);
251 // kAddr1 does not exist in the map.
252 EXPECT_FALSE(HandleAddressMessage(buffer
));
253 map
= GetAddressMap();
254 EXPECT_EQ(1u, map
.size());
257 MakeAddrMessage(RTM_DELADDR
, 0, AF_INET
, kAddr2
, kEmpty
, &buffer
);
258 EXPECT_TRUE(HandleAddressMessage(buffer
));
259 map
= GetAddressMap();
260 EXPECT_EQ(0u, map
.size());
263 TEST_F(AddressTrackerLinuxTest
, IgnoredMessage
) {
264 const IPAddressNumber kEmpty
;
265 const IPAddressNumber
kAddr0(kAddress0
, kAddress0
+ arraysize(kAddress0
));
266 const IPAddressNumber
kAddr3(kAddress3
, kAddress3
+ arraysize(kAddress3
));
270 MakeAddrMessage(RTM_NEWADDR
, 0, AF_UNSPEC
, kAddr3
, kAddr0
, &buffer
);
272 MakeAddrMessage(RTM_NEWADDR
, 0, AF_INET
, kEmpty
, kEmpty
, &buffer
);
274 MakeAddrMessage(RTM_DELROUTE
, 0, AF_INET6
, kAddr3
, kEmpty
, &buffer
);
275 EXPECT_FALSE(HandleAddressMessage(buffer
));
276 EXPECT_TRUE(GetAddressMap().empty());
278 // Valid message after ignored messages.
279 NetlinkMessage
nlmsg(RTM_NEWADDR
);
280 struct ifaddrmsg msg
= {};
281 msg
.ifa_family
= AF_INET
;
282 nlmsg
.AddPayload(&msg
, sizeof(msg
));
283 // Ignored attribute.
284 struct ifa_cacheinfo cache_info
= {};
285 nlmsg
.AddAttribute(IFA_CACHEINFO
, &cache_info
, sizeof(cache_info
));
286 nlmsg
.AddAttribute(IFA_ADDRESS
, &kAddr0
[0], kAddr0
.size());
287 nlmsg
.AppendTo(&buffer
);
289 EXPECT_TRUE(HandleAddressMessage(buffer
));
290 EXPECT_EQ(1u, GetAddressMap().size());
293 TEST_F(AddressTrackerLinuxTest
, AddInterface
) {
297 MakeLinkMessage(RTM_NEWLINK
,
298 IFF_LOOPBACK
| IFF_UP
| IFF_LOWER_UP
| IFF_RUNNING
,
300 EXPECT_FALSE(HandleLinkMessage(buffer
));
301 EXPECT_TRUE(GetOnlineLinks()->empty());
303 // Ignores not IFF_LOWER_UP.
304 MakeLinkMessage(RTM_NEWLINK
, IFF_UP
| IFF_RUNNING
, 0, &buffer
);
305 EXPECT_FALSE(HandleLinkMessage(buffer
));
306 EXPECT_TRUE(GetOnlineLinks()->empty());
309 MakeLinkMessage(RTM_DELLINK
, IFF_UP
| IFF_LOWER_UP
| IFF_RUNNING
, 0, &buffer
);
310 EXPECT_FALSE(HandleLinkMessage(buffer
));
311 EXPECT_TRUE(GetOnlineLinks()->empty());
314 MakeLinkMessage(RTM_NEWLINK
, IFF_UP
| IFF_LOWER_UP
| IFF_RUNNING
, 0, &buffer
);
315 EXPECT_TRUE(HandleLinkMessage(buffer
));
316 EXPECT_EQ(1u, GetOnlineLinks()->count(0));
317 EXPECT_EQ(1u, GetOnlineLinks()->size());
319 // Ignores redundant enables.
320 MakeLinkMessage(RTM_NEWLINK
, IFF_UP
| IFF_LOWER_UP
| IFF_RUNNING
, 0, &buffer
);
321 EXPECT_FALSE(HandleLinkMessage(buffer
));
322 EXPECT_EQ(1u, GetOnlineLinks()->count(0));
323 EXPECT_EQ(1u, GetOnlineLinks()->size());
325 // Verify adding another online device (e.g. VPN) is considered a change.
326 MakeLinkMessage(RTM_NEWLINK
, IFF_UP
| IFF_LOWER_UP
| IFF_RUNNING
, 1, &buffer
);
327 EXPECT_TRUE(HandleLinkMessage(buffer
));
328 EXPECT_EQ(1u, GetOnlineLinks()->count(0));
329 EXPECT_EQ(1u, GetOnlineLinks()->count(1));
330 EXPECT_EQ(2u, GetOnlineLinks()->size());
333 TEST_F(AddressTrackerLinuxTest
, RemoveInterface
) {
336 // Should disappear when not IFF_LOWER_UP.
337 MakeLinkMessage(RTM_NEWLINK
, IFF_UP
| IFF_LOWER_UP
| IFF_RUNNING
, 0, &buffer
);
338 EXPECT_TRUE(HandleLinkMessage(buffer
));
339 EXPECT_FALSE(GetOnlineLinks()->empty());
340 MakeLinkMessage(RTM_NEWLINK
, IFF_UP
| IFF_RUNNING
, 0, &buffer
);
341 EXPECT_TRUE(HandleLinkMessage(buffer
));
342 EXPECT_TRUE(GetOnlineLinks()->empty());
344 // Ignores redundant disables.
345 MakeLinkMessage(RTM_NEWLINK
, IFF_UP
| IFF_RUNNING
, 0, &buffer
);
346 EXPECT_FALSE(HandleLinkMessage(buffer
));
347 EXPECT_TRUE(GetOnlineLinks()->empty());
349 // Ignores deleting down interfaces.
350 MakeLinkMessage(RTM_DELLINK
, IFF_UP
| IFF_RUNNING
, 0, &buffer
);
351 EXPECT_FALSE(HandleLinkMessage(buffer
));
352 EXPECT_TRUE(GetOnlineLinks()->empty());
354 // Should disappear when deleted.
355 MakeLinkMessage(RTM_NEWLINK
, IFF_UP
| IFF_LOWER_UP
| IFF_RUNNING
, 0, &buffer
);
356 EXPECT_TRUE(HandleLinkMessage(buffer
));
357 EXPECT_FALSE(GetOnlineLinks()->empty());
358 MakeLinkMessage(RTM_DELLINK
, IFF_UP
| IFF_LOWER_UP
| IFF_RUNNING
, 0, &buffer
);
359 EXPECT_TRUE(HandleLinkMessage(buffer
));
360 EXPECT_TRUE(GetOnlineLinks()->empty());
365 } // namespace internal